@gajae-code/coding-agent 0.15.5 → 0.15.6

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 (155) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/dist/types/async/job-manager.d.ts +83 -0
  3. package/dist/types/cli/auth-gateway-cli.d.ts +17 -0
  4. package/dist/types/cli/model-presets-cli.d.ts +9 -0
  5. package/dist/types/cli/update-cli.d.ts +2 -0
  6. package/dist/types/commands/auth-gateway.d.ts +3 -0
  7. package/dist/types/commands/gc.d.ts +13 -0
  8. package/dist/types/commands/model-presets.d.ts +21 -0
  9. package/dist/types/config/autorouting-tier-map.d.ts +96 -0
  10. package/dist/types/config/file-lock.d.ts +49 -2
  11. package/dist/types/config/internal/model-preset-registry-test-state.d.ts +4 -0
  12. package/dist/types/config/internal/model-preset-registry-test-support.d.ts +3 -0
  13. package/dist/types/config/keybindings.d.ts +3 -2
  14. package/dist/types/config/model-preset-registry.d.ts +368 -0
  15. package/dist/types/config/model-profile-activation.d.ts +39 -0
  16. package/dist/types/config/model-profiles.d.ts +5 -3
  17. package/dist/types/config/model-registry.d.ts +11 -5
  18. package/dist/types/config/settings-schema.d.ts +9 -0
  19. package/dist/types/coordinator-mcp/model-preset.d.ts +7 -5
  20. package/dist/types/coordinator-mcp/projection-scan.d.ts +46 -0
  21. package/dist/types/extensibility/extensions/types.d.ts +2 -5
  22. package/dist/types/gjc-runtime/empty-delete-gc.d.ts +58 -0
  23. package/dist/types/gjc-runtime/gc-runtime.d.ts +2 -0
  24. package/dist/types/gjc-runtime/session-state-lock.d.ts +35 -6
  25. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +6 -0
  26. package/dist/types/index.d.ts +1 -0
  27. package/dist/types/main.d.ts +3 -1
  28. package/dist/types/modes/components/jobs-overlay-model.d.ts +4 -2
  29. package/dist/types/modes/jobs-observer.d.ts +36 -0
  30. package/dist/types/sdk/broker/broker.d.ts +3 -0
  31. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +3 -0
  32. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +4 -0
  33. package/dist/types/sdk/client/discovery.d.ts +1 -0
  34. package/dist/types/sdk/host/model-pin.d.ts +7 -2
  35. package/dist/types/sdk/host/sdk-run-capability.d.ts +1 -0
  36. package/dist/types/sdk/host/session-runtime.d.ts +15 -1
  37. package/dist/types/sdk/prompt-deadline-manager.d.ts +11 -1
  38. package/dist/types/sdk/protocol/adapter-validation.d.ts +2 -0
  39. package/dist/types/sdk/router/session-router.d.ts +9 -0
  40. package/dist/types/session/account-inventory.d.ts +1 -0
  41. package/dist/types/session/agent-session.d.ts +19 -7
  42. package/dist/types/session/fold-coordinator.d.ts +201 -0
  43. package/dist/types/session/sdk-run-capability-internal.d.ts +7 -0
  44. package/dist/types/session/sdk-run-capability.d.ts +2 -0
  45. package/dist/types/telemetry/control.d.ts +11 -0
  46. package/dist/types/telemetry/events.d.ts +20 -0
  47. package/dist/types/telemetry/index.d.ts +3 -0
  48. package/dist/types/telemetry/transport.d.ts +22 -0
  49. package/dist/types/tools/bash-interactive.d.ts +23 -0
  50. package/dist/types/tools/index.d.ts +6 -5
  51. package/dist/types/web/search/providers/base.d.ts +9 -4
  52. package/dist/types/web/search/providers/xai.d.ts +2 -1
  53. package/dist/types/web/search/types.d.ts +14 -0
  54. package/package.json +10 -7
  55. package/scripts/generate-hotkeys-docs.ts +4 -0
  56. package/scripts/generate-sdk-operation-inventory.ts +3 -3
  57. package/src/async/job-manager.ts +671 -39
  58. package/src/cli/auth-broker-cli.ts +40 -12
  59. package/src/cli/auth-gateway-cli.ts +273 -97
  60. package/src/cli/config-cli.ts +2 -2
  61. package/src/cli/fast-help.ts +3 -0
  62. package/src/cli/model-presets-cli.ts +100 -0
  63. package/src/cli/update-cli.ts +40 -5
  64. package/src/cli.ts +6 -2
  65. package/src/commands/auth-gateway.ts +12 -8
  66. package/src/commands/gc.ts +19 -0
  67. package/src/commands/model-presets.ts +24 -0
  68. package/src/config/autorouting-tier-map.ts +32 -0
  69. package/src/config/file-lock-gc.ts +9 -4
  70. package/src/config/file-lock.ts +775 -59
  71. package/src/config/internal/model-preset-registry-test-state.ts +28 -0
  72. package/src/config/internal/model-preset-registry-test-support.ts +11 -0
  73. package/src/config/keybindings.ts +6 -2
  74. package/src/config/model-preset-registry.ts +2799 -0
  75. package/src/config/model-profile-activation.ts +115 -28
  76. package/src/config/model-profile-contract.ts +4 -1
  77. package/src/config/model-profiles.ts +51 -9
  78. package/src/config/model-registry.ts +1021 -122
  79. package/src/config/settings-schema.ts +11 -0
  80. package/src/config/settings.ts +6 -1
  81. package/src/coordinator-mcp/model-preset.ts +32 -17
  82. package/src/coordinator-mcp/projection-scan.ts +571 -0
  83. package/src/coordinator-mcp/server.ts +19 -24
  84. package/src/coordinator-mcp/session-reaper.ts +9 -3
  85. package/src/extensibility/extensions/loader.ts +0 -1
  86. package/src/extensibility/extensions/types.ts +2 -3
  87. package/src/extensibility/gjc-plugins/runtime-adapters.ts +1 -0
  88. package/src/gjc-runtime/empty-delete-gc.ts +301 -0
  89. package/src/gjc-runtime/gc-render.ts +29 -0
  90. package/src/gjc-runtime/gc-runtime.ts +174 -11
  91. package/src/gjc-runtime/session-state-lock.ts +1242 -141
  92. package/src/gjc-runtime/session-state-sidecar.ts +76 -3
  93. package/src/index.ts +1 -0
  94. package/src/internal-urls/docs-index.generated.ts +9 -8
  95. package/src/lsp/config.ts +4 -3
  96. package/src/lsp/path-trust.ts +12 -6
  97. package/src/main.ts +9 -2
  98. package/src/modes/acp/acp-agent.ts +11 -5
  99. package/src/modes/components/jobs-overlay-model.ts +99 -16
  100. package/src/modes/components/model-selector.ts +158 -18
  101. package/src/modes/components/status-line/segments.ts +6 -1
  102. package/src/modes/controllers/extension-ui-controller.ts +1 -1
  103. package/src/modes/controllers/input-controller.ts +23 -6
  104. package/src/modes/interactive-mode.ts +14 -1
  105. package/src/modes/jobs-observer.ts +149 -16
  106. package/src/modes/runtime-init.ts +1 -1
  107. package/src/modes/utils/injected-user-submission.ts +15 -1
  108. package/src/prompts/tools/bash.md +2 -2
  109. package/src/prompts/tools/fold-receipt.md +3 -0
  110. package/src/prompts/tools/job.md +1 -1
  111. package/src/sdk/acp/adapter.ts +17 -2
  112. package/src/sdk/broker/broker.ts +48 -21
  113. package/src/sdk/broker/lifecycle.ts +32 -6
  114. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  115. package/src/sdk/bus/chat-daemon-runtime.ts +11 -1
  116. package/src/sdk/bus/kind-aware-reconciliation.ts +36 -6
  117. package/src/sdk/bus/prompt-reconciliation.ts +28 -4
  118. package/src/sdk/bus/slack-conversation.ts +5 -1
  119. package/src/sdk/cli/session-cli.ts +12 -1
  120. package/src/sdk/client/discovery.ts +3 -1
  121. package/src/sdk/host/control/dispatch.ts +3 -0
  122. package/src/sdk/host/model-pin.ts +185 -25
  123. package/src/sdk/host/sdk-run-capability.ts +1 -0
  124. package/src/sdk/host/session-runtime.test.ts +371 -37
  125. package/src/sdk/host/session-runtime.ts +364 -52
  126. package/src/sdk/prompt-deadline-manager.ts +16 -1
  127. package/src/sdk/protocol/adapter-validation.ts +27 -0
  128. package/src/sdk/protocol/operation-inventory.generated.json +2 -2
  129. package/src/sdk/protocol/operation-registry.ts +4 -1
  130. package/src/sdk/router/session-router.ts +228 -96
  131. package/src/sdk/session.ts +83 -12
  132. package/src/session/account-inventory.ts +27 -11
  133. package/src/session/agent-session.ts +678 -103
  134. package/src/session/fold-coordinator.ts +433 -0
  135. package/src/session/sdk-run-capability-internal.ts +15 -0
  136. package/src/session/sdk-run-capability.ts +2 -0
  137. package/src/session/session-manager.ts +5 -4
  138. package/src/setup/provider-presets.json +1 -1
  139. package/src/slash-commands/helpers/credential-switch.ts +6 -1
  140. package/src/task/executor.ts +19 -3
  141. package/src/telemetry/control.ts +26 -0
  142. package/src/telemetry/events.ts +142 -0
  143. package/src/telemetry/index.ts +3 -0
  144. package/src/telemetry/transport.ts +87 -0
  145. package/src/tools/bash-interactive.ts +182 -85
  146. package/src/tools/bash.ts +772 -67
  147. package/src/tools/index.ts +7 -5
  148. package/src/tools/tool-catalog.generated.ts +1 -1
  149. package/src/web/search/provider.ts +120 -11
  150. package/src/web/search/providers/anthropic.ts +89 -17
  151. package/src/web/search/providers/base.ts +9 -4
  152. package/src/web/search/providers/gemini.ts +87 -15
  153. package/src/web/search/providers/openai-compatible.ts +23 -8
  154. package/src/web/search/providers/xai.ts +98 -12
  155. package/src/web/search/types.ts +16 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.15.6] - 2026-08-30
