The "Available variables" block merged into the background on desktop and the
hand-rolled chips used light-theme greens (bg-green-100/text-green-800) that
clashed with the dark UI. Rebuild it on the project's primitives:
- Container: a delineated `rounded-lg border bg-card` panel with a `border-b`
header (title + "click to insert" hint); the chips sit in a recessed
`bg-background` tray below it, so the section reads as a distinct group with
depth instead of a faint box.
- Chips: the shared `Badge` component — `green` (theme-aware) for variables
already used in the template, `secondary` for the rest; monospace, normal
weight, clickable.
- Badge: give the color variants (blue/green/orange/pink/purple/red/yellow)
hover states to match default/secondary/destructive, so consumers don't
hand-roll hover colors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extract the "Available Variables" panel out of promptMeta into its own
`variablesPanel`. Desktop keeps it in the left pane under the tab selector
(reference beside the editor); mobile now renders it after the editor instead of
between the tabs and the editor, so the template editor sits directly under the
tabs on small screens.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The provider, knowledge and prompt edit pages share one 2-pane shell, but
mobile and the intro block had drifted. Align them:
- Mobile: drop the wrapping Card on provider + knowledge (knowledge-form-layout,
settings-provider) so all three render the stacked form directly in
`flex min-h-0 flex-1 flex-col gap-4 p-4` (matches the prompt page; gap-4 to
match the p-4 edge padding).
- Intro: use a `flex flex-col gap-2 text-center` wrapper with
`<h2 class="text-2xl font-semibold">` + a `text-muted-foreground` description
everywhere — knowledge was an `<h1>`, the prompt used `items-center gap-1`, and
both leaned on a `mt-2` margin instead of the container gap.
Desktop shell (root, ResizablePanelGroup 45/55, left Card + CardContent py-6,
grip handle, per-pane scroll) was already uniform. The right-pane content stays
page-specific (accordion / markdown editor / textarea).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mirror the knowledge/provider edit pages: replace the single-column form +
sticky footer with a responsive 2-pane layout (desktop ResizablePanelGroup,
mobile single column). Left pane = centered intro + prompt identity + the
System/Human tab selector + the variables palette; right pane = the template
editor that fills the panel.
Move actions into the AppHeader: Validate + Save, plus an ellipsis menu (Reset,
Diff) shown only when a user override exists — no Cancel. Convert the inline
error alerts to a single submitError-driven toast, and the loading/error/
not-found branches to StatusCard. Drop the now-unused handleBack.
Shared UI tweaks supporting the editor:
- Textarea: add an `autoSize` opt-out (default true) so the editor can flex-fill
its parent (the auto-size hook's inline max-height otherwise clamps it).
- TabsTrigger: add `gap-2` (matches Button) so an icon + label aren't glued.
Align the panel/Card structure with the knowledge layout (py-6 intro,
overflow-y-auto left, overflow-hidden fill-editor right, grip handle, 45/55
split); style the tab bar like the dashboard analytics tabs (bg-background list
+ bg-card active, full-width flex-1 triggers).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduce a shared AppHeader compound family (AppHeader / AppHeaderAction /
AppHeaderActions / AppHeaderContent / AppHeaderTitle) in a single module and
fold the page-header action button into it as AppHeaderAction (renamed from the
former HeaderButton). Every page header now composes this family instead of
copy-pasting the sticky <header> shell:
- settings pages (account, api-tokens, prompt(s), provider(s))
- main-app lists (dashboard, flows, templates, resources, knowledges, new-flow)
- detail headers (flow, template, knowledge) keep their bespoke breadcrumb
content as AppHeaderContent children; their action clusters move into
AppHeaderActions; sibling sheets/dialogs stay outside the header
This removes the duplicated shell across ~15 sites and the drift between copies
(the family owns the one canonical sticky shell + the SidebarTrigger/Separator).
Reorganize components/layouts into per-area subfolders:
- app/ app-layout + the AppHeader family (app-header.tsx)
- main/ main-layout, main-sidebar (+ test)
- settings/ settings-layout, settings-sidebar (+ test)
- flows/ flows-layout
Delete settings-page-header.tsx (superseded by AppHeader).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rebuild the provider settings page to match the knowledge editor:
- responsive 2-pane layout — left Card with the centered intro + Type/Name,
right scrollable panel with the agent-config accordion; mobile collapses
to a single-column Card (via useBreakpoint). Each pane scrolls
independently inside a fixed-height root (no whole-page scroll).
- move Save / Test / Delete into the page header (SettingsPageHeader actions);
drop the sticky-bottom action bar and the now-unused Cancel/handleBack.
- surface mutation/validation errors as sonner toasts instead of inline
Alerts (single submitError-driven effect).
- redesign the test-results modal: shrink-0 status icon, result/metadata as
badges, wrapping monospace error block, colored per-agent pass count.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mirror the main app layout: SettingsLayout now renders only
SidebarProvider + SettingsSidebar + SidebarInset + Outlet, with no shared
header. Each settings page renders its own header via a new shared
SettingsPageHeader (sticky h-12 bar with an optional actions slot). The
sidebar is extracted into a self-contained SettingsSidebar component that
computes the "Back to App" returnUrl from location.state; its behavior is
covered by the new settings-sidebar.test (migrated from the removed
settings-layout.test). settings-account.test now wraps the page in a
SidebarProvider since the page renders its own SidebarTrigger.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
pnpm 11 installs globally-added binaries to $PNPM_HOME/bin and treats that
directory being absent from PATH as a hard error, so `pnpm add -g license-checker`
in the frontend-compiler stage failed ("global bin directory is not in PATH")
whenever the frontend layer cache was invalidated. Prepend $PNPM_HOME/bin to PATH.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
settings-providers.tsx redeclared its own ProviderType→icon map (and imported all
11 icon components) duplicating the registry already in provider-icon.tsx. Export
that map and consume it here, dropping the duplicate map and the 11 icon imports.
providerLabels/providerTypes stay (labels, single-use). No visual change — the
icons still render monochrome at their existing sizes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
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>
The added Claude/Bedrock rows put "✅ adaptive-only" in the narrow Thinking
column, which broke the source pipe alignment of the carefully-padded tables.
Use a plain ✅ in the Thinking column (the adaptive-only detail already lives in
the Use Case text and the Adaptive Thinking note) and re-pad the rows so the
columns line up again.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review nits:
- schema.resolvers.go: log (not swallow) bedrock.DefaultModels errors so an
invalid BEDROCK_MODELS_PATH no longer yields a silently-empty model list.
- settings-providers.tsx: derive the create-provider type list from an
exhaustive Record<ProviderType,string> so a future ProviderType is a compile
error here instead of silently missing from the menu.
- trim two doc comments (convertModelReasoningMode, ReasoningFields) to lead
with the load-bearing contract instead of restating the name.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
Code review found the providers were fully wired in code but missing from
several user-facing surfaces:
- MiniMax (#328): add to .env.example, docker-compose env passthrough,
backend/docs/config.md env table, README provider list + a MiniMax
configuration section, and backend/docs/database.md PROVIDER_TYPE enum.
- Claude Opus 4.7/4.8 (#288): add to the README Claude and Bedrock model
catalogs and correct the model counts (10→11 Claude, 21→24 Bedrock); note
4.7/4.8 are adaptive-thinking-only in the Adaptive Thinking section.
- llms_how_to.md: scope the "Temperature=1.0" rule to budget thinking and add
an adaptive-thinking caveat (4.7/4.8 reject sampling params), so the guide no
longer contradicts the shipped adaptive code path.
- docker-compose: point the Bedrock config/models default mount at the tracked
examples/configs/bedrock-glm-flash.* files (the README-documented path) so a
plain `docker compose up` no longer creates empty placeholder directories.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Three QA-found edge cases in the provider form:
- Choosing "Use <x> as custom" set the model without running onOptionSelect, so
reasoning/price stayed stale for the typed model. Fire onOptionSelect with the
synthetic option so they reset like a dropdown pick.
- Selecting effort max/xhigh on an adaptive-capable model with mode unset left
the backend with no way to route the reasoning (it dropped it). Auto-set mode
to Adaptive, since max/xhigh are adaptive-thinking effort levels.
- Add zod cross-field refines (minLength<=maxLength, reasoning.maxTokens<=32000)
that native HTML5 validation can't express, mirroring the new backend checks.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
The QA audit found minimax was wired into production everywhere but omitted
from provider-enumeration test data, so a future regression dropping it would
go uncaught. Add minimax to ProviderType.Valid()'s validTypes table, to the
GetSecretPatterns config (expected count 29→30, exercising the "MiniMax Key"
redaction pattern), and to clearConfigEnv's hermetic env list.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
onOptionSelect reset reasoning.mode and reasoning.effort when the agent model
changes but left reasoning.maxTokens untouched, so a budget token value set for
a previous model leaked into the next one (e.g. switching from a budget-capable
model to an adaptive-only model kept the stale value in the form). Reset it
alongside mode/effort. Found during comprehensive provider QA.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
The ReasoningFields mode/effort selects used `defaultValue`, making them
uncontrolled — Radix reads it once on mount, so the `setValue` resets in
onOptionSelect (reset reasoning on model change) updated form state but never
the visible selection. Result: after switching models the selectors showed
stale values (e.g. mode "Adaptive" when the field was cleared to null; effort
left blank when a stale 4.7/4.8 "xhigh" had no item under opus-4-6). Switch to
controlled `value` so the display follows the reset. Also drop a dead
empty-comment block in onOptionSelect.
Found during Layer 3 live verification on the docker stack.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The component declared control as Control<FormData> (z.output, required
name/type) but receives the form's Control<FormInput> (z.input, optional
name/type), which `tsc -b` (the production build typecheck) rejects with
"Type 'undefined' is not assignable to type 'string'". `tsc --noEmit -p
tsconfig.json` did not catch it; `pnpm run build` (tsc -b && vite build) now
passes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
Switching an agent's model left the prior reasoning.mode/effort in the form
(onOptionSelect only reset price), so a stale budget mode or an effort the new
model doesn't support could be persisted. Now the model picker also resets
reasoning: adaptive-only models lock to adaptive, others clear mode + effort.
Verified: tsc --noEmit + eslint clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ports the per-agent reasoning UI to support adaptive thinking, gated by each
model's declared capability (the reasoning fragment) instead of a model-name
regex:
- new ReasoningFields component: a reasoning Mode select (adaptive | budget,
shown only for adaptive-capable models, locked to adaptive for adaptive-only)
and an effort select whose options follow the model's allowed efforts
(incl. xhigh/max).
- getReasoningEffort handles xhigh/max; getReasoningMode + the form schema and
transformFormToGraphQL carry the chosen mode through to the API.
Verified locally: tsc --noEmit and eslint clean. Runtime verification on the
stack (Layer 3) is the next step.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
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>
Adds reasoning { mode efforts } to the modelConfigFragment and regenerates
GraphQL types, so the provider settings UI can gate the reasoning mode/effort
controls by each model's declared capability (ModelReasoningMode incl.
adaptive_only) instead of a model-name regex.
Groundwork for the adaptive-thinking settings UI port.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds ModelReasoningInfo (mode + allowed efforts) to the GraphQL ModelConfig so
the frontend can gate the reasoning mode/effort UI by each model's declared
capability instead of a model-name regex. New ModelReasoningMode enum
(budget | adaptive | adaptive_only) mirrors the models.yml descriptor; the
converter maps pconfig adaptive-only -> GraphQL adaptive_only.
Backend groundwork for the Layer 2 frontend adaptive-thinking UI.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
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>
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>
Reworks PR #332 to follow the repo's provider-doc convention instead of
its README-marketing form:
- add examples/configs/atlas.provider.yml, modeled on the existing
aggregator example configs (deepinfra/openrouter/novita)
- list Atlas Cloud in the README aggregators line
- LLM_SERVER_PROVIDER left EMPTY for direct access — it is a LiteLLM
model-name prefix, and #332 incorrectly recommended `openai`, which
would break /models discovery for Atlas's vendor-prefixed model ids
Dropped from #332 (not matching any existing aggregator's docs): vendor
logo/banner, UTM-tracked links, and the static 59-model table.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The documented "minimum 12 characters" and "common weak passwords
prohibited" did not match the enforced policy. Both backend
(strongPasswordValidatorString / `stpass`) and frontend (zod schema in
password-change-form.tsx) enforce: 8-100 chars, valid if 16+ chars OR
8-15 chars with a number, lowercase, uppercase, and special char from
!@#$&*. No common-password denylist exists in code.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Use the package-path form for the tester utilities
(go run ./cmd/ctester, go run ./cmd/etester test) instead of shell
glob / single-file invocations, which are more portable and avoid the
multi-file compile pitfall.
- Add -verbose to the container etester example so it matches the local
example.
- Wrap the new README Quick Start pointer across multiple lines; rendered
Markdown is unchanged.
Issue #61 asked for a proper guide on how to start using PentAGI. A
first-use guide (How to Use PentAGI After Login) already covers what to
do after login, but the maintainer kept the issue open until an article
about installing and configuring the product is published.
Add examples/guides/installation_configuration.md, a concise ordered
walkthrough that connects the existing detailed README sections into a
single path: choose installer vs manual Docker Compose, set core server
variables (PUBLIC_URL, CORS_ORIGINS, security vars), configure and test
an LLM provider with ctester, configure and test the embedding provider
with etester, optionally add search providers and the Graphiti/Langfuse/
observability stacks, then start and verify the stack and change the
default admin password. It ends with a quick checklist and links forward
to the existing post-login usage guide.
The guide links to the relevant README reference sections rather than
duplicating them. A single pointer link is added at the top of the
README Quick Start section for discoverability.
Docs only. No installer behavior, runtime code, env vars, or schema
changes. Every environment variable named in the guide already exists in
.env.example and backend/pkg/config/config.go.
Add a troubleshooting subsection to the Embedding Configuration and
Testing section for the common case where a flow starts but then waits
indefinitely with no subtasks progressing. As noted on the issue, this
is frequently caused by a misconfigured or unreachable embedding
provider rather than by the flow itself.
The subsection points users to "docker logs pentagi" as the first
check, to the etester "test" command to validate the embedding provider
and database connection without starting a flow, and to the specific
.env settings to verify (EMBEDDING_PROVIDER, EMBEDDING_MODEL,
EMBEDDING_URL, EMBEDDING_KEY, the LLM-provider fallback, PROXY_URL, and
HTTP_CLIENT_TIMEOUT). Documentation only: no new environment variables,
no provider default changes, and no code or test changes.
Refs #322
Address review feedback on PR #325: capitalize SGLang to match the
project's name and clarify that tool calling and function calling
refer to the same capability.
Refs #309
Add a troubleshooting subsection to the Docker Image Configuration
section explaining that "failed to select primary docker image via llm
call" (older versions: "failed to get primary docker image") is raised
when PentAGI's first LLM call fails during image selection, not when
Docker or the registry is unhealthy. Points users to PentAGI and LLM
backend logs, provider URL/key/model verification, and tool-call parser
configuration for custom/OpenAI-compatible/vLLM/sglang backends.
Disabled-by-default audit feature (EVIDENCE_RECEIPTS_ENABLED): appends a
hash-chained JSONL receipt per finished/failed toolcall under
<DATA_DIR>/flow-<id>/evidence/receipts.jsonl, recording toolcall
provenance plus SHA-256 hashes of args/result (no raw content).
Integration adapted to current main: the original PR built the receipt
from a database.Toolcall returned by ce.db.UpdateToolcall*Result, which
the executor no longer uses after the ToolCallLogProvider (tclp) refactor.
Receipts are now built from the in-scope toolcall data at the tclp log
sites and recorded non-fatally, so a receipt failure is logged and never
fails an otherwise-successful toolcall.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The "failed to select primary docker image via llm call" symptom was
attributed to tool-call parser failures, but image selection is a plain
text completion (providers.go: prv.Call -> WrapGenerateFromSinglePrompt),
not a tool call. That error is a generic LLM-backend failure of the
`simple` agent type and is already covered in its own README section.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Issue #313 reported flows that stall after a few steps when running a
custom OpenAI-compatible backend (LiteLLM in front of llama.cpp serving
qwen3.6-35b via LLM_SERVER_*). The backend returned malformed tool-call
arguments, surfaced as 'Failed to parse tool call arguments as JSON'
HTTP 500s and cascading retries. The maintainer fixed the stall in the
latest build by sanitizing wrong function-call arguments.
Add a troubleshooting subsection under Custom LLM Provider Configuration
that explains the root cause and how to diagnose it:
- Custom OpenAI-compatible backends must return valid tool-call
(function-call) JSON; llama.cpp, SGLang, and vLLM usually require a
specific tool-call parser and matching chat template, and not every
setup produces valid tool calls out of the box.
- Symptoms: 'Failed to parse tool call arguments as JSON', flow stalls,
looping tool calls, the 'failed to select primary docker image via
llm call' start-of-flow failure, and unexpected backend HTTP errors.
- Investigation: check PentAGI and backend/proxy logs, validate with the
ctester utility before a full flow, confirm the parser/chat template
match the model, and update PentAGI (recent builds sanitize malformed
function-call arguments).
Docs only. No tool-call parser code, provider runtime, schema, migration,
or config-default changes. Wording frames compatibility as dependent on
the backend's OpenAI-compatible tool-call behavior rather than claiming
every llama.cpp backend is supported.