Commit Graph
56 Commits
Author SHA1 Message Date
Sergey KozyrenkoandClaude Opus 4.8 2853c97549 feat(reasoning): add three-state On/Off/Default reasoning control
Add an explicit reasoning Off to the per-agent config, backed by the langchaingo
tri-state API. Off emits llms.WithReasoningDisabled() (the provider disable wire)
via BuildOptions, and UsesAdaptiveThinking is guarded so Off overrides the
adaptive-only auto-adaptive.

Per-model capability is derived at runtime from llms.ReasoningSupportFor and
surfaced through GraphQL ModelReasoningInfo, so the UI only offers Off where it
actually disables: cannotDisable reports when Off would be rejected (always-on
models) OR a silent no-op (an unclassified default-on model whose disable wire is
omitted), and capability is surfaced for any thinking-capable model (e.g. Gemini,
which declares thinking without a reasoning block). A new
ProviderType.ReasoningProvider() supplies the provider to the resolver.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 19:50:43 +07:00
Sergey KozyrenkoandClaude Opus 4.8 9876c13ea8 docs(providers): restore the DeepSeek legacy reasoning-format contract
The openai-compat consolidation dropped the comment warning that DeepSeek needs
the legacy top-level "reasoning_effort" string form; without it a maintainer
could add openai.WithModernReasoningFormat() to the shared opts and silently
break DeepSeek thinking mode. Restore it at the shared opts choke point.

Also fix two stale pointers: glm/qwen config.yml cited
WithPreserveReasoningContent() "in glm.go/qwen.go", but it moved to
openaicompat.go during that same consolidation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 17:02:21 +07:00
Sergey KozyrenkoandClaude Opus 4.8 d3c46c7158 test: close the coverage gaps flagged by the review
- providers: prove a stale user-provider row does not knock out a valid USER
  sibling (TestGetProviders_StaleUserRowSpansValidSibling — ollama builds keyless
  so it survives beside a skipped minimax; side-by-side verified).
- settings-provider: cover the create-form ?type=/?id= guards (disabled/unknown
  type and clone-of-disabled bounce to the list; an enabled type renders). These
  had zero coverage — a swap/drop-return regression would have shipped green.
- knowledge-form: cover performSave's server-document reset branch (untouched
  fields reflect the returned document under keepDirtyValues), and the useBlocker
  "Save and leave" path via a real data router (proceeds the blocked nav, does
  NOT honor a CREATE redirect). Swap the negative no-navigate assertion's
  setTimeout(0) flush for a deterministic Save-disabled anchor.

Each test mutation-verified to fail on the reverted production code; 652 frontend
tests + go test green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 00:55:29 +07:00
Sergey KozyrenkoandClaude Opus 4.8 84d87cf474 refactor(providers): apply review follow-ups (degrade log, count helper, empty menu)
From a strict re-review of the recent commits (no blocker/high/security found):
- providers.go GetProviders: the skip covers ANY unbuildable saved provider, not
  only a disabled type — drop the misleading "of unavailable type" wording and
  lower the line to Debug (it re-fires on every providers fetch; WithError keeps
  the reason).
- settings-prompt countVariableUses: drop the redundant seed-in-map side effect;
  the component already falls back to `?? 0` for unused variables, so the loop's
  own `?? 0` is the only seed needed.
- settings-providers create menu: render a disabled "No available provider types"
  placeholder instead of a silently-empty menu (loading / no-keys / failed-query
  states), with a test covering it.

Counts live-verified unchanged (AgentType 1->3 on the stand); go test + 646
frontend tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 23:45:36 +07:00
Sergey KozyrenkoandClaude Opus 4.8 08a24c9abd fix(providers): skip unavailable user providers instead of failing the whole list
A saved user provider whose type is no longer enabled (e.g. its API key was
removed) made GetProviders return an error for the ENTIRE `providers` query —
one stale row blocked all flow creation in the UI ("No available providers").
Skip and log such rows, mirroring how startup already tolerates disabled
default providers. Pre-existing robustness gap, not introduced by this branch.

Verified live on the docker stand: the `providers` query went from a hard
error to returning all 10 enabled providers (the stale minimax row skipped),
and flow creation works again. Adds a side-by-side regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 22:10:40 +07:00
Sergey KozyrenkoandClaude Opus 4.8 a1908536b7 test(providers): extend the price-consistency guard to all 9 providers
anthropic, bedrock, and gemini also carry per-agent prices in config.yml but
were not covered. Adding them confirms no current drift and guards them going
forward. bedrock's loaders take a *config.Config, so they're wrapped with an
empty config to read the embedded catalog.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 13:55:26 +07:00
Sergey KozyrenkoandClaude Opus 4.8 4ecf2bbac1 fix(providers): correct model prices from a full official-source audit
Audited all 133 catalog models across 9 providers against official pricing
pages, each delta independently re-verified. openai/anthropic/gemini/glm/kimi
were already correct (0 changes). Corrections:

