Commit Graph
82 Commits
Author SHA1 Message Date
Gadfly ea4fd9bbff feat(codex): carry editor context beside the user's words, not inside them
Changing editor state used to be pasted straight into the message text,
spending the user message's native budget and polluting history replay.
Each turn now freezes structured additionalContext fragments instead
(ide_context, open_tabs, workspace_context, referenced_files_<index>,
terminal_context_<index>), so every fragment enjoys its own native budget
and the request text stays pristine.

The service sniffs the selected CLI once per child process via
app-server generate-json-schema --experimental to learn whether
turn/start accepts additionalContext, and re-sniffs after a runtime
replacement; discovery never creates a thread or turn and cancels leave
it early. Older CLIs get the official desktop text envelope with UTF-8
text-element byte ranges shifted accordingly, and history replay strips
that envelope so users only ever see their own request.

Cover the flow with schema-probe, fallback, cancellation and daemon
tests on the bridge side plus context-budget, payload-copy and display
sanitizer tests on the Java side; document the contract in
docs/codex/app-server.md.
2026-10-25 21:37:23 -07:00
Gadfly e78a9ca897 fix(codex): preserve streamed messages and replay tool batches consistently
Codex streaming could omit commentary, reasoning, and edit cards between
batches until the conversation was reloaded. Historical exec wrappers also
collapsed supported parallel calls into generic exec cards and used command
labels that differed from live rendering.

Preserve snapshot ordering and complete message corrections:
- Compare complete raw message content when selecting the transported suffix;
  keep structural signatures limited to snapshot scheduling.
- Apply a buffered full snapshot before its dependent tail update advances
  the sequence barrier, retaining intermediate items during React batching
  and stream completion.

Restore recorded tool batches without guessing result ownership:
- Associate Promise.all and Promise.allSettled results with their original
  array slots, including independently printed index labels in forEach and
  bounded for loops.
- Retain labeled arrays, primitives, plain text, and label-like values.
- Restore mixed command and write_stdin batches while keeping polling tied
  to the original process card.
- Match identical commands through confirmed process identities or unique
  explicit absolute working directories, including file URIs and Windows
  paths, while preserving literal POSIX backslashes.
- Never assign unindexed parallel process receipts by arrival order; retain
  the original wrapper whenever ownership cannot be established.

Keep local Promise computations out of the visible tool timeline:
- Preserve Promise.resolve expressions and indexed results as internal data
  without executing historical source.
- Filter these entries through the shared rendering predicate so they neither
  create cards nor interrupt command groups in live or historical messages.
- Separate rejection metadata from result fields, distinguish Promise.all
  values from settled envelopes, and decode nested local receipts only when
  the source proves that the complete settled receipt was printed.
- Keep flattened local Promise.all output in its original wrapper rather
  than interpreting data fields named status or error as execution outcomes.

Align historical command rows with live presentation:
- Preserve recorded summaries, approval reasons, and parsed command actions.
- Accept both list_files and listFiles directory action names.
- Remove generated English command summaries and retain Bash tool identities
  for legacy reads and searches so the shared renderer controls row labels.

Extend Java, React, and browser regression coverage for snapshot ordering,
process ownership, mixed batches, local result preservation, command labels,
and continuous tool grouping. Update the Codex runtime documentation and
browser fixtures to describe the resulting behavior.

Validation:
- 199 Java tests passed across CodexKnownExecReplayTest,
  HistoryMessageInjectorTest, CodexHistoryPageIndexTest, and
  StreamMessageCoalescerStreamEndHookTest.
- Gradle checkstyleMain passed.
- 67 targeted frontend tests passed across snapshot callbacks, MessageItem,
  GenericToolBlock, tool constants, and command presentation.
- TypeScript test-project checking and git diff --check passed.
2026-10-25 21:37:23 -07:00
Gadfly a457ee3429 fix(claude): let subagents keep their own permission mode instead of the parent's
The PreToolUse hook read the parent's cached mode for every call, so a
worker running under the native auto reviewer got forced to "ask" as soon
as the parent switched modes, and a worker's EnterPlanMode/ExitPlanMode
mutated the parent Query or opened a parent plan-approval dialog.

Recognized permission_mode values from the hook input now win over the
parent state for worker calls; worker plan transitions, plan-file
ownership and the SDK-only dontAsk/bubble modes yield to the native
permission flow, and missing or unknown modes still fall back to the
parent policy.
2026-10-21 21:21:17 +08:00
zhukunpenglinyutong f836375305 fix(codex): keep the permission mode and the effective sandbox in sync
Full Auto could run sandboxed while the selector still read Full Auto. The
permission mode is app-level state that survives a reinstall, but the access
scope only lived in webview localStorage, so a wiped snapshot or a
pre-native-scope migration left the app-server on workspace-write and denied
writes outside the project — with no way to see why. The permissions panel made
it worse: it reported the legacy .idea record as both "desired" and "effective",
so it claimed full access while the runtime was sandboxed, and changing it there
was overwritten by the next message.

- Derive the access scope from the authoritative mode whenever no explicit
  choice is recorded ('default' source), so a reinstall self-heals; an explicit
  'user'/'native'/'migrated' scope is never overridden.
- Honour a persisted sandbox in the snapshot migration and stop treating the
  never-written `codexFullAccessExplicit` flag as the only Full Auto evidence;
  pair a persisted full-access preset with danger-full-access.
- Drive the permissions panel from the chat state (the value every turn sends)
  and write panel changes back into it; show "effective" only from the
  app-server's thread/settings/updated echo, never the requested value.
- Stop reporting fabricated sandboxDesired/sandboxEffective/sandboxConflict
  from ProjectConfigHandler, and drop the matching webview branches.
- Export buildTurnSettings and pin the mode -> approval/sandbox contract with
  tests, since the webview mirrors that mapping.
- Delete codex-sandbox-resolution.js and utils/permission-mapper.js: both were
  unreferenced by production code, and the latter encoded a platform-dependent
  Full Auto mapping that no longer exists.

