@gajae-code/coding-agent 0.15.6 → 0.16.1

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 (270) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/dist/types/async/job-manager.d.ts +32 -1
  3. package/dist/types/browser-backend.d.ts +12 -0
  4. package/dist/types/cli/args.d.ts +2 -0
  5. package/dist/types/cli/root-flags.d.ts +14 -0
  6. package/dist/types/cli/update-cli.d.ts +14 -0
  7. package/dist/types/cli.d.ts +7 -0
  8. package/dist/types/commands/launch.d.ts +10 -0
  9. package/dist/types/commands/sdk.d.ts +2 -0
  10. package/dist/types/config/autorouting-tier-map.d.ts +24 -0
  11. package/dist/types/config/billing-path.d.ts +25 -0
  12. package/dist/types/config/config-schema-version.d.ts +13 -1
  13. package/dist/types/config/file-lock.d.ts +5 -0
  14. package/dist/types/config/model-registry.d.ts +22 -0
  15. package/dist/types/config/settings-schema.d.ts +27 -8
  16. package/dist/types/config/settings.d.ts +2 -0
  17. package/dist/types/coordinator-mcp/projection-scan.d.ts +8 -0
  18. package/dist/types/crash/record-loader.d.ts +15 -0
  19. package/dist/types/extensibility/extensions/types.d.ts +8 -3
  20. package/dist/types/gjc-runtime/launch-worktree-reservation.d.ts +21 -0
  21. package/dist/types/gjc-runtime/launch-worktree.d.ts +25 -1
  22. package/dist/types/gjc-runtime/managed-owner-supervisor.d.ts +2 -0
  23. package/dist/types/gjc-runtime/session-state-lock.d.ts +22 -0
  24. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +66 -1
  25. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +1 -0
  26. package/dist/types/gjc-runtime/tmux-sessions.d.ts +27 -0
  27. package/dist/types/main.d.ts +1 -0
  28. package/dist/types/master-mode/context.d.ts +21 -0
  29. package/dist/types/master-mode/first-request.d.ts +34 -0
  30. package/dist/types/master-mode/snapshot.d.ts +32 -0
  31. package/dist/types/modes/acp/acp-agent.d.ts +21 -21
  32. package/dist/types/modes/components/frictionless-onboarding-selector.d.ts +10 -0
  33. package/dist/types/modes/components/model-selector.d.ts +4 -0
  34. package/dist/types/modes/components/oauth-selector.d.ts +1 -0
  35. package/dist/types/modes/components/session-selector.d.ts +1 -1
  36. package/dist/types/modes/components/sessions-dashboard.d.ts +2 -1
  37. package/dist/types/modes/components/status-line/model-name.d.ts +18 -0
  38. package/dist/types/modes/components/status-line/priority-row.d.ts +34 -0
  39. package/dist/types/modes/components/status-line/segments.d.ts +10 -0
  40. package/dist/types/modes/interactive-mode.d.ts +16 -2
  41. package/dist/types/modes/print-mode.d.ts +17 -0
  42. package/dist/types/modes/theme/theme.d.ts +2 -1
  43. package/dist/types/modes/types.d.ts +2 -0
  44. package/dist/types/modes/ui-language.d.ts +7 -1
  45. package/dist/types/sdk/broker/broker.d.ts +79 -2
  46. package/dist/types/sdk/broker/endpoint-authority.d.ts +24 -0
  47. package/dist/types/sdk/broker/ensure.d.ts +3 -0
  48. package/dist/types/sdk/broker/index.d.ts +3 -0
  49. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +6 -0
  50. package/dist/types/sdk/broker/lifecycle.d.ts +40 -0
  51. package/dist/types/sdk/broker/master-capability.d.ts +10 -0
  52. package/dist/types/sdk/broker/session-index.d.ts +40 -11
  53. package/dist/types/sdk/broker/session-scope.d.ts +72 -0
  54. package/dist/types/sdk/broker/spawn-authority.d.ts +201 -0
  55. package/dist/types/sdk/broker/spawn-substrate.d.ts +30 -0
  56. package/dist/types/sdk/broker/startup-budget.d.ts +52 -0
  57. package/dist/types/sdk/broker/state-version.d.ts +21 -1
  58. package/dist/types/sdk/broker/worktree-occupancy.d.ts +28 -0
  59. package/dist/types/sdk/bus/chat-daemon-control.d.ts +3 -0
  60. package/dist/types/sdk/bus/discord-daemon.d.ts +1 -1
  61. package/dist/types/sdk/bus/index.d.ts +9 -1
  62. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +1 -1
  63. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +1 -1
  64. package/dist/types/sdk/bus/slack-conversation.d.ts +1 -1
  65. package/dist/types/sdk/bus/slack-daemon.d.ts +1 -1
  66. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +1 -1
  67. package/dist/types/sdk/cli/index.d.ts +1 -0
  68. package/dist/types/sdk/cli/master-cli.d.ts +63 -0
  69. package/dist/types/sdk/cli/rows.d.ts +12 -5
  70. package/dist/types/sdk/cli/session-cli.d.ts +20 -3
  71. package/dist/types/sdk/client/client.d.ts +3 -2
  72. package/dist/types/sdk/host/control/dispatch.d.ts +10 -0
  73. package/dist/types/sdk/host/control/index.d.ts +1 -1
  74. package/dist/types/sdk/host/control/operations.d.ts +2 -0
  75. package/dist/types/sdk/host/control/runtime-gate.d.ts +21 -7
  76. package/dist/types/sdk/host/events.d.ts +1 -0
  77. package/dist/types/sdk/host/host.d.ts +10 -0
  78. package/dist/types/sdk/host/query/cursor.d.ts +4 -2
  79. package/dist/types/sdk/host/query/handlers.d.ts +1 -0
  80. package/dist/types/sdk/host/query/revision-store.d.ts +1 -0
  81. package/dist/types/sdk/host/session-runtime.d.ts +70 -17
  82. package/dist/types/sdk/lifecycle/broker-client.d.ts +6 -0
  83. package/dist/types/sdk/lifecycle/service.d.ts +15 -3
  84. package/dist/types/sdk/lifecycle-session.d.ts +3 -1
  85. package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -5
  86. package/dist/types/sdk/receipt-state.d.ts +2 -0
  87. package/dist/types/sdk/router/session-router.d.ts +6 -0
  88. package/dist/types/sdk/session.d.ts +16 -0
  89. package/dist/types/sdk/startup-capability.d.ts +2 -1
  90. package/dist/types/sdk/turn-result.d.ts +6 -0
  91. package/dist/types/session/agent-session.d.ts +52 -7
  92. package/dist/types/session/credential-store-errors.d.ts +1 -0
  93. package/dist/types/session/fold-coordinator.d.ts +29 -2
  94. package/dist/types/session/session-manager.d.ts +79 -2
  95. package/dist/types/session/yield-queue.d.ts +5 -4
  96. package/dist/types/setup/frictionless-onboarding.d.ts +1 -0
  97. package/dist/types/tools/ask.d.ts +1 -0
  98. package/dist/types/tools/bash.d.ts +16 -0
  99. package/dist/types/tools/browser/launch.d.ts +10 -0
  100. package/dist/types/tools/browser/registry.d.ts +8 -0
  101. package/dist/types/tools/gh.d.ts +8 -0
  102. package/dist/types/tools/index.d.ts +10 -10
  103. package/dist/types/tools/job.d.ts +3 -1
  104. package/dist/types/utils/external-editor.d.ts +7 -0
  105. package/examples/extensions/README.md +1 -1
  106. package/examples/extensions/pirate.ts +7 -4
  107. package/package.json +7 -7
  108. package/scripts/generate-sdk-operation-inventory.ts +13 -1
  109. package/scripts/verify-gjc-sdk-canonicalization.ts +35 -1
  110. package/src/async/job-manager.ts +107 -9
  111. package/src/browser-backend.ts +29 -0
  112. package/src/cli/accounts-cli.ts +9 -5
  113. package/src/cli/args.ts +17 -0
  114. package/src/cli/fast-help.ts +1 -0
  115. package/src/cli/plugin-cli.ts +29 -0
  116. package/src/cli/root-flags.ts +5 -0
  117. package/src/cli/update-cli.ts +140 -23
  118. package/src/commands/launch.ts +86 -18
  119. package/src/commands/sdk.ts +135 -28
  120. package/src/config/autorouting-tier-map.ts +12 -0
  121. package/src/config/billing-path.ts +42 -0
  122. package/src/config/config-schema-version.ts +18 -1
  123. package/src/config/file-lock.ts +158 -83
  124. package/src/config/model-preset-registry.ts +178 -23
  125. package/src/config/model-profiles.ts +5 -5
  126. package/src/config/model-registry.ts +291 -42
  127. package/src/config/model-resolver.ts +5 -0
  128. package/src/config/settings-schema.ts +27 -8
  129. package/src/config/settings.ts +51 -15
  130. package/src/coordinator-mcp/projection-scan.ts +27 -6
  131. package/src/coordinator-mcp/question-state.ts +9 -11
  132. package/src/coordinator-mcp/server.ts +115 -21
  133. package/src/crash/index-store.ts +2 -0
  134. package/src/crash/record-loader.ts +10 -0
  135. package/src/defaults/gjc/skills/deep-interview/SKILL.md +1 -1
  136. package/src/extensibility/extensions/runner.ts +27 -0
  137. package/src/extensibility/extensions/types.ts +8 -3
  138. package/src/extensibility/gjc-plugins/installer.ts +51 -11
  139. package/src/extensibility/runtime-skill-discovery.ts +110 -3
  140. package/src/extensibility/skills.ts +22 -12
  141. package/src/gjc-runtime/launch-worktree-reservation.ts +242 -0
  142. package/src/gjc-runtime/launch-worktree.ts +285 -4
  143. package/src/gjc-runtime/managed-owner-supervisor.ts +63 -51
  144. package/src/gjc-runtime/session-state-lock.ts +213 -14
  145. package/src/gjc-runtime/session-state-sidecar.ts +938 -39
  146. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +4 -7
  147. package/src/gjc-runtime/tmux-owner-isolation.ts +18 -3
  148. package/src/gjc-runtime/tmux-sessions.ts +252 -13
  149. package/src/hooks/skill-state.ts +6 -0
  150. package/src/internal-urls/docs-index.generated.ts +15 -15
  151. package/src/internal-urls/issue-pr-protocol.ts +4 -2
  152. package/src/main.ts +61 -3
  153. package/src/master-mode/context.ts +50 -0
  154. package/src/master-mode/first-request.ts +65 -0
  155. package/src/master-mode/snapshot.ts +205 -0
  156. package/src/modes/acp/acp-agent.ts +610 -161
  157. package/src/modes/components/footer.ts +4 -2
  158. package/src/modes/components/frictionless-onboarding-selector.ts +48 -2
  159. package/src/modes/components/model-selector.ts +76 -8
  160. package/src/modes/components/oauth-selector.ts +6 -1
  161. package/src/modes/components/session-selector.ts +23 -15
  162. package/src/modes/components/sessions-dashboard.ts +8 -5
  163. package/src/modes/components/settings-selector.ts +1 -0
  164. package/src/modes/components/status-line/model-name.ts +53 -0
  165. package/src/modes/components/status-line/priority-row.ts +107 -0
  166. package/src/modes/components/status-line/segments.ts +23 -9
  167. package/src/modes/components/tool-status-header.ts +151 -15
  168. package/src/modes/controllers/command-controller.ts +1 -1
  169. package/src/modes/controllers/event-controller.ts +30 -4
  170. package/src/modes/controllers/extension-ui-controller.ts +13 -13
  171. package/src/modes/controllers/input-controller.ts +30 -2
  172. package/src/modes/controllers/selector-controller.ts +200 -98
  173. package/src/modes/interactive-mode.ts +36 -12
  174. package/src/modes/print-mode.ts +64 -0
  175. package/src/modes/prompt-action-autocomplete.ts +30 -4
  176. package/src/modes/runtime-init.ts +12 -9
  177. package/src/modes/theme/theme.ts +5 -0
  178. package/src/modes/types.ts +2 -0
  179. package/src/modes/ui-language.ts +49 -2
  180. package/src/modes/utils/ui-helpers.ts +22 -3
  181. package/src/prompts/agent-fragments/browser-aside.md +22 -0
  182. package/src/prompts/system/master-mode.md +28 -0
  183. package/src/prompts/tools/ask.md +1 -1
  184. package/src/prompts/tools/bash.md +1 -0
  185. package/src/prompts/tools/job.md +1 -1
  186. package/src/sdk/acp/adapter.ts +5 -0
  187. package/src/sdk/broker/broker.ts +1646 -27
  188. package/src/sdk/broker/endpoint-authority.ts +86 -0
  189. package/src/sdk/broker/ensure.ts +81 -3
  190. package/src/sdk/broker/index.ts +3 -0
  191. package/src/sdk/broker/lifecycle-ledger.ts +6 -0
  192. package/src/sdk/broker/lifecycle.ts +440 -75
  193. package/src/sdk/broker/master-capability.ts +232 -0
  194. package/src/sdk/broker/session-index.ts +121 -17
  195. package/src/sdk/broker/session-scope.ts +272 -0
  196. package/src/sdk/broker/spawn-authority.ts +1031 -0
  197. package/src/sdk/broker/spawn-substrate.ts +591 -0
  198. package/src/sdk/broker/startup-budget.ts +144 -2
  199. package/src/sdk/broker/state-version.ts +43 -14
  200. package/src/sdk/broker/transport.ts +1 -0
  201. package/src/sdk/broker/worktree-occupancy.ts +90 -0
  202. package/src/sdk/bus/chat-daemon-control.ts +5 -2
  203. package/src/sdk/bus/chat-daemon-runtime.ts +136 -18
  204. package/src/sdk/bus/discord-daemon.ts +50 -10
  205. package/src/sdk/bus/index.ts +84 -7
  206. package/src/sdk/bus/kind-aware-reconciliation.ts +296 -48
  207. package/src/sdk/bus/lifecycle-commands.ts +4 -0
  208. package/src/sdk/bus/notification-service.ts +22 -5
  209. package/src/sdk/bus/prompt-reconciliation.ts +7 -2
  210. package/src/sdk/bus/reconciliation-store.ts +55 -31
  211. package/src/sdk/bus/slack-conversation.ts +1 -1
  212. package/src/sdk/bus/slack-daemon.ts +72 -38
  213. package/src/sdk/bus/telegram-daemon-contract.ts +1 -1
  214. package/src/sdk/cli/index.ts +1 -0
  215. package/src/sdk/cli/master-cli.ts +259 -0
  216. package/src/sdk/cli/rows.ts +41 -15
  217. package/src/sdk/cli/session-cli.ts +297 -26
  218. package/src/sdk/client/client.ts +14 -8
  219. package/src/sdk/host/control/dispatch.ts +101 -40
  220. package/src/sdk/host/control/index.ts +2 -0
  221. package/src/sdk/host/control/operations.ts +2 -0
  222. package/src/sdk/host/control/runtime-gate.ts +203 -11
  223. package/src/sdk/host/events.ts +1 -0
  224. package/src/sdk/host/host.ts +29 -2
  225. package/src/sdk/host/query/cursor.ts +52 -7
  226. package/src/sdk/host/query/handlers.ts +33 -12
  227. package/src/sdk/host/query/revision-store.ts +12 -0
  228. package/src/sdk/host/session-runtime.test.ts +673 -14
  229. package/src/sdk/host/session-runtime.ts +674 -103
  230. package/src/sdk/host/surface-policy.ts +3 -3
  231. package/src/sdk/lifecycle/broker-client.ts +28 -0
  232. package/src/sdk/lifecycle/service.ts +279 -20
  233. package/src/sdk/lifecycle-session.ts +17 -4
  234. package/src/sdk/prompt-deadline-manager.ts +2 -1
  235. package/src/sdk/protocol/operation-inventory.generated.json +105 -3
  236. package/src/sdk/protocol/operation-registry.ts +14 -4
  237. package/src/sdk/receipt-state.ts +10 -0
  238. package/src/sdk/router/session-router.ts +219 -118
  239. package/src/sdk/session.ts +416 -195
  240. package/src/sdk/startup-capability.ts +1 -0
  241. package/src/sdk/turn-result.ts +22 -0
  242. package/src/session/agent-session.ts +1628 -318
  243. package/src/session/blob-store.ts +15 -5
  244. package/src/session/credential-store-errors.ts +2 -0
  245. package/src/session/fold-coordinator.ts +40 -3
  246. package/src/session/internal/managed-session-storage.ts +153 -78
  247. package/src/session/session-manager.ts +850 -97
  248. package/src/session/yield-queue.ts +24 -10
  249. package/src/setup/frictionless-onboarding.ts +2 -0
  250. package/src/slash-commands/builtin-registry.ts +41 -0
  251. package/src/task/executor.ts +9 -4
  252. package/src/telemetry/events.ts +1138 -12
  253. package/src/tools/ask-contract.test.ts +64 -0
  254. package/src/tools/ask-contract.ts +36 -1
  255. package/src/tools/ask.ts +10 -8
  256. package/src/tools/bash-interactive.ts +11 -2
  257. package/src/tools/bash.ts +412 -75
  258. package/src/tools/browser/launch.ts +37 -0
  259. package/src/tools/browser/registry.ts +99 -9
  260. package/src/tools/cron.ts +6 -4
  261. package/src/tools/descriptors.test.ts +15 -0
  262. package/src/tools/descriptors.ts +5 -1
  263. package/src/tools/gh.ts +104 -48
  264. package/src/tools/github-cache.ts +2 -2
  265. package/src/tools/index.ts +10 -6
  266. package/src/tools/job.ts +4 -1
  267. package/src/tools/monitor.ts +12 -9
  268. package/src/tools/resolve.ts +30 -10
  269. package/src/tools/tool-catalog.generated.ts +2 -2
  270. package/src/utils/external-editor.ts +72 -1
