@gajae-code/coding-agent 0.16.3 → 0.16.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/dist/types/cli/args.d.ts +2 -2
  3. package/dist/types/cli/root-flags.d.ts +4 -2
  4. package/dist/types/cli.d.ts +1 -1
  5. package/dist/types/commands/launch.d.ts +1 -1
  6. package/dist/types/config/autorouting-tier-map.d.ts +3 -0
  7. package/dist/types/config/model-registry.d.ts +4 -0
  8. package/dist/types/config/model-resolver.d.ts +9 -0
  9. package/dist/types/config/settings-schema.d.ts +29 -1
  10. package/dist/types/discovery/claude-plugins.d.ts +3 -1
  11. package/dist/types/discovery/helpers.d.ts +2 -0
  12. package/dist/types/extensibility/gjc-plugins/mcp-policy.d.ts +16 -0
  13. package/dist/types/extensibility/gjc-plugins/paths.d.ts +2 -0
  14. package/dist/types/extensibility/runtime-skill-discovery.d.ts +1 -1
  15. package/dist/types/extensibility/shared-events.d.ts +1 -1
  16. package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
  17. package/dist/types/modes/components/assistant-message.d.ts +1 -2
  18. package/dist/types/modes/components/settings-selector.d.ts +6 -1
  19. package/dist/types/modes/components/status-line/command.d.ts +35 -0
  20. package/dist/types/modes/components/status-line/index.d.ts +1 -0
  21. package/dist/types/modes/components/status-line/types.d.ts +5 -0
  22. package/dist/types/modes/components/tool-status-header.d.ts +14 -0
  23. package/dist/types/modes/controllers/event-controller.d.ts +6 -0
  24. package/dist/types/modes/interactive-mode.d.ts +1 -0
  25. package/dist/types/modes/types.d.ts +1 -0
  26. package/dist/types/runtime-mcp/client.d.ts +9 -1
  27. package/dist/types/runtime-mcp/manager.d.ts +7 -1
  28. package/dist/types/runtime-mcp/pool.d.ts +22 -3
  29. package/dist/types/runtime-mcp/transports/stdio.d.ts +0 -4
  30. package/dist/types/runtime-mcp/types.d.ts +22 -0
  31. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +12 -0
  32. package/dist/types/sdk/bus/slack-live-provider.d.ts +6 -0
  33. package/dist/types/sdk/bus/slack-provider.d.ts +12 -0
  34. package/dist/types/sdk/host/session-runtime.d.ts +23 -0
  35. package/dist/types/sdk/session-api-key.d.ts +26 -0
  36. package/dist/types/sdk/transport/serve-cli.d.ts +1 -1
  37. package/dist/types/session/agent-session.d.ts +9 -0
  38. package/dist/types/setup/paseo/announce.d.ts +111 -0
  39. package/dist/types/setup/paseo/setup-deps.d.ts +2 -1
  40. package/dist/types/system-prompt.d.ts +2 -0
  41. package/dist/types/task/executor.d.ts +2 -1
  42. package/dist/types/tools/fetch.d.ts +7 -0
  43. package/dist/types/tools/index.d.ts +8 -0
  44. package/dist/types/tools/path-utils.d.ts +2 -0
  45. package/dist/types/tools/search.d.ts +6 -0
  46. package/package.json +7 -7
  47. package/scripts/capture-status-line-custom-editor-showcase.ts +151 -0
  48. package/scripts/generate-sdk-operation-inventory.ts +9 -0
  49. package/scripts/verify-status-line-custom-editor-showcase.ts +309 -0
  50. package/src/cli/args.ts +20 -9
  51. package/src/cli/root-flags.ts +5 -3
  52. package/src/config/autorouting-tier-map.ts +1 -0
  53. package/src/config/file-lock.ts +181 -17
  54. package/src/config/model-preset-registry.ts +5 -3
  55. package/src/config/model-profiles.ts +40 -0
  56. package/src/config/model-registry.ts +57 -11
  57. package/src/config/model-resolver.ts +48 -0
  58. package/src/config/settings-schema.ts +33 -1
  59. package/src/config/settings.ts +1 -0
  60. package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +11 -11
  61. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +13 -2
  62. package/src/discovery/builtin.ts +13 -4
  63. package/src/discovery/claude-plugins.ts +12 -4
  64. package/src/discovery/helpers.ts +10 -2
  65. package/src/extensibility/gjc-plugins/compiler.ts +208 -58
  66. package/src/extensibility/gjc-plugins/installer.ts +13 -12
  67. package/src/extensibility/gjc-plugins/mcp-policy.ts +81 -52
  68. package/src/extensibility/gjc-plugins/paths.ts +13 -0
  69. package/src/extensibility/gjc-plugins/runtime-adapters.ts +758 -16
  70. package/src/extensibility/runtime-skill-discovery.ts +77 -151
  71. package/src/extensibility/shared-events.ts +1 -1
  72. package/src/extensibility/skills.ts +44 -16
  73. package/src/gjc-runtime/repository-binding.ts +1 -1
  74. package/src/gjc-runtime/session-state-lock.ts +92 -2
  75. package/src/internal-urls/docs-index.generated.ts +7 -7
  76. package/src/main.ts +72 -34
  77. package/src/modes/DESIGN.md +54 -0
  78. package/src/modes/components/assistant-message.ts +22 -9
  79. package/src/modes/components/model-selector.ts +166 -33
  80. package/src/modes/components/settings-selector.ts +1075 -235
  81. package/src/modes/components/status-line/command.ts +190 -0
  82. package/src/modes/components/status-line/index.ts +1 -0
  83. package/src/modes/components/status-line/segments.ts +32 -5
  84. package/src/modes/components/status-line/types.ts +5 -0
  85. package/src/modes/components/tool-status-header.ts +393 -21
  86. package/src/modes/controllers/command-controller.ts +2 -0
  87. package/src/modes/controllers/event-controller.ts +148 -5
  88. package/src/modes/controllers/selector-controller.ts +21 -0
  89. package/src/modes/interactive-mode.ts +47 -1
  90. package/src/modes/types.ts +1 -0
  91. package/src/modes/utils/ui-helpers.ts +1 -0
  92. package/src/prompts/system/system-prompt.md +8 -0
  93. package/src/prompts/tools/search.md +2 -0
  94. package/src/runtime-mcp/client.ts +60 -17
  95. package/src/runtime-mcp/manager.ts +171 -14
  96. package/src/runtime-mcp/pool.test.ts +209 -0
  97. package/src/runtime-mcp/pool.ts +224 -23
  98. package/src/runtime-mcp/transports/stdio.ts +158 -24
  99. package/src/runtime-mcp/types.ts +24 -0
  100. package/src/sdk/broker/broker.ts +5 -4
  101. package/src/sdk/bus/chat-daemon-control.ts +1 -1
  102. package/src/sdk/bus/chat-daemon-runtime.ts +37 -1
  103. package/src/sdk/bus/slack-daemon.ts +92 -2
  104. package/src/sdk/bus/slack-live-provider.ts +12 -0
  105. package/src/sdk/bus/slack-provider.ts +5 -0
  106. package/src/sdk/cli/session-cli.ts +9 -6
  107. package/src/sdk/host/session-runtime.test.ts +2 -2
  108. package/src/sdk/host/session-runtime.ts +275 -43
  109. package/src/sdk/protocol/operation-inventory.generated.json +66 -0
  110. package/src/sdk/session-api-key.ts +94 -0
  111. package/src/sdk/session.ts +73 -29
  112. package/src/sdk/transport/serve-cli.ts +3 -3
  113. package/src/session/agent-session.ts +123 -38
  114. package/src/session/contribution-prep.ts +214 -21
  115. package/src/setup/paseo/announce.ts +450 -0
  116. package/src/setup/paseo/setup-deps.ts +15 -3
  117. package/src/slash-commands/builtin-registry.ts +1 -0
  118. package/src/system-prompt.ts +4 -0
  119. package/src/task/executor.ts +2 -1
  120. package/src/task/index.ts +17 -4
  121. package/src/tools/bash.ts +35 -8
  122. package/src/tools/cron.ts +1 -1
  123. package/src/tools/fetch.ts +29 -1
  124. package/src/tools/index.ts +8 -0
  125. package/src/tools/job.ts +8 -2
  126. package/src/tools/monitor.ts +8 -2
  127. package/src/tools/path-utils.ts +7 -0
  128. package/src/tools/search.ts +116 -58
  129. package/src/tools/skill.ts +22 -2
  130. package/src/tools/subagent.ts +3 -1
  131. package/src/tools/tool-catalog.generated.ts +8 -1
  132. package/src/web/insane/bridge.ts +113 -23
  133. package/src/web/search/providers/perplexity.ts +102 -41