Tests: webview 2440 passed (tsc clean), ProjectConfigHandler/CodexInteraction
handler tests, 32 persistent-codex-service tests.
2026-10-19 19:38:48 +08:00
Gadfly fe95dd8ef4 fix: help CLI detection catch the standalone-installed codex and trust only proven versions
- Discover the CLI in the official standalone installer layouts on both
  the Java detector and the Node resolver: CODEX_INSTALL_DIR, Windows
  %LOCALAPPDATA%\\Programs\\OpenAI\\Codex\\bin, and
  ${CODEX_HOME:-~/.codex}/packages/standalone/current in both the
  bin/ and flat layouts, without scanning unselected releases/
- Mark Codex installed only when "codex --version" really prints
  "codex-cli <version>"; a half-installed npm launcher that still
  executes no longer poses as a working CLI (docs contract updated)
- Point the chat diagnostics card and the CLI install dialog at the
  official per-platform install/update instructions instead of the
  old npm-first recipe, and sync the new wording across all ten UI
  languages (zh also aligns 供应商管理 with the settings label)
2026-10-16 16:32:39 +08:00
Gadfly 7b244ae09b Merge branch 'feature/v0.6.0' into fix/clipboard-image-paste-lifecycle 2026-10-11 07:30:06 +08:00
朱昆鹏 bb7f2970aa Merge pull request #1904 from 57ggfk/feature/v0.5.9-optimize-opencode-process-display
feat(opencode): show tool calls and thinking in the process stream
2026-10-10 12:59:45 +08:00
Gadfly d21a8f4ed7 fix(codex): count history list messages through a native tally pipeline
The history list could not say how many messages each Codex thread
holds, because the thread listing only summarizes turns and the webview
had to guess from whatever fragment happened to be loaded. Add a
codex.countThreadMessages daemon method that walks the native history
pages, dedupes messages by uuid, and caches each tally per thread
revision, and give the webview a concurrency-capped queue that counts
the visible sessions and merges the results into paginated publishes
without losing edits or deletions made in between. Item reads that
return incomplete without a continuation cursor now fail loudly instead
of collapsing a partially hydrated turn into an empty transcript.
2026-10-09 16:49:16 +08:00
Gadfly 6c3632fc6e fix(codex): retire auxiliary title work on turn abort and keep it out of transport tests
The Linux CI job failed on stopBeforeNativeTurnIdentityDoesNotReplayAndConfirmsProcessExit:
the fixture's isolated HOME has no config, so title generation defaulted on and its
thread/read RPC plus auxiliary app-server child raced the abort's process-exit
assertion.

- codexAbortTurnPersistent cancels the session's titleAbort alongside the turn
  stop: a user-requested stop retires the naming work instead of leaving a
  lingering title child alive for up to 15 seconds.
- CodexFixtureDaemon writes aiTitleGenerationEnabled=false into the isolated
  home so transport integration tests never depend on the global title setting.
2026-10-09 13:59:27 +08:00
Gadfly ff871138c4 Merge remote-tracking branch 'zhukunpenglinyutong/feature/v0.6.0' into fix/clipboard-image-paste-lifecycle
# Conflicts:
#	ai-bridge/services/codex/persistent-codex-service.js
2026-10-09 13:44:44 +08:00
Gadfly 441368d04d fix(codex): name new threads mid-turn and keep reload batches intact
- Start the auxiliary title request as soon as the native threadStarted
  event announces the thread instead of after the whole turn settles.
  Only the first created thread claims the attempt, a failed bootstrap
  leaves retried or queued sends eligible, and teardown cancels and
  awaits every pending listener.
- Register the persistent app-server daemon in the Node process panel
  and keep its descendants off the orphan list; panel restart stops only
  the daemon so multi-turn session state survives.
- Group consecutive same-page history slices into one pending queue
  entry so backpressure cannot drop a middle batch and split reloaded
  tool cards with separators; failed scripts requeue with their
  grouping and order intact.
- Carry recorded turn/thread ownership onto replayed legacy messages and
  recover agentMessage items whose body is a plain content string, so
  reloaded transcripts merge each tool batch into a single card.
- Pair legacy wrapper commands with native receipts by process id and
  keep ambiguous same-text commands as wrappers instead of guessing
  their outcomes.
2026-10-09 13:34:08 +08:00
zhukunpenglinyutong d5b153f8c0 fix(codex): fall back to the next Codex CLI when the chosen install cannot start
A machine commonly carries several `codex` installs (version managers, npm
global prefixes, a manual download) and only some of them are complete.
Discovery returned the first match, so an incomplete copy - typically an
`@openai/codex` npm launcher whose platform package is missing - was picked,
died with `spawn ... ENOENT` before READY, and took the whole turn down with
a bare exit code.

- listCliCandidates() keeps every PATH match (`which -a` / `where`), the env
  override, home candidates, well-known bin dirs and the login shell, then
  dedupes by real path; resolution still spawns no child process, since CLI
  version probing belongs to the settings page.
- classifyCodexCli() judges a candidate from filesystem facts only: the npm
  launcher is resolved through its symlink to its `@openai/codex` package,
  and an install whose platform binary cannot be confirmed is demoted behind
  every confirmed candidate rather than dropped, so a heuristic can never
  take away a working CLI.
- resolveCodexCli() returns the ordered `candidates` plus the `rejected`
  entries with a concrete reason; the full candidate list survives as startup
  fallbacks, and an explicit override that only looks incomplete is honoured.
- CodexAppServerService gains a bounded `startupAttempts`: a death before
  READY advances to the next candidate, emits `runtimeFallback`, and only
  fails when every candidate is exhausted. Exits after READY never retry,
  because nothing was dispatched before the handshake completed. Transport
  events during a start in flight are deferred to the startup loop so their
  synchronous `exited`/`processError` cannot pre-empt the fallback.
- The client keeps a bounded, sanitized stderr tail and attaches the launch
  command and that tail to `err.details` when a start dies, so a startup
  death is no longer only an exit code. The canonical message is unchanged
  for existing consumers; the runtime failure text appends the per-CLI
  attempt results and an actionable hint.
- CodexNativeHistoryReader matches the exit line by prefix (not `matches`),
  so a wrapped line with diagnostics still permits the read-only history
  fallback.