- deepseek-v4-pro: 1.74/3.48/0.0145 -> 0.435/0.87/0.003625 (catalog was 4x the
  official DeepSeek rate).
- bedrock mistral-large-3-675b: 4.0/12.0 -> 0.5/1.5 (8x overstatement; old
  Mistral Large 24.07 rate).
- minimax M3 0.6/2.4 -> 0.3/1.2, M2.7 0.4/1.1 -> 0.3/1.2, M2.7-highspeed
  0.4/1.1 -> 0.6/2.4, all +0.06 cache (permanent-50%-off effective rates).
- qwen3.6-35b-a3b: 0.248/1.485 -> 0.375/2.25 (catalog had the China-mainland
  price, not the International endpoint the rest of the catalog uses).
- qwen: add cache_read = 0.20 x input (implicit-cache rule) to 16 open-source
  models that were missing it.

config.yml agent prices synced for deepseek-v4-pro and MiniMax-M3 (guard test
keeps them aligned).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 13:44:59 +07:00
Sergey KozyrenkoandClaude Opus 4.8 dad1be429e feat(providers): declare reasoning efforts for gpt-5.2-codex and gpt-5-pro
Verified per the official OpenAI model pages:
- gpt-5.2-codex: [low, medium, high, xhigh]
- gpt-5-pro: [high] (the page states it "only supports reasoning.effort: high")

Other openai reasoning models (gpt-5, gpt-5.1 = no xhigh; gpt-5-mini/nano,
codex variants, o-series) keep the default — their official pages do not
enumerate an accepted effort set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 13:44:58 +07:00
Sergey KozyrenkoandClaude Opus 4.8 ebeddf4e76 fix(providers): set qwen cache_read to the documented 20% implicit-cache rate
Alibaba Model Studio's context-cache doc bills cached input tokens at 20% of the
input price (implicit hits, International endpoint). Most of the qwen catalog
already used 20%; align the outliers and guard against future drift.

- qwen3.7-max 1.25 -> 0.5, qwen3.7-plus 0.2 -> 0.08: corrects an earlier change
  that read a "50% discount" off the model-pricing page; the authoritative rate
  is 20%, so the original 0.5 for qwen3.7-max was already correct.
- qwen3.6-{max-preview,plus,flash}, qwen3.5-{plus,flash}: 10% -> 20% stale
  outliers, with matching config.yml agent-price updates.

Add TestAgentConfigPricesMatchCatalog: GetPriceInfoForType returns the agent
price with no catalog fallback, so config.yml drift silently mis-prices cost.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 05:04:13 +07:00
Sergey KozyrenkoandClaude Opus 4.8 2f9e86391e feat(providers): declare reasoning efforts for the remaining xhigh openai models
Verified per the OpenAI model pages (reasoning.effort support):
- gpt-5.4-mini, gpt-5.4-nano, gpt-5.2: [low, medium, high, xhigh]
- gpt-5.2-pro: [medium, high, xhigh] (no low)

gpt-5 / gpt-5.1 keep the default [low, medium, high] (no xhigh; gpt-5 uses
"minimal", not representable in the UI enum). Codex variants are unverified
and left for a follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 05:04:12 +07:00
Sergey KozyrenkoandClaude Opus 4.8 de7db21448 feat(providers): declare reasoning efforts so xhigh/max surface in the UI
The settings effort dropdown is driven by a model's reasoning.efforts and
falls back to [low, medium, high] when absent, so xhigh/max were never
selectable for OpenAI-compatible models even though the backend accepts them.

Declare the verified accepted levels:
- glm-5.2: [high, max] (Z.AI: GLM-5.2 reasoning_effort accepts only high/max,
  so the default low/medium were also wrong for it)
- gpt-5.4: [low, medium, high, xhigh] (OpenAI GPT-5.4/5.5 effort enum)

Other openai/gpt-5.x entries still need per-model effort verification.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 04:39:31 +07:00
Sergey KozyrenkoandClaude Opus 4.8 8bbbdbf7c5 fix(providers): correct qwen3.7-max cache_read to the official rate
cache_read was 0.5; the Alibaba Model Studio official price (International)
is 1.25 per 1M tokens (a 50% discount on the 2.5 input rate). Pre-existing
inaccuracy, unrelated to the qwen3.7-plus addition.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 03:56:04 +07:00
Sergey KozyrenkoandClaude Opus 4.8 b40091d68f fix(providers): correct kimi-k2.7-code and qwen3.7-plus prices to official rates
Replace the placeholder estimates with verified list prices (USD per 1M tokens):
- kimi-k2.7-code: 0.95 / 4.00 / 0.19 cache (platform.kimi.ai official) —
  identical input/output to k2.6, only the cache rate differs.
- qwen3.7-plus: 0.4 / 1.6 / 0.2 cache (Alibaba Model Studio official,
  International base <=256K tier) — the earlier estimate conflated it with
  the qwen3.7-max tier and was ~2.5x too high.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 03:54:31 +07:00