6
+
7
+ - Auth metadata remains session-only when a compatibility registry has auth storage but no owner accessor, preventing an unscoped OAuth account lookup from attributing a registry-scoped API-key request to the wrong account.
8
+
9
+ - Every prompt no longer throws inside the session metadata resolver when the model registry does not implement `getAuthStorageOwner`. `80bbc96192` added the lookup as a required call in the resolver that runs on every prompt, but `buildSessionMetadata` takes `owner?: object` and 65 test files construct `AgentSession` with a deliberately minimal `modelRegistry` stub, so the resolver raised `TypeError: this.#modelRegistry.getAuthStorageOwner is not a function`. The throw stranded session admission, which then reported the misleading `Agent session admission is busy due to same-session reentrancy` on every following prompt, so a single missing method surfaced as ~45 failures and 5-second timeouts across six CI test shards in ten unrelated suites (IRC roster delivery, `respondAsBackground` visibility, deferred shell publication, coordinator activity labels, and others). The two optional-argument resolver call sites are now optional calls, matching the existing defensive convention in `account-inventory.ts`; the auth-credential call sites (`resolveOAuthPinTarget`, `invalidateCredentialMatching`, `markUsageLimitReached`) deliberately keep the strict call because they genuinely require a real registry owner and passing `undefined` there would change credential ownership scoping.
10
+ - SDK prompt controls now reject empty and whitespace-only text before client correlation, turn allocation, transcript mutation, or provider activity across CLI, MCP, ACP, and direct session controls; multiline and Unicode prompts remain valid. (#5059)
11
+ - Added disabled-by-default privacy-preserving update telemetry with a versioned allowlist, random local UUIDv4 install ID, bounded nonblocking HTTPS transport, explicit `telemetry.enabled` control, and the `GJC_DISABLE_TELEMETRY` emergency kill switch. Events never include prompts, argv, paths, environment, secrets, account/model/provider/repository identity, arbitrary errors, hostname, username, machine ID, or IP-derived identity. (#5046)
12
+ - A running foreground command can now be folded into a background job with the fold chord (default `Alt+Shift+B`, plus `Cmd+B` on macOS; remappable via `app.tool.backgroundFold`). The turn ends as a clean stop-after-result rather than an abort, and the folded job's completion automatically wakes a fresh turn carrying a receipt — the command's output, a retrieval handle, and the original request — so the interrupted task is finished instead of abandoned. All three command surfaces fold — managed non-PTY bash, editor/ACP client-terminal commands, and PTY-mode commands — and a folded command is never killed or restarted by folding (a folded PTY continues output-only, so it stops accepting input). Folded jobs keep their original deadlines, folded work is visible in the status line and jobs overlay with its delivery state, completions arriving close together merge into one wake turn, and `task`/`subagent` waits are deliberately not foldable. The previous `Ctrl+B` default could never work: `Ctrl+B` is already `tui.editor.cursorLeft` (and is tmux's default prefix), so the keypress fell through to cursor movement whenever nothing was foldable.
13
+ - Background job results are no longer silently lost in two pre-existing cases that also affected plain `async: true` bash. A job id with a queued or in-flight delivery is no longer recycled, which previously gave the pending delivery a mismatched generation and discarded it before it was ever delivered; and a delivery callback that fails after its job record was evicted is now retried, with a retry-cap failure recorded as visibly failed instead of vanishing with no dead letter.
14
+ - Fixed `AsyncJobManager.dispose()` ordering: it marked itself disposed before running owner cleanups, and the delivery loop is inert once disposed, so a failure an owner cleanup settled could never be drained. Registration is now closed by its own flag, which keeps cleanups from registering fresh work without disabling delivery.
15
+ - ACP prompt terminal publication no longer waits behind post-prompt worker integration or recovery work. SDK prompts pass the correlated `agent_end` boundary through immediately, while the existing bounded integration drain continues independently, preventing streamed turns from remaining pending until `sdk.promptDeadlineMs` when owned subagent work lingers. (#5030)
16
+
17
+ ### Fixed
18
+
19
+ - Session resume no longer spends minutes in a CPU-hot 5ms loop when `runtime-state.json.lock` contains corrupt or unprovenanced debris. Session-state acquisition now uses a two-second monotonic wall-time budget with capped exponential backoff and typed exact-path diagnostics; stale malformed records are reclaimed only when their local host provenance and dead PID are proved, old empty legacy lock directories are removed only through exact tree identity, and live, foreign, or replacement owners remain fail-closed. (#5062)
20
+
21
+ - `gjc sdk session tail` no longer rejects the host's `event_replay_result` control frame when its response position includes `generation` and `lastSeq` but no event `seq`; replay metadata is kept out of the event-ring tail while malformed event positions remain fail-closed. (#5055)
22
+
23
+ - Coordinator no longer treats native exact-unlink placeholders (empty `.gjc-delete-*.json`) as live projection JSON. Directory scans skip dotfiles before open; truncated canonical projections remain parse candidates and fail closed, while the parse cap applies only after filtering debris. Session-state lock reclaim reuses one quarantine name per acquire cycle and removes a verified-empty leftover at that name before exchange — deletion is the native identity-bound `exactUnlinkDirect`, so a replacement planted at the reserved name is refused instead of deleted. `gjc gc --empty-delete-receipts --root/--manifest` validates every operand before any store can prune, reports or prunes only operator-supplied empty receipts matching the strict UUID namespace (inode identity + symlink-root reject; no hardcoded host paths), and surfaces native retained recovery paths and discovery failures as report errors. Receipt discovery is fail-closed under concurrent cleanup: a candidate that vanishes between `readdir` and `lstat` is recorded as a `skipped`/`raced` row instead of silently shrinking the report.
24
+
25
+ - Fold control operations now report success only after the foreground fold transaction commits, while rejected fold requests follow the existing warning path; cleanup-triggered delivery failures remain eligible for bounded retry and visible dead-letter recording during manager disposal, and folded jobs expose read-only detail rows in the jobs overlay.
26
+ - Generic file-lock release now retries transient Windows sharing denials and quarantines a verified self-owned lock when deletion remains unavailable, using an in-process acquisition generation rather than reclaiming every live lock with the same PID. Terminal `agent_end` publication remains independent of coordinator sidecar persistence, and a repeated interactive exit escalates through bounded postmortem cleanup. (#4943)
27
+
28
+ - A one-shot `gjc sdk` command no longer idles for five seconds after its response is written. `SessionRouter` bounded four waits with `Bun.sleep` inside `Promise.race`; the race settles on the winner but does not cancel the loser, and a pending `Bun.sleep` keeps the event loop alive, so work that finished in milliseconds still owed the rest of the budget before the process could exit. `gjc sdk session list` wrote its result at 0.50s and exited at 5.51s. The startup attach budget, shutdown timeout, bounded notification work, and replay backoff now use the existing `cancellableSleep` helper with an `AbortController` cancelled once the race settles, and the reconcile interval is unref'd so a Router started without a matching `stop()` does not hold a host proce…
29
+
5
30
  ## [0.15.5] - 2026-08-29
6
31
 
7
32
  - Bash now blocks tmux input commands that resolve to the agent's own pane before spawning the shell, including direct pane targets, session aliases, explicit socket forms, shell wrappers, and inspected script indirection. Read-only inspection and cross-session orchestration remain available, while blocked input cannot reach the transcript as a user turn. (#5039)
@@ -653,7 +678,7 @@
653
678
  ### Added
654
679
 
655
680
  - The SDK `models.list/current` (Q10) catalog now lists model profiles as synthetic `gajae-code/<profile>` entries (e.g. `gajae-code/codex-eco`), and selecting one through `model.set` (or the ACP Model picker) activates the profile for the live session only; global persistence remains the explicit `gjc --mpreset <name> --default` or TUI default-selection path. ACP/SDK clients such as Paseo can therefore offer presets like ordinary models; only availability-filtered profiles are advertised, the reserved `gajae-code` namespace fails closed on collision, and `config.patch` serializes with profile activation through the session admission boundary.
656
- - Added first-class `cline-pass` and `commandcode-goat` provider presets with documented API endpoints, environment-variable credentials, non-hardcoded live model discovery from models.dev and the Command Code Provider API, and prefix-based Claude routing.
681
+ - Added first-class `cline-pass` and `commandcode-goat` provider presets with documented API endpoints, environment-variable credentials, non-hardcoded live model discovery from models.dev and the Command Code Provider API; Command Code models stay on its documented OpenAI-compatible transport regardless of model name.
657
682
  - Registered the `jetbrains-junie` provider in the famous-provider ordering and the `JUNIE_API_KEY` credential help so JetBrains AI (Junie) Claude models surface in `/model`, `--list-models` and `gjc --help` alongside the other first-class providers (#3626).
658
683
  - Added lease-backed MCP connection pooling with typed recovery, shared HTTP/SSE sessions, per-lease callback demultiplexing, and authorization binding scopes that keep credential secrets out of pool keys.
659
684
  - Added plugin registry v2 as the single execution authority for plugin tools, subskills, and prompt appendices, with digest verification at final use.
@@ -21,6 +21,12 @@ export interface AsyncJob {
21
21
  setupFailureSummary?: string;
22
22
  /** Safe, bounded summary of a terminal local (non-provider) failure kind. */
23
23
  localErrorSummary?: LocalErrorSummary;
24
+ /** Compact delivery-failure marker retained while the job row remains live. */
25
+ deliveryFailure?: {
26
+ attempt: number;
27
+ lastError?: string;
28
+ recordedAt: number;
29
+ };
24
30
  metadata?: AsyncJobMetadata;
25
31
  /**
26
32
  * Registry id of the agent that registered the job (e.g. "0-Main",
@@ -38,6 +44,8 @@ export interface AsyncJob {
38
44
  */
39
45
  export declare function jobElapsedMs(job: Pick<AsyncJob, "startTime" | "endTime">, now?: number): number;
40
46
  export interface AsyncJobMetadata {
47
+ /** Set once a foreground wait has been folded, so surfacing can show folded work. */
48
+ backgrounded?: boolean;
41
49
  subagent?: {
42
50
  id: string;
43
51
  agent: string;
@@ -170,11 +178,50 @@ export interface AsyncJobManagerOptions {
170
178
  onJobComplete: (jobId: string, text: string, job?: AsyncJob) => void | Promise<void>;
171
179
  maxRunningJobs?: number;
172
180
  retentionMs?: number;
181
+ maxDeadLetterOverflowOwners?: number;
182
+ }
183
+ export interface AsyncJobAdmission {
184
+ readonly manager: AsyncJobManager;
173
185
  }
174
186
  export interface AsyncJobDisposeDiagnostics {
175
187
  stuckJobIds: string[];
176
188
  deliveriesDrained: boolean;
177
189
  }
190
+ /** Per-job public delivery classification. Exactly one value per terminal job. */
191
+ export type JobDeliveryState = "pending" | "delivered" | "failed-visible";
192
+ /** One job as projected by {@link AsyncJobManager.getJobsSnapshot}. */
193
+ export interface AsyncJobSnapshotEntry {
194
+ id: string;
195
+ kind: string;
196
+ label: string;
197
+ status: AsyncJob["status"];
198
+ generation: string;
199
+ backgrounded: boolean;
200
+ deliveryState: JobDeliveryState;
201
+ }
202
+ /** Scalar delivery-failure evidence that may outlive its AsyncJob record. */
203
+ export interface DeadLetteredJobSnapshotEntry {
204
+ jobId: string;
205
+ generation: string;
206
+ ownerId?: string;
207
+ /** Whether the failed delivery originated from a backgrounded job. */
208
+ backgrounded?: boolean;
209
+ attempt: number;
210
+ lastError?: string;
211
+ recordedAt: number;
212
+ }
213
+ /**
214
+ * One atomic projection of job + delivery state.
215
+ *
216
+ * Computed in a single synchronous pass with no interleaved awaits so it cannot
217
+ * tear, and consumed verbatim: a UI that re-derives delivery classification from
218
+ * separate getters can disagree with this and produce a job that is in no public
219
+ * state at all.
220
+ */
221
+ export interface AsyncJobsSnapshot {
222
+ jobs: AsyncJobSnapshotEntry[];
223
+ deadLettered: DeadLetteredJobSnapshotEntry[];
224
+ }
178
225
  export interface AsyncJobDeliveryState {
179
226
  queued: number;
180
227
  delivering: boolean;
@@ -209,6 +256,8 @@ export interface AsyncJobRegisterOptions {
209
256
  metadata?: AsyncJobMetadata;
210
257
  onProgress?: (text: string, details?: Record<string, unknown>) => void | Promise<void>;
211
258
  lifecycle?: AsyncJobLifecycleCleanup;
259
+ /** Reserved capacity consumed atomically by this registration. */
260
+ admissionToken?: AsyncJobAdmission;
212
261
  }
213
262
  /**
214
263
  * Filter applied to job query/cancel APIs. With `ownerId`, results are
@@ -411,6 +460,10 @@ export declare class AsyncJobManager {
411
460
  */
412
461
  getJobPromise(id: string, generation: string): Promise<void> | undefined;
413
462
  getRunningJobs(filter?: AsyncJobFilter): AsyncJob[];
463
+ /** Whether a new running job can be admitted without starting side effects. */
464
+ hasCapacity(filter?: AsyncJobFilter): boolean;
465
+ reserveCapacity(): AsyncJobAdmission;
466
+ releaseCapacity(token: AsyncJobAdmission): void;
414
467
  getRecentJobs(limit?: number, filter?: AsyncJobFilter): AsyncJob[];
415
468
  getAllJobs(filter?: AsyncJobFilter): AsyncJob[];
416
469
  /**
@@ -450,6 +503,18 @@ export declare class AsyncJobManager {
450
503
  /** Run producer cleanups, then perform the legacy destructive subagent purge. */
451
504
  runOwnerCleanups(filter?: AsyncJobFilter): void;
452
505
  getDeliveryState(filter?: AsyncJobFilter): AsyncJobDeliveryState;
506
+ /**
507
+ * One synchronous pass over jobs plus delivery state.
508
+ *
509
+ * Every returned job carries exactly one {@link JobDeliveryState}, and
510
+ * dead-lettered evidence is included even when its record is already gone, so
511
+ * no terminal job can end up invisible to the UI.
512
+ */
513
+ getJobsSnapshot(filter?: AsyncJobFilter): AsyncJobsSnapshot;
514
+ retainParkedDelivery(job: AsyncJob, text: string): void;
515
+ retainDeliveryClaim(job: AsyncJob): void;
516
+ releaseDeliveryClaim(generation: string): void;
517
+ clearParkedDelivery(generation: string): void;
453
518
  hasPendingDeliveries(filter?: AsyncJobFilter): boolean;
454
519
  watchJobGenerations(jobIds: string[]): AsyncJobWatchHandle;
455
520
  watchJobs(jobIds: string[]): number;
@@ -460,6 +525,19 @@ export declare class AsyncJobManager {
460
525
  * matching agent registered; with no filter, cancels every running job
461
526
  * (used by `dispose()` to nuke the manager's state).
462
527
  */
528
+ /**
529
+ * Synchronously fail a running job AND enqueue its delivery, exactly once.
530
+ *
531
+ * An externally owned wait -- an ACP client terminal, say -- can fail while its
532
+ * owner is being torn down. `cancel()` is the wrong tool there: it marks the job
533
+ * cancelled, and the cancelled path deliberately enqueues NO delivery, so the
534
+ * failure would never become visible to anyone. This is the single transition
535
+ * that both fails the job and delivers that failure in one synchronous block, so
536
+ * it cannot lose the race against disposal.
537
+ */
538
+ failNow(jobId: string, generation: string, errorText: string, options?: {
539
+ abort?: boolean;
540
+ }): boolean;
463
541
  cancelAll(filter?: AsyncJobFilter): void;
464
542
  waitForOwnerInFlightDeliveries(ownerId: string, options?: {
465
543
  timeoutMs?: number;
@@ -468,6 +546,11 @@ export declare class AsyncJobManager {
468
546
  timeoutMs?: number;
469
547
  }): Promise<boolean>;
470
548
  getLastDisposeDiagnostics(): AsyncJobDisposeDiagnostics;
549
+ /**
550
+ * Mark a running job as backgrounded (folded out of its foreground call).
551
+ * Read by getJobsSnapshot so folded work stays visible; safe to call twice.
552
+ */
553
+ markBackgrounded(jobId: string, generation: string): boolean;
471
554
  waitForAll(): Promise<void>;
472
555
  drainDeliveries(options?: {
473
556
  timeoutMs?: number;
@@ -1,9 +1,11 @@
1
+ import { type AuthCredentialSnapshot, type CredentialHealthResult } from "@gajae-code/ai/core";
1
2
  export type AuthGatewayAction = "serve" | "token" | "status" | "check";
2
3
  export interface AuthGatewayCommandArgs {
3
4
  action: AuthGatewayAction;
4
5
  flags: {
5
6
  json?: boolean;
6
7
  bind?: string;
8
+ provider?: string;
7
9
  regenerate?: boolean;
8
10
  /**
9
11
  * Disable bearer-token auth on inbound requests. Useful when the gateway
@@ -14,5 +16,20 @@ export interface AuthGatewayCommandArgs {
14
16
  };
15
17
  }
16
18
  declare const ACTIONS: readonly AuthGatewayAction[];
19
+ export declare function resolveAuthGatewayReadiness(input: {
20
+ noAuth: boolean;
21
+ tokenPresent: boolean;
22
+ credentialCount: number;
23
+ modelCount: number;
24
+ }): {
25
+ ready: boolean;
26
+ reason: "token_missing" | "provider_credential_missing" | "provider_catalog_empty" | null;
27
+ };
28
+ export declare function normalizeProviderScope(provider: string | undefined): string | undefined;
29
+ export declare function filterCredentialCheckResults(results: readonly CredentialHealthResult[], provider: string | undefined): CredentialHealthResult[];
30
+ export declare function redactBrokerUrl(rawUrl: string): string;
31
+ export declare function hasEnabledProviderCredential(snapshot: Pick<AuthCredentialSnapshot, "credentials">, provider: string): boolean;
32
+ export declare function matchesProviderCredential(entry: AuthCredentialSnapshot["credentials"][number], apiKey: string): boolean;
33
+ export declare function assertEnabledProviderCredential(snapshot: Pick<AuthCredentialSnapshot, "credentials">, provider: string): void;
17
34
  export declare function runAuthGatewayCommand(cmd: AuthGatewayCommandArgs): Promise<void>;
18
35
  export { ACTIONS as AUTH_GATEWAY_ACTIONS };
@@ -0,0 +1,9 @@
1
+ export declare const MODEL_PRESETS_ACTIONS: readonly ["status", "refresh", "rollback", "pin", "unpin", "disable", "enable"];
2
+ export type ModelPresetsAction = (typeof MODEL_PRESETS_ACTIONS)[number];
3
+ export interface ModelPresetsCommandArgs {
4
+ action: ModelPresetsAction;
5
+ revision?: string;
6
+ json?: boolean;
7
+ agentDir?: string;
8
+ }
9
+ export declare function runModelPresetsCommand(args: ModelPresetsCommandArgs): Promise<void>;
@@ -1,6 +1,7 @@
1
1
  import { Settings } from "../config/settings";
2
2
  import { type UpdateChannel } from "../config/update-channel";
3
3
  import { type NotificationProvider } from "../sdk/bus/config";
4
+ import type { TelemetryDetails, TelemetryEventName } from "../telemetry";
4
5
  import { type GithubReleaseLookupOptions } from "./github-release";
5
6
  export interface UpdateCommandOptions {
6
7
  force: boolean;
@@ -150,6 +151,7 @@ export interface UpdateCommandDependencies {
150
151
  restartDaemon?: (settings: Settings) => Promise<void>;
151
152
  recoverNotifications?: (settings: Settings) => Promise<void>;
152
153
  runPostUpdateRecovery?: (runtimePath: string) => Promise<void>;
154
+ recordTelemetryEvent?: (event: TelemetryEventName, details: TelemetryDetails) => unknown;
153
155
  exit?: (code: number) => never;
154
156
  }
155
157
  export type PostUpdateRecoverySpawn = (argv: string[]) => Promise<number>;
@@ -20,6 +20,9 @@ export default class AuthGateway extends Command {
20
20
  description: string;
21
21
  char: string;
22
22
  };
23
+ provider: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
24
+ description: string;
25
+ };
23
26
  regenerate: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
24
27
  description: string;
25
28
  };
@@ -2,6 +2,7 @@ import { Command } from "@gajae-code/utils/cli";
2
2
  export default class Gc extends Command {
3
3
  static description: string;
4
4
  static strict: boolean;
5
+ static delegateHelp: boolean;
5
6
  static flags: {
6
7
  json: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
7
8
  char: string;
@@ -28,6 +29,18 @@ export default class Gc extends Command {
28
29
  description: string;
29
30
  default: boolean;
30
31
  };
32
+ "empty-delete-receipts": import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
33
+ description: string;
34
+ default: boolean;
35
+ };
36
+ root: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
37
+ description: string;
38
+ multiple: true;
39
+ };
40
+ manifest: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
41
+ description: string;
42
+ multiple: true;
43
+ };
31
44
  };
32
45
  static examples: string[];
33
46
  run(): Promise<void>;
@@ -0,0 +1,21 @@
1
+ import { Command } from "@gajae-code/utils/cli";
2
+ export default class ModelPresets extends Command {
3
+ static description: string;
4
+ static args: {
5
+ action: import("@gajae-code/utils/cli").ArgDescriptor & {
6
+ description: string;
7
+ required: false;
8
+ options: readonly ["status", "refresh", "rollback", "pin", "unpin", "disable", "enable"];
9
+ };
10
+ revision: import("@gajae-code/utils/cli").ArgDescriptor & {
11
+ description: string;
12
+ required: false;
13
+ };
14
+ };
15
+ static flags: {
16
+ json: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
17
+ description: string;
18
+ };
19
+ };
20
+ run(): Promise<void>;
21
+ }
@@ -16821,6 +16821,102 @@ export declare const TIER_MAP_SKIP_LIST: {
16821
16821
  readonly baseline: true;
16822
16822
  readonly rationale: "pre-feature baseline; not yet curated";
16823
16823
  };
16824
+ readonly "kiro/auto": {
16825
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16826
+ };
16827
+ readonly "kiro/claude-haiku-4-5": {
16828
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16829
+ };
16830
+ readonly "kiro/claude-haiku-4.5": {
16831
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16832
+ };
16833
+ readonly "kiro/claude-opus-4-5": {
16834
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16835
+ };
16836
+ readonly "kiro/claude-opus-4-6": {
16837
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16838
+ };
16839
+ readonly "kiro/claude-opus-4-7": {
16840
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16841
+ };
16842
+ readonly "kiro/claude-opus-4-8": {
16843
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16844
+ };
16845
+ readonly "kiro/claude-opus-4.5": {
16846
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16847
+ };
16848
+ readonly "kiro/claude-opus-4.6": {
16849
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16850
+ };
16851
+ readonly "kiro/claude-opus-4.7": {
16852
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16853
+ };
16854
+ readonly "kiro/claude-opus-4.8": {
16855
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16856
+ };
16857
+ readonly "kiro/claude-opus-5": {
16858
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16859
+ };
16860
+ readonly "kiro/claude-sonnet-4": {
16861
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16862
+ };
16863
+ readonly "kiro/claude-sonnet-4-5": {
16864
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16865
+ };
16866
+ readonly "kiro/claude-sonnet-4-6": {
16867
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16868
+ };
16869
+ readonly "kiro/claude-sonnet-4.5": {
16870
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16871
+ };
16872
+ readonly "kiro/claude-sonnet-4.6": {
16873
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16874
+ };
16875
+ readonly "kiro/claude-sonnet-5": {
16876
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16877
+ };
16878
+ readonly "kiro/deepseek-3-2": {
16879
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16880
+ };
16881
+ readonly "kiro/deepseek-3.2": {
16882
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16883
+ };
16884
+ readonly "kiro/glm-5": {
16885
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16886
+ };
16887
+ readonly "kiro/gpt-5-6-luna": {
16888
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16889
+ };
16890
+ readonly "kiro/gpt-5-6-sol": {
16891
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16892
+ };
16893
+ readonly "kiro/gpt-5-6-terra": {
16894
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16895
+ };
16896
+ readonly "kiro/gpt-5.6-luna": {
16897
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16898
+ };
16899
+ readonly "kiro/gpt-5.6-sol": {
16900
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16901
+ };
16902
+ readonly "kiro/gpt-5.6-terra": {
16903
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16904
+ };
16905
+ readonly "kiro/minimax-m2-1": {
16906
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16907
+ };
16908
+ readonly "kiro/minimax-m2-5": {
16909
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16910
+ };
16911
+ readonly "kiro/minimax-m2.1": {
16912
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16913
+ };
16914
+ readonly "kiro/minimax-m2.5": {
16915
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16916
+ };
16917
+ readonly "kiro/qwen3-coder-next": {
16918
+ readonly rationale: "Kiro API-key catalog addition; not yet curated";
16919
+ };
16824
16920
  };
16825
16921
  export declare const CURATED_TIER_MAP: AutoroutingCuratedTierMap;
16826
16922
  /** Canonical JSON uses sorted object keys and preserves array order. */
@@ -1,3 +1,4 @@
1
+ import type { NativeDirectoryTreeResult, NativeExactUnlinkResult } from "@gajae-code/natives";
1
2
  export interface FileLockOptions {
2
3
  staleMs?: number;
3
4
  retries?: number;
@@ -9,8 +10,12 @@ export interface FileLockOptions {
9
10
  /** Previous local host identities accepted only when deciding stale-owner reclamation. */
10
11
  previousOwnerHostIds?: readonly string[];
11
12
  }
13
+ /** Release retries cover transient Windows/Dropbox handle denial without extending the lock indefinitely. */
14
+ export declare const FILE_LOCK_RELEASE_RETRY_ATTEMPTS = 5;
15
+ export declare const FILE_LOCK_RELEASE_RETRY_DELAY_MS = 10;
12
16
  export declare const FileLockTestHooks: {
13
17
  afterParentMkdir?: (lockPath: string) => void | Promise<void>;
18
+ nativeQuarantineBindings?: () => NativeFileLockBindings;
14
19
  };
15
20
  /**
16
21
  * Returns the OS-provided process start timestamp for PID-reuse detection.
@@ -25,16 +30,46 @@ export declare const FileLockTestHooks: {
25
30
  */
26
31
  export declare function processStartTime(pid: number): string | null;
27
32
  /** @internal */
33
+ export interface FileLockGcObservation {
34
+ info: FileLockOwnerToken;
35
+ bytes: string;
36
+ identity: GenericFileLockDirIdentity;
37
+ }
38
+ /** Capture owner bytes and the identity proving those exact bytes came from this tree. */
39
+ export declare function readFileLockObservationForGc(lockDir: string): Promise<FileLockGcObservation | null>;
40
+ /** @internal */
28
41
  export declare function readFileLockInfoForGc(lockDir: string): Promise<FileLockOwnerToken | null>;
29
42
  /** Owner identity stamped into a `<file>.lock/info` record. */
30
43
  export interface FileLockOwnerToken {
31
44
  pid: number;
32
45
  start_time?: string;
46
+ /** Encoding marker for the canonical UTC process-start identity. */
47
+ start_time_format?: string;
33
48
  owner_host_id?: string;
49
+ /** Unique acquisition generation, present on locks created by this runtime. */
50
+ owner_token?: string;
34
51
  timestamp: number;
35
52
  }
36
53
  /** Outcome of a guarded lock-dir removal attempt (`removeFileLockDirForGc`). */
37
- export type FileLockGcRemoval = "removed" | "owner_changed" | "missing";
54
+ export type FileLockGcRemoval = "removed" | "owner_changed" | "missing" | "cleanup_failed";
55
+ /** Identity evidence carried by the generic stale verdict into a later removal. */
56
+ export interface GenericFileLockDirIdentity {
57
+ rootDev: string;
58
+ rootIno: string;
59
+ infoDev: string;
60
+ infoIno: string;
61
+ infoNlink: string;
62
+ infoSize: string;
63
+ infoMtimeNs: string;
64
+ infoCtimeNs: string;
65
+ infoSha256: string;
66
+ }
67
+ export type GenericFileLockDirStaleVerdict = {
68
+ stale: false;
69
+ } | {
70
+ stale: true;
71
+ identity: GenericFileLockDirIdentity;
72
+ };
38
73
  /**
39
74
  * @internal
40
75
  * Fail-closed removal of a lock dir whose owner is expected to be dead or
@@ -52,7 +87,7 @@ export type FileLockGcRemoval = "removed" | "owner_changed" | "missing";
52
87
  * directory, so the residual read->unlink window cannot be fully eliminated,
53
88
  * but the reclaim-after-stale scenario the issue describes is now guarded.
54
89
  */
55
- export declare function removeFileLockDirForGc(lockDir: string, expected: FileLockOwnerToken): Promise<FileLockGcRemoval>;
90
+ export declare function removeFileLockDirForGc(lockDir: string, expected: FileLockOwnerToken, preVerdictIdentity?: GenericFileLockDirIdentity): Promise<FileLockGcRemoval>;
56
91
  /**
57
92
  * @internal
58
93
  * READ-ONLY verdict on an EXISTING generic `<file>.lock/` directory that another lock
@@ -71,6 +106,17 @@ export declare function removeFileLockDirForGc(lockDir: string, expected: FileLo
71
106
  * the object is no longer the one that was judged.
72
107
  */
73
108
  export declare function genericFileLockDirIsStale(lockDir: string, staleMs: number, ownerHostId?: string): Promise<boolean>;
109
+ /**
110
+ * Render a generic stale verdict together with the root and owner-file identity that
111
+ * verdict actually observed. A caller that removes the directory must require a later
112
+ * native snapshot to carry this same identity; a snapshot taken only after a clone was
113
+ * installed is not authority for the stale verdict.
114
+ */
115
+ export declare function genericFileLockDirStaleVerdict(lockDir: string, staleMs: number, ownerHostId?: string): Promise<GenericFileLockDirStaleVerdict>;
116
+ type NativeFileLockBindings = {
117
+ snapshotDirectoryTree(lockPath: string): NativeDirectoryTreeResult;
118
+ exactRemoveDirectoryTree(lockPath: string, snapshot: NonNullable<NativeDirectoryTreeResult["snapshot"]>): NativeExactUnlinkResult;
119
+ };
74
120
  /**
75
121
  * Serializes all contenders, including callers in the same process. Because this
76
122
  * API exposes no ownership token, recursive acquisition is indistinguishable
@@ -78,3 +124,4 @@ export declare function genericFileLockDirIsStale(lockDir: string, staleMs: numb
78
124
  * that fact through its own `lockHeld` path instead of acquiring it again.
79
125
  */
80
126
  export declare function withFileLock<T>(filePath: string, fn: () => Promise<T>, options?: FileLockOptions): Promise<T>;
127
+ export {};
@@ -0,0 +1,4 @@
1
+ import type { ModelPresetRegistryTrustedKey } from "../model-preset-registry";
2
+ export declare function getModelPresetRegistryTestTrustedKeys(agentDir: string): ReadonlyMap<string, ModelPresetRegistryTrustedKey> | undefined;
3
+ export declare function modelPresetRegistryTestUrlsAllowed(agentDir: string): boolean;
4
+ export declare function runWithModelPresetRegistryTestTrust<T>(agentDir: string, trustedKeys: ReadonlyMap<string, ModelPresetRegistryTrustedKey>, operation: () => T): T;
@@ -0,0 +1,3 @@
1
+ import type { ModelPresetRegistryTrustedKey } from "../model-preset-registry";
2
+ /** Runs one test operation with scoped trust. This module is denied by package exports. */
3
+ export declare function withModelPresetRegistryTestTrust<T>(agentDir: string, trustedKeys: ReadonlyMap<string, ModelPresetRegistryTrustedKey>, operation: () => T): T;
@@ -60,6 +60,7 @@ declare module "@gajae-code/tui" {
60
60
  }
61
61
  export declare function defaultMessageQueueKeysForPlatform(platform?: NodeJS.Platform): KeyId;
62
62
  export declare function defaultClipboardPasteImageKeysForPlatform(platform?: NodeJS.Platform): KeyId[];
63
+ export declare function defaultForegroundFoldKeysForPlatform(platform?: NodeJS.Platform): KeyId[];
63
64
  /**
64
65
  * All keybindings definitions: TUI + app-specific.
65
66
  */
@@ -241,8 +242,8 @@ export declare const KEYBINDINGS: {
241
242
  readonly description: "Expand tools";
242
243
  };
243
244
  readonly "app.tool.backgroundFold": {
244
- readonly defaultKeys: "ctrl+b";
245
- readonly description: "Fold/background supported foreground tool";
245
+ readonly defaultKeys: KeyId[];
246
+ readonly description: "Fold supported foreground tool into a background job";
246
247
  };
247
248
  readonly "app.editor.external": {
248
249
  readonly defaultKeys: "ctrl+g";