- webview: a `codexCliUnavailable` error pattern with reinstall / `CODEX_BIN`
  guidance, localized in all ten locales.

Also bump the version to 0.6.0-beta1.
2026-10-09 13:02:28 +08:00
Gadfly 74d7cd255f fix(codex): address remaining review findings across daemon, plugin and webview
- Return NO_THREAD from compact/review before enqueueing a threadless
  operation, matching the daemon's public guard.
- Cache Codex CLI status for 30s per dependencies root: the discovery
  chain shells out a login shell when nothing resolves and ran on every
  request.
- Give an acked compaction its own 60s announcement budget before the
  uncertainty watchdog retires the runtime, since capture_step_context
  can outlast the 10s stop budget.
- Drop dead codex.listTurns/listItems plumbing (daemon, handler map,
  app-server doc) and the legacy cross-package SDK fallback in
  DependencyManager/SdkDefinition.
- webview: reset hunk state at each file header in multi-file unified
  diffs, key the edit preview by item instead of drifting index, unlock
  threadless compaction echoes whose threadId arrives omitted, and
  localize the plan-refinement prompt in all ten locales.
2026-10-06 04:18:48 +08:00
Gadfly 983705f5d0 feat(codex): migrate Codex runtime to persistent app-server
Replace the per-turn `codex exec` TypeScript SDK path with a persistent
`codex app-server --listen stdio://` JSON-RPC connection managed by the
Node daemon: Java -> DaemonBridge -> persistent CodexAppServerService ->
native app-server, one initialized child per chat host with native
thread/turn lifecycle.

Node (ai-bridge):
- Add app-server stdio client (handshake, request/reply registries,
  classified errors, uncertainty budget) and the operation service
  (session FIFO, frozen settings revisions, reverse interactions,
  item/plan/compaction projections, launch-config rebuild at idle).
- Add persistent per-session service wrapper, CLI resolver with legacy
  dependency fallback, sanitized runtime environments, native history/
  subagents/catalog readers, privacy journal, and ephemeral text
  requests for prompt enhancement, commit generation and session titles.
- Remove the TypeScript SDK load path and JSONL re-read from live turns.

Java:
- Rewrite CodexSDKBridge on the provider facade: structured daemon
  routing with channel/epoch/runtime-generation gates, thread ownership
  registry, interaction registry with page tokens, native history
  reader with offline-only legacy fallback, and daemon lifecycle
  coordination.
- Add interaction/data/workspace-diff handlers, file navigation helper,
  native file-change undo plan (patch reversal, rename baselines), and
  Codex history merger for restored sessions.
- Route Codex runtime management to the shared CLI detection page;
  drop the Codex SDK dependency definition and install entries.
- Wire send identity (clientMessageId), stream-end release on startup
  errors, and per-origin diff/undo receipt routing.

Webview:
- Add native plan state, compaction status, turn activity, session edit
  ledger, workspace diff dialog, patch/file-change cards, command
  presentation, desktop attachment envelope handling, and Codex command
  dispatch (/compact, /diff, /approvals, execute plan).
- Align skill filtering with the native `enabled` field, complete the
  codexQuota locale block for all 10 languages, and keep cached
  normalization for high-volume message rendering.

BREAKING CHANGE (internal): Codex approvals switch from boolean file
IPC to structured bidirectional events carrying runtime/thread/turn/
item/RPC identity. Other providers keep their existing protocols.
Approval requests now follow Codex native policy instead of treating
every started tool as pending.

Verified: Node 1142 tests (1139 passed / 3 platform skips), Java 1655
tests across 204 suites plus Checkstyle/JaCoCo, webview 2178 vitest
tests and tsc, four-viewport Playwright suites, openspec strict
validation (71 requirements / 392 scenarios), JDK21 buildPlugin.
2026-10-05 03:18:18 +08:00
57ggfk e2e2264d76 feat(opencode): show tool calls and thinking in the process stream
OpenCode 1.18 run --format json pushes each part only once with
terminal state: text/reasoning arrive as complete parts and the tool
part arrives as a single completed event. The parser assumed a
two-phase started->completed tool flow, so it emitted orphan
tool_results that never rendered, and the missing --thinking flag made
the CLI suppress reasoning parts entirely.

- classify events by part.type (text/reasoning/tool), keeping legacy
  top-level type matching as fallback
- synthesize the tool_use + tool_result pair from the single terminal
  tool event, keyed on part.callID; started-dedup keeps future
  two-phase pushes converging on one card
- pass the plugin thinking toggle down to --thinking (Java stdin ->
  channel -> argv); bypassPermissions maps to --auto
- emit only the novel suffix when a part is re-pushed with cumulative
  text, so text never doubles in the UI
- capture real 1.18.32 event samples and replay them as test fixtures

The streaming toggle stays a documented no-op for OpenCode until a
serve-based integration lands (see docs/plans plan for the matrix).
2026-09-30 23:18:22 +08:00
57ggfk 3b0d711c14 docs: add screenshot of the Codex writer-conflict error card 2026-09-29 14:14:27 +08:00
57ggfk 1d78be55b0 fix(codex): stop overlapping turn processes and resend loops around interrupts
Codex holds a per-thread writer lock for the whole turn, so spawning a
second resume while the previous process is still alive fails with
"thread-store conflict: already has an active writer", which the UI
misdiagnosed as an expired session thread. Interrupting with queued
messages could also resend them in a burst via late stream-end echoes.

- serialize codex sends per channel and terminate a still-alive previous
  turn process before spawning a new one (CodexSDKBridge)
- dispatch at most one queued message per idle period (useMessageQueue)
- keep a freshly dispatched turn's loading state when an interrupted
  turn's late onStreamEnd/showLoading echoes arrive, so the queue drain
  cannot re-fire mid-boot
- classify "already has an active writer" as its own diagnostic with
  retry guidance in 10 locales instead of suggesting a new session