Sergey KozyrenkoandClaude Opus 4.8 f489e13ed4 docs(providers): drop unverifiable superlative from glm-5.2 description
"the only GLM model that honors reasoning_effort" is an unenforceable
prose claim; state the capability the entry actually carries instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 03:47:13 +07:00
Sergey KozyrenkoandClaude Opus 4.8 35c77ae5aa test(providers): scan the whole catalog for adaptive modes in the M7 pin
The M7 pin only checked models actually assigned to an agent type, so an
adaptive reasoning mode declared on an unassigned catalog model would pass
silently. Add a second loop over every catalog model so any openaicompat
provider that declares adaptive/adaptive-only fails loudly — matching the
guard's stated intent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 03:47:12 +07:00
Sergey KozyrenkoandClaude Sonnet 4.6 2d8bce7ccb feat(providers): add glm-5.2, kimi-k2.7-code, qwen3.7-plus to model catalogs
- glm/models.yml: add glm-5.2 (only GLM model supporting reasoning_effort=high/max)
- kimi/models.yml: add kimi-k2.7-code (code-specialist above k2.6)
- qwen/models.yml: add qwen3.7-plus (cost-efficient tier below qwen3.7-max)

Prices for kimi-k2.7-code and qwen3.7-plus are estimated from adjacent
catalog entries and should be verified against official pricing pages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 03:11:20 +07:00
Sergey KozyrenkoandClaude Sonnet 4.6 a69e19f751 feat(providers): allow xhigh/max reasoning_effort on the OpenAI-compatible path
The per-agent options builder only emitted WithReasoning for low/medium/high,
and the langchaingo fork clamped xhigh/max to high in GetEffort (treating them
as adaptive-only). OpenAI GPT-5.5 and GLM-5.2 now expose xhigh/max as real
reasoning_effort levels, so that clamp encodes a stale invariant.

Extend the effort switch to pass xhigh/max through; the fork's GetEffort clamp
is removed in the local langchaingo (propagated via vendor) so the OpenAI
transport emits the real level. Adaptive (anthropic/bedrock) and budget paths
are unaffected — GetEffort is called only by the OpenAI transport. Validity is
gated per model by ModelReasoningInfo.Efforts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 02:18:57 +07:00
Sergey KozyrenkoandClaude Sonnet 4.6 40debd150d test(providers): pin openaicompat providers off adaptive thinking (M7)
Adaptive thinking (thinking.type=adaptive + output_config.effort) is an
Anthropic-protocol mode the langchaingo OpenAI transport cannot emit, and
the openaicompat Call path never threads PrepareAdaptiveCallOptions. So an
adaptive reasoning mode declared in an openaicompat provider's models.yml
would silently no-op.

Assert that none of the openaicompat-backed providers (qwen, glm, deepseek,
kimi, minimax) resolve to adaptive thinking for any agent type. The day
someone adds an adaptive model/mode to one of their configs, this fails
loudly instead of dropping the thinking budget in silence.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 00:52:49 +07:00
Sergey Kozyrenko 124a1e1084 Merge remote-tracking branch 'origin/fix/ram-consumption' into integrate/open-prs 2026-06-25 20:11:59 +07:00
Dmitry Ng 9caa6a8775 fix(backend): update LRU cache implementation to use non-expirable version
- Replaced expirable LRU cache with non-expirable lru.Cache in multiple files for improved performance and reduced resource usage.
- Introduced a new function, newSummarizerCache, to create a fixed-size LRU cache for summarizer results, eliminating the need for background goroutines.
- Updated related code to ensure compatibility with the new cache implementation.
2026-06-25 12:28:10 +03:00
Sergey Kozyrenko ac32a8e996 fixup! fix(providers): don't crash startup when a disabled provider's external config is unreadable 2026-06-25 09:56:14 +07:00
Sergey KozyrenkoandClaude Opus 4.8 f441ec1c4d fix(providers): don't crash startup when a disabled provider's external config is unreadable
NewProviderController loaded every provider's default config (NewConfig) in an
ungated loop that treated any error as fatal, while actual provider construction
(New) is correctly gated on Enabled. A disabled provider pointed at an unreadable
BEDROCK_CONFIG_PATH (or the equivalent custom/ollama external config) therefore
aborted startup, even though that provider was never going to be used.

