Die Claude-CLI-Permission-Engine parst eine Allowlist-Regel via split("__")
zu {serverName, toolName} und vergleicht den Servernamen per strenger
Gleichheit (===); ein '*' wirkt ausschliesslich im Tool-Teil, nie im
Server-Teil. Die generalisierte Form "mcp__*<name>*" parste damit zu einem
Server namens "*<name>*" und matchte NIE -> jeder ueber die MCP-Liste
eingetragene Server wurde headless still abgelehnt (Regression aus 5f7dec6).
- ClaudeCliService.cs: Allowlist-Glob mcp__*<name>* -> mcp__<name>__*
(exakter Server + Tool-Wildcard, dieselbe Form wie mcp__web-search-prime__*);
Kommentar erklaert die strenge Server-Gleichheit.
- index.html: UI-Hinweis korrigiert - Name muss exakt dem Tool-Praefix
entsprechen (z.B. UnityMCP, nicht Unity); Freigabe als mcp__<name>__*.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bisher wurden Workflow-Subagent-Outputs nur beim sauberen FinalizeChain in
die DB gerettet - bei Abbruch (529/Timeout/Stop/Hard-Kill) war alles weg,
Tokens standen auf 0.
- A) Inkrementelle Persistenz: MaybeFlushWorkflowProgress() (throttled 6s)
schreibt workflow_info + Token + runId waehrend des Laufs -> ueberlebt
Hard-Kill (OOM/Redeploy), wo kein catch/finally laeuft.
- B) Output-Rettung: ReadLive liest jetzt vollstaendige Subagent-Outputs aus
journal.jsonl (nicht nur Counts), inkl. State.
- C) Token-Fix: neuer assistant-Branch -> CliEventType.Usage; EffectiveUsage()
rettet Orchestrator-Token bei Abbruch statt 0.
- D) Resume: Feld/Migration workflow_run_id; FinalizeChain persistiert die
runId; naechster Chat injiziert einen resumeFromRunId-Hinweis.
- UI: Workflow-Status-Modal zeigt geretteten Output + runId/"fortsetzbar"-Banner.
Build 0/0, ReadLive gegen echtes journal.jsonl verifiziert, adversarial 2x geprueft.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- MCP: replace fixed single Unity field with a generic list of servers
({name, url, token?}); dynamic mcp-config + allowlist glob mcp__*<name>*
per entry; new mcp-servers-ui.js editor (no data migration)
- Models: frontend refresh button wired to existing POST /api/models/refresh,
reloads optgroups and restores selection
- Model: add sonnet-5 alias + dropdown option (bare "sonnet" stays 4.6)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ergänzt mcp__UnityMCP__* neben mcp__unity__* in der --allowed-tools-Liste
(innerhalb von hasUnityMcp), damit ein unter dem Namen "UnityMCP" statt
"unity" laufender MCP-Server im headless -p-Pfad nicht still abgelehnt wird.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die runId ist bereits mit "wf_" praefixiert; der Code erzeugt
<proj>/workflows/<runId>.json. Die Kurz-Referenzen in den Code-Kommentaren
(WorkflowProgressTracker, ClaudeCliService, AnthropicService, SessionEndpoint)
nutzten faelschlich das doppelte "wf_"-Praefix.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Dynamic ultracode workflows run as a detached background task with their
own transcript dir, so their subagent events never flow through the main
-p stream. The previous parent_tool_use_id tap therefore captured nothing
for real workflows and the status stayed "none" the whole run.
Replace the tap with a file-based reader:
- TapWorkflowLaunch parses the "Transcript dir:" line from the Workflow
tool_result and registers the run.
- WorkflowProgressTracker becomes a per-session registry of transcript
paths (no longer a stream accumulator).
- WorkflowTelemetryReader reads journal.jsonl for live counts (running)
and <runId>.json for rich per-agent telemetry (completed); FinalizeChain
persists the rich JSON into chains.workflow_info.
- Modal renders phases + a per-agent list (label/phase/state/tokens/
tool-calls/duration) instead of the obsolete tool breakdown.
Sync ARCHITECTURE.md, ARCHITECTURE_QUICK.md and README.md to the new
mechanism.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Workflow-status: a new WorkflowProgressTracker singleton taps the
suppressed dynamic-workflow subagent events (those carrying
parent_tool_use_id) into per-session telemetry without altering the
existing guard; the snapshot is serialized into the new chains.workflow_info
column on FinalizeChain (ChainId-matched so a panel member of the same
session cannot clear it) and exposed via GET /api/sessions/{id}/workflow-status
(live -> persisted -> none). The header menu gains a 'Workflow-Status' entry
with a modal that live-polls every 2s while running and self-stops on close.
Panel on-demand: Fusion/MoA is now a transient per-request multiModelMode
flag (like plan/ultracode) instead of a persisted session column. Session
settings keep only the panel members + moa_layers; the mode <select> was
removed and the composer dropdown drives the mode per request.
Docs: ARCHITECTURE.md, ARCHITECTURE_QUICK.md and README.md updated for both
features plus the already-shipped z.ai/GLM provider, GLM 5.2+ effort
passthrough, web-search-prime MCP and the ultracode toggle.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The composite mode control (#planModeBtn) now opens a dropdown menu
instead of cycling, following the emoji-picker pattern: each mode is an
entry with icon + label + description, the active one marked with a
check. Direct jumps between modes are now possible, so selecting
plan/ultracode resets the persisted panel mode to avoid running both the
panel and the CLI worker. Unified the active button states.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A new transient per-request toggle state (off→plan→ultracode→fusion→moa)
that whitelists the CLI's Workflow + Task tools so Anthropic's native
dynamic-workflow orchestration runs in gott's headless -p mode without a
permission gate (the engine silently denies Workflow otherwise). Effort is
raised to xhigh (the real ultracode equivalent; "ultracode" itself is not a
valid effort value) without downgrading an explicit max. Only enabled for
Claude models (z.ai/GLM has no workflow runtime) and not in plan mode. The
frontend injects a "use a workflow" hint, like plan mode injects its own.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GLM models cannot run Anthropic's server-side WebSearch/WebFetch, so when a
GLM model has web search enabled and ZaiApiKey is set, GenerateMcpConfig
registers z.ai's web_search_prime HTTP MCP server and CreateCliStartInfo
allows mcp__web-search-prime__* while disallowing the native WebSearch/WebFetch
tools — otherwise the model tries the (headless-ungranted) native tool first
and only falls back to the MCP search on the second attempt.
Effort is now passed through for GLM-5.2 and newer (version compare, not a
prefix match, so 5.3/6 are picked up automatically and glm-5.2[1m]/glm-5-turbo
parse correctly); older GLM models still drop CLAUDE_CODE_EFFORT_LEVEL.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Route glm:-prefixed models through the CLI/Anthropic path: ResolveModelId
strips the glm: prefix, and CreateCliStartInfo activates the z.ai
Anthropic-compatible endpoint (ANTHROPIC_BASE_URL/AUTH_TOKEN) only for that
process when IsZaiModel matches, leaving every other request's OAuth login
untouched. GLM model list is loaded through the existing model cache and
exposed via /api/models/glm with a "GLM (z.ai)" optgroup in the agent form.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- TelegramService: build the chat context with the session owner instead
of the bot owner, so a public/shared bot resolves the agent for foreign
sessions; credentials/CLI permission stay with the bot owner.
- Agent cards: render an effort badge next to the model badge when an
agent has an explicit reasoning effort set.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The cronjob notification ran the notify-agent on the result summary and
sent only its reaction to Telegram. When the agent merely acknowledged the
summary (e.g. "👍"), the actual cronjob result never reached Telegram —
the user got a header plus an emoji and no information.
Send the real result as the guaranteed first Telegram message, then run
the notify-agent best-effort and send its reaction as a separate second
message. The agent run is wrapped in try/catch with a canRunNotifyAgent
guard instead of the old return-aborts, so a missing key / OpenAI without
key / unavailable CLI only skips the reaction — the result is already
delivered. The notify-agent still persists its reaction to the web history
automatically (ChatNonStreaming / ChatNonStreamingViaCli).
TelegramService.SendNotification now uses SendLongMessage so long results
are chunked into 4096-char messages instead of being rejected whole.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bring the docs in line with the recently shipped features:
- Multi-model panel: all MoA rounds are now persisted (F5-safe) with a
per-member JSON transcript (layer/totalLayers/segments); member tokens
are folded into the worker usage via seedUsage (live badge + DB).
- CLI parser filters subagent internals centrally via the
parent_tool_use_id guard → no nameless tool boxes in stream or history.
- Per-member token badges: panel_member_done and the persisted JSON carry
the token fields, rendered by the shared buildPanelMemberMeta helper.
- Composer toggle: _modePersist serializes mode PATCHes and sendMessage
awaits them, preventing the MoA single-round race.
- CLI fallback now also covers cronjobs and Telegram; keyless providers
(nvidia/gemini/minimax/pollinations) resolve server keys instead of
hard-failing on a missing user key.
- Krea: one request per image (batchSize no longer sent to the API).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
memberUsage was already populated for CLI members (from the result event)
and Anthropic-API members (via the tool loop), but it was never written to
the panel_member_done SSE event or the persisted content JSON, so the
frontend had no token data to render.
Add the token fields (input/output/cacheRead/cacheCreation) to both the
SSE event and the persisted JSON, and render them via a shared
buildPanelMemberMeta helper used by both the live stream and history, so
the badge survives F5. OpenAI members (no per-turn tokens), error members,
and pre-existing history without token fields fall through to no badge.
The badge is display-only; aggregation into the worker/chain total via
seedUsage is unchanged, so there is no double counting and no DB migration.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When a panel member spawned a subagent via the Agent tool, the Claude CLI
emitted the subagent's internal steps as separate top-level messages
carrying parent_tool_use_id: tool_use blocks arrived as type:"assistant"
(no handler → dropped) and the matching tool_result as type:"user", which
created a nameless, label-less collapsible box in the frontend — both in
the live stream and in the persisted history (same segment source).
Skip any top-level event with a non-empty parent_tool_use_id at the single
stream JSON parser, so subagent internals never become CliStreamEvents.
This covers worker and panel-member paths at once. The Agent tool call
itself (parent_tool_use_id=null) stays visible, and the final result event
— which aggregates subagent tokens — carries no parent_tool_use_id, so the
token balance is unaffected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two bugs surfaced when driving the composite toggle (off→plan→fusion→moa)
in an all-CLI setup (no API keys):
1. MoA ran only 1 round instead of the configured 2. cycleCompositeMode
fired the multiModelMode PATCH un-serialized and sendMessage did not
await it, so a message sent right after toggling loaded the session
before 'moa' was committed → the backend read the prior 'fusion' value
→ 1 round. Persisted totalLayers in the DB confirmed fusion (1) for all
post-toggle chains. Serialize mode PATCHes into a promise chain (last
click wins, in order) and await it in sendMessage/sendMessageDirect.
2. A read-only panel member could still write files. ClaudeCliService
hard-coded --permission-mode acceptEdits, which auto-accepts Write/Edit
regardless of --allowed-tools, so a member running with planMode=true
(tools limited to Read/Glob/Grep) could still call write_file. Use
'plan' when planMode is set; this also closes the same latent hole for
regular plan-mode users on the shared CLI path.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cronjobs and Telegram bots threw a hard error when an agent had no
assigned user API key, even for providers (nvidia/gemini/minimax/
pollinations) whose server-side key ChatEndpoint resolves automatically
via ResolveProviderConfig. The guard blocked every non-empty provider
instead of only "openai", so e.g. the nvidia agent failed on "Jetzt
ausführen" although the normal chat worked.
Mirror ChatEndpoint's three-way handling at all three sites
(ExecuteCronjob, SendCronjobNotification, TelegramService.HandleMessage):
- Anthropic (empty provider): Claude CLI fallback when permitted/available
- "openai": hard error (no server key, no CLI equivalent)
- other providers: pass through with empty token; server key resolved later
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The panel agents card wrapped its agent chips in a display:flex container;
render them in a plain div so they flow naturally with the surrounding
layout instead of being forced onto one flex row.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the separate panel_usage SSE event + frontend accumulator with
server-side seeding of the worker's usage object. Both the done-event and
FinalizeChain read from the same usage, so panel (Fusion/MoA) member tokens
now flow into the live badge AND the DB as a single source of truth — the
badge no longer drops to the worker-only value after F5.
- RunPanel takes a TokenUsage usageSink; accumulates member costs after the
Task.WhenAll barrier (single-threaded, no lock)
- ChatEndpoint passes panelUsage as seedUsage to all three worker paths
- StreamChat / StreamChatViaCli / OpenAI StreamChat fold seedUsage into usage
at creation time, so every exit path persists it
- OpenAI done-events extended with cacheCreation/cacheRead fields for live
consistency when seeded by Anthropic members
- chat.js: remove redundant _panelUsage / _addPanelUsage / panel_usage
- TODO.md: mark the live-only v1 boundary closed, note the new mechanism
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The composer had two separate mode buttons (plan + panel). Fold them into a
single #planModeBtn that cycles through every operating mode in one place:
Off -> Plan -> Fusion -> MoA -> Off. Cleaner UI, one affordance instead of two.
Plan stays transient (reset on session switch, never persisted) while
Fusion/MoA persist to the session via apiUpdateSession({multiModelMode}) and
are read server-side from ctx.MultiModelMode. The compat var _planModeActive
is kept in sync (true iff mode === 'plan') so sendMessage and modals.js read
it unchanged. No text label — icon + tint only.
- index.html: drop the separate panel button, reuse #planModeBtn
- chat.css: unified states (plan/fusion/moa tints) on #planModeBtn
- chat.js: cycleCompositeMode / initCompositeMode / _renderCompositeBtn
replace the split plan/panel functions
- chat-page.js: single wiring block, init from session.multiModelMode
- ARCHITECTURE_QUICK.md: document the unified toggle
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Panel member token usage was tracked but discarded, so the cost badge only
ever showed the worker's tokens — misleading for MoA where the real cost is
roughly rounds x agents. Collect each member's usage and add it to the badge.
Each member fills its own TokenUsage in parallel (Anthropic loop via the
existing memberUsage, CLI via the now-captured CliChatResult return value;
OpenAI members stay null, nachruestbar). RunPanel sums them after the
Task.WhenAll barrier — single-threaded, so no lock or Interlocked needed —
across all MoA rounds and emits a panel_usage SSE event before panel_done.
The frontend adds those tokens onto the worker totals in the done handler so
the badge reflects the full chain cost.
- SseHelper: add TokenUsage.Add()
- AnthropicService.Panel.cs: PanelMemberResult.Usage, accumulate per round
after the barrier, emit panel_usage; RunPanelMemberViaCli returns usage
- chat.js: _panelUsage state, panel_usage case, add to worker tokens on done,
reset on stream start
- TODO.md: check off the member-token item
v1 limit: live badge only — FinalizeChain still persists worker tokens, so a
reload shows worker-only cost.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Previously only the final proposer layer was persisted, so after a reload
the intermediate MoA rounds and their "Runde k/N" dividers were gone — the
history showed only the last refined round, not the full live view. Persist
every proposer round instead, tagging each member's JSON transcript with
its layer index, and rebuild the round structure on reload.
- AnthropicService.Panel.cs: persist every round unconditionally; drop the
now-dead persist parameter and isFinalLayer local; write layer/totalLayers
into the transcript; iteration = layer*100+index+1 so DB rows are
layer-aware (no UNIQUE constraint on chain_id/iteration, id-based ordering)
- history.js: group panel bubbles by layer on reload and insert the
"Runde k / N" divider on round change for MoA (totalLayers > 1), matching
the live startPanelLayer view; back-compat for old format (default layer 1)
- TODO.md: check off the MoA persistence item
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Krea removed the batchSize parameter ("Generation batch size is no longer
supported, submit one request per output"), so every image request failed
with HTTP 422 — breaking session/agent avatar generation. Drop batchSize
from the payload and instead send one request per requested image in a
loop, collecting all returned jobs. Endpoint paths, Bearer auth and base
URL are unchanged.
- KreaService: remove batchSize from payload
- KreaService: loop record.BatchSize times, one POST per image, aggregate
jobs (handles both array and single-object responses)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Three related panel-member improvements:
Tool-box streaming fix: correlate tool boxes by tool ID instead of a
single pointer (fixes orphaned spinners and empty boxes when a member
calls multiple tools in one message), forward CLI ToolEnd to capture the
tool input (command/path), normalize tool names, clean up orphaned
spinners on finalize, and add a blinking cursor during text streaming.
Image/screenshot support: CLI panel members now extract image refs from
the last user message (like the worker) and drop them as temp files
readable via the Read tool, so members can see screenshots and file
attachments instead of being blind on image-based questions.
Reload persistence: each member persists a structured JSON transcript
({name, model, segments:[text|tool]}) instead of plain text, so a reload
restores text AND tool boxes interleaved exactly like live. history.js
renders the transcript and keeps back-compat for the old [Panel: Name]
plaintext format.
- AnthropicService.Agents.cs: NonStreamingLoopCallbacks.TranscriptSink,
loop collects text/tool segments, tool input added to combined event
- AnthropicService.Panel.cs: CLI member ID-correlation + ToolEnd input +
image refs + transcript; RunPanelMember persists one JSON transcript
- stream-ui.js: tool boxes keyed by ID, name normalization, cursor,
orphaned-spinner cleanup
- history.js: render JSON transcript with tool boxes, plaintext fallback
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Panel members run read-only (PlanMode / tool-less) but kept their normal
agent prompt, so they repeatedly attempted write/execute/git actions that
the read-only filter blocks — getting stuck in failing tool loops and
wasting tokens. Append an explicit proposer role clarification to each
member's system prompt so they go straight to analysis + text proposal
and leave the actual writing/committing to the synthesizer agent.
- ChatService: PanelMemberRolePrompt constant (read-only, propose-only)
- PrepareContext: append the role prompt to each panel member's SystemPrompt
- Covers all three provider paths (Anthropic direct, CLI/OpenAI via
ExtractSystemPromptText)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extend the panel engine with a layer loop: Fusion is one proposer round,
MoA runs N rounds where each round after the first sees the previous
round's responses via <previous_layer_responses> and refines its answer.
Only the final round is persisted; intermediate rounds are live-only.
Rounds are clamped to 1-5.
- SessionRecord + migration: moa_layers column (default 2)
- RunPanel: layer loop with per-member cloned message injection
- CloneForMember / BuildPreviousLayerBlock helpers for member isolation
- SSE: panel_layer_start / panel_layer_done events
- Frontend: layer_index composite keying, round dividers, MoA option
- Docs: ARCHITECTURE + ARCHITECTURE_QUICK updated
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Panel members now stream token-by-token and show tool uses in real time
(like the session agent) instead of delivering text only at completion.
The key constraint is byte-level safety: N members flushing SSE frames
concurrently on the shared HttpResponse would interleave and corrupt the
stream, so a SemaphoreSlim gate serializes the writes (not the model work).
- SseHelper.TryWriteSse takes an optional write-lock (default null, backward
compatible)
- NonStreamingLoopCallbacks carries SseGate + MemberIndex; _text/_tool/_error
events are tagged with the member index (review/finalizer stay at -1, no gate)
- CLI members forward TextDelta/ToolStart/ToolResult live instead of
discarding everything but the final text
- Anthropic-API members stream per tool-round via the loop callbacks; OpenAI
members fall back to collected text at panel_member_done
- Frontend demuxes by member index into per-bubble interleaved text/tool
rendering
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Panel agents answer the user prompt in parallel (read-only, non-streaming);
their responses are merged into the worker's last user message as a
<panel_responses> block, and the session agent synthesizes one final
streamed answer. The RunPanel engine is built layer-ready for future MoA.
- New session fields: multi_model_mode (off/fusion), panel_agent_ids (CSV)
with idempotent column migration
- New partial Services/AnthropicService.Panel.cs holding the RunPanel engine
- Provider-agnostic members: Anthropic RunNonStreamingToolLoop / OpenAI
CompleteText / CLI plan-mode; all forced read-only, persisted with Tag=panel
- SSE events: panel_start, panel_member_start, panel_member_done, panel_done
- Frontend: multi-agent picker, live panel bubbles, history rendering
- Graceful degradation: panel errors fall back to worker-only
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Previously a session could only be reassigned to another user via a
manual DB UPDATE. This adds it to the session edit UI for every owner of
a session (not just admins) - the ownership check in HandleUpdate
(existing.UserId == userId) already guarantees the caller owns the
session, so handing over one's own session is safe.
Backend:
- ProfileEndpoint: new GET /api/users returning a minimal user directory
(userId/username/displayName only) for any logged-in user. The
admin-gated /api/admin/users stays the source for sensitive fields
(defaultPath/canUseCli/isAdmin).
- SessionEndpoint.HandleUpdate: validate the target user exists (400 if
not) and pass allowUserReassign: true to UpdateSession.
- DatabaseService.UpdateSession: new allowUserReassign flag; only then is
a non-empty userId applied as user_id (empty/null is ignored - a
session must always have an owner).
Frontend:
- index.html: hidden #sessionOwnerRow with a user picker card in the
session edit form (existing sessions only).
- cards.js: buildUserCard helper for the picker.
- session-page.js: initSessionUserPicker loads users via apiGetUsers(),
preselects the current owner, and on an actual owner change asks for
confirmation (irreversible - the session leaves the user's own list).
- api.js: apiGetUsers() -> /api/users.
- ARCHITECTURE.md: document /api/users.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pasted screenshots all share the same filename (e.g. "image.png"), so the
placeholder substitution in _renderUserTextContent resolved every
placeholder to the FIRST matching inline image via find() - showing the
first image N times. Data itself was always correct (DB/agent received
all images; a refresh rendered them properly).
Match images consumingly (findIndex + splice on a copy) instead: labels
and inlineImages are built in the same order, so same-named images now
map one-to-one. Also fix the same latent issue in the legacy attachment
path in history.js (_autoLoadImageAttachments), keeping the shift()
fallback.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds the new claude-fable-5 model (released 2026-06-09) as a selectable
model alongside the existing Claude models:
- ChatService.ResolveModelId: map "fable" and "fable-5" to claude-fable-5
- index.html: fable-5 option in the model dropdown (after opus-4-8)
- ARCHITECTURE.md: model list + resolution table updated
Default stays opus-4-8. The invite-only sibling Mythos 5 is intentionally
not included.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The ask_user_choice MCP tool blocks the CLI process (short-polling
ChoiceAnswers) until the user answers, after which the same
ChatStreamingAsync invocation continues. isUserChoice was set true when
the choice was raised but never reset, so both steering gates (the
tool-boundary kill and the turn-end check, each guarded by
!isUserChoice) stayed blocked for the rest of the run. A message thrown
in after answering was not drained at the next boundary; it lingered in
the queue and only arrived at chain end as a Close() leftover — the user
saw it "come in only at the very end" instead of in between.
Reset isUserChoice (and choiceToolCallId) as soon as the choice tool's
result comes back, before the steering check, so a message injected
during the choice pause takes effect at the next boundary just like
without a preceding choice. As a side effect the stop reason and error
handling after an answered choice are now correct (end_turn / real
errors surfaced) instead of staying awaiting_user_choice. CLI-specific:
the API path finalizes the chain on awaiting_user_choice, so it is
unaffected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A steering message confirmed to the user as injected:true could still be
lost: after the loop's last HasPending check it runs out and the chain
finalizes (done event + final messages still streaming — the "few extra
messages" the user sees), then the finally block called Clear() and threw
the queue away. A message arriving in that window was accepted
(IsStreaming still true, Stop runs only in finally) but never drained and
never persisted, so it vanished after F5. Platform-independent; Windows
only widened the window via slower CLI teardown.
Replace the queue with a per-session gated state: Open() at chain start,
Close() at chain end. TryEnqueue() and Close() are mutually exclusive via
a per-session lock, so a confirmed injection can no longer be lost — the
loop either drains it or Close() returns it as leftover. The endpoint now
opens the gate at chain start, uses TryEnqueue as the authoritative check
(false → client resends as a normal message), and in finally closes the
gate and persists any leftover as Type="steer" instead of discarding it,
so it survives F5 and the model sees it on the next message.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
After a steering kill-and-restart the new claude child read the
<work_in_progress> transcript, merely acknowledged the injected message,
and ended the turn waiting passively for a background task that no longer
existed (the kill also killed its child background processes). Add an
explicit instruction to the work_in_progress block: actively continue and
finish the task this run instead of just acknowledging, and treat any
previously started background/async operations as gone (restart them if
needed) rather than waiting on them.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Claude CLI child process inherited the gott server's CWD because
CreateCliStartInfo never set WorkingDirectory. On Linux systemd usually
sets WorkingDirectory= to the workspace, so it worked by accident; on
Windows the service starts from its install directory, so the CLI's own
built-in tools resolved relative patterns (e.g. Glob "Sources/**")
against the wrong directory and returned "No files found", while
absolute paths still worked. --add-dir only grants access, it does not
set the CWD.
Thread the workspace through ChatStreamingAsync -> RunCliStreamingAsync
-> CreateCliStartInfo and set psi.WorkingDirectory (guarded by
Directory.Exists). GetStatusAsync stays without a CWD.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Shorten the streaming-mode input placeholder from
"💬 Einwurf an die laufende Arbeit… (Enter)" to a terse "Einwurf...".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When the chat is opened while a chain is already streaming, the recovery
poll (_streamingPollInterval) is started. Its forced pollHistory(true)
renders the DB messages while the live SSE bubbles render them too — the
live bubbles never advance lastKnownMessageId, so the poll re-fetches the
same assistant message and renders a second bubble.
Make live SSE and the recovery poll mutually exclusive:
- Stop a lingering recovery poll at the start of a real live stream so the
SSE renders alone.
- Re-ensure the regular (isStreaming-guarded) history polling idempotently
in the finally block, so it is not left off after entering a running chain.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Let the user inject a message into a running chain instead of only being
able to abort it. While a chain streams, typing + Enter sends the text to
a new /api/chat/steer endpoint; it is drained at the next iteration
boundary, wrapped with a hint so the model actively classifies it
("complements the task -> keep working" vs. "changes course -> adjust"),
and stored as a Type="steer" user message so it survives reload.
Shared infrastructure (provider-agnostic):
- SteeringQueue: out-of-band queue keyed by sessionId, mirrored from
StreamingTracker (Enqueue/Drain/Clear).
- Program.cs registers it as a singleton and passes it to AnthropicService.
- ChatEndpoint: POST /api/chat/steer enqueues only while IsStreaming,
Clear() in the finally.
- ChatService.BuildHistoryFromDb groups Type="steer" so no two
consecutive user turns are produced on re-chat.
- Frontend api.js/chat.js/bubbles.js/history.js + chat.css render the
optimistic steer bubble and the steer_injected SSE event; Enter during
a stream sends a steer instead of being blocked.
Anthropic API path:
- Drain point B (tool boundary, merged into the tool_result user turn)
and C (turn end -> inject + continue instead of finalize).
Claude CLI path (kill-and-restart):
- The agentic loop runs inside the claude child, so true mid-turn inject
is impossible. On a pending steer the child is killed at the next tool
boundary, progress is rebuilt from the DB as a <work_in_progress>
transcript, and the CLI is restarted with the steer appended.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Snapshot the agent's effort onto the chain (like model) so it survives
reload, archive and shared chains, then show it in the chain-end meta line.
- ChainRecord.Effort + chains.effort column (TryAddColumn migration).
- CreateChain INSERT carries the value.
- ChatService snapshots agent.Effort at chain creation, but only for Claude
models – OpenAI providers store '' so there is no misleading badge.
- Anthropic streaming + CLI done-events include effort for the live path.
- chat.js buildMetaBadges renders "Effort: <level>" after the model badge,
only when a value is set.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move the effort dropdown out of the collapsed "Weitere Einstellungen"
section to sit right under the model selector, so it is always visible
when configuring an agent.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Opus 4.5+ and Sonnet 4.6+ support a new "effort" knob that controls how
much budget the model spends on thinking and tool calls. Plumb it through
end to end so each agent can pick its own level.
Storage & shape:
- New TEXT column agents.effort (default '') added via TryAddColumn.
- AgentRecord.Effort + INSERT/UPDATE in DatabaseService.Agents.cs.
- ChatContext.Effort + SubAgentContext.Effort so the value travels with the
request alongside model and tool settings.
Agent editor:
- Effort dropdown above git-commit behavior in the agent form (low/medium/
high/xhigh/max plus empty = "use default"). Always visible; on OpenAI
providers the value is sent but silently ignored.
- agent-page.js load/save and AgentEndpoint create/update wired up.
Anthropic API path:
- StreamChat and RunNonStreamingToolLoop add output_config: { effort } when
effort is set and not "high" – empty/null/"high" means "omit and let the
API pick its default".
- Sub-agents (preparer/review/finalizer) get the parameter through
RunAgentChat so each step uses its own agent's effort.
Anthropic CLI path:
- ClaudeCliService.ChatStreamingAsync takes an effort parameter and exports
CLAUDE_CODE_EFFORT_LEVEL on the spawned process. Env-var beats the
--effort flag because it also covers "max" and "ultracode".
- StreamChatViaCli, ChatNonStreamingViaCli, RunSubAgentViaCli, and the
ChatEndpoint anthropic branches all hand the value through.
ARCHITECTURE.md / ARCHITECTURE_QUICK.md updated with the new field.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New Anthropic flagship released 30 May 2026. Adds the dropdown entry as
the new default for fresh agents, maps "opus-4-8" -> "claude-opus-4-8" in
ResolveModelId, and bumps the "opus" alias from 4.7 to 4.8 so the family
shortcut tracks the latest release.
ARCHITECTURE.md updated to list opus-4-8 in both the field reference and the
model-resolution block.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Since March 2026 the 1M-token context window is the default for Opus 4.6/4.7
and Sonnet 4.6 – no separate variant or beta header needed. The "[1m]" suffix
on model IDs is dead code now and would even produce HTTP 400 against the
current API.
Cleanup:
- Drop 3 [1m] options from the agent model dropdown; default selection moves
from opus-4-7[1m] to opus-4-7.
- Drop 5 [1m] mappings from ResolveModelId and add a defensive Replace as a
safety net for any agent record still holding an old value.
- One-shot startup migration on agents.model + chains.model strips the suffix
so existing chains can be re-chatted without errors.
- ARCHITECTURE.md reflects the slimmed list and explains why 1M is now default.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wenn ein Telegram-Bot eine Nachricht empfängt und für den Agent kein
API-Key zugewiesen ist, fiel der Bot bisher hart aus ("Kein API-Key
für diesen Agent zugewiesen"). Im Web-UI wird in dem Fall bereits auf
Claude-CLI zurückgefallen – das macht der Telegram-Pfad jetzt analog.
- AnthropicService.Cli: Neue Methode ChatNonStreamingViaCli(...) für
Non-SSE-Caller (Telegram). Macht dasselbe wie StreamChatViaCli aber
ohne SSE: System-Prompt + Auto-Context, History-Kontext-Block, letzte
User-Message (inkl. Image/PDF-Refs), Text + tool_use + tool_result in
DB persistieren, finalen Text zurückgeben + FinalizeChain mit echten
Token-Counts vom CLI-Result.
- TelegramService: Bei userApiKey == null jetzt CanUseCli, IsAdmin und
IsCliAvailable prüfen. Bei OpenAI-Providern bleibt der Hard-Fail
(kein CLI-Äquivalent). Spezifische Fehlermeldungen pro Szenario.
Zusätzlich Schutz gegen leere Antwort.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Frontend sendet PDFs als type:'document'-Block (chat.js), aber
ExtractLastUserImageRefs filterte nur 'image' und 'file' → PDFs landeten
nie als Temp-Datei im CLI-Workspace und Claude konnte sie nicht per
Read-Tool öffnen.
- maxIterations aus Server-Settings an OpenAI-StreamChat durchreichen (war hardcoded 10)
- Auto-Continue: tool_choice="required" erzwingt Tool-Call statt erneuter Ankündigung,
wird nach erfolgreichem Tool-Call wieder auf "auto" zurückgesetzt
- Direktive Continuation-Message statt einfaches "Continue."
- StripOldThinking: <think>-Blöcke aus älteren Assistant-Messages entfernen (nur letzte 4 behalten),
reduziert Kontext-Inflation die ab ~20k Tokens zu Tool-Call-Degradation führt
- reasoning_split=true entfernt (wird von MiniMax-API ignoriert)
- parallel_tool_calls=false für MiniMax (Streaming, Non-Streaming, Payload-Preview)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MiniMax-M2.7 stoppt häufig nach Action-Ankündigung ohne Tool-Call (z.B. "Lass mich X machen:" → stop).
Auto-Continue erkennt das per Heuristik und injiziert automatisch "Continue." als User-Message (max 3×).
MiniMax-Sampling: temperature=1.0, top_p=0.95 (offizielle Empfehlung für agentic Performance).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Auto-Context (Embedding-Suche) für OpenAI-Provider aktiviert: BuildAutoContextAsync
auf internal static refactored und in StreamChat + ChatNonStreaming integriert
- Tool-Results mit Role="tool" (OpenAI-Konvention) werden in BuildHistoryFromDb
jetzt korrekt erkannt (vorher nur Role="user"/Anthropic)
- Payload-Preview zeigt für OpenAI-Provider echtes API-Format (function-Wrapper,
tool_choice:"auto", max_tokens, stream_options, extra_body)
- Tool-Input (Argumente) wird im SSE tool_end-Event mitgesendet (fehlte im OpenAI-Pfad)
- Leere Bubbles durch Whitespace-only Text nach </think>-Extraktion behoben
(Trim in DB-Save, BuildHistoryFromDb und Frontend-Guard)
- History-Toggle-Bug: var→const in for-Loop (Block-Scoping für Closures),
tool_result-Matching per data-tool-call-id statt blindes letztes Element
- Non-Streaming max_tokens für MiniMax auf 32768 + extra_body.reasoning_split
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
OpenAI-kompatible Provider (MiniMax, DeepSeek-R1, QwQ, Kimi K2, etc.) verloren bei
jeder neuen Iteration ihre eigene Chain-of-Thought, weil thinking-Messages aus der
DB-History rausgefiltert wurden. Folge: Modell kündigt Action an, ruft Tool aber
nicht auf → Stream endet mit finish_reason:stop ohne Tool-Call. Zusätzlich fehlte
der ask_user_choice-Intercept (Tool wurde als unbekannt abgelehnt) und es gab keine
Diagnose-Möglichkeit für unerwartete Stop-Verhalten.
- ChatService.BuildHistoryFromDb(includeThinking): neuer Parameter, fügt
thinking-Messages als {type:"thinking"}-Block in die Assistant-Message ein.
Text/Tool-Use derselben Iteration werden via AppendToLastMessage angehängt
→ ein Assistant-Block enthält [thinking, text, tool_use…].
- OpenAiService.ConvertMessage + StreamChat + ChatNonStreaming: Thinking als
<think>...</think>-Prefix dem Assistant-Content voranstellen (Per-Iteration und
beim DB-History-Aufbau). Konvention von MiniMax-Docs, wird auch von DeepSeek-R1,
QwQ, Kimi K2 verstanden.
- ChatEndpoint, SessionEndpoint, CronjobService, TelegramService, ToolService:
includeThinking je nach Provider durchgereicht. Anthropic-Pfad bleibt aus
(lehnt thinking-Blöcke ohne Signature ab).
- OpenAiService: ask_user_choice-Intercept im Streaming-Pfad (analog
AnthropicService.Streaming) – Tool nicht ausführen, SSE user_choice rausschicken,
mit stopReason awaiting_user_choice finalisieren und return.
- OpenAiService: MiniMax-SSE-Debug-Log in data/openai-debug/ (JSONL: Header +
Roh-data-Zeilen + Summary mit promptTokens/completionTokens/finishReason/
toolCalls/duration) – nur für provider=="minimax", nicht-blockierend.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Anthropic hat Anfang März 2026 die Default-Cache-TTL stillschweigend
von 1h auf 5min gesenkt. Bei Sessions mit Pausen >5min wird der Cache
jedes Mal neu geschrieben (teuer). Dieser Commit aktiviert die
extended 1h-TTL über beide Pfade.
API-Pfad (AnthropicService):
- Beta-Header "extended-cache-ttl-2025-04-11" hinzugefügt
- Falsches Top-Level cache_control (Root-Level wurde ignoriert) entfernt
- Neue Helper ApplyCacheControlToLast() setzt cache_control idempotent
auf das letzte Element via JSON-Roundtrip zu Dictionary
- 2 Cache-Breakpoints pro Iteration:
* Letztes Tool (cached gesamten Tool-Block)
* Letzter System-Prompt-Block (cached System-Prompt)
- Sub-Agent-Loop (Preparer/Review/Finalizer): String-System-Prompt wird
bei Bedarf in Block-Form mit cache_control konvertiert
CLI-Pfad (ClaudeCliService):
- Env-Var ENABLE_PROMPT_CACHING_1H=1 für jeden CLI-Child-Prozess gesetzt
(offizieller Opt-in seit Claude CLI 2.1.108, gilt für API-Key,
Bedrock, Vertex, Foundry)
Aktivierung: Umgebungsvariable GOTT_CLI_DEBUG_BYTES=1
Im Debug-Modus wird ein TeeReadStream zwischengeschaltet, der alle rohen Bytes
vom Claude-CLI-Prozess in eine .bin-Datei schreibt (vor dem UTF-8-Decode).
Zusätzlich wird jedes Vorkommen von U+FFFD im decoded Output mit Position,
Kontext und FFFD-Counter in eine .log-Datei protokolliert.
Logs landen in data/cli-debug/cli-stdout-{timestamp}.{bin,log}.
So können wir das intermittierende �-Problem auf Windows beweisbar einkreisen:
- Wenn .bin valide UTF-8-Bytes enthält aber .log FFFD-Treffer hat → unser Decoder
- Wenn .bin bereits invalide Bytes (CP1252) enthält → Claude-CLI/Node ist schuld
- Wenn .bin bereits EF BF BD enthält → Anthropic-Server schickt schon kaputt
Im Default-Modus (Env-Var nicht gesetzt) bleibt der ursprüngliche Default-Reader
aktiv – kein zusätzlicher Disk-IO im Normalbetrieb.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Setzt die folgenden Commits zurück, da sie das Problem nicht behoben haben:
- e75c437 fix(encoding): UTF-8 prozess-global + 16-KB-StreamReader für CLI-Output
- bfd550e fix: UTF-8-Encoding gehärtet (SSE-Reader + CLI-Workspace)
- 32aad7f fix: UTF-8-Encoding für Claude CLI auf Windows erzwingen
Trotz cmd.exe-Wrapper mit chcp 65001, explizitem UTF-8-StreamReader (16 KB Buffer,
ohne BOM-Detection), Console.OutputEncoding global auf UTF-8 und LANG/LC_ALL/
PYTHONIOENCODING-Env-Vars treten weiterhin Replacement-Chars (�) für Umlaute
und Em-Dashes auf Windows auf. Der Bug muss separat per Diagnose-Logging
nachgestellt werden.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Zwei zusätzliche Härtungen gegen intermittierende �-Replacement-Chars
(Umlaute, Em-Dash) im CLI-Output unter Windows:
- Program.cs: Auf Windows Console.OutputEncoding/InputEncoding = UTF-8
setzen. Wirkt prozess-global via Win32 SetConsoleOutputCP/SetConsoleCP
und wird von direkt gestarteten Child-Prozessen geerbt – ergänzt den
bestehenden chcp-65001-cmd-Wrapper. In try/catch, falls als Windows-
Dienst ohne Console gestartet.
- ClaudeCliService.cs: stdout-Lesen mit eigenem StreamReader (16-KB-
Buffer, explizit UTF-8 ohne BOM-Detection) statt Default-Reader (1 KB).
Verhindert, dass bei gefragmentierten Pipe-Reads Multi-Byte-UTF-8-
Sequenzen über Buffer-Grenzen aufgesplittet werden und der Decoder
den State verliert.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- AnthropicService.Streaming.cs + OpenAiService.cs: SSE-StreamReader nutzt
jetzt expliziten UTF-8-Encoder mit 16-KB-Buffer (statt default 1 KB) und
ohne BOM-Detection. Verhindert intermittierende Replacement-Chars (�),
die entstehen können, wenn Multi-Byte-UTF-8-Sequenzen ungünstig über die
Read-Boundary eines NetworkStreams gesplittet werden.
- ClaudeCliService.cs: cmd.exe-Wrapper jetzt mit /D (AutoRun-Skripte aus
Registry deaktivieren) und WorkingDirectory wird auf den Session-Workspace
gesetzt. Vorher erbte der Child-Prozess das CWD von gott (bei Windows-
Diensten C:\WINDOWS\system32).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Auf Windows kam es sporadisch zu Replacement-Chars (�) für Umlaute
und Em-Dash, weil claude.exe Output mit CP1252/CP850 schreiben konnte.
Lösung: CLI über cmd.exe wrappen und Codepage 65001 (UTF-8) erzwingen,
zusätzlich LANG/LC_ALL/PYTHONIOENCODING auf UTF-8 setzen.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Claude Opus 4.7 als neues Default-Modell, 1M-Context-Varianten für Sonnet/Opus
- 5 neue Krea-Bildmodelle (z-image, qwen-2512, nano-banana-2, seedream-5-lite, seededit)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Statt Hard-Error "Kein API-Key zugewiesen" nutzen Sub-Agents jetzt
Claude CLI als Fallback. Preparer wird nur übersprungen wenn weder
Key noch CLI verfügbar sind.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pfade werden auf Windows nativ mit Backslashes zurückgegeben statt zu Forward-Slashes konvertiert. Navigation von Laufwerk (C:) zurück zur Laufwerksliste ermöglicht.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remote-Verbindungen erkennen jetzt das OS des Clients und passen die Tool-Description
dynamisch an (PowerShell für Windows, Bash für Linux). Neues remote.sh Script für
Linux/macOS-Clients mit embedded Python WebSocket-Client.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- recalled_context-Header verstärkt (klare Nutzungs-Anweisung statt passivem Hinweis)
- SSE-Event 'auto_context' ans Frontend senden für Live-Anzeige
- Auto-Context als Message (type=auto_context) in DB speichern
- Aufklappbare Auto-Context-Box im Chat-Stream und History-Rendering
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Process.Dispose() gibt nur den Handle frei, killt aber nicht den Prozess.
Jetzt wird per CancellationToken.Register() der gesamte Prozessbaum
(entireProcessTree: true) sofort beendet wenn der User auf Stoppen klickt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Neues Server-Setting NvidiaApiKey – wenn gesetzt, wird direkt
integrate.api.nvidia.com verwendet statt g4f.space Proxy.
Thinking-Modelle (kimi-k2, qwq, deepseek-r1) erhalten automatisch
chat_template_kwargs und reasoning-Output wird als klappbare
Denkprozess-Bubble im Chat angezeigt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- CLAUDE_CLI_PATH Umgebungsvariable als höchste Priorität bei CLI-Suche
- CreateCliStartInfo() Helper dedupliziert ProcessStartInfo-Erstellung
- .cmd-Wrapper-Logik entfernt (nicht benötigt)
- PATH-Suche priorisiert .exe für Windows
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wenn eine ältere ask_user_choice-Chain als Text-only geladen wird,
geht der tool_use verloren, aber das tool_result in der nächsten Chain
bleibt – Anthropic API antwortet mit 400 "unexpected tool_use_id".
Neue FixOrphanedToolResults()-Funktion entfernt diese verwaisten Blöcke.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Statt powershell.exe als Kindprozess mit 2>&1 zu starten (was CLIXML-Parsing-Fehler
bei rohem stderr verursacht), wird System.Diagnostics.Process direkt verwendet.
Zusätzlich werden harmlose CLIXML-Progress-Meldungen aus stderr herausgefiltert.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Neue Felder CanCreateAgents und CanUseCli im UserRecord (Default: true)
- DB-Migration mit Abwärtskompatibilität (bestehende User behalten alle Rechte)
- Admin-UI: Checkboxen für beide Berechtigungen pro User
- AgentEndpoint: Prüfung auf CanCreateAgents beim Erstellen
- ChatEndpoint: CLI-Fallback nur wenn CanUseCli erlaubt
- Frontend: Neuer-Agent-Button und Agent-Page bei fehlender Berechtigung gesperrt
- Chat: Proaktive Warnung wenn kein API-Key und keine CLI-Berechtigung
- Bug Fix: is_public fehlte im Agent-INSERT (Public Agents erst nach erneutem Speichern sichtbar)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sessions können jetzt einen Unity MCP-Server (URL + Token) konfigurieren.
Die CLI erhält automatisch die MCP-Config mit korrektem Transport-Typ
(URL-basierte Erkennung: /sse → SSE, sonst HTTP für streamableHttp).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TodoWrite → todo_write Mapping in Backend und Frontend ergänzt.
Todo-Liste wird jetzt aus dem Input-Array gebaut statt aus dem
Result, da die CLI nur einen generischen Erfolgstext zurückgibt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Read-Tool wird jetzt immer erlaubt (nicht nur mit Workspace), und
/tmp/gott-cli-images/ wird als --add-dir hinzugefügt, damit gesendete
Bilder von der CLI gelesen werden können.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Long-Poll durch Short-Poll ersetzt (MCP-Server pollt jede Sekunde statt einer blockierenden HTTP-Anfrage)
- Expliziter Lambda-Rückgabetyp Task<IResult> für ASP.NET Minimal API Endpoints (behebt 200 empty body Bug)
- Freitext-Option bei Choice-Buttons ("Eigene Antwort…") für freie User-Eingabe
- Stop während ask_user_choice markiert Chain als awaiting_user_choice statt stopped (Kontext bleibt erhalten)
- ask_user_choice System-Prompt-Instruktion breiter formuliert (Quiz, Multiple-Choice etc.)
- Text wird jetzt immer in DB gespeichert, auch bei ask_user_choice
- Key-Check Model auf claude-haiku-4-5 geändert
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MCP-Server erweitert um ask_user_choice (Long-Poll), memory_read, memory_write
und memory_list Tools. MCP-Config wird jetzt immer generiert (nicht nur bei
Remote-Verbindung). InternalEndpoint um PendingChoices + choice-respond Endpoint
ergänzt. Frontend differenziert CLI-Modus (choice-respond API) vs. API-Modus.
Gesamter :::ASK_USER_CHOICE::: Text-Marker-Mechanismus aus ClaudeCliService,
AnthropicService, markdown.js und stream-ui.js entfernt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Python MCP-Server (stdio, JSON-RPC 2.0) für remote_execute via Claude CLI
- Interner API-Endpoint /api/internal/remote-execute mit Token-Auth
- MCP-Config wird automatisch generiert wenn Remote-Verbindung vorhanden
- Auth-Middleware: /api/internal/ von Auth ausgenommen
- Frontend: :::ASK_USER_CHOICE::: Blöcke als interaktive Buttons rendern
- Streaming: Unvollständige Choice-Blöcke werden während des Streams versteckt
- tool-ui.js: MCP-Tool-Namen generisch normalisieren (mcp__server__tool → tool)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
workCt steuert den CLI-Prozess (nur Stop-Button), sseCt die SSE-Writes
(Client-Disconnect). Page-Reload cancelt nur sseCt → CLI läuft weiter.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Result-Div wird nicht mehr leer erstellt bei tool_use – erst wenn
tatsächlich ein Result vorliegt. Header wird nachträglich clickable
gemacht wenn das Result später eintrifft.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Tool-Namen/Inputs von CLI-Konvention auf gott-Konvention mappen (Edit→edit_file, file_path→path etc.)
- Text vor Tool-Use in DB flushen für korrekte Reihenfolge (statt alles am Ende als Blob)
- lineBuffer in ClaudeCliService vor Tool-Start und bei Text-Block-Ende flushen
- ToolResult-Events parsen und in DB speichern (CLI sendet diese als type:"user" Messages)
- Errors in DB speichern und als SSE-Event senden
- Bild-Attachments als Temp-Dateien für CLI bereitstellen (Read-Tool kann sie lesen)
- Frontend: tool_result Handler, Tool-Name-Normalisierung, appendToolResult()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ClaudeCliService: Marker-basierte ask_user_choice Erkennung im Stream-Parser
- AnthropicService: StreamChatViaCli mit allowUserChoice, planMode, webSearch
- BuildHistoryContext erweitert für tool_use/tool_result (Choice-Antworten)
- Tool-Use Records werden in DB persistiert (Poll-Kompatibilität)
- CLI Tools konfigurierbar: Workspace/Plan-Modus/WebSearch/kein Workspace
- OAuth DB-Felder für zukünftige Token-Verwaltung
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>