Verified: webview 1878 tests, ai-bridge codex suites, and GUI runs in
WebStorm (interrupt, queue drain, interrupt stress rounds).
2026-09-29 14:00:39 +08:00
zhukunpenglinyutong eb28254f13 Record reproducible performance evidence and remaining host validation limits
Close the implementation checklist with work-count baselines, regression results, review fixes and independent rollback boundaries. Explicitly separate browser and automated verification from unperformed JetBrains JCEF profiling.

Constraint: Local commits only; no remote push or release
Confidence: high
Scope-risk: narrow
Tested: Webview 1857, Codex Node 59, Java 1424 passed with 14 skipped, Chromium input E2E 5, TypeScript, Checkstyle and production build
Not-tested: Real JCEF latency, heap profiling and native multi-window interaction
Directive: Do not interpret synthetic work-count reductions as measured end-to-end smoothness
2026-09-28 19:16:05 +08:00
朱昆鹏 4a00ea16b7 Merge pull request #1880 from changshunxu520/fix/custom-model-verbatim-and-exact-sdk-model
fix(model): keep custom Claude model ids verbatim and pass exact model id to the SDK
2026-09-23 21:19:53 +08:00
徐长顺 4d7ec69491 fix(model): never rewrite a user-defined custom Claude model id
Custom models are the user's explicit choice and must be sent verbatim,
even when the id is in the retired-model migration table. Previously a
custom claude-opus-4-6 was rewritten to claude-opus-5 on both sides
(webview alias table and SessionState.normalizeRetiredModelId), so the
dropdown showed two check marks and the request went to the wrong model.

- Drop claude-opus-4-6 from both migration tables: it is still served by
  the API (verified with `claude -p --model claude-opus-4-6[1m]`), so it
  never met the table's "fails at the API" criterion.
- webview: normalizeClaudeModelId() takes an optional set of custom ids
  and returns those unchanged; every restore/compare/select call site
  passes it. ModelInfo gains isCustom; custom models are read through a
  shared utils/customClaudeModels.ts.
- webview: a custom model whose id is in the migration table shows a
  "Retired" badge with a tooltip. The id is still sent as-is; the badge
  only informs. i18n keys added for all locales.
- Java: SessionState/ClaudeSession.setModelVerbatim(); handleSetModel
  (explicit webview selection) uses it. Restore paths keep setModel() so
  stale built-in ids still self-heal.
- Java: guard a null settings service in
  ModelProviderHandler.resolveConfiguredClaudeModelFromSettings.
- docs/fix: write-up of both root causes and the verification steps.
2026-09-22 16:38:24 +08:00
hesixian 316acd97e0 docs: record the DSH question follow-up fixes
The doc's "次生风险" section listed three defects that are now fixed in this
same PR, so it records what each fix does (clientId wait, stale-response
logging, plan detail + provider title) instead of a to-do list. The remaining
item stays as a lead: it is an isolated Claude-path IPC file, not DSH.
2026-09-17 17:54:19 +08:00
hesixian 8af6176dc8 fix(ask-user-question): submit the manual answer together with the options
The custom answer box only rendered while the "Other" row was ticked, and
`formatAnswers` only attached its text in that state, so a dialog that offered
1/2/3 plus a manual answer could not be used as "option + a note", a question
without options required discovering the "Other" row first, and text typed
before clicking an option was silently dropped at submit.

- QuestionSection: the input is always available; a question without options
  drops the "Other" row and focuses the input on arrival.
- useAskUserQuestionState: typing selects "Other" automatically (on a
  single-select question that replaces the picked option, the only value that
  question can carry); picking a predefined option on a single-select question
  clears the box so no text is left behind that would not be submitted;
  emptying the box releases the marker again; clicking "Other" focuses the
  input in the same tick, and a typed answer alone is enough to proceed.
- answerState: formatAnswers() always carries typed text - single-select the
  custom answer wins, the precedence the DSH encoding expects where `custom`
  overrides the choice, multi-select labels plus the note - and the new
  syncOtherSelection() keeps the marker and the box in step.
- tests: 10 cases over option-only, typing, single-select replace, clearing,
  multi-select with a note, an option-less question, an empty submit, and the
  internal marker never reaching the backend.