@@ -67,7 +67,7 @@ export interface ForkContextSeedOptions {
67
67
  signal?: AbortSignal;
68
68
  }
69
69
  import type { AuthCredentialSelector } from "@gajae-code/ai/core";
70
- import { type AsyncJob, type AsyncJobDeliveryState, AsyncJobManager } from "../async";
70
+ import { type AsyncJob, type AsyncJobDeliveryState, AsyncJobManager, type FoldReason, type JobFoldEvent } from "../async";
71
71
  import type { Rule } from "../capability/rule";
72
72
  import { type ModelRegistry } from "../config/model-registry";
73
73
  import { type ResolvedModelRoleValue, type ScopedModelSelection } from "../config/model-resolver";
@@ -109,7 +109,7 @@ import { type ConfiguredFallbackChain, type FallbackChainRuntimeState } from "./
109
109
  export { DefaultModelSelectionRecoveryError } from "./default-model-selection";
110
110
  import type { ClientBridge, ClientBridgePermissionOption, ClientBridgePermissionOutcome, ClientBridgePermissionToolCall } from "./client-bridge";
111
111
  import { type ContributionPrepOptions, type ContributionPrepResult } from "./contribution-prep";
112
- import { type FoldAdapter, FoldCoordinator } from "./fold-coordinator";
112
+ import { type FoldAdapter, FoldCoordinator, type ForegroundFoldOutcome } from "./fold-coordinator";
113
113
  import type { MemoryGuardRestoreResult } from "./memory-guard-checkpoint-participant";