Extract the config-loading loop into buildDefaultConfigs and gate the failure on
Enabled: a disabled provider whose external config can't be read is logged and
skipped; an enabled provider still fails loudly. Tests cover both paths
(disabled + bad path non-fatal, enabled + bad path fatal).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 09:26:00 +07:00
Sergey KozyrenkoandClaude Opus 4.8 7867a73a6a test(providers): guard providerRegistry against AllProviderTypes drift
A type present in only one of the two hand-maintained lists fails silently:
accepted by the API then erroring "unknown provider type" at construction, or
rejected 422 despite working. Assert set-equality and canonical names so drift
fails in CI instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 09:49:00 +07:00
Sergey KozyrenkoandClaude Opus 4.8 2f3df495fa test(pconfig): cover the adaptive-thinking backstop (refs #288)
UsesAdaptiveThinking/PrepareAdaptiveCallOptions had no test coverage after the
native-langchaingo migration removed the old transport-layer tests. Add table
tests: an adaptive-only model forces adaptive over an agent's budget choice or an
absent reasoning block, while budget-only models stay untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 09:49:00 +07:00
Sergey KozyrenkoandClaude Opus 4.8 b8b90f8349 refactor(providers): use native adaptive thinking from the langchaingo fork
Adaptive thinking (Claude Opus 4.7+) is now implemented natively in the
vxcontrol/langchaingo fork (v0.1.14-update.6): the anthropic and bedrock clients
emit thinking.type=adaptive + output_config.effort and omit the sampling params
adaptive models reject. PentAGI no longer patches the serialized request body.

- pconfig.PrepareAdaptiveCallOptions appends llms.WithAdaptiveReasoning; the
  ctx-effort plumbing (WithAdaptiveEffort/AdaptiveEffortFromContext) is removed.
- Delete the bedrock smithy Build middleware and anthropic http RoundTripper
  (adaptive_thinking.go + tests in both packages) that rewrote the request body.
- Bump the langchaingo require to v0.1.14-update.6; refresh llms_how_to.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 00:47:32 +07:00
Sergey KozyrenkoandClaude Opus 4.8 28036f652c refactor(providers): table-driven provider registry
The provider controller repeated every provider type across five hand-written
blocks (default-config wiring, key-gated instantiation, GetProvider fallback,
NewProvider, buildProviderFromConfig) plus the API-layer Valid() whitelist.

Introduce pkg/providers/registry.go: a providerRegistry table whose entries hold
the per-type constructors and credential gating, with small adapter helpers
(ignoreConfig/fromData) absorbing the signature variance (bedrock/ollama/custom
take *config.Config; the rest don't). The controller now wires and looks up
providers in loops over the table. Valid() validates against the new canonical
provider.AllProviderTypes list (no heavyweight import, no cycle).

Adding a provider's backend wiring drops from ~6 edits across these functions to
one registry entry. providers.go shrinks ~300 lines; behavior is unchanged
(same exported funcs, same gating) and all provider/server/graph tests stay green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 19:07:11 +07:00
Sergey KozyrenkoandClaude Opus 4.8 93c36483c7 refactor(providers): extract shared openaicompat base for OpenAI-compatible providers
deepseek/glm/kimi/qwen/minimax were near-verbatim clones — identical struct +
13 interface methods, differing only in constants, env accessors, and two flags.
Extract pkg/providers/openaicompat with a Spec + a shared Provider implementing
the interface; each provider now keeps only its constants, embedded config/models,
the Default*/Build* loaders, and a thin New() that delegates to openaicompat.New.
Each provider file drops from ~190 to ~78 lines with zero behavior change (same
exported funcs; per-provider tests stay green). The native openai provider is
intentionally left separate (no model prefix / reasoning-preservation).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 18:58:11 +07:00
Sergey KozyrenkoandClaude Opus 4.8 7e61bbea61 refactor(pconfig): centralize adaptive-thinking helpers, dedup bedrock/anthropic (refs #288)
The bedrock and anthropic adaptive_thinking.go files carried ~96 byte-identical
lines (prepareCallOptions, usesAdaptiveThinking, modelReasoningMode,
reasoningConfigForType, agentConfigForType, the effort context key), and
agentConfigForType was a third copy of the agent-type switch pconfig already
owns in GetPriceInfoForType.

Move the model-agnostic logic onto pconfig.ProviderConfig:
AgentConfigForType (now also backing GetPriceInfoForType), UsesAdaptiveThinking,
PrepareAdaptiveCallOptions, and the WithAdaptiveEffort/AdaptiveEffortFromContext
context helpers. Each provider now keeps only its transport-specific pieces:
the smithy Build middleware (bedrock) / http RoundTripper (anthropic) and
rewriteAdaptiveThinkingBody. Also drop the dead delete(payload,"top_k") in the
anthropic rewrite — langchaingo's Messages payload only serializes
temperature/top_p. Backstop tests rewired to the pconfig API; all provider tests
+ go vet pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 18:05:07 +07:00
Sergey KozyrenkoandClaude Opus 4.8 4c0f4204ca feat(pconfig): validate agent config ranges on create/update (refs #288)
The GraphQL createProvider/updateProvider path applied no field validation, so
a direct API call (bypassing the browser's native HTML5 form validation) could
persist nonsensical values (temperature 99, negative price, an inverted
min/max length window, a reasoning budget over the 32000 engine cap).

Add ProviderConfig.Validate()/AgentConfig.Validate(), called after
patchProviderConfig in both CreateProvider and UpdateProvider. It is deliberately
permissive — 0 means "unset" and provider-specific tuning ranges remain the LLM
API's responsibility — so it only rejects universally-invalid values and never a
valid provider-specific config. Found during comprehensive provider QA.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 16:46:21 +07:00
Sergey KozyrenkoandClaude Opus 4.8 55335feb17 feat(minimax): add MiniMax provider with full app/UI/installer parity (refs #328)
Reworks external PR #328 (octo-patch). The PR added only the provider core;
this brings MiniMax to full parity with the other providers (qwen) so it is
selectable and configurable in the UI and installer.

Applied from the PR (verified against MiniMax's official API docs — M3/M2.7/
M2.7-highspeed are real current models; corrected the M3 description from the
PR's "512K" to the documented ~1M context):
- minimax provider package (OpenAI-compatible https://api.minimax.io/v1),
  config.yml, models.yml, tests; MINIMAX_API_KEY/SERVER_URL/PROVIDER env vars;
  ProviderMiniMax type + DefaultProviderNameMiniMax; providers.go wiring;
  Valid() whitelist.

Added for completeness:
- goose migration adding 'minimax' to the PROVIDER_TYPE enum + database
  ProviderTypeMinimax const.
- GraphQL: minimax in ProviderType enum, ProvidersModelsList,
  ProvidersReadinessStatus, DefaultProvidersConfig; resolvers wire default
  config/models + enabled status; gqlgen regenerated.
- Frontend: MiniMax icon (lobehub), provider-icon + settings-providers
  registration + provider type list; regenerated GraphQL types.
- Installer wizard: provider form, screen, list, registry, env-var mappings,
  locale strings + help text.
- ctester/ftester: -type/-provider minimax support.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:24:04 +07:00
Sergey KozyrenkoandClaude Opus 4.8 001566c11a test(bedrock,pconfig,converter): cover adaptive-thinking backstop + reasoning (refs #288)
Closes audit-found coverage gaps:
- bedrock: TestBackstopForcesAdaptiveForAdaptiveOnlyModel (adaptive-only model
  forces adaptive with no agent reasoning block) + a negative case for a
  non-reasoning model. The Anthropic backstop already had an httptest test;
  Bedrock had none.
- pconfig: ReasoningConfig.EffectiveMode (incl. max_tokens->budget inference)
  and IsZero.
- converter: ConvertModels reasoning mapping (pconfig adaptive-only ->
  GraphQL adaptive_only, efforts passthrough, nil for no descriptor).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 14:35:34 +07:00
Sergey KozyrenkoandClaude Opus 4.8 177b138851 feat(anthropic): adaptive thinking + Opus 4.7/4.8 (refs #288)
Extends adaptive-thinking support from Bedrock to the direct Anthropic provider.
langchaingo emits only budget thinking, so adaptive is applied by rewriting the
request body — for Anthropic via an http RoundTripper (the Messages API carries
thinking and sampling params at the top level), wired through the injectable
http.Client. prepareCallOptions forces adaptive for adaptive-only models (the
models.yml capability descriptor is the single source of truth) and stashes the
effort in context for the transport.

- adaptive_thinking.go: RoundTripper + rewrite (thinking->adaptive,
  output_config.effort, display=summarized, strip temperature/top_p/top_k).
- models.yml: add claude-opus-4-7 / claude-opus-4-8 (adaptive-only) + reasoning
  descriptors on the adaptive models (4.6/sonnet-4.6).
- Verified by a credit-free httptest integration test asserting the rewritten
  body on the wire; the shape is also accepted by the real Anthropic API. Full
  live e2e pending account credits/model access.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 11:05:59 +07:00
Sergey KozyrenkoandClaude Opus 4.8 014e49494e fix(pconfig): parse ModelConfig.reasoning in custom (un)marshalers (refs #288)
ModelConfig has custom UnmarshalYAML/UnmarshalJSON/MarshalYAML/MarshalJSON that
map fields by hand, so the reasoning capability descriptor added earlier was
silently dropped on load (Reasoning stayed nil). That made the Bedrock
adaptive-only backstop a no-op (modelReasoningMode never saw adaptive-only).
Handle `reasoning` in all four marshalers, mirroring `price`, plus a round-trip
regression test. Found via the anthropic adaptive integration test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 11:05:59 +07:00
Sergey KozyrenkoandClaude Opus 4.8 7b01517bcd feat(bedrock): harden adaptive thinking + add Opus 4.7/4.8 (refs #288)
Makes adaptive-thinking models usable safely and adds Opus 4.7/4.8 to the
catalog so they are selectable and configurable.

- middleware: strip temperature/top_p/top_k and set thinking.display=summarized
  when rewriting to adaptive. Opus 4.7+ reject sampling params (AWS: "no longer
  supported", 400) and default display to "omitted" (empty reasoning text).
- models.yml: add us.anthropic.claude-opus-4-7 and us.anthropic.claude-opus-4-8,
  plus a ModelReasoningInfo capability descriptor (mode + allowed efforts) on the
  adaptive models (4.6/4.7/4.8/sonnet-4.6).
- provider backstop: force adaptive for adaptive-only models (Opus 4.7/4.8)
  regardless of agent config, so selecting them cannot 400 on budget thinking.
  The capability descriptor is the single source of truth (no model-name regex).

Verified: unit tests cover the body rewrite (sampling strip + display); a live
Bedrock run of the adaptive path on us.anthropic.claude-opus-4-6-v1 passed 21/23
(the 2 failures were 429 throttling, not the mechanism). Opus 4.7/4.8 could not
be exercised live -- this AWS account lacks model access (403), not a code
issue; their correctness rests on the AWS docs + the 4.6 live run + unit tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 10:19:30 +07:00
Sergey KozyrenkoandClaude Opus 4.8 ca9283b93e feat(bedrock): integrate adaptive thinking mechanism backend (refs #288)
Integrates the backend half of PR #288 onto our branch (the frontend is
reworked separately in our codegen style), 3-way merged so the #233
config/models-path changes are preserved:
- adaptive_thinking.go: smithy Build middleware that rewrites the langchaingo
  Converse body from thinking{type:enabled,budget_tokens} to
  thinking{type:adaptive} + output_config.effort, wired via WithAPIOptions and
  prepareCallOptions in Call/CallEx/CallWithTools.
- pconfig: ReasoningConfig.Mode (adaptive|budget) + EffectiveMode/IsZero.
- GraphQL: ReasoningMode enum, reasoning.mode field, xhigh/max effort levels.

Drops the dead llms.WithMetadata adaptive branch from AgentConfig.BuildOptions
(nothing reads opts.Metadata on the Bedrock path; adaptive is applied per-call
by the provider) and updates the unit test accordingly.

Hardening still pending (next commit): strip temperature/top_p/top_k and set
display:summarized for adaptive requests, add Opus 4.7/4.8 catalog entries with
a model reasoning-capability descriptor + force-adaptive backstop, and a live
Bedrock repro. Until then Opus 4.7 should not be selected for an agent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 09:59:48 +07:00
Sergey KozyrenkoandClaude Opus 4.8 06e37d8026 feat(bedrock): support external config and model catalog paths (refs #233)
Reworks PR #233 to follow the existing config-path pattern and make an
externally-added Bedrock model fully usable from the web UI.

- BEDROCK_CONFIG_PATH: replace the embedded per-agent config (model
  assignments + prices), mirroring OLLAMA_SERVER_CONFIG_PATH /
  LLM_SERVER_CONFIG_PATH. DefaultProviderConfig now takes *config.Config
  and reads the external file when set, else the embedded config.yml.
- BEDROCK_MODELS_PATH: merge an external model catalog onto the embedded
  models.yml so new ids appear and are selectable under Settings ->
  Providers. DefaultModels now takes *config.Config and the resolver +
  provider construction pass it through; new ids are added, a matching
  name overrides the embedded entry.

Wires both through docker-compose, .env.example, config.md and the README,
and ships examples/configs/bedrock-glm-flash.{provider,models}.yml using the
real AWS Bedrock id zai.glm-4.7-flash (In-Region, no inference-profile
prefix, 4K max output).

Dropped from #233: the ProviderConfig.Name field and the SeedDefaultProviders
mechanism (a per-user DB write fired on startup and inside the read-only
SettingsProviders resolver) -- the config already reaches the UI through
DefaultProvidersConfig without any DB rows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 08:30:10 +07:00
Mriganka 94ec0a0689 fix(providers): clarify misleading docker image LLM error (#312)
Fixes #312

Root cause:
During flow creation the first LLM call selects the primary Docker
image. When the configured LLM backend is unsupported or returns 404,
prv.Call fails, but the wrapped error read "failed to get primary
docker image". Users repeatedly interpreted this as a Docker problem
(see #312, #309, #203) and debugged Docker instead of their LLM
provider configuration.

Solution:
Reword the wrapped error to "failed to select primary docker image
via llm call" so the LLM provider is identified as the failing
component while still mentioning the image selection step.

Testing:
go build ./pkg/providers/ -> OK
2026-05-31 10:09:57 +05:30
Dmitry Ng 83c263e98e feat(qwen): enhance agent configurations with thinking control parameters
Updated the Qwen agent configuration to include `extra_body` parameters for thinking control across various models. Added `enable_thinking` and `preserve_thinking` options for reasoning agents, while utility agents have `enable_thinking` set to false. Adjusted the Qwen client initialization to support these new configurations. Updated test report to reflect changes in success rates and latencies.
2026-05-29 00:06:47 +03:00
Dmitry Ng 643ff7d218 feat(providers): Update model configurations for various LLM providers: qwen, kimi, glm, deepseek, gemini 2026-05-28 15:41:17 +03:00
Dmitry Ng e674113745 Merge pull request #317 from mason5052/codex/issue-314-deepseek-v4-models
fix(deepseek): update default model names to DeepSeek V4
2026-05-28 00:09:25 +04:00
mason5052 24176c2805 fix(deepseek): explicitly disable thinking mode for non-thinking Flash roles
DeepSeek V4 thinking mode defaults to enabled on both deepseek-v4-flash
and deepseek-v4-pro; non-thinking behavior requires an explicit toggle.
Per official docs, in thinking mode temperature/top_p/presence_penalty/
frequency_penalty are ignored, so the existing Flash role sampling knobs
would have been silently no-ops without the toggle.

Add extra_body.thinking.type=disabled to the five non-thinking Flash
roles so deepseek-v4-flash actually runs in non-thinking mode and
honors the role's temperature/top_p settings:

- simple, simple_json, adviser, searcher, enricher

Pro roles (primary_agent, assistant, generator, refiner, reflector,
coder, installer, pentester) intentionally keep thinking enabled (the
V4 default) for reasoning, tool-use, and security analysis.

PentAGI provider config already supports extra_body as a first-class
yaml field on AgentConfig and forwards it through openai.WithExtraBody,
which the vxcontrol langchaingo fork serializes at the top level of the
Chat Completions request - the same pattern Kimi uses for tool_choice.
No code, schema, or LiteLLM prefix changes required.

Touches:
- backend/pkg/providers/deepseek/config.yml (embedded production config)
- examples/configs/deepseek.provider.yml (user-facing example)

No change to role-to-model mapping, model metadata, pricing, README
wording, LiteLLM prefix, unrelated providers, lifecycle, queues, or
installer flow.
2026-05-22 12:26:28 -04:00
mason5052 67bf76514b docs(deepseek): align V4 model metadata with official pricing and context
- Update model descriptions to reflect V4 1M context window (up to 384K output)
  instead of legacy 128K wording in models.yml and README.
- Split Flash and Pro pricing per official DeepSeek API docs:
  - deepseek-v4-flash: input 0.14 / output 0.28 / cache_hit 0.0028 per 1M tokens
  - deepseek-v4-pro:   input 0.435 / output 0.87 / cache_hit 0.003625 per 1M tokens
- Apply per-role price split across all 13 role configs in both the embedded
  config.yml and the user-facing examples/configs/deepseek.provider.yml.
- Replace stale "cache pricing is 10% of input cost" claim in the README,
  which no longer holds for either V4 model.
- No change to LiteLLM prefix behavior, role-to-model mapping, lifecycle,
  queues, GraphQL schema, migrations, frontend, or installer flow.
2026-05-22 12:04:14 -04:00
Dmitry Ng ff35909f52 Merge pull request #303 from mason5052/codex/issue-280-ollama-tool-support-validation
fix: clarify Ollama models without tool support
2026-05-22 01:08:52 +04:00
mason5052 3113ff3aa3 fix(deepseek): update default model names to DeepSeek V4
The DeepSeek provider config still defaulted to the legacy
`deepseek-chat` and `deepseek-reasoner` model names, which the
upstream DeepSeek API has announced for deprecation on 2026-07-24.
A first-run install therefore breaks once the legacy names are
removed.

Swap the defaults to the current DeepSeek V4 family:

- non-thinking roles use `deepseek-v4-flash`
- reasoning-heavy roles use `deepseek-v4-pro`

The change is limited to the embedded `config.yml` / `models.yml`
inside `backend/pkg/providers/deepseek`, the matching example at
`examples/configs/deepseek.provider.yml`, the `DeepSeekAgentModel`
fallback constant in `deepseek.go`, and three doc references
(README.md, backend/docs/config.md, backend/docs/llms_how_to.md)
plus one installer help string in
`backend/cmd/installer/wizard/locale/locale.go`. LiteLLM prefix
behavior is untouched.
2026-05-21 15:44:30 -04:00
Dmitry Ng 1bb7f8a9a0 feat(flow): add WaitTaskCompletion method and associated tools for assistant
- Introduced WaitTaskCompletion method in FlowWorker interface to block until the current task completes or the context expires.
- Implemented signalTaskComplete to manage task completion signaling across goroutines.
- Added waitFlowCompletion tool to handle waiting for task completion with configurable timeout.
- Updated assistant provider to include wait functionality for flow completion.
- Enhanced templates and tool registry to support new wait functionality.
2026-05-16 22:52:51 +03:00
Dmitry Ng 161afb8b59 fix(cast,providers): replace invalid tool call JSON arguments with empty object
When an LLM emits a truncated or malformed arguments field (e.g. "{") instead of valid JSON, downstream consumers such as LiteLLM reject the entire request with a 400 Bad Request, causing the chain to degrade into an infinite retry loop.

- SanitizeToolCallArguments now falls back to "{}" after control-char escaping if the result is still not valid JSON, fixing already-stored chains on restore
- callWithRetries logs a warning and substitutes "{}" at the moment the bad arguments arrive from the LLM, preventing them from ever reaching the database
- Added test cases for truncated JSON, partial objects, and empty strings
2026-05-15 01:03:04 +03:00
mason5052 73d5b8366d fix: drop unverified ollama tags and broaden hint context
Address review on PR #303.

- helpers.go: remove the concrete model examples (llama3.1, qwen2.5, mistral-nemo) from the Ollama tools-unsupported hint. PentAGI does not verify Ollama model capabilities from upstream metadata, so a hard-coded list of supposedly tool-capable tags is risky and ages poorly. The hint now points users to select an Ollama model whose own metadata advertises tool/function calling support.

- helpers.go: rewrite the comment and error wording so it is no longer flow-only. The helper is shared by NewFlowProvider and NewAssistantProvider, so the message now refers to tool execution in flows and assistant sessions, and the doc-comment notes that wording must stay context-neutral.

- helpers_test.go: tighten TestWrapToolCallIDTemplateError to match the new wording, ban the previous concrete model tags, and ban flow-only language ('flow execution', 'flow creation'). The test still verifies that the original underlying error is wrapped via errors.Is.

Signed-off-by: mason5052 <ehehwnwjs5052@gmail.com>
2026-05-06 22:11:12 -04:00
mason5052 552eda8746 fix: clarify Ollama models without tool support
## Summary
Surface an actionable hint when an Ollama model that does not support
tool/function calling is selected for a flow or assistant session, so
users do not have to parse a five-wrap-deep "failed to determine tool
call ID template" stack trace to figure out why flow creation fails.

## Problem
A user on an Ollama deployment of `gemma3:27b-it-q4_K_M` reports that
the Provider/LLM test passes the basic completion checks but flow
creation fails with:

  failed to create flow worker: failed to get flow provider: failed
  to determine tool call ID template: failed to collect tool call ID
  samples: all sample collection attempts failed: failed to call LLM:
  400 Bad Request: registry.ollama.ai/library/gemma3:27b-it-q4_K_M
  does not support tools

The underlying signal "does not support tools" is emitted by the
Ollama API itself; PentAGI buries it five wraps deep, so the user is
left guessing whether the issue is configuration, networking, or
something internal to PentAGI.

## Solution
Add an unexported helper `wrapToolCallIDTemplateError` in
`pkg/providers/helpers.go` that detects the upstream "does not support
tools" substring and prepends a one-sentence guidance message naming
the constraint and a few known-good Ollama tags
(`llama3.1`, `qwen2.5`, `mistral-nemo`). All other errors keep the
existing wording. The original error is preserved via `%w` so log
spans, langfuse traces, and any future `errors.Is/As` callers continue
to work.

Both call sites in `pkg/providers/providers.go`
(`NewFlowProvider`, `NewAssistantProvider`) now route through the
helper.

No schema, API, or DB changes. No new lifecycle state. No background
work. The behavior change is the wording of one error string in one
upstream-defined failure case.

## User Impact
- Users who pick an Ollama model without tool support get a clear,
  actionable error during flow / assistant creation instead of a deep
  stack trace.
- Users on tool-capable models (Anthropic, OpenAI, Bedrock, and
  tool-capable Ollama tags) see no behavioral or message change.
- No restart, migration, or configuration step required.

## Test Plan
- New table-driven test `TestWrapToolCallIDTemplateError` covers:
  - nil error -> nil
  - upstream "does not support tools" chain (matching the real five-
    wrap shape) -> actionable message + `errors.Is` round-trips to the
    original error
  - generic non-tools error -> existing wrap text preserved, no
    new guidance appended
- `go test ./pkg/providers/...` passes locally.
- `go build ./...` and `go vet ./pkg/providers/...` clean.

Closes #280

Signed-off-by: mason5052 <ehehwnwjs5052@gmail.com>
2026-05-06 18:30:32 -04:00
Dmitry Ng f57e988586 feat(cast): add JSON control character sanitization for tool call arguments
- Implemented `SanitizeJSONControlChars` to escape literal control characters in JSON string values, ensuring compliance with the JSON specification.
- Enhanced `SanitizeToolCallArguments` method to apply sanitization across tool call arguments in the chain.
- Added comprehensive tests for both sanitization functions to validate behavior with various input scenarios.
2026-05-03 00:48:47 +03:00
Dmitry NgandOctopus 956c11eadc feat: introduce engagement-log/technical-channel language policy across agent prompts
- Replaced ambiguous "user's language" guidance in tools/args.go with explicit engagement-log vs technical-channel markers per field, with strong English-only requirement for vector-store and search-engine queries.
- Added a unified LANGUAGE POLICY block to every agent prompt (primary_agent, assistant, pentester, coder, installer, searcher, memorist, generator, refiner, reporter, enricher), tailored per agent based on its actual tool set.
- Extended template variables and tool access (TerminalToolName, FileToolName) for coder, pentester, installer, memorist, generator, refiner, and enricher to match their runtime tool registrations.
- Fixed inverted UseAgents condition and removed misleading vector-store write references in assistant prompt; corrected MEMORY SYSTEM INTEGRATION for mode-specific tool references.
- Compressed COMPLETION REQUIREMENTS across templates and aligned closing-tool guidance with the channel mapping (engagement-log message vs technical-channel result).

Fixes #285.

Co-Authored-By: Octopus <liyuan851277048@icloud.com>
2026-04-30 15:29:56 +03:00