Verified in the IDE (session-2754c72b): a two-question batch answered with
back/next returned {"back_test_q1":"C. 改后的答案"} and
{"back_test_q2":{"selected":[],"custom":"正常"}} - the changed answer
survived the round trip and the typed note arrived as `custom`. Webview
tests: 182 files / 1586 passed, plus the tsc typecheck (npm test).
2026-09-17 17:10:49 +08:00
hesixian 36f87e1a7d fix(dsh): answer only the session's own question and approval waterfalls
`$events` is a host-wide stream: the gateway broadcasts every forwarded
waterfall to every client, and the modern turn subscribed to it without asking
who a request belonged to. A question - or an approval - raised by another
session (another IDE tab, or the user's own `dsh web` window) therefore popped
this window's dialog, and since the host settles a waterfall for whoever
answers first, this turn also stole the reply. Users saw the options appear in
a window that never asked for them.

A DSH agent id IS its session id (host: "agent and its session share one id,
1:1, same axis"), and the host puts it on the frame as `agentId`, so ownership
is a plain id comparison.

- events.js: projectRemoteEventFrame() carries `agentId`; new exported
  waterfallBelongsToSession(agentId, sessionId). A frame without an owner
  (older host) keeps the previous behaviour.
- message-service.js: the `$events` handler ignores foreign approvals and
  questions with a debug line before prompting. Ignoring is not a rejection -
  the request stays pending for the client that owns it. `ready` / `cancel`
  are unchanged, and lastActivityAt now only counts this session's frames, so
  other sessions' traffic cannot mask a silent turn.
- tests: waterfall frame shape plus an ownership truth table.

Verified with a local mock host that pushes one foreign and one own waterfall
in the same run: the installed bridge prompted [["foreign"]] in the dialog and
answered it, while the fixed bridge prompts only this session's questions.
ai-bridge tests: 757 passed, 0 failed (dsh suite 115/115).
2026-09-17 16:52:13 +08:00
hesixian b6caf90d14 fix(dsh): echo the caller-declared question ids in AskUserQuestion answers
The AskUserQuestion dialog is shared with Claude, which matches answers by
question TEXT, so it keys its answer object by the question text and folds a
typed "Other" answer into the option labels. The DSH bridge forwarded those
keys as the answer `id` - but DSH requires the caller-declared `question.id`
("stable caller-declared id ... echoed in the answer"). The asking model
received a batch of ids it had never issued, could not tell which answer
belonged to which question, and read the reply as invalid; users answered in
the DSH Web UI instead.

- mapQuestionAnswers(): resolve each dialog answer by question text and emit
  the declared id; keep free text in `custom` (a custom answer replaces the
  choice on a single-select question, so `selected` stays empty) instead of
  appending it to the option labels, matching the shipped Web client.
- Report questions the dialog left unanswered as `{ id, selected: [] }` and
  keep a cancelled dialog as `{ answers: [] }`, so "skipped" and "no answer"
  stay distinguishable.
- Fall back to the dialog's own keys when no question matches (legacy host or
  a non-DSH payload), so the human's answer is never dropped.
- Both bridges (legacy /api/respond and modern $events/result) pass the
  questions through.

Verified against the DSH transcripts that exposed the bug (session bacd2ec0,
2026-09-17: ids prescheck/otherfix now come back instead of the question
texts), against a live dsh 0.1.5-rc.1 host, which accepts the plugin's
$events/result envelope as-is, and in the IDE (session-2754c72b: a cc-gui
answer returns {"id":"abc_test", ...}). ai-bridge tests: 756 passed, 0 failed
(dsh suite 114/114).

Fixes #1846
2026-09-17 15:18:24 +08:00
朱昆鹏 101de2d2d8 Merge pull request #1763 from Mrlihao/feature/v0.5.6
feat(claude) Claude 增加国产厂商coding plan用量查询
2026-09-04 21:54:08 +08:00
zhukunpenglinyutong 1bd55ef153 fix: unify permission-mode normalization and dedupe runtime mode transitions
- PermissionModeHandler: read the raw stored mode in handleGetMode and let
  normalizeModeForCurrentProvider apply the legacy autoEdit alias and
  per-provider fallbacks, so omp read and write paths map the same stored
  value to the same effective mode.
- persistent-query-service: delegate setPermissionModePersistent transitions
  to applyPermissionModeToRuntime after the epoch guard, removing the
  duplicated Full Auto rebuild-sentinel and SDK-switch logic; hook,
  applyDynamicControls, and daemon paths now share one rule set.
- docs: record native auto mode's known limitations (upstream claude-sonnet
  classifier dependency; repository-level allow rules apply before the
  classifier, matching Claude Code semantics).
2026-09-04 21:26:08 +08:00
Mrlihao 53a6cfee55 feat(claude): pluggable relay usage vendors for plan usage queries
- Introduce a provider.claude.usage package with a RelayUsageVendor SPI
  (host/path matching + probe), an ordered vendor registry, a shared
  TTL/stale cache keyed by vendor + endpoint + credential, a pooled
  HTTP transport with a test seam, and shared capacity-payload builders
- Migrate the existing z.ai/bigmodel.cn quota probe to ZaiUsageVendor
  with unchanged behavior; ClaudePlanUsageService stays the facade and
  still falls back to the cached SDK rate_limit snapshot
- Add MiniMaxUsageVendor (coding_plan/remains endpoint, remaining-to-
  used percent conversion, per-model entry selection with general
  fallback, weekly_status gating) and KimiCodingUsageVendor
  (api.kimi.com/coding /v1/usages, duration-based 5h/7d window
  classification, remaining/used compatible parsing)
- Cover each vendor with parsing fixtures, host identification
  (including look-alike negatives), cache TTL/stale and credential
  fallback tests; the webview payload contract is unchanged, so no
  frontend change is needed
2026-09-03 12:57:19 +08:00
Gadfly ae562df899 feat: add native auto-approval modes for Claude and Codex
Claude Code and Codex CLI both shipped classifier-driven auto-approval
modes. Expose them as a new unified "auto" permission mode, distinct
from the existing unrestricted bypassPermissions (now labeled
"Full Auto" in the UI).

Claude (Agent SDK >= 0.3.182):
- Map unified "auto" to permissionMode "auto" and let the SDK's
  classifier-driven flow decide approvals; the PreToolUse hook yields
  to the SDK in auto mode instead of forcing a manual prompt.
- Live-switch via query.setPermissionMode(); when the SDK rejects a
  live switch, keep the previous mode instead of committing a state
  the runtime refused.
- Entering/leaving Full Auto rewrites the runtime signature to a
  rebuild sentinel because allowDangerouslySkipPermissions is frozen
  at spawn; acquireRuntime then disposes and recreates the runtime.
- Guard setPermissionModePersistent with the runtime session epoch so
  stale requests from dead tabs cannot mutate the live runtime.

Codex (SDK/CLI >= 0.146.0):
- Inject approvals_reviewer="auto_review" via CodexOptions.config
  before constructing the Codex client, with approvalPolicy on-request
  and sandboxMode workspace-write; external env overrides cannot
  weaken the forced native-auto settings.
- Send approvals_reviewer="user" in every non-auto mode so resumed
  threads do not inherit a previous auto_review configuration.
- Suppress the plugin's own approval bridge for item.started and
  file_change events in auto mode; those events arrive after the
  native reviewer has already decided.
- Probe the installed SDK version before enabling auto and surface a
  clear error when it is below the verified floor.

Host layers:
- Normalize modes per provider in Java and webview (auto only for
  claude/codex; legacy autoEdit migrates to acceptEdits, or default on
  omp); reject unknown mode strings in SessionState.
- Gate the webview mode selector on the Codex SDK capability probe and
  reset a persisted auto selection when the SDK is too old.
- Add "auto" to the Plan Approval dialog, status bar widget, and all
  Java/webview locale bundles; rename the bypassPermissions label to
  "Full Auto".

Known limitation: Claude's auto mode depends on the upstream API
serving a claude-sonnet model for the safety classifier. When no
sonnet model is available (e.g. third-party relay endpoints), tool
calls that require classification fail with a retryable error while
read-only operations keep working.