114
114
  import { type CustomMessage } from "./messages";
115
115
  import type { BranchSummaryEntry, CompactionEntry, NewSessionOptions, PreparedNewSession, RecoveryHydrationContext, RecoveryHydrationPromotionFence, SessionContext, SessionManagerCloseOutcome, SessionMemoryStats } from "./session-manager";
@@ -399,6 +399,8 @@ export interface PromptOptions {
399
399
  streamingBehavior?: "steer" | "followUp";
400
400
  /** When set to "sequential", this follow-up is delivered one prompt at a time even if followUpMode is "all". */
401
401
  followUpQueuePolicy?: "respect-mode" | "sequential";
402
+ /** When set to "sequential", this steer is delivered on its own even if steeringMode is "all". */
403
+ steerQueuePolicy?: "respect-mode" | "sequential";
402
404
  /** Optional tool choice override for the next LLM call. */
403
405
  toolChoice?: ToolChoice;
404
406
  /** Send as developer/system message instead of user. Providers that support it use the developer role; others fall back to user. */
@@ -524,6 +526,10 @@ interface EphemeralTurnResult {
524
526
  replyText: string;
525
527
  assistantMessage: AssistantMessage;
526
528
  }
529
+ export declare class SessionDisposalIncompleteError extends Error {
530
+ constructor(label?: string);
531
+ }
532
+ export declare function isSessionDisposalIncompleteError(error: unknown): error is SessionDisposalIncompleteError;
527
533
  export interface AgentBashArtifactStore {
528
534
  saveArtifact(content: string, toolType: string): Promise<string | undefined>;
529
535
  getArtifactPath(id: string): Promise<string | null>;
@@ -570,6 +576,7 @@ export declare class WorkerIntegrationRequestScheduler {
570
576
  enqueue(): void;
571
577
  flush(): Promise<void>;
572
578
  flushWithOutcome(): Promise<WorkerIntegrationOutcome>;
579
+ joinOwnedRequests(): Promise<void>;
573
580
  }
574
581
  export type StreamingEditParsedToolCall = {
575
582
  toolCall: ToolCall;
@@ -747,6 +754,11 @@ export declare class AgentSession {
747
754
  * Call this when completely done with the session.
748
755
  */
749
756
  dispose(): Promise<void>;
757
+ /** Join the retained teardown owner without allocating another public deadline. */
758
+ awaitDisposeCompletion(): Promise<void>;
759
+ setDisposeTimeoutForTests(timeoutMs: number): void;
760
+ trackPostPromptTaskForTests(task: Promise<void>): void;
761
+ requestWorkerIntegrationForTests(): void;
750
762
  /**
751
763
  * Strict writer close for ACP session delete. On the first attempt it flushes
752
764
  * pending writes, then returns the certainty-aware close outcome so the caller
@@ -805,6 +817,13 @@ export declare class AgentSession {
805
817
  * proceeds.
806
818
  */
807
819
  awaitSessionSettlement(): Promise<void>;
820
+ /** Test seam: hold prompt admission while bypassing a pending selection fence. */
821
+ runWithPromptAdmissionForTests(body: () => Promise<void>): Promise<void>;
822
+ queueCoordinatorRuntimeStatePersistForTests(event: AgentSessionEvent, gate: Promise<void>): Promise<void>;
823
+ parkAgentEndForCoordinatorPersistForTests(event: Extract<AgentSessionEvent, {
824
+ type: "agent_end";
825
+ }>): void;
826
+ flushParkedAgentEndForCoordinatorPersistForTests(): void;
808
827
  drainAsyncJobDeliveriesForAcp(options?: {
809
828
  timeoutMs?: number;
810
829
  }): Promise<boolean>;
@@ -862,11 +881,31 @@ export declare class AgentSession {
862
881
  get sdkPermissionMode(): "prompt" | "allow" | "deny";
863
882
  /** Register or clear the SDK reverse permission provider for this session. */
864
883
  setSdkPermissionProvider(provider: ((toolCall: ClientBridgePermissionToolCall, options: ClientBridgePermissionOption[], signal?: AbortSignal) => Promise<ClientBridgePermissionOutcome>) | undefined): void;
884
+ /**
885
+ * Subscribe to folds of this session's foreground waits. Backed by the
886
+ * session-owned manager (or the process-global instance for legacy setups)
887
+ * so the SDK host can publish one `bash_folded` frame per fold.
888
+ */
889
+ onJobFold(listener: (event: JobFoldEvent) => void): () => void;
865
890
  /**
866
891
  * Ask the active managed foreground bash call to return as a background job.
867
892
  * Returns false when no supported foreground tool is currently backgroundable.
893
+ * `reason` names the trigger (`chord` for the keybinding, `sdk_control` for
894
+ * the `bash.background` control) and is recorded on the folded job.
895
+ */
896
+ requestForegroundBashBackground(reason?: FoldReason, adapter?: FoldAdapter): Promise<boolean>;
897
+ /**
898
+ * Typed variant of {@link requestForegroundBashBackground} for the SDK
899
+ * `bash.background` control (C52), which must distinguish "this fold moved
900
+ * the wait" from "an earlier fold already moved it" from "nothing to fold".
901
+ *
902
+ * `already_backgrounded` is reported when no wait is foldable but this
903
+ * session still has a running job that a fold (steer, chord, timer, or a
904
+ * prior control call) moved out of the foreground: `metadata.foldReason` is
905
+ * set only by folds, never by `async: true` starts, so it is the exact
906
+ * evidence that the wait the client is asking about has already left.
868
907
  */
869
- requestForegroundBashBackground(): Promise<boolean>;
908
+ requestForegroundBashBackgroundOutcome(reason?: FoldReason, adapter?: FoldAdapter): Promise<ForegroundFoldOutcome>;
870
909
  /**
871
910
  * Get all configured tool names (built-in via --tools or default, plus custom tools).
872
911
  */
@@ -939,7 +978,7 @@ export declare class AgentSession {
939
978
  /** Current follow-up mode */
940
979
  get followUpMode(): "all" | "one-at-a-time";
941
980
  /** Current interrupt mode */
942
- get interruptMode(): "immediate" | "wait";
981
+ get toolInterruptPolicy(): "abort_tools" | "finish_tools";
943
982
  /** Current session file path, or undefined if sessions are disabled */
944
983
  get sessionFile(): string | undefined;
945
984
  /** Current session ID */
@@ -1014,7 +1053,7 @@ export declare class AgentSession {
1014
1053
  * @throws Error if no model selected or no API key available (when not streaming)
1015
1054
  */
1016
1055
  prompt(text: string, options?: PromptOptions): Promise<void>;
1017
- promptCustomMessage<T = unknown>(message: Pick<CustomMessage<T>, "customType" | "content" | "display" | "details" | "attribution">, options?: Pick<PromptOptions, "streamingBehavior" | "toolChoice" | "followUpQueuePolicy" | "onPreflightAccepted" | "onPreflightAcceptCommit" | "preflightSignal" | "sdkRunCapability">): Promise<void>;
1056
+ promptCustomMessage<T = unknown>(message: Pick<CustomMessage<T>, "customType" | "content" | "display" | "details" | "attribution">, options?: Pick<PromptOptions, "streamingBehavior" | "toolChoice" | "followUpQueuePolicy" | "steerQueuePolicy" | "onPreflightAccepted" | "onPreflightAcceptCommit" | "preflightSignal" | "sdkRunCapability">): Promise<void>;
1018
1057
  /**
1019
1058
  * Queue a steering message to interrupt the agent mid-run.
1020
1059
  */
@@ -1041,6 +1080,7 @@ export declare class AgentSession {
1041
1080
  triggerTurn?: boolean;
1042
1081
  deliverAs?: "steer" | "followUp" | "nextTurn";
1043
1082
  followUpQueuePolicy?: "respect-mode" | "sequential";
1083
+ steerQueuePolicy?: "respect-mode" | "sequential";
1044
1084
  /** INTERNAL trusted option: origin of a hidden next-turn message —
1045
1085
  * "turn" (produced by the current turn's continuation machinery,
1046
1086
  * purged by a terminal abort) or "external" (background producers,
@@ -1160,6 +1200,7 @@ export declare class AgentSession {
1160
1200
  timeoutMs?: number;
1161
1201
  cause?: "user_interrupt" | "new_session" | "session_switch" | "compaction" | "handoff" | "tool_abort" | "internal";
1162
1202
  silent?: boolean;
1203
+ preserveCompaction?: boolean;
1163
1204
  }): Promise<void>;
1164
1205
  /**
1165
1206
  * Private terminal-abort seam: read the CURRENT turn's attempt epoch WITHOUT
@@ -1394,6 +1435,10 @@ export declare class AgentSession {
1394
1435
  onBeforeMutation?: () => void;
1395
1436
  /** Run inside the selection admission after the durable mutation. */
1396
1437
  onAfterMutation?: () => void;
1438
+ /** Test seam: pause after idle drain but before mutation admission. */
1439
+ onBeforeMutationAdmissionForTests?: () => Promise<void>;
1440
+ /** Test seam: pause after mutation admission activates, before its closed-fence recheck. */
1441
+ onAfterMutationAdmissionReadyForTests?: () => Promise<void>;
1397
1442
  }): Promise<DefaultModelSelectionResult>;
1398
1443
  /**
1399
1444
  * Cycle to next/previous model.
@@ -1490,10 +1535,10 @@ export declare class AgentSession {
1490
1535
  */
1491
1536
  setFollowUpMode(mode: "all" | "one-at-a-time"): void;
1492
1537
  /**
1493
- * Set interrupt mode.
1538
+ * Set the tool interrupt policy (whether a steer aborts in-flight tools).
1494
1539
  * Saves to settings.
1495
1540
  */
1496
- setInterruptMode(mode: "immediate" | "wait"): void;
1541
+ setToolInterruptPolicy(policy: "abort_tools" | "finish_tools"): void;
1497
1542
  /**
1498
1543
  * Manually compact the session context.
1499
1544
  * Aborts current agent operation first.
@@ -0,0 +1 @@
1
+ export declare const CREDENTIAL_STORE_UNREADABLE_MESSAGE = "Credential store is unreadable. Back up the database, then have an operator run PRAGMA integrity_check or REINDEX; no automatic repair was attempted.";
@@ -23,7 +23,7 @@
23
23
  * delivery therefore still carries its receipt and can never silently
24
24
  * degrade into an ordinary receipt-less completion.
25
25
  */
26
- import type { AsyncJob } from "../async/job-manager";
26
+ import type { AsyncJob, FoldReason } from "../async/job-manager";
27
27
  /**
28
28
  * Idle-flush merge window.
29
29
  *
@@ -62,6 +62,8 @@ export interface FoldReceipt {
62
62
  foldedAt: number;
63
63
  /** Only command kinds can change directory; task-style waits never do. */
64
64
  cwdSensitive: boolean;
65
+ /** What triggered the fold; recorded on the job as `metadata.foldReason`. */
66
+ reason: FoldReason;
65
67
  }
66
68
  /** A terminal completion observed for a folded job. */
67
69
  export interface ForegroundTerminalPayload {
@@ -104,6 +106,26 @@ export type FoldRequestResult = {
104
106
  status: "capture-failed";
105
107
  reason: string;
106
108
  };
109
+ /**
110
+ * Session-level answer to "fold the foreground bash now". Consumed by the SDK
111
+ * `bash.background` control, whose declared error codes are exactly these
112
+ * non-folded statuses.
113
+ */
114
+ export type ForegroundFoldOutcome = {
115
+ status: "folded";
116
+ jobId: string;
117
+ } | {
118
+ status: "already_backgrounded";
119
+ } | {
120
+ status: "no_active_bash";
121
+ } | {
122
+ status: "not_foldable";
123
+ reason: string;
124
+ };
125
+ /** Map a non-folded outcome onto the C52 `bash.background` error contract (`not_foldable` | `already_backgrounded` | `no_active_bash`). */
126
+ export declare function bashBackgroundControlError(outcome: Exclude<ForegroundFoldOutcome, {
127
+ status: "folded";
128
+ }>): Error;
107
129
  /** What a delivery should carry, decided by the durable slot state (T2). */
108
130
  export type FoldDeliveryDisposition = {
109
131
  kind: "ordinary";
@@ -166,8 +188,13 @@ export declare class FoldCoordinator {
166
188
  * Nothing awaits before the slot is reserved and the fence is armed, so a
167
189
  * completion or a steering submission that races the capture cannot slip
168
190
  * past into the old turn.
191
+ *
192
+ * A `steer` fold is the one trigger that does NOT end the turn: the steer
193
+ * that caused it must be consumed by the same run at the tool boundary
194
+ * right after the fold result (subagent-await parity), so no fence is
195
+ * armed, no stop is requested, and no remaining intent is captured.
169
196
  */
170
- requestFold(explicit?: FoldAdapter): Promise<FoldRequestResult>;
197
+ requestFold(explicit?: FoldAdapter, reason?: FoldReason): Promise<FoldRequestResult>;
171
198
  /**
172
199
  * T2. Decide what a delivery carries, branching on the DURABLE slot state
173
200
  * rather than on transient hand-off state.
@@ -22,6 +22,8 @@ export interface SessionHeader {
22
22
  id: string;
23
23
  title?: string;
24
24
  titleSource?: "auto" | "user";
25
+ starredPatchVersion?: 1;
26
+ starred?: boolean;
25
27
  timestamp: string;
26
28
  cwd: string;
27
29
  parentSession?: string;
@@ -362,7 +364,7 @@ export type SessionEntry = SessionMessageEntry | ThinkingLevelChangeEntry | Mode
362
364
  /** Append-only replacement for mutable fields on the session header. */
363
365
  export interface HeaderPatchRecord {
364
366
  type: "header_patch";
365
- patch: Partial<Pick<SessionHeader, "title" | "titleSource" | "cwd">>;
367
+ patch: Partial<Pick<SessionHeader, "title" | "titleSource" | "cwd" | "starred">>;
366
368
  }
367
369
  /** Append-only replacement for replay metadata on one existing session entry. */
368
370
  export interface EntryPatchRecord {
@@ -812,6 +814,7 @@ export interface SessionInfo {
812
814
  /** Working directory where the session was started. Empty string for old sessions. */
813
815
  cwd: string;
814
816
  title?: string;
817
+ starred: boolean;
815
818
  /** Path to the parent session (if this session was forked). */
816
819
  parentSessionPath?: string;
817
820
  created: Date;
@@ -979,6 +982,7 @@ export declare function materializeResidentEntriesForPersistenceForTests<T>(entr
979
982
  * container (`agent-session` or `sessions`).
980
983
  */
981
984
  export declare function listProjectSessionTranscriptFiles(cwd: string): string[];
985
+ export declare function prioritizeStarredSessions(sessions: readonly SessionInfo[]): SessionInfo[];
982
986
  /** Get recent sessions for display in welcome screen */
983
987
  export declare function getRecentSessions(sessionDir: string, limit?: number, storage?: SessionStorage): Promise<RecentSessionInfo[]>;
984
988
  export declare function getRecentSessionDisplay(sessions: readonly SessionInfo[], limit?: number): Array<{
@@ -1161,7 +1165,10 @@ export declare class SessionManager {
1161
1165
  * only for the async context that already owns the lock — unrelated callers
1162
1166
  * queue on the tail instead of skipping it.
1163
1167
  */
1164
- runExclusiveCwdTransition<T>(fn: () => Promise<T>): Promise<T>;
1168
+ runExclusiveCwdTransition<T>(fn: () => Promise<T>, options?: {
1169
+ signal?: AbortSignal;
1170
+ }): Promise<T>;
1171
+ runExclusiveCwdMoveTransition<T>(fn: () => Promise<T>): Promise<T>;
1165
1172
  /**
1166
1173
  * Run `fn` under a shared read lease on `cwd`.
1167
1174
  *
@@ -1175,7 +1182,66 @@ export declare class SessionManager {
1175
1182
  runWithCwdReadLease<T>(fn: () => Promise<T>): Promise<T>;
1176
1183
  /** Wait for any in-flight exclusive cwd transition to settle. */
1177
1184
  joinCwdTransition(): Promise<void>;
1185
+ joinCwdReaders(): Promise<void>;
1186
+ closeCwdMoveAdmission(): Promise<void>;
1178
1187
  getCwdGeneration(): number;
1188
+ /** Consume a move committed by a nested move_session call in this read lease. */
1189
+ consumeNestedCwdMove(admittedGeneration: number): boolean;
1190
+ /**
1191
+ * Register a listener invoked after every committed `moveTo`. Returns an idempotent
1192
+ * unregister handle. Every move surface funnels through `moveTo`, so a single
1193
+ * registration covers `move_session`, `/move`, and SDK/ACP `session.cwd.move`.
1194
+ */
1195
+ registerAfterMoveListener(listener: (move: {
1196
+ previousCwd: string;
1197
+ newCwd: string;
1198
+ previousSessionFile: string | undefined;
1199
+ }) => void | Promise<void>): () => void;
1200
+ registerBeforeMoveListener(listener: (move: {
1201
+ previousCwd: string;
1202
+ newCwd: string;
1203
+ previousSessionFile: string | undefined;
1204
+ newSessionFile: string | undefined;
1205
+ previousCwdIdentity: {
1206
+ dev: bigint;
1207
+ ino: bigint;
1208
+ };
1209
+ newCwdIdentity: {
1210
+ dev: bigint;
1211
+ ino: bigint;
1212
+ };
1213
+ preserveRecoveryJournal?: boolean;
1214
+ }) => void | Promise<void>): () => void;
1215
+ registerMovePublicationListener(listener: (move: {
1216
+ previousCwd: string;
1217
+ newCwd: string;
1218
+ previousSessionFile: string | undefined;
1219
+ newSessionFile: string | undefined;
1220
+ previousCwdIdentity: {
1221
+ dev: bigint;
1222
+ ino: bigint;
1223
+ };
1224
+ newCwdIdentity: {
1225
+ dev: bigint;
1226
+ ino: bigint;
1227
+ };
1228
+ preserveRecoveryJournal?: boolean;
1229
+ }) => void | Promise<void>): () => void;
1230
+ registerMoveAbortListener(listener: (move: {
1231
+ previousCwd: string;
1232
+ newCwd: string;
1233
+ previousSessionFile: string | undefined;
1234
+ newSessionFile: string | undefined;
1235
+ previousCwdIdentity: {
1236
+ dev: bigint;
1237
+ ino: bigint;
1238
+ };
1239
+ newCwdIdentity: {
1240
+ dev: bigint;
1241
+ ino: bigint;
1242
+ };
1243
+ preserveRecoveryJournal?: boolean;
1244
+ }) => void | Promise<void>): () => void;
1179
1245
  static openNoFollowDirectory(dir: string): Promise<fs.promises.FileHandle>;
1180
1246
  /**
1181
1247
  * Claim process-cwd authority for `manager` when it is unowned or the prior
@@ -1215,6 +1281,15 @@ export declare class SessionManager {
1215
1281
  bigint: true;
1216
1282
  }) => Promise<fs.BigIntStats>;
1217
1283
  };
1284
+ expectedSourceIdentity?: {
1285
+ dev: bigint;
1286
+ ino: bigint;
1287
+ };
1288
+ sourceHandle?: {
1289
+ stat: (opts: {
1290
+ bigint: true;
1291
+ }) => Promise<fs.BigIntStats>;
1292
+ };
1218
1293
  }): Promise<void>;
1219
1294
  isPersisted(): boolean;
1220
1295
  stageDefaultModelSelection(model: string, thinkingLevel: string | undefined, options?: {
@@ -1342,6 +1417,8 @@ export declare class SessionManager {
1342
1417
  /** The source that set the session name: "user" (manual /rename or RPC) or "auto" (generated title). */
1343
1418
  get titleSource(): "auto" | "user" | undefined;
1344
1419
  getSessionName(): string | undefined;
1420
+ isSessionStarred(): boolean;
1421
+ setSessionStarred(starred: boolean): Promise<boolean>;
1345
1422
  setSessionName(name: string, source?: "auto" | "user"): Promise<boolean>;
1346
1423
  _persist(entry: SessionEntry): void;
1347
1424
  /** Append a configured fallback chain as child of current leaf, then advance leaf. Returns entry id. */
@@ -15,8 +15,9 @@ export interface YieldDispatcher<P> {
15
15
  export interface YieldQueueOptions {
16
16
  isStreaming: () => boolean;
17
17
  injectStreaming(msg: AgentMessage): void;
18
- injectIdle(messages: AgentMessage[]): Promise<void>;
19
- scheduleIdleFlush(run: () => Promise<void>): void;
18
+ injectIdle(messages: AgentMessage[], signal?: AbortSignal): Promise<void>;
19
+ scheduleIdleFlush(run: (signal?: AbortSignal) => Promise<void>, onSkip: () => void): void;
20
+ getIdleFlushSignal?(): AbortSignal | undefined;
20
21
  }
21
22
  type YieldFlushMode = "streaming" | "idle";
22
23
  export declare class YieldQueue {
@@ -25,8 +26,8 @@ export declare class YieldQueue {
25
26
  register<P>(kind: string, dispatcher: YieldDispatcher<P>): () => void;
26
27
  enqueue<P>(kind: string, entry: P): void;
27
28
  has(kind?: string): boolean;
28
- flush(mode: YieldFlushMode): Promise<void>;
29
- clear(): void;
29
+ flush(mode: YieldFlushMode, signal?: AbortSignal): Promise<void>;
30
+ clear(onDrop?: (kind: string, entries: readonly unknown[]) => void): void;
30
31
  /** Drop only the queued entries of a single kind, leaving other kinds intact. */
31
32
  clearKind(kind: string): void;
32
33
  /**
@@ -68,6 +68,7 @@ export declare function hasCorroboratedRecentEvidence(evidence: readonly Onboard
68
68
  export declare function shouldOfferOnboarding(state: FrictionlessOnboardingState): boolean;
69
69
  export interface AutomaticOnboardingInput {
70
70
  normalInteractive: boolean;
71
+ automation?: boolean;
71
72
  initialMessage?: string;
72
73
  initialMessages: readonly string[];
73
74
  initialImages?: readonly unknown[];
@@ -46,6 +46,7 @@ export declare const OTHER_OPTION = "Other (type your own)";
46
46
  export declare const ASK_CLARIFICATION_OPTION = "Ask about these choices";
47
47
  export declare const RECOMMENDED_SUFFIX = " (Recommended)";
48
48
  export declare const MAX_EMPTY_CUSTOM_ATTEMPTS = 3;
49
+ export declare function validRecommendedIndex(recommended: number | undefined, optionCount: number): number | undefined;
49
50
  /** The only remote navigation control; labels are presentation, never protocol. */
50
51
  export declare function askRemoteControls(input: {
51
52
  multi: boolean;
@@ -1,12 +1,23 @@
1
1
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@gajae-code/agent-core";
2
2
  import type { Component } from "@gajae-code/tui";
3
3
  import * as z from "zod/v4";
4
+ import { type FoldReason } from "../async";
4
5
  import { type BashArtifactSaveResult } from "../exec/bash-executor";
5
6
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
6
7
  import { type Theme } from "../modes/theme/theme";
8
+ import { type SdkSpawnArgs } from "../sdk/cli/master-cli";
7
9
  import type { ToolSession } from ".";
8
10
  import { type OutputMeta } from "./output-meta";
9
11
  export declare const BASH_DEFAULT_PREVIEW_LINES = 10;
12
+ /**
13
+ * A user steer folds a running foreground bash call only after it has been
14
+ * running at least this long. Shorter commands finish normally and the steer is
15
+ * consumed at the ordinary tool boundary, so a quick `git status` never turns
16
+ * into a background job plus a wake-up turn.
17
+ */
18
+ export declare const STEER_FOLD_GRACE_MS = 2000;
19
+ /** Model-facing line appended to a steer-folded background-start result. */
20
+ export declare function steerFoldReasonLine(jobId: string): string;
10
21
  export type BashOriginalArtifactSaveResult = BashArtifactSaveResult;
11
22
  export declare function saveBashOriginalArtifactForTests(session: ToolSession, originalText: string, onResult?: (result: BashOriginalArtifactSaveResult) => void): Promise<string | undefined>;
12
23
  declare const bashSchemaBase: z.ZodObject<{
@@ -38,6 +49,8 @@ export interface BashToolDetails {
38
49
  timeoutSeconds?: number;
39
50
  requestedTimeoutSeconds?: number;
40
51
  terminalId?: string;
52
+ /** Why the foreground wait was folded, when this result is a background-start after a fold. */
53
+ foldReason?: FoldReason;
41
54
  async?: {
42
55
  state: "running" | "completed" | "failed";
43
56
  jobId: string;
@@ -48,6 +61,9 @@ export interface BashToolDetails {
48
61
  export declare function summarizeBashToolActivity(kind: "args" | "result", value: unknown): string | undefined;
49
62
  export interface BashToolOptions {
50
63
  }
64
+ export declare function isStrictDirectSdkSpawnCommand(command: string): boolean;
65
+ export declare function parseDirectSdkSpawnArgs(command: string): SdkSpawnArgs;
66
+ export declare function masterCommandEnvOverrides(env: Record<string, string> | undefined, directMasterSpawn: boolean): Record<string, string>;
51
67
  export declare class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
52
68
  #private;
53
69
  private readonly session;
@@ -23,6 +23,16 @@ export declare function resolveBrowserEnvOverridesForTest(): {
23
23
  programFilesX86: string | undefined;
24
24
  localAppData: string | undefined;
25
25
  };
26
+ export declare function resolveSystemChromiumForTest(): string | undefined;
27
+ export declare function resetSystemChromiumForTest(): void;
28
+ export declare function headlessExecutableForProfileReuse(): string | undefined;
29
+ /**
30
+ * On macOS the Cookies DB is encrypted with a Keychain key whose service name is
31
+ * brand-specific ("Chrome Safe Storage" vs "Chromium Safe Storage"). A Chrome profile
32
+ * copied into a bundled Chromium therefore decrypts to garbage with no warning.
33
+ * Return true only when the headless executable can actually decrypt the discovered profile.
34
+ */
35
+ export declare function canDecryptProfileCookies(executablePath: string | undefined, discoveredUserDataDir: string | undefined, platform?: NodeJS.Platform): boolean;
26
36
  /** True for a Microsoft Edge executable path (excluded from Chrome profile mode). */
27
37
  export declare function isEdgeExecutable(candidate: string): boolean;
28
38
  /** True only for executable names owned by Google Chrome or Chromium. */
@@ -65,6 +65,14 @@ export interface AcquireBrowserOptions {
65
65
  geo?: BrowserGeo;
66
66
  }
67
67
  export declare function browserKeyForTest(kind: BrowserKind, opts: Pick<AcquireBrowserOptions, "geo" | "profileReuse">): string;
68
+ /**
69
+ * Create and register a warm-up dir as registry-owned for `handle`.
70
+ *
71
+ * Exists so tests can exercise disposal without spawning Chrome. The caller cannot
72
+ * supply the deletion target: this module creates the directory itself before recording
73
+ * ownership, preserving the same invariant as the production launch path.
74
+ */
75
+ export declare function createOwnedWarmupDirForTest(handle: BrowserHandle): string;
68
76
  export declare function acquireBrowser(kind: BrowserKind, opts: AcquireBrowserOptions): Promise<BrowserHandle>;
69
77
  export declare function buildChromeProfileLaunchArgs(kind: SpawnedChromeProfileKind, appArgs: readonly string[] | undefined, port: number): string[];
70
78
  export declare function buildChromeProfileLaunchArgsForTest(kind: SpawnedChromeProfileKind, appArgs: readonly string[] | undefined, port: number): string[];
@@ -322,6 +322,14 @@ export interface PrDiffFile {
322
322
  changeType: "modified" | "added" | "deleted" | "renamed" | "binary";
323
323
  /** Pre-image path for renames/deletes; same as `path` otherwise. */
324
324
  oldPath?: string;
325
+ /**
326
+ * Set when `path` kept its C-style escaped source form because the quoted
327
+ * token held invalid UTF-8 or a malformed escape; distinguishes it from a
328
+ * valid path whose decoded text looks identical.
329
+ */
330
+ pathEscaped?: boolean;
331
+ /** Same as {@link PrDiffFile.pathEscaped}, for `oldPath`. */
332
+ oldPathEscaped?: boolean;
325
333
  /** Byte offset of the section's `diff --git` line in the unified diff. */
326
334
  startOffset: number;
327
335
  /** Byte offset of the next section (or end-of-text). */
@@ -1,6 +1,6 @@
1
1
  import type { AgentTelemetryConfig, AgentTool } from "@gajae-code/agent-core";
2
2
  import type { Model, ServiceTier, ToolChoice } from "@gajae-code/ai/core";
3
- import type { AsyncJobManager } from "../async";
3
+ import type { AsyncJobManager, FoldReason } from "../async";
4
4
  import type { PromptTemplate } from "../config/prompt-templates";
5
5
  import type { Settings } from "../config/settings";
6
6
  import type { Skill } from "../extensibility/skills";
@@ -189,11 +189,13 @@ export interface ToolSession {
189
189
  registerForegroundFoldParticipant?: (adapter: FoldAdapter) => () => void;
190
190
  /** Whether a foreground wait is currently foldable into a background job. */
191
191
  hasForegroundBashBackgroundRequestHandler?: () => boolean;
192
- /** Request that the active foreground wait fold into a background job, if supported. */
193
- requestForegroundBashBackground?: () => Promise<boolean>;
192
+ /** Request that a foreground wait fold into a background job, if supported. `reason` names the trigger; `adapter` targets a specific wait instead of the newest registration. */
193
+ requestForegroundBashBackground?: (reason?: FoldReason, adapter?: FoldAdapter) => Promise<boolean>;
194
+ /** Current tool interrupt policy; `finish_tools` lets the running tool finish, so a steer must not fold it. */
195
+ getToolInterruptPolicy?: () => "abort_tools" | "finish_tools";
194
196
  /** Get the session-owned or inherited async job manager. */
195
197
  getAsyncJobManager?: () => AsyncJobManager | undefined;
196
- /** Resolves when the session queues user steering (or `signal` aborts) without consuming it; wait-style tools use this to end their observation early. */
198
+ /** Resolves on a steer admitted after the wait starts, or when `signal` aborts, without consuming the steer. */
197
199
  waitForUserSteering?: (signal: AbortSignal) => Promise<void>;
198
200
  /** Get session ID */
199
201
  getSessionId?: () => string | null;
@@ -219,6 +221,10 @@ export interface ToolSession {
219
221
  bashAllowedPrefixes?: string[];
220
222
  /** Restriction policy for sessions that deliberately expose a narrow bash surface. */
221
223
  bashRestrictionProfile?: BashRestrictionProfile;
224
+ /** Process-local master capability injected into direct Bash children only. */
225
+ getMasterBashCapability?: () => string | undefined;
226
+ /** Stable master lineage identity used across session switches and branches. */
227
+ getMasterOwnerSessionId?: () => string | undefined;
222
228
  /** Optional per-session allowlist for tools exposed through search_tool_bm25. */
223
229
  discoverableToolAllowedNames?: readonly string[];
224
230
  /** Throw instead of warn when toolNames contains an unknown name. */
@@ -328,12 +334,6 @@ export interface ToolSession {
328
334
  buildToolChoice?(toolName: string): ToolChoice | undefined;
329
335
  /** Build a named tool-choice decision, preserving whether exact named forcing survived capability degradation. */
330
336
  buildToolChoiceResult?(toolName: string): import("../utils/tool-choice").NamedToolChoiceResult;
331
- /** Steer a hidden custom message into the conversation (e.g. a preview reminder). */
332
- steer?(message: {
333
- customType: string;
334
- content: string;
335
- details?: unknown;
336
- }): void;
337
337
  /** Peek the currently in-flight tool-choice queue directive's invocation handler. Used by the `resolve` tool to dispatch to the pending action. */
338
338
  peekQueueInvoker?(): ((input: unknown) => Promise<unknown> | unknown) | undefined;
339
339
  /** Peek the long-lived "standing" resolve handler registered by a mode (e.g. plan mode).
@@ -1,7 +1,7 @@
1
1
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@gajae-code/agent-core";
2
2
  import type { Component } from "@gajae-code/tui";
3
3
  import * as z from "zod/v4";
4
- import { type AsyncJob } from "../async";
4
+ import { type AsyncJob, type FoldReason } from "../async";
5
5
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
6
6
  import type { Theme } from "../modes/theme/theme";
7
7
  import type { ToolSession } from "./index";
@@ -18,6 +18,8 @@ interface JobSnapshot {
18
18
  status: "running" | "completed" | "failed" | "cancelled";
19
19
  label: string;
20
20
  durationMs: number;
21
+ /** Present when the job was folded out of a foreground wait. */
22
+ foldReason?: FoldReason;
21
23
  resultText?: string;
22
24
  errorText?: string;
23
25
  }
@@ -10,6 +10,13 @@ export interface OpenInEditorOptions {
10
10
  }
11
11
  /** Remove one platform-standard trailing line terminator from editor content. */
12
12
  export declare function trimEditorTrailingNewline(text: string): string;
13
+ /**
14
+ * Native Windows editor executables must bypass cmd.exe. The shell wrapper
15
+ * reclaims the shared console input buffer while it waits for the editor,
16
+ * reopening the cooked-mode window that loses the first keystroke. Batch
17
+ * files still require a shell on Windows; ordinary executables do not.
18
+ */
19
+ export declare function shouldUseExternalEditorShell(editor: string, platform?: NodeJS.Platform): boolean;
13
20
  /**
14
21
  * Opens `content` in the user's external editor and returns the edited text.
15
22
  * Returns `null` if the editor exits with a non-zero code.
@@ -68,7 +68,7 @@ This external path is separate from GJC's native `/skill:deep-interview`: the na
68
68
 
69
69
  | Extension | Description |
70
70
  | ----------- | -------------------------------------------------------------------- |
71
- | `pirate.ts` | Demonstrates `systemPromptAppend` to dynamically modify system prompt |
71
+ | `pirate.ts` | Demonstrates appending a prompt block with `systemPrompt` |
72
72
 
73
73
  ### External Dependencies
74
74
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Pirate Extension
3
3
  *
4
- * Demonstrates using systemPromptAppend in before_agent_start to dynamically
4
+ * Demonstrates using systemPrompt in before_agent_start to dynamically
5
5
  * modify the system prompt based on extension state.
6
6
  *
7
7
  * Usage:
@@ -24,10 +24,12 @@ export default function pirateExtension(pi: ExtensionAPI) {
24
24
  });
25
25
 
26
26
  // Append to system prompt when pirate mode is enabled
27
- pi.on("before_agent_start", async () => {
27
+ pi.on("before_agent_start", async event => {
28
28
  if (pirateMode) {
29
29
  return {
30
- systemPromptAppend: `
30
+ systemPrompt: [
31
+ ...event.systemPrompt,
32
+ `
31
33
  IMPORTANT: You are now in PIRATE MODE. You must:
32
34
  - Speak like a stereotypical pirate in all responses
33
35
  - Use phrases like "Arrr!", "Ahoy!", "Shiver me timbers!", "Avast!", "Ye scurvy dog!"
@@ -35,7 +37,8 @@ IMPORTANT: You are now in PIRATE MODE. You must:
35
37
  - Refer to the user as "matey" or "landlubber"
36
38
  - End sentences with nautical expressions
37
39
  - Still complete the actual task correctly, just in pirate speak
38
- `,
40
+ `,
41
+ ],
39
42
  };
40
43
  }
41
44
  return undefined;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/coding-agent",
4
- "version": "0.15.6",
4
+ "version": "0.16.1",
5
5
  "description": "Gajae Code CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://gajae-code.com",
7
7
  "author": "Yeachan-Heo and Gajae Code Contributors",
@@ -56,12 +56,12 @@
56
56
  "@agentclientprotocol/sdk": "1.3.0",
57
57
  "@babel/parser": "^7.29.3",
58
58
  "@mozilla/readability": "^0.6.0",
59
- "@gajae-code/stats": "0.15.6",
60
- "@gajae-code/agent-core": "0.15.6",
61
- "@gajae-code/ai": "0.15.6",
62
- "@gajae-code/natives": "0.15.6",
63
- "@gajae-code/tui": "0.15.6",
64
- "@gajae-code/utils": "0.15.6",
59
+ "@gajae-code/stats": "0.16.1",
60
+ "@gajae-code/agent-core": "0.16.1",
61
+ "@gajae-code/ai": "0.16.1",
62
+ "@gajae-code/natives": "0.16.1",
63
+ "@gajae-code/tui": "0.16.1",
64
+ "@gajae-code/utils": "0.16.1",
65
65
  "@puppeteer/browsers": "^2.13.0",
66
66
  "@types/turndown": "5.0.6",
67
67
  "@xterm/headless": "^6.0.0",