package/CHANGELOG.md CHANGED
@@ -2,6 +2,65 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.16.4] - 2026-09-05
6
+ ### Added
7
+
8
+ - Added selectable `astra-lite`, `astra-default`, and `astra-heavy` CODEX presets with `ASTRA-` labels, plus `astra-fable` and `astra-fable-opus` cross-family review combinations. Existing presets and automatic provider recommendations remain unchanged.
9
+ - An interactive `gjc` now shows up inside [Paseo](https://paseo.sh) by itself, controllable from the desktop and mobile apps, instead of only being reachable when Paseo started it. Every terminal session already registered its SDK endpoint with the broker, and GJC's ACP surface already resolves a `live` index entry straight to the running host — a `session/load` attaches to it rather than resuming a second copy — so the only thing missing was telling the Paseo daemon the session exists. That is now done at interactive startup with `paseo import --provider <key> --cwd <cwd> <session-id>`, which makes the terminal session and the Paseo agent the same live session rather than two transcripts. The announcement is gated so it costs nothing when it cannot apply: an absent `$PASEO_HOME/config.json` (default `~/.paseo/config.json`), no enabled GJC ACP provider entry, no `paseo` on PATH, a daemon that is not listening, or a session the broker does not yet report as live each stop it before anything is spawned. The daemon check is a plain socket probe rather than a CLI invocation because the Paseo CLI blocks indefinitely when its daemon is down (measured: no output and no exit after two minutes), and the liveness check exists because importing a not-yet-registered id would make `session/load` fork a second host for a session that is already running. While the daemon is merely not up yet, the probe retries every 30 seconds for approximately ten minutes on unref'd timers, so launching Paseo after the terminal still works; the loaded opt-in can cancel its own pending or active announcement, changes made by another process apply on the next launch, and Paseo's own duplicate-import refusal is read as success. Interactive-only by construction — a `gjc acp` provider process never builds the interactive mode, so an imported session cannot announce itself back. Create-only by construction too: GJC adds an entry and never deletes, archives, or rewrites one, so it can never remove an agent you still wanted. The consequence is yours to manage — every interactive start gets a fresh session id (including `gjc -c`), so each launch adds one row, and ending a session leaves its row listed as `idle` until a send fails with `SDK session attachment is stale` and Paseo marks it `error`; prune with `paseo delete <agent-id>`. Opt-in: the new operator-owned `paseo.autoImport` setting is **off by default**, so a repository cannot enable it and an installation that never asks for it never reads a Paseo file, probes a socket, or spawns the CLI; enable it with `gjc config set paseo.autoImport true` (Settings → Interaction → "Announce Sessions to Paseo"). See [`docs/terminal-app-integrations.md`](../../docs/terminal-app-integrations.md#announcing-interactive-sessions).
10
+ - Corrected a stale claim in [`docs/external-control-readiness.md`](../../docs/external-control-readiness.md): interactive `gjc` sessions *are* broker-registered and *are* listed by ACP clients, and an ACP `session/load` against a live entry attaches to the running host instead of resuming a copy.
11
+ - An externally submitted prompt against a session on the SDK-only host runtime no longer hangs forever after its turn has already finished. That runtime published the lifecycle boundary as a bare `{ type, sessionId }` frame: it computed each ended invocation's `commandId`/`turnId` for durable reconciliation and then discarded them at publication, and it never carried a normalized outcome at all — only the `agent_failed` diagnostic was published per invocation with its correlation. An ACP client matches a terminal against the correlation it was acknowledged under and requires the outcome, so a real `agent_end` was rejected as `acp_prompt_terminal_dropped` / `incomplete_correlation`, `session/prompt` never settled, and the client sat in `working` until the 30-minute prompt deadline (reproduced against Paseo 0.6.1 attached to a live interactive session: the terminal rendered the full answer while Paseo showed the agent `running` indefinitely). An owned `agent_end` is now published once per ended invocation carrying that invocation's correlation and a normalized `stopped` outcome, mirroring the existing `agent_failed` shape. Frames that terminalize nothing are unchanged and stay uncorrelated: `agent_start`, a host-originated run with no owning invocation (autonomous continuation, cron, monitor), and a continuing maintenance checkpoint (`pruned`/`compacted`/`promoted`) — which is published but is deliberately not a terminal boundary, so stamping it would settle a client's prompt mid-turn. The ACP ownership gate is untouched.
12
+ - An ACP client attached to a *live interactive* session now receives the turn it submitted: assistant text, thinking, and tool calls stream as they happen instead of arriving as an empty completed turn. The SDK-only host runtime subscribed to lifecycle and watchdog events only — its two `tool_execution_*` handlers just renewed a deadline watchdog and it never subscribed to `message_update`/`message_end` at all — so it published no agent wire events and an attached client could drive the session and watch the turn settle without receiving a single word of the answer (measured against Paseo 0.6.1: `paseo logs` showed the prompt and nothing else, with `--filter tools` and `--filter text` both reporting no activity). It now streams the same five events the notifications runtime does (`message_update`, `message_end`, `tool_execution_start`/`update`/`end`), built with the same shared `toAgentWireEventPayload` producer so the wire shape cannot drift from what ACP maps. Delivery matches the notifications runtime too: one frame per owning invocation, sent directly to the connection that submitted the turn and carrying that invocation's correlation. It deliberately does **not** go through the session event ring — that ring is bounded by frame count with no byte ceiling, so streaming high-frequency chunks through it would evict the lifecycle events clients depend on (including the `agent_end` that settles their prompt) and would broadcast a turn's content to every authenticated subscriber rather than the one that asked for it. A turn nobody submitted over the SDK (an ordinary terminal prompt, an autonomous continuation, cron, monitor) has no owning connection and streams nothing.
13
+ - `gjc` no longer reports an error at every interactive launch when the Paseo daemon requires a password. `paseo import` refuses with `Cannot connect to daemon ...: Password required`, which the socket probe cannot anticipate because the TCP connect succeeds; that refusal is now read as a quiet skip instead of a failed announcement. GJC has no credential setting and reads no Paseo credential file: `paseo import` runs with the session's own environment, so an exported `PASEO_PASSWORD` is used and an absent one simply skips.
14
+
15
+ - Status-line settings now include a draft-local spatial custom editor with exact-slot keyboard reordering, hidden-segment palette management, command text configuration, persisted Confirm/Exit semantics, live multi-row preview compatibility, narrow/Unicode rendering, and deterministic visual evidence.
16
+ - Added opt-in `reasoningLanguage: english` guidance for technical work while preserving the user's requested response language; the default remains off.
17
+
18
+ ### Changed
19
+
20
+ - Interactive assistant `text_delta` presentation now coalesces eligible updates into the latest message projection before the existing TUI frame while preserving ordered event processing, immediate non-text updates, and authoritative final output. Session/transcript replacement and disposal cancel stale presentation; temporary TUI stop/start rearms current live text before the first restarted frame without invalidating live historical image callbacks.
21
+
22
+ ### Fixed
23
+
24
+ - Credential replacement lookups now propagate the owning request's cancellation through scoped and allowed unscoped retries, preventing aborted turns from continuing OAuth preparation or selecting another key.
25
+ - Removing the committed status-line command segment or clearing its trusted command now cancels the running process and clears stale output; draft-only previews remain side-effect-free.
26
+ - Slack inbound acknowledgment reactions now use bounded, abortable, tracked provider work that drains on shutdown or attachment retirement without delaying accepted turns; rejected or timed-out reactions emit sanitized diagnostics.
27
+ - Task repository bindings now accept explicit `relativeSubdir: "."` as the already-bound worktree root, avoiding unnecessary launch retries while retaining traversal, absolute-path, symlink-escape, and sibling-repository rejection.
28
+ - Blank optional task output schemas now inherit the configured agent/session schema instead of failing successful subagents at completion; malformed nonempty schemas and required-field validation remain fail-closed.
29
+ - The read-URL cache is now bounded (FIFO, 64 keys), so long-lived TUI and SDK-host processes no longer retain every fetched page's full output and image payload for the process lifetime; an evicted entry simply refetches on the next read, and unpersisted sessions sharing a working directory remain isolated by session identity.
30
+ - The insane-search web bridge now kills the engine's whole process group instead of only the `python3` process. `killChild` promised a group kill but the engine was not spawned detached, so when the bridge timeout fired mid-flight (25s default vs the engine's internal 90s playwright budget), `node` and headless `chromium` children survived as orphans. The engine now leads its own POSIX process group and receives group-wide SIGTERM→SIGKILL escalation even when the group leader exits during the grace period, with a direct child-kill fallback on Windows.
31
+ - Contribution-prep outbound artifacts now redact complete AWS credentials, including AKIA/ASIA access-key IDs and SecretAccessKey/SessionToken values in shell-style and escaped JSON forms, while preserving structured output and existing GitHub, Slack, authorization-header, and cookie redaction.
32
+ - Model preset registry URL and disable overrides now resolve only from explicitly inherited or user-owned environment sources, so a checkout `.env` cannot suppress updates or redirect signed-registry polling while dependency injection, HTTPS validation, signatures, ETags, cache, and offline behavior remain unchanged (#5300).
33
+ - OpenCode Go's provider conversation identity now remains distinct from generic cache affinity across normal turns and maintenance calls, so the required session header reuses the session manager's opaque lifecycle without accepting auth-gateway prompt-derived cache keys (#5295).
34
+ - Perplexity web search now clamps upstream search breadth to the API's 3–100 contract, retries one structurally empty completion, rejects malformed or ungrounded success payloads through the provider fallback path, and preserves valid grounded responses.
35
+ - Architect/task subagents now retry API-key lookup without the parent session id after a scoped miss, so broker OAuth that works for `gjc -p --no-session` is not thrown away as `Agent run failed` / 0 tokens (#5081 follow-up). Failures still throw `provider_unavailable` without leaking the token.
36
+ - Python work that completes after strict session disposal now returns its result without attempting to append to the closed session transcript.
37
+ - SDK-hosted workflow tools now retain the logical session id for ask, skill, deep-interview, and ultragoal state paths while job, monitor, bash, cron, task, and subagent ownership routes through a separate opaque async endpoint key. Explicit provider session identities no longer create encoded duplicate workflow trees or redirect endpoint-owned work to another live session.
38
+ - Explicit root startup `--thinking off` and `--thinking=off` now override a configured higher startup default while leaving the provider `Effort` catalog unchanged.
39
+ - Skills installed from marketplace plugins are now enumerated into sessions instead of only resolving by exact name. `loadSkills` asked the `native` provider alone, so every installed plugin skill was absent from `/` autocomplete and from the `skill` tool's `Available:` list while `gjc skill list` reported it and the discovery fallback still loaded it — 46 installed skills presented as 5. The already-registered marketplace provider is now loaded alongside `native`, keeping `<plugin>:<skill>` namespacing and per-item scope trust.
40
+ - File-content search now has a call-wide timeout (`timeout`, default 5 seconds, range 0.5–60) that is forwarded through internal-URL resolution and native grep together with cancellation. Native scans poll cancellation around each bounded file, and the tool joins cancellation cleanup before returning instead of leaving scope resolution, archive scratch, or grep workers running after a timeout. Timeout failures tell callers to narrow the scope or explicitly increase the budget, while user cancellation remains a distinct tool abort.
41
+ - `restart:sdk-broker -- --close-session-hosts` now continues replacing the broker when its pre-restart session-host listing fails, reports the partial teardown with exit code 1, tolerates another authenticated restart caller retiring the same exact broker identity, and catches other top-level failures instead of emitting an unhandled-rejection crash record.
42
+ - `install:dev` now builds the workspace native addon before linking the source CLI, preventing fresh or cleaned development checkouts from failing startup with a missing or stale addon. The installer also supports the local `--dev` binary shortcut.
43
+ - Plain and explicit-model launches now refresh a missing provider's cached dynamic catalog before resolving a qualified startup selector, so configured models such as `glm-zcode/glm-5.3` no longer open in `no-model` state while preserving cache-only startup for already available models.
44
+ - The explicit thinking-choice gate for xAI models now derives from the parsed grok generation (4.5+) shared with `@gajae-code/ai`, instead of the exact ids `grok-4.5`/`grok-4.6`. A future grok release failed the id list, so `supportsReasoningEffort` stayed `false` and the user's thinking level was silently dropped from requests; reseller-hosted grok routes (OpenRouter & co.) keep their existing audited-transport behavior.
45
+
46
+ - The status-line usage segment now paints only the active model's provider, so switching to Grok no longer keeps a stale Claude 5h/7d pair. Canonical Grok Build reports render only their authoritative weekly window, while monthly credits are omitted instead of being mislabeled as `7d`.
47
+
48
+ - Bundled plugin MCP launchers now execute Node `.mjs` entrypoints on Linux from startup-authenticated interpreter bytes and a complete copied-file snapshot. Runtime options cannot precede the entrypoint, path-qualified/shebang commands fail closed, unexpected post-install files quarantine the bundle, and canonical registry identity plus the complete copied-file manifest are rebound before every spawn. Runtime captures the interpreter and authenticated bundle files through bounded stable handles into a unique owner-only launch capsule; the Node loader returns authenticated captured module bytes while preserving file-URL relative imports and blocking package/CommonJS/native escapes. Concurrent connections use separate authority. Capsule cleanup failures retain ownership and fence reconnect until cleanup succeeds. Bun, macOS, and Windows bundled stdio launch fail closed pending equivalent loader and owner/process-tree authority; capsules do not provide hostile-same-UID process isolation.
49
+
50
+ - Moving the `/model` preset cursor now reuses the authentication snapshot produced by catalog and credential refreshes instead of resolving every profile against the full model catalog on each Up/Down keypress; auth-dependent preset actions remain blocked until the initial static refresh and the availability snapshot are complete.
51
+ - Bundled Grok Build models now explicitly declare `reasoning_effort` support only for catalog-supported models, so `grok-build/grok-4.6:xhigh` reaches the Responses request while unsupported Grok models remain fail-closed. (#5264)
52
+ - Mid-run OpenAI remote-compaction fallback failures now stop before another provider request, surface the local summarization error through ACP/SDK terminal handling, and leave the uncompacted context unsubmitted. Successful local fallback still commits the compaction and resumes normally.
53
+ - Opening `/model` now renders the preset landing before constructing the full model browser catalog. Canonical search indexing, sorting, and the redundant offline registry refresh are deferred until the user searches or chooses a browse action, while the lightweight preset-availability check remains immediate and scoped or direct-search selectors still load immediately.
54
+ - Slack lean notifications now publish only finalized assistant answers and actionable states instead of the internal lifecycle, identity, and activity frame stream. Final answer delivery uses the message reference as a durable publication identity, so repeated unpositioned SDK frames no longer post duplicate replies; accepted inbound Slack messages receive a 👀 reaction while GJC awaits the agent's answer.
55
+ - `/model` provider-tab refreshes now reuse the already loaded static catalog and update only the selected provider's discovery state, avoiding repeated signed preset registry work while retaining full-catalog refresh behavior for static configuration changes.
56
+ - Added the `command` status-line segment for user-produced HUD content. It runs
57
+ configured user/global shell commands in the background with scheduled cached
58
+ refreshes, bounded timeout/output, ANSI sanitization, placeholder degradation,
59
+ disposal cancellation, and custom-editor configuration while preserving
60
+ synchronous TUI rendering; project-scoped settings cannot trigger execution.
61
+
62
+ - Business/Enterprise/Team ChatGPT accounts can bind GPT-5.6 Sol again. The Codex entitlement preflight treated only `plan_type` values containing `"pro"` as eligible, so an `openai-codex` OAuth account on a Business/Enterprise/Team plan was rejected at model-binding/subagent setup time with a spurious entitlement error even though the backend accepts the request. Exact Pro/Business/Enterprise/Team tiers are now recognized as entitled, Plus/Free remain rejected, and unfamiliar plan names are deferred to the provider rather than guessed locally.
63
+
5
64
  ## [0.16.3] - 2026-09-04
6
65
 
7
66
  ## [0.16.2] - 2026-09-04
@@ -1,4 +1,4 @@
1
- import { type Effort } from "@gajae-code/ai/core";
1
+ import { type RootThinkingLevel } from "./root-flags";
2
2
  export type Mode = "text" | "json" | "acp";
3
3
  export type ParseArgsAuthority = "local" | "acp" | "deferred";
4
4
  export interface Args {
@@ -21,7 +21,7 @@ export interface Args {
21
21
  mcpConfig?: string;
22
22
  /** Opt a standalone session out of conventional MCP autoload (mutually exclusive with --mcp-config). */
23
23
  noMcp?: boolean;
24
- thinking?: Effort;
24
+ thinking?: RootThinkingLevel;
25
25
  continue?: boolean;
26
26
  resume?: string | true;
27
27
  help?: boolean;
@@ -1,4 +1,6 @@
1
1
  import { type FlagDescriptor } from "@gajae-code/utils/cli";
2
+ export declare const ROOT_THINKING_LEVELS: readonly ["off", ...import("@gajae-code/ai").Effort[]];
3
+ export type RootThinkingLevel = (typeof ROOT_THINKING_LEVELS)[number];
2
4
  /** Public launch flags shared by root help, completion, and the launch command. */
3
5
  export declare const ROOT_LAUNCH_FLAGS: {
4
6
  model: FlagDescriptor<"string"> & {
@@ -104,7 +106,7 @@ export declare const ROOT_LAUNCH_FLAGS: {
104
106
  };
105
107
  thinking: FlagDescriptor<"string"> & {
106
108
  description: string;
107
- options: readonly ["minimal", "low", "medium", "high", "xhigh", "max"];
109
+ options: readonly ["off", ...import("@gajae-code/ai").Effort[]];
108
110
  };
109
111
  "no-rules": FlagDescriptor<"boolean"> & {
110
112
  description: string;
@@ -239,7 +241,7 @@ export declare const LAUNCH_PARSE_FLAGS: {
239
241
  };
240
242
  thinking: FlagDescriptor<"string"> & {
241
243
  description: string;
242
- options: readonly ["minimal", "low", "medium", "high", "xhigh", "max"];
244
+ options: readonly ["off", ...import("@gajae-code/ai").Effort[]];
243
245
  };
244
246
  "no-rules": FlagDescriptor<"boolean"> & {
245
247
  description: string;
@@ -127,7 +127,7 @@ export declare class RootHelpCommand extends Command {
127
127
  };
128
128
  thinking: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
129
129
  description: string;
130
- options: readonly ["minimal", "low", "medium", "high", "xhigh", "max"];
130
+ options: readonly ["off", ...import("@gajae-code/ai").Effort[]];
131
131
  };
132
132
  "no-rules": import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
133
133
  description: string;
@@ -120,7 +120,7 @@ export default class Index extends Command {
120
120
  };
121
121
  thinking: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
122
122
  description: string;
123
- options: readonly ["minimal", "low", "medium", "high", "xhigh", "max"];
123
+ options: readonly ["off", ...import("@gajae-code/ai").Effort[]];
124
124
  };
125
125
  "no-rules": import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
126
126
  description: string;
@@ -781,6 +781,9 @@ export declare const TIER_MAP_SKIP_LIST: {
781
781
  readonly "nvidia/upstage/solar-10.7b-instruct": {
782
782
  readonly rationale: "post-rebase catalog addition from dev; not yet curated";
783
783
  };
784
+ readonly "openai-codex/gpt-6-astra": {
785
+ readonly rationale: "GPT-6 Astra catalog addition (2026-09-03 release); not yet curated";
786
+ };
784
787
  readonly "openai-codex/gpt-daybreak-blue-latest": {
785
788
  readonly rationale: "post-rebase catalog addition from dev; not yet curated";
786
789
  };
@@ -368,6 +368,10 @@ export declare class ModelRegistry {
368
368
  /**
369
369
  * Reload models from disk (embedded + accepted registry + custom from models.yml).
370
370
  */
371
+ refreshStatic(): Promise<void>;
372
+ /**
373
+ * Reload models from disk and refresh runtime provider discovery state.
374
+ */
371
375
  refresh(strategy?: ModelRefreshStrategy): Promise<void>;
372
376
  refreshInBackground(strategy?: ModelRefreshStrategy): void;
373
377
  refreshProvider(providerId: string, strategy?: ModelRefreshStrategy): Promise<void>;
@@ -33,6 +33,15 @@ export declare function parseModelString(modelStr: string): {
33
33
  id: string;
34
34
  thinkingLevel?: ThinkingLevel;
35
35
  } | undefined;
36
+ export declare function resolveStartupModelRefreshSelectors(options: {
37
+ model?: string;
38
+ provider?: string;
39
+ credential?: string;
40
+ continue?: boolean;
41
+ resume?: string | boolean;
42
+ hasStartupProfile: boolean;
43
+ }, settings: ModelRoleSettings): ModelSelectorValue | undefined;
44
+ export declare function refreshMissingQualifiedModelProviders(selectors: ModelSelectorValue | undefined, modelRegistry: Pick<ModelRegistry, "getAvailable" | "getDiscoverableProviders" | "refreshProvider">): Promise<boolean>;
36
45
  /**
37
46
  * Format a model as "provider/modelId" string.
38
47
  */
@@ -27,7 +27,7 @@ export declare const TAB_METADATA: Record<SettingTab, {
27
27
  icon: `tab.${string}`;
28
28
  }>;
29
29
  /** Status line segment identifiers */
30
- export type StatusLineSegmentId = "gajae" | "pi" | "model" | "mode" | "path" | "git" | "pr" | "subagents" | "jobs" | "token_in" | "token_out" | "token_total" | "token_rate" | "cost" | "context_pct" | "context_total" | "time_spent" | "time" | "session" | "hostname" | "cache_read" | "cache_write" | "session_name" | "usage";
30
+ export type StatusLineSegmentId = "gajae" | "pi" | "model" | "mode" | "path" | "git" | "pr" | "subagents" | "jobs" | "token_in" | "token_out" | "token_total" | "token_rate" | "cost" | "context_pct" | "context_total" | "time_spent" | "time" | "session" | "hostname" | "cache_read" | "cache_write" | "session_name" | "usage" | "command";
31
31
  /** Submenu choice metadata. */
32
32
  export type SubmenuOption<V extends string = string> = {
33
33
  value: V;
@@ -1306,6 +1306,25 @@ export declare const SETTINGS_SCHEMA: {
1306
1306
  readonly options: readonly import("../thinking-metadata").ThinkingLevelMetadata[];
1307
1307
  };
1308
1308
  };
1309
+ readonly reasoningLanguage: {
1310
+ readonly type: "enum";
1311
+ readonly values: readonly ["off", "english"];
1312
+ readonly default: "off";
1313
+ readonly ui: {
1314
+ readonly tab: "model";
1315
+ readonly label: "Reasoning Language";
1316
+ readonly description: "Optionally reason through development work in English while preserving the user's response language";
1317
+ readonly options: readonly [{
1318
+ readonly value: "off";
1319
+ readonly label: "Off";
1320
+ readonly description: "Do not add reasoning-language guidance";
1321
+ }, {
1322
+ readonly value: "english";
1323
+ readonly label: "English";
1324
+ readonly description: "Reason through technical work in English and answer in the user's language";
1325
+ }];
1326
+ };
1327
+ };
1309
1328
  readonly hideThinkingBlock: {
1310
1329
  readonly type: "boolean";
1311
1330
  readonly default: false;
@@ -1915,6 +1934,15 @@ export declare const SETTINGS_SCHEMA: {
1915
1934
  readonly description: "Show the interactive GitHub star reminder when gh is authenticated";
1916
1935
  };
1917
1936
  };
1937
+ readonly "paseo.autoImport": {
1938
+ readonly type: "boolean";
1939
+ readonly default: false;
1940
+ readonly ui: {
1941
+ readonly tab: "interaction";
1942
+ readonly label: "Announce Sessions to Paseo";
1943
+ readonly description: "Global-only operator opt-in. When enabled, and only when a GJC ACP provider is already registered in Paseo and its daemon is already running, import each interactive session into Paseo so it can be driven from there. Project settings cannot enable it. Never starts the Paseo daemon or removes imported entries; stale entries must be pruned in Paseo. Never runs when Paseo is absent.";
1944
+ };
1945
+ };
1918
1946
  readonly "crashReport.nudge": {
1919
1947
  readonly type: "boolean";
1920
1948
  readonly default: true;
@@ -1 +1,3 @@
1
- export {};
1
+ import { type Skill } from "../capability/skill";
2
+ import type { LoadContext, LoadResult } from "../capability/types";
3
+ export declare function loadMarketplaceSkills(ctx: LoadContext, allowedLevels?: ReadonlySet<"user" | "project">): Promise<LoadResult<Skill>>;
@@ -236,6 +236,8 @@ export declare function resolveActiveProjectRegistryPath(cwd: string): Promise<s
236
236
  * never alias as the project registry.
237
237
  */
238
238
  export declare function resolveOrDefaultProjectRegistryPath(cwd: string): Promise<string | undefined>;
239
+ /** Invalidate the exact user/project registry pair and their resolved-root cache entry. */
240
+ export declare function invalidateClaudePluginRoots(home: string, cwd?: string): Promise<void>;
239
241
  /**
240
242
  * List installed GJC plugin roots from the GJC plugin registry and, when present,
241
243
  * the nearest project-scoped registry resolved from `cwd`.
@@ -16,6 +16,22 @@ export declare function assertDnsResolvesPublic(hostname: string, label?: string
16
16
  export interface StdioPolicyContext {
17
17
  pluginRoot: string;
18
18
  }
19
+ export interface StdioInvocationTarget {
20
+ kind: "launcher";
21
+ launcher: "node" | "bun";
22
+ entrypoint: string;
23
+ executablePath: string;
24
+ ownedRelativePath: string;
25
+ ownedRelativePaths: string[];
26
+ cwd: string;
27
+ }
28
+ /**
29
+ * Resolve the exact executable file selected by the supported stdio grammar.
30
+ * Bare Node/Bun launchers accept a direct bundled entrypoint as argv[0]; no
31
+ * manifest-controlled runtime options or subcommands precede it. Path-qualified
32
+ * commands are unsupported because they bypass the verified module wrapper.
33
+ */
34
+ export declare function classifyStdioInvocation(entry: GjcPluginMcpManifestEntry, ctx: StdioPolicyContext): StdioInvocationTarget;
19
35
  /** stdio launcher/path confinement policy. */
20
36
  export declare function assertStdioAllowed(entry: GjcPluginMcpManifestEntry, ctx: StdioPolicyContext): void;
21
37
  /**
@@ -1,5 +1,7 @@
1
1
  export declare function gjcPluginUserRoot(): string;
2
2
  export declare function gjcPluginProjectRoot(cwd: string): string;
3
+ export declare function gjcPluginSafeDirectoryName(name: string): string;
4
+ export declare function gjcPluginInstallRoot(scope: "user" | "project", cwd: string, name: string): string;
3
5
  export declare function rootContainsGjcManifest(dir: string): Promise<boolean>;
4
6
  export declare function discoverGjcPluginRoots({ cwd }: {
5
7
  cwd: string;
@@ -1,5 +1,5 @@
1
1
  import type { SkillsSettings } from "../config/settings-schema";
2
- import type { Skill } from "./skills";
2
+ import { type Skill } from "./skills";
3
3
  export type RuntimeSkillDiscoverySource = "project" | "user";
4
4
  export interface RuntimeSkillDiscoveryCandidate {
5
5
  name: string;
@@ -152,7 +152,7 @@ export interface AgentEndEvent {
152
152
  sdkRunToken?: string;
153
153
  /** Indicates whether the loop ended normally, suspended, cancelled, or entered maintenance. */
154
154
  stopReason?: "completed" | "paused" | "cancelled" | "maintenance";
155
- /** Present for maintenance checkpoints; non-aborted checkpoints are not terminal. */
155
+ /** Present for maintenance checkpoints; only committed maintenance outcomes are non-terminal. */
156
156
  maintenanceOutcome?: MidRunMaintenanceOutcome;
157
157
  }
158
158
  /** Fired at the start of each turn */
@@ -83,6 +83,8 @@ export declare const SessionStateLockTestHooks: {
83
83
  forcedQuarantineName?: string;
84
84
  /** @internal Observes bounded acquisition retries without changing their timing. */
85
85
  afterAcquireContention?: (lockFile: string, attempt: number, elapsedMs: number) => void;
86
+ /** @internal Observes process-local admission without altering on-disk ownership. */
87
+ afterLocalTransitionQueued?: (transitionDir: string) => void;
86
88
  /** @internal Runs after transition mkdir contention and before stale-claim inspection. */
87
89
  afterTransitionClaimContention?: (transitionDir: string) => void | Promise<void>;
88
90
  };
@@ -10,10 +10,9 @@ interface AssistantMessageUpdateOptions {
10
10
  export declare class AssistantMessageComponent extends Container {
11
11
  #private;
12
12
  private hideThinkingBlock;
13
- private readonly onImageUpdate?;
14
13
  private readonly onVisibleMutation?;
15
14
  private readonly hintSession?;
16
- constructor(message?: AssistantMessage, hideThinkingBlock?: boolean, onImageUpdate?: (() => void) | undefined, viewportAnchorId?: string, onVisibleMutation?: (() => void) | undefined, hintSession?: ProviderSafetyStopHintSession | undefined);
15
+ constructor(message?: AssistantMessage, hideThinkingBlock?: boolean, onImageUpdate?: () => void, viewportAnchorId?: string, onVisibleMutation?: (() => void) | undefined, hintSession?: ProviderSafetyStopHintSession | undefined);
17
16
  invalidate(): void;
18
17
  setHideThinkingBlock(hide: boolean): void;
19
18
  setToolResultImages(toolCallId: string, images: ImageContent[]): void;
@@ -5,7 +5,7 @@ import { type SettingPath } from "../../config/settings";
5
5
  import type { StatusLinePreset, StatusLineSegmentId, StatusLineSeparatorStyle } from "../../config/settings-schema";
6
6
  import type { GjcRuntimeSnapshotProvider } from "../../extensibility/gjc-plugins/runtime-quarantine";
7
7
  import { type NotificationsEditorOperations } from "./notifications-settings-editor";
8
- import type { StatusLineSegmentOptions } from "./tool-status-header";
8
+ import type { StatusLinePreviewParts, StatusLineSegmentOptions } from "./tool-status-header";
9
9
  /**
10
10
  * Dynamic context for settings that need runtime data.
11
11
  * Some settings (like thinking level) are managed by the session, not Settings.
@@ -42,6 +42,7 @@ export interface StatusLinePreviewSettings {
42
42
  separator?: StatusLineSeparatorStyle;
43
43
  segmentOptions?: StatusLineSegmentOptions;
44
44
  previewHighlightSegment?: StatusLineSegmentId;
45
+ previewHighlightStyle?: "focus" | "selected";
45
46
  sessionAccent?: boolean;
46
47
  maxRows?: number;
47
48
  }
@@ -70,6 +71,10 @@ export interface SettingsCallbacks {
70
71
  onStatusLinePreview?: (settings: StatusLinePreviewSettings) => void;
71
72
  /** Get current rendered status line for inline preview */
72
73
  getStatusLinePreview?: (width?: number) => string;
74
+ /** Render a status-line preview for supplied draft settings without mutating the live status line. */
75
+ getStatusLinePreviewForSettings?: (settings: StatusLinePreviewSettings, width?: number) => string;
76
+ /** Render status-line segment groups for supplied draft settings without mutating the live status line. */
77
+ getStatusLinePreviewPartsForSettings?: (settings: StatusLinePreviewSettings, width?: number) => StatusLinePreviewParts;
73
78
  /** Called when plugins change */
74
79
  onPluginsChanged?: () => void;
75
80
  /** Called when asynchronously rebuilt settings content needs a repaint. */
@@ -0,0 +1,35 @@
1
+ export declare const STATUS_LINE_COMMAND_DEFAULT_MAX_LENGTH = 80;
2
+ export declare const STATUS_LINE_COMMAND_MAX_LENGTH = 256;
3
+ export interface StatusLineCommandOptions {
4
+ command?: string;
5
+ timeoutMs?: number;
6
+ refreshMs?: number;
7
+ maxLength?: number;
8
+ }
9
+ export interface ResolvedStatusLineCommandOptions {
10
+ command: string;
11
+ timeoutMs: number;
12
+ refreshMs: number;
13
+ maxLength: number;
14
+ }
15
+ export interface StatusLineCommandResult {
16
+ stdout: string;
17
+ stderr: string;
18
+ exitCode: number;
19
+ timedOut: boolean;
20
+ outputTruncated: boolean;
21
+ }
22
+ export declare function normalizeStatusLineCommandOptions(value: unknown): ResolvedStatusLineCommandOptions;
23
+ /**
24
+ * Run a configured status-line command without making the synchronous render
25
+ * path wait on it. The streams are drained with a hard byte cap and the whole
26
+ * process group is killed when the timeout expires.
27
+ */
28
+ export declare function runStatusLineCommand(command: string, options: {
29
+ cwd: string;
30
+ shell: string;
31
+ shellArgs: readonly string[];
32
+ env: Record<string, string>;
33
+ timeoutMs: number;
34
+ signal?: AbortSignal;
35
+ }): Promise<StatusLineCommandResult>;
@@ -1,3 +1,4 @@
1
+ export * from "./command";
1
2
  export * from "./presets";
2
3
  export * from "./segments";
3
4
  export * from "./separators";
@@ -57,6 +57,11 @@ export interface SegmentContext {
57
57
  resetUnit?: "m" | "h";
58
58
  }>;
59
59
  } | null;
60
+ command?: {
61
+ output: string | null;
62
+ failed: boolean;
63
+ pending: boolean;
64
+ };
60
65
  }
61
66
  export interface RenderedSegment {
62
67
  content: string;
@@ -5,6 +5,8 @@ import type { AgentSession } from "../../session/agent-session";
5
5
  import { type SkillActiveEntry } from "../../skill-state/active-state";
6
6
  import type { ActionRegistry, FocusDomain } from "../action-registry";
7
7
  import { type JobsSnapshot } from "../jobs-observer";
8
+ import { type StatusLineCommandOptions } from "./status-line/command";
9
+ import type { SeparatorDef } from "./status-line/types";
8
10
  export interface StatusLineSegmentOptions {
9
11
  model?: {
10
12
  showThinkingLevel?: boolean;
@@ -28,6 +30,7 @@ export interface StatusLineSegmentOptions {
28
30
  usage?: {
29
31
  mode?: "used" | "remaining";
30
32
  };
33
+ command?: StatusLineCommandOptions;
31
34
  }
32
35
  export interface StatusLineSettings {
33
36
  preset?: StatusLinePreset;
@@ -36,6 +39,7 @@ export interface StatusLineSettings {
36
39
  separator?: StatusLineSeparatorStyle;
37
40
  segmentOptions?: StatusLineSegmentOptions;
38
41
  previewHighlightSegment?: StatusLineSegmentId;
42
+ previewHighlightStyle?: "focus" | "selected";
39
43
  showHookStatus?: boolean;
40
44
  showSkillHud?: boolean;
41
45
  showActionHints?: boolean;
@@ -48,11 +52,19 @@ export interface StatusLineComponentOptions {
48
52
  getKeybindings?: () => KeybindingsManager;
49
53
  focusDomain?: FocusDomain;
50
54
  keyDisplayContext?: KeyDisplayContext;
55
+ onUpdate?: () => void;
51
56
  }
52
57
  export interface StatusLineActionHint {
53
58
  id: AppKeybinding;
54
59
  content: string;
55
60
  }
61
+ export interface StatusLinePreviewParts {
62
+ left: string[];
63
+ leftIds: StatusLineSegmentId[];
64
+ right: string[];
65
+ rightIds: (StatusLineSegmentId | null)[];
66
+ separator: SeparatorDef;
67
+ }
56
68
  /**
57
69
  * Produces whole, bound action hints for the current focus domain. The registry
58
70
  * remains the authority for availability; KEYBINDINGS remains the authority for
@@ -100,6 +112,8 @@ export declare class StatusLineComponent implements Component {
100
112
  * everything fits on one row.
101
113
  */
102
114
  getPreviewContent(width: number): string;
115
+ getPreviewContentForSettings(width: number, previewSettings: StatusLineSettings): string;
116
+ getPreviewPartsForSettings(width: number, previewSettings: StatusLineSettings): StatusLinePreviewParts;
103
117
  getCacheStatsForTest(): {
104
118
  rowHits: number;
105
119
  rowMisses: number;
@@ -14,6 +14,12 @@ export declare class EventController {
14
14
  private ctx;
15
15
  constructor(ctx: InteractiveModeContext);
16
16
  dispose(): void;
17
+ /** Temporary TUI stop discards scheduling, not historical assistant callback lifetimes. */
18
+ suspendAssistantTextPresentation(): void;
19
+ /** Rearm before the first restarted frame, even without a new provider event. */
20
+ resumeAssistantTextPresentation(): void;
21
+ /** Session/transcript replacement invalidates callbacks before removing old children. */
22
+ resetAssistantTextPresentation(): void;
17
23
  subscribeToAgent(): void;
18
24
  handleEvent(event: AgentSessionEvent): Promise<void>;
19
25
  clearIrcExpiryTimers(): void;
@@ -213,6 +213,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
213
213
  }): Promise<void>;
214
214
  flushPendingBashComponents(): void;
215
215
  isKnownSlashCommand(text: string): boolean;
216
+ resetAssistantTextPresentation(): void;
216
217
  /** Advances the sticky-viewport source only for semantic transcript output. */
217
218
  recordVisibleTranscriptMutation(): void;
218
219
  addMessageToChat(message: AgentMessage, options?: {
@@ -259,6 +259,7 @@ export interface InteractiveModeContext {
259
259
  extractAssistantText(message: AssistantMessage): string;
260
260
  /** Records one semantic visible-transcript mutation for the sticky viewport. */
261
261
  recordVisibleTranscriptMutation?(): void;
262
+ resetAssistantTextPresentation(): void;
262
263
  updateEditorTopBorder(): void;
263
264
  updateEditorBorderColor(): void;
264
265
  rebuildChatFromMessages(policy: TranscriptRebuildPolicy): void;
@@ -1,4 +1,12 @@
1
- import type { MCPGetPromptResult, MCPPrompt, MCPRequestOptions, MCPResource, MCPResourceReadResult, MCPResourceTemplate, MCPServerCapabilities, MCPServerConfig, MCPServerConnection, MCPToolCallResult, MCPToolDefinition } from "./types";
1
+ import type { MCPGetPromptResult, MCPPrompt, MCPRequestOptions, MCPResource, MCPResourceReadResult, MCPResourceTemplate, MCPServerCapabilities, MCPServerConfig, MCPServerConnection, MCPToolCallResult, MCPToolDefinition, MCPTransport } from "./types";
2
+ import { MCPExpectedFailure } from "./types";
3
+ /** Failed connection whose still-owned transport cleanup can be retried explicitly. */
4
+ export declare class MCPConnectionCleanupFailure extends MCPExpectedFailure {
5
+ #private;
6
+ constructor(cause: unknown, transport: MCPTransport);
7
+ /** Retry the same retained transport cleanup; failures preserve all prior causes. */
8
+ close(): Promise<void>;
9
+ }
2
10
  /**
3
11
  * Connect to an MCP server.
4
12
  * Has a 30 second timeout to prevent blocking startup.
@@ -8,6 +8,7 @@ import { type TSchema } from "@gajae-code/ai/core";
8
8
  import type { SourceMeta } from "../capability/types";
9
9
  import type { CustomTool } from "../extensibility/custom-tools/types";
10
10
  import type { AuthStorage } from "../session/auth-storage";
11
+ import { MCPConnectionCleanupFailure } from "./client";
11
12
  import { MCPConnectionPool, type MCPPoolLease } from "./pool";
12
13
  import type { MCPProtocolObservation } from "./protocol";
13
14
  import type { MCPToolDetails } from "./tool-bridge";
@@ -200,6 +201,10 @@ export declare class MCPManager {
200
201
  }): Promise<T>;
201
202
  /** Read-only test seam for pending retired lease-release records. */
202
203
  get retiredLeaseReleaseCountForTests(): number;
204
+ /** Read-only test seam for retained failed-connection cleanup owners. */
205
+ get pendingConnectionCleanupCountForTests(): number;
206
+ /** Read-only test seam for retained failed-connection cleanup causes. */
207
+ getPendingConnectionCleanupFailureForTests(name: string): MCPConnectionCleanupFailure | undefined;
203
208
  /**
204
209
  * Get all connected server names.
205
210
  */
@@ -223,7 +228,8 @@ export declare class MCPManager {
223
228
  * Tears down the stale connection, re-resolves auth, establishes a new
224
229
  * connection, reloads tools, and notifies consumers.
225
230
  * Concurrent calls for the same server share one reconnection attempt.
226
- * Returns the new connection, or null if reconnection failed.
231
+ * Returns the new connection, or null if reconnection fails after cleanup.
232
+ * Throws a retryable cleanup failure while the previous transport owner remains incomplete.
227
233
  */
228
234
  reconnectServer(name: string): Promise<MCPServerConnection | null>;
229
235
  /**
@@ -1,3 +1,4 @@
1
+ import { MCPConnectionCleanupFailure } from "./client";
1
2
  import { type MCPPoolKeyIdentity, type MCPPoolKeyOptions, type MCPPoolSharingMode } from "./pool-key";
2
3
  import { type MCPRequestOptions, type MCPServerConfig, type MCPServerConnection } from "./types";
3
4
  export type { MCPPoolCapabilityProfile, MCPPoolKeyIdentity, MCPPoolKeyOptions, MCPPoolSharingMode } from "./pool-key";
@@ -18,8 +19,9 @@ export declare class MCPPoolAcquireAbortError extends Error {
18
19
  readonly code: "MCP_POOL_ACQUIRE_ABORTED";
19
20
  readonly serverName: string;
20
21
  readonly poolKey: string;
21
- cleanup?: Promise<unknown>;
22
- constructor(serverName: string, poolKey: string, cause: unknown, cleanup?: Promise<unknown>);
22
+ readonly cleanup?: Promise<void>;
23
+ readonly cleanupGeneration?: number;
24
+ constructor(serverName: string, poolKey: string, cause: unknown, cleanup?: Promise<void>, cleanupGeneration?: number);
23
25
  }
24
26
  export declare class MCPPoolLeaseInvalidatedError extends Error {
25
27
  readonly code: "MCP_POOL_LEASE_INVALIDATED";
@@ -60,6 +62,8 @@ export interface MCPPoolAcquireOptions extends MCPPoolKeyOptions {
60
62
  advertiseRoots?: boolean;
61
63
  onNotification?: (method: string, params: unknown) => void;
62
64
  onRequest?: (method: string, params: unknown) => Promise<unknown>;
65
+ /** @internal Synchronous handoff for a pool-owned abandoned-acquire cleanup flight. */
66
+ onCleanupPending?: (error: MCPPoolAcquireAbortError) => void;
63
67
  }
64
68
  export interface MCPConnectionPoolOptions {
65
69
  sharedPoolIdleMs?: number;
@@ -105,6 +109,7 @@ type PendingWaiter = {
105
109
  settled: boolean;
106
110
  claimed: boolean;
107
111
  removeAbortListener?: () => void;
112
+ onCleanupPending?: (error: MCPPoolAcquireAbortError) => void;
108
113
  };
109
114
  type PendingEntry = {
110
115
  claims: number;
@@ -118,7 +123,7 @@ type PendingEntry = {
118
123
  cancellationReason?: unknown;
119
124
  openAbortController: AbortController;
120
125
  openSignal?: AbortSignal;
121
- settlement?: Promise<unknown>;
126
+ settlement?: Promise<void>;
122
127
  };
123
128
  /** A lease over one physical MCP connection. */
124
129
  export interface MCPPoolLease {
@@ -182,6 +187,20 @@ export declare class MCPConnectionPool {
182
187
  awaitRestart(key: string): Promise<boolean>;
183
188
  finishRestart(key: string, error?: unknown): void;
184
189
  releaseRestart(key: string): void;
190
+ private retainCancelledAcquireCleanup;
191
+ private notifyPendingAcquireCleanup;
192
+ /** @internal Whether this pool still owns the notified abandoned-acquire flight. */
193
+ hasPendingAcquireCleanup(error: MCPPoolAcquireAbortError): boolean;
194
+ /** @internal Current retained failure for one notified abandoned-acquire generation. */
195
+ getPendingAcquireCleanupFailure(error: MCPPoolAcquireAbortError): MCPConnectionCleanupFailure | undefined;
196
+ /** @internal Prevent manager-level duplication of the pool's retained cleanup owner. */
197
+ ownsPendingAcquireCleanupFailure(error: unknown): boolean;
198
+ /** Read-only test seam for abandoned-acquire cleanup owners. */
199
+ get pendingAcquireCleanupCountForTests(): number;
200
+ /** Read-only test seam for the current retained abandoned-acquire cleanup failure. */
201
+ getPendingAcquireCleanupFailureForTests(name: string): MCPConnectionCleanupFailure | undefined;
202
+ /** @internal Join and retry one generation of abandoned acquisition cleanup. */
203
+ closePendingAcquireCleanup(key: string, generation: number): Promise<void>;
185
204
  acquire(name: string, config: MCPServerConfig, options?: MCPPoolAcquireOptions): Promise<MCPPoolLease>;
186
205
  private waitForPendingEntry;
187
206
  private scheduleZeroClaimCleanup;
@@ -23,7 +23,3 @@ export declare class StdioTransport implements MCPTransport {
23
23
  notify(method: string, params?: Record<string, unknown>): Promise<void>;
24
24
  close(): Promise<void>;
25
25
  }
26
- /**
27
- * Create and connect a stdio transport.
28
- */
29
- export declare function createStdioTransport(config: MCPStdioServerConfig): Promise<StdioTransport>;