Design doc: docs/feat/native-auto-approval-mode.md
2026-09-02 10:51:11 +08:00
toxehandClaude fb0d146816 docs: plan-usage mockup SVGs for the PR description
- claude-plan-usage-overview.svg: the chat input area with the usage
  bar's location highlighted in the ContextBar right tool cluster.
- claude-plan-usage-states.svg: the three pace states (green/yellow/red).
- claude-plan-usage-windows.svg: window switching + worst-window dot.

Vector mockups drawn from the component's exact CSS colors and geometry.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-18 07:17:09 -04:00
lijianhong 4ab851f780 fix(webview): publish restored history through OSR frame fences
Problem and evidence:

Multi-project startup could restore complete history state and React DOM while the first visible Remote JCEF OSR surface kept a blank or partial backing image. Hover repaired only locally damaged regions, while a real resize or tab remap restored the full viewport without another history query, message update, reload, or browser recreation. The data path was therefore correct; the missing completion boundary was publication of a current full frame through Chromium, CefRenderHandler, the JetBrains backing image, and Swing.

DOM and bridge protocol:

Preserve historyLoadComplete calls that arrive before React callback registration, including explicit zero-message history. Emit history_dom_committed from a layout effect with a monotonic content revision so the signal means only that the restored message DOM committed. Bind Java handling to the owning JBCefBrowser, CefBrowser, page generation, frontend-ready epoch, and content revision; reject stale callbacks without treating rAF, timers, load completion, or executeJavaScript submission as rendered pixels.

OSR handler integration and compatibility:

Wrap the JetBrains default JBCefOSRHandlerFactory rather than replacing its component, input, IME, HiDPI, shared-memory, or disposal behavior. Install the wrapper whenever supplied because Remote JCEF may force OSR after the requested rendering mode is selected. Fail closed if a wrapped Remote browser cannot be constructed. Discover CefNativeRenderHandler reflectively so the same binary loads on IDEA 2023.3, 2024.1, 2024.3, and 2025.2. Forward the final Remote non-popup frame with dirtyRectsCount zero and the classic OSR frame with a full-viewport rectangle; pass popup and unrelated frames through unchanged.

Publication fence and ownership:

Add SurfaceFrameFence with latest pending request, one active attempt, and a published watermark. A request carries browser identities, page generation, ready epoch, content revision, request serial, and attempt id. Exact phase-applied acknowledgments open the frame gates: the first matching OnPaint drains stale in-flight work, phase B restores the damage source, and only the second matching OnPaint is forwarded as a full frame. Completion advances the watermark only after the default handler receives that frame and the current Swing surface is painted.

Keep request serial and attempt ownership separate. Timeout releases only its exact attempt, retains the logical pending request, and never loops by itself. A newer pending request receives a guarded handoff; late frames, acknowledgments, timeout callbacks, or paint tasks from A cannot complete B, cancel B's timeout, or clear the same request after it is re-armed with a new attempt id.

Damage and activation behavior:

Generate the two required Chromium damage frames with an alternating two-pixel raster sentinel outside the React root. Restore the transparent baseline on completion or cancellation and coordinate ordinary repaint requests around the strict pulse. The publication path never changes app zoom, font scale, scroll position, or React layout.

Create frontend-ready revision zero even while hidden, but arm it only when the real native surface is showing, displayable, and has valid bounds. A new history commit supersedes older content revisions. Tab activation and window showing wake existing unpublished work; once content is published, ordinary OSR activation only presents the cached JetBrains backing image and does not create a serial or manufacture Chromium damage. Ready loss, generation changes, browser replacement, and disposal invalidate pending, active, published, timeout, and frontend pulse ownership together. Windowed JCEF keeps its existing bounds and repaint path.

Scope and relationship:

Build on the preceding hidden-tab lifecycle fix so inactive pages retain work without running bridge retry or watchdog recovery loops. Do not call loadHTML, reload, or recreate as part of surface publication, consume watchdog recovery budget, or change provider, model, context-usage, and session routing behavior. The daemon heartbeat restart burst observed after system sleep is independent and remains tracked by issue 1601.

Validation:

- Full Gradle test suite and checkstyleMain passed after the squash.
- WebView production TypeScript and Vite build passed.
- Frontend suite passed 127 files and 1091 tests, including TypeScript test checking.
- git diff --check passed with no generated-file pollution.
- R18 passed repeated IDEA 2025.2 multi-project restored startups without blank first tabs or visible tab-switch layout jitter.
- Sleep/wake validation retained a timed-out publication and successfully re-armed the same serial with a new attempt after activation, without a WebView reload/recreate storm.

Refs #1592
2026-08-07 10:46:13 +08:00
朱昆鹏 f3c828627b Merge pull request #1417 from moritzfl/opencode-implementation-plan
docs(opencode): draft documents for opencode implementation
2026-07-28 18:21:04 +08:00
moritz f61400bcfe docs(opencode): draft documents for opencode implementation 2026-07-02 21:38:37 +02:00
Miguel Angelo Fernández IglesiasandClaude Opus 4.8 866469cde3 fix(mcp): address maintainer security review
- High: render marketplace links only for http(s) schemes with
  target=_blank/noopener — blocks javascript: DOM-XSS in the webview.
- Restrict registry-provided command to an allowlist of known runners;
  unknown runners are flagged unverified and risky install options show a
  prominent warning banner before adding.
- Trust the 'official' badge only from the outer registry _meta and only
  when it carries structured metadata (not mere key presence).
- Cap HTTP response bodies at 10 MB to prevent memory-exhaustion DoS.
- Send GITHUB_TOKEN only to an exact GitHub host allowlist.
- Copilot import preview now shows the full spec (env/headers included).
- Translate docs/feat/mcp-marketplace.md to English.
- Add McpMarketplaceHttpClientTest and allowlist/official mapper tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 04:35:13 +02:00
Miguel Angelo Fernández IglesiasandClaude Opus 4.8 39e168eb06 fix(mcp): address Copilot review feedback
- Only send GITHUB_TOKEN to GitHub hosts to avoid leaking it to third-party
  registries (McpMarketplaceHttpClient).
- Wrap marketplace search request parsing in the async try/catch so malformed
  content yields a structured error instead of failing the handler.
- Drop the redundant on-mount marketplace search; the debounced effect performs
  the initial (persisted-source) load.
- Compute the import preview summary once per item.
- Narrow McpInstallOption.type to the known transports.
- Restore gradlew.bat to the upstream version (autocrlf artifact).
- Update docs/feat/mcp-marketplace.md to the shipped state.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 04:00:50 +02:00
Miguel Angelo Fernández Iglesias f7c3e58ef0 feat(mcp): enhance MCP Marketplace integration with initial patch implementation and UI dialog 2026-06-15 02:46:30 +02:00
Miguel Angelo Fernández Iglesias 751e0f2212 feat(mcp): add initial documentation for MCP Marketplace integration 2026-06-15 02:45:19 +02:00
Gadflyandzhuzhihang 7462a91544 feat: integrate Claude Code Task tracking API with agent group visualization
This commit implements comprehensive support for the new structured Task management
API (TaskCreate/TaskUpdate/TaskGet/TaskList) introduced in Claude Code SDK, with
enhanced agent workflow visualization through a collapsible group UI.

## Core Implementation

### 1. Tool Constants & Classification (toolConstants.ts)
- Add TASK_MANAGE_TOOL_NAMES set: taskcreate/taskupdate/taskget/tasklist
- Add AGENT_TOOL_NAMES set: task/agent/spawn_agent
- Enable unified tool name normalization for agent-related tools

### 2. AgentGroupBlock Component
A collapsible visualization component for agent/task tool invocations:
- **State Management**: Persist expand/collapse state via expandedState utility
- **Metadata Display**: Show agent type, description (truncated to 120 chars), completion status
- **Subagent Integration**: Load and render subagent conversation history on expansion
- **Statistics**: Display execution metrics (totalDurationMs/totalTokens/toolUseCount)
- **Nested Content**: Render absorbed following tool_use blocks within the group
- **Auto-refresh**: Poll subagent session every 2s during streaming

### 3. Task Extraction Logic (todoToolNormalization.ts)
Implement extractAccumulatedTasks() with two-pass algorithm:

**Pass 1 - Task ID Resolution**:
- Scan user tool_result messages to extract real numeric task IDs
- Primary source: raw.toolUseResult.task.id (from SDK metadata)
- Fallback: Parse task ID from content text
- Build tool_use_id → taskId mapping for subsequent resolution

**Pass 2 - Task Accumulation**:
- Process TaskCreate/TaskUpdate blocks in assistant messages
- Resolve real task IDs using the mapping from Pass 1
- Normalize to TodoItem format with: id/content/status/blockedBy
- Support both subject (title) and description fields
- Deduplicate by task ID (later TaskUpdate overwrites earlier TaskCreate)

### 4. MessageItem Grouping Logic (MessageItem.tsx)
Dynamic agent_group formation with block absorption:

**Detection**:
- Identify agent tool blocks (AGENT_TOOL_NAMES) as group anchors
- TaskCreate/TaskUpdate blocks without accumulated tasks also form agent groups

**Absorption Rules**:
- Absorb subsequent tool_use blocks until hitting:
  * Another agent/task tool (new group start)
  * Text content block (group boundary)
  * End of message
- Absorbed blocks render inside AgentGroupBlock's expanded content

**UI Hiding**:
- Hide standalone tool cards for Task management tools (similar to todowrite/update_plan)
- Only show accumulated tasks in StatusPanel TodoList

### 5. Expand/Collapse State Persistence (expandedState.ts, new)
- getPersistedExpanded(key): Read state from localStorage
- setPersistedExpanded(key, value): Persist state with fallback
- Key format: "agent-group-{toolUseId}" or "agent-group-{messageIndex}"

### 6. Type Extensions
- RawTodoItem: Add optional subject/description fields for TaskCreate/TaskUpdate
- Support both legacy (content/step/title) and new (subject/description) field names

### 7. Styling (task.less)
- .agent-group-container: Container for agent group blocks
- .agent-group-content: Nested content area with padding
- Reuse existing task header/expansion styles

## Integration Points

- **StatusPanel/TodoList**: Receive accumulated tasks from new Task API
- **SubagentContext**: Load subagent history for agent blocks
- **ContentBlockRenderer**: Conditionally render AgentGroupBlock vs standard tool blocks
- **useChatComputations**: Call extractAccumulatedTasks() for task aggregation

## Behavior Changes

- Task management tools (TaskCreate/TaskUpdate/TaskGet/TaskList) no longer show
  individual tool cards in the message stream
- Agent/task invocations now appear as collapsible groups with nested tool calls
- Task list in StatusPanel includes both legacy todowrite and new Task API tasks
- Expand/collapse state persists across page reloads

Refs: https://github.com/zhukunpenglinyutong/jetbrains-cc-gui/pull/1220
Co-authored-by: zhuzhihang <zhuzhihang@corp.netease.com>
2026-06-10 23:18:43 +08:00
XiangYunbin 2b75d8332c Merge tag 'v0.4.1' into feature-codex-env-setting 2026-05-07 17:05:36 +08:00
zkpaiminmin e40f530833 fix: absorb corrective snapshots in stream delta normalizer
Track each block's stream mode (incremental vs snapshot) per (kind, blockIndex).
Once a block is confirmed in cumulative-snapshot mode, silently absorb later
divergent payloads instead of treating them as fresh deltas. Prevents the
character-level concatenation duplication ("Let me implementNow I can see...")
seen with mimo-v2.5-pro / GLM / MiniMax when the model emits a corrective
rewrite mid-stream.

Also bump version to 0.4.1.
2026-05-06 09:11:48 +08:00
zkpaiminmin ef35c59bc3 fix: normalize cumulative stream deltas to prevent content duplication
Some Claude-compatible providers send cumulative snapshots in stream
deltas instead of incremental fragments. This causes the frontend to
display duplicated content as each delta repeats all prior text.

Add stream-delta-normalizer.js that tracks per-block content snapshots
and extracts only the novel suffix before forwarding to the UI layer.
2026-04-30 14:37:34 +08:00
zkpaiminmin f8a1db1e05 fix(webview): fix streaming reconcile race in messageSync and bump version to Alpha5
- Protect raw.message.content blocks (not just top-level .content string) in
  preserveStreamingAssistantContent to prevent ABCDE→ABC→ABCDEF flicker
- Add tests for the reconcile race fix in messageSync.test.ts
- Update streaming duplication post-mortem: document real root cause as
  frontend reconcile race (stage 2/3 rewritten), demote ReplayDeduplicator
  endsWith fix to irrelevant for current bug
- Bump version to 0.4.1-Alpha5
2026-04-29 18:15:18 +08:00
zkpaiminmin 0a3e5238fb fix: replace window callback overrides with subscriber registry for provider updates
Introduces runtimeProviderCapabilities.ts as a central subscriber registry
for provider-list and active-provider window callbacks. Multiple React
components previously raced to override the same window.updateProviders /
window.updateActiveProvider slots, producing non-deterministic teardown.
The registry routes each Java-bridge event to all live subscribers
regardless of mount order.

- webview: add runtimeProviderCapabilities.ts with subscribe/emit/install APIs
- webview: migrate useSettingsWindowCallbacks and RuntimeProviderSelect to the registry
- webview: call installRuntimeProviderDispatchers() once in main.tsx
- webview: fix SubagentList stale-closure in polling interval (use refs)
- java: add FontConfigService magic-number validation to reject non-font binaries
- java: add describePromptEnhancerConfig() for safe, compact provider logging
- java: improve OpenFileHandler path resolution and test coverage
- ai-bridge: export extractAppendedDelta; guard against null systemPrompt in Codex path
- ai-bridge: expand prompt-enhancer test suite (179 additions)
- tests: add SubagentHistoryServiceValidateIdTest, OpenFileHandlerTest
- i18n: add missing keys across all 10 locale files
2026-04-29 16:21:37 +08:00
zkpaiminmin b326a1a101 Preserve the streaming duplication repair context
Capture the Claude provider streaming duplication root-cause analysis, completed P0 mitigation evidence, and follow-up hardening plan so future work can continue from a durable record.

Constraint: User requested committing only the currently staged code

Constraint: Staged change is documentation-only

Rejected: Include additional cleanup or implementation edits | outside the requested staged commit

Confidence: high

Scope-risk: narrow

Reversibility: clean

Directive: Keep this record aligned with any later streaming deduplication phases

Tested: Inspected git diff --cached --stat and staged document contents

Not-tested: Code tests were not run because the staged change is documentation-only
2026-04-29 11:42:36 +08:00
XiangYunbin 5827eee205 Add codex provider extension environment var setting 2026-04-21 11:18:10 +08:00
zkpaiminmin 0ea542e5ef refactor(package): reorganize Java package structure by domain
Move classes from root package into domain-specific sub-packages:
- action/dev: OpenDevToolsAction
- action/editor: QuickFixWithClaudeAction, SendFilePathToInputAction, SendSelectionToTerminalAction
- action/tab: CreateNewTabAction, DetachTabAction, RenameTabAction
- action/vcs: GenerateCommitMessageAction
- ui/detached: DetachedChatFrame, DetachedWindowManager
- ui/toolwindow: ClaudeChatWindow, ClaudeSDKToolWindow, CodeSnippetManager
- i18n: ClaudeCodeGuiBundle
- permission: ToolInterceptor
- session: ClaudeSession, SessionLoadService
- settings: CodemossSettingsService
- skill: CodexSkillService, SkillService

Update all import references across handlers, providers, session and test files accordingly.
2026-03-22 20:38:34 +08:00
zkpaiminmin a05d54939e refactor: extract ClaudeSDKBridge into single-responsibility modules
Split the monolithic ClaudeSDKBridge (1600+ lines) into 12 focused classes:
- ClaudeBridgeUtils, ClaudeDaemonCoordinator, ClaudeDaemonRequestExecutor
- ClaudeJsonOutputExtractor, ClaudeLogSanitizer, ClaudeMcpQueryService
- ClaudeProcessInvoker, ClaudeQueryExecutor, ClaudeRequestParamsBuilder
- ClaudeRewindService, ClaudeSessionQueryService, ClaudeStreamAdapter

Add refactor verification test and implementation plan document.
2026-03-17 13:45:16 +08:00
zkpaiminmin 4386dd6ebd chore: rename project to CC GUI and bump version to 0.2.9
- Rename from "Claude Code GUI" to "CC GUI (originally Claude Code GUI)" to mitigate Claude trademark risks
- Update plugin ID from com.github.idea-claude-code-gui to com.github.jetbrains-long-gui
- Bump version from 0.2.8 to 0.2.9
- Update logo and icons to reduce locale-specific elements
- Update README (EN/ZH) with new name and security review policy
- Add MIT license badge to README
2026-03-15 12:46:15 +08:00
zkpaiminmin 8dcbcb4be3 refactor: split large handler and hook modules into focused files
Split ProviderHandler.java into ClaudeProviderOperations,
CodexProviderOperations, ModelProviderHandler, NodePathHandler,
PermissionModeHandler, ProviderImportExportSupport, and
ProviderOrderingService. Split SettingsHandler.java into
InputHistoryHandler, ProjectConfigHandler, SoundSettingsHandler,
and UsagePushService. Split useWindowCallbacks into windowCallbacks/
with registerCallbacks sub-modules. Extract settings hooks into
useSettingsBasicActions, useSettingsPageState, useSettingsThemeSync.
Add messageSync unit tests.
2026-03-13 01:06:00 +08:00
zkpaiminmin cd97b7cfeb chore: bump version to 0.2.8 and localize remote images
Replace remote CDN images with local assets for logo, payment QR codes,
and WeChat group QR code to improve reliability and reduce external
dependencies. Update CHANGELOG and What's New dialog for v0.2.8 release.
2026-03-12 19:34:14 +08:00
hpstream 66aee71d3f docs: add comprehensive manual testing checklist for project-level prompts 2026-03-07 10:06:22 +08:00