@gajae-code/coding-agent 0.11.3 → 0.11.5

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 (213) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/types/cli/notify-cli.d.ts +5 -1
  3. package/dist/types/cli/worktree-cli.d.ts +8 -25
  4. package/dist/types/commands/gc.d.ts +4 -0
  5. package/dist/types/commands/worktree.d.ts +7 -32
  6. package/dist/types/config/settings-schema.d.ts +20 -0
  7. package/dist/types/export/html/template.generated.d.ts +1 -1
  8. package/dist/types/gjc-runtime/deep-interview-state.d.ts +28 -0
  9. package/dist/types/gjc-runtime/gc-runtime.d.ts +9 -0
  10. package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -0
  11. package/dist/types/gjc-runtime/managed-owner-admission.d.ts +42 -0
  12. package/dist/types/gjc-runtime/managed-owner-supervisor.d.ts +41 -0
  13. package/dist/types/gjc-runtime/state-argv.d.ts +38 -0
  14. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +9 -0
  15. package/dist/types/gjc-runtime/ultragoal-owner-loss-recovery.d.ts +94 -0
  16. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +1 -0
  17. package/dist/types/harness-control-plane/owner.d.ts +3 -1
  18. package/dist/types/internal-urls/local-protocol.d.ts +18 -0
  19. package/dist/types/main.d.ts +2 -2
  20. package/dist/types/modes/components/ansi-display-validator.d.ts +2 -0
  21. package/dist/types/modes/components/custom-editor.d.ts +8 -3
  22. package/dist/types/modes/components/notifications-settings-editor.d.ts +4 -0
  23. package/dist/types/modes/components/session-observer-overlay.d.ts +3 -1
  24. package/dist/types/modes/components/settings-selector.d.ts +2 -0
  25. package/dist/types/modes/components/tool-transcript-format.d.ts +77 -0
  26. package/dist/types/modes/components/transcript-viewer-overlay.d.ts +3 -0
  27. package/dist/types/modes/controllers/goal-mode-controller.d.ts +8 -1
  28. package/dist/types/modes/controllers/input-controller.d.ts +8 -2
  29. package/dist/types/modes/controllers/selector-controller.d.ts +15 -0
  30. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +3 -0
  31. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +16 -0
  32. package/dist/types/plan-mode/approved-plan.d.ts +1 -0
  33. package/dist/types/runtime-mcp/manager.d.ts +2 -0
  34. package/dist/types/runtime-mcp/oauth-discovery.d.ts +12 -1
  35. package/dist/types/sdk/broker/broker.d.ts +1 -0
  36. package/dist/types/sdk/broker/discovery.d.ts +10 -0
  37. package/dist/types/sdk/broker/ensure.d.ts +24 -1
  38. package/dist/types/sdk/broker/internal.d.ts +3 -0
  39. package/dist/types/sdk/broker/session-index.d.ts +12 -0
  40. package/dist/types/sdk/broker/state-version.d.ts +2 -1
  41. package/dist/types/sdk/bus/chat-daemon-cli.d.ts +3 -1
  42. package/dist/types/sdk/bus/chat-daemon-control.d.ts +39 -4
  43. package/dist/types/sdk/bus/config-commands.d.ts +8 -0
  44. package/dist/types/sdk/bus/config.d.ts +22 -0
  45. package/dist/types/sdk/bus/index.d.ts +162 -2
  46. package/dist/types/sdk/bus/notification-service.d.ts +71 -8
  47. package/dist/types/sdk/bus/session-control.d.ts +11 -8
  48. package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +5 -0
  49. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +6 -3
  50. package/dist/types/sdk/bus/telegram-daemon-control.d.ts +23 -4
  51. package/dist/types/sdk/bus/telegram-daemon.d.ts +214 -20
  52. package/dist/types/sdk/session.d.ts +16 -1
  53. package/dist/types/secrets/index.d.ts +4 -2
  54. package/dist/types/secrets/obfuscator.d.ts +1 -1
  55. package/dist/types/session/agent-session.d.ts +31 -2
  56. package/dist/types/session/artifacts.d.ts +30 -8
  57. package/dist/types/session/internal/managed-session-scope.d.ts +7 -0
  58. package/dist/types/session/internal/managed-session-storage.d.ts +63 -6
  59. package/dist/types/session/session-manager.d.ts +88 -18
  60. package/dist/types/session/session-storage.d.ts +27 -0
  61. package/dist/types/session/streaming-output.d.ts +4 -0
  62. package/dist/types/task/executor.d.ts +9 -0
  63. package/dist/types/tool-discovery/tool-index.d.ts +2 -0
  64. package/dist/types/tools/ask.d.ts +87 -12
  65. package/dist/types/tools/bash-skill-urls.d.ts +2 -2
  66. package/dist/types/tools/browser/screenshot-format.d.ts +8 -0
  67. package/dist/types/tools/browser/tab-protocol.d.ts +11 -0
  68. package/dist/types/tools/browser/tab-supervisor.d.ts +1 -1
  69. package/dist/types/tools/browser/tab-worker-path-resolver.d.ts +2 -0
  70. package/dist/types/tools/browser/tab-worker-smoke.d.ts +16 -0
  71. package/dist/types/tools/index.d.ts +4 -0
  72. package/dist/types/tools/path-utils.d.ts +9 -14
  73. package/dist/types/tools/render-utils.d.ts +1 -8
  74. package/dist/types/tools/resource-gc.d.ts +14 -0
  75. package/dist/types/utils/image-loading.d.ts +23 -0
  76. package/dist/types/utils/image-resize.d.ts +2 -0
  77. package/dist/types/utils/pasted-image-loading.d.ts +39 -0
  78. package/dist/types/utils/pasted-image-path.d.ts +21 -19
  79. package/dist/types/web/scrapers/html-to-markdown.d.ts +5 -0
  80. package/dist/types/web/scrapers/types.d.ts +1 -5
  81. package/package.json +25 -9
  82. package/scripts/generate-sdk-operation-inventory.ts +2 -0
  83. package/scripts/run-threat-model-check.ts +60 -0
  84. package/src/cli/notify-cli.ts +40 -18
  85. package/src/cli/worktree-cli.ts +9 -287
  86. package/src/cli.ts +10 -9
  87. package/src/commands/gc.ts +11 -1
  88. package/src/commands/sdk.ts +10 -4
  89. package/src/commands/worktree.ts +10 -53
  90. package/src/config/model-profiles.ts +15 -15
  91. package/src/config/settings-schema.ts +17 -0
  92. package/src/daemon/runtime.ts +2 -2
  93. package/src/defaults/gjc/skills/deep-interview/SKILL.md +70 -49
  94. package/src/defaults/gjc/skills/ralplan/SKILL.md +0 -6
  95. package/src/defaults/gjc/skills/team/SKILL.md +7 -9
  96. package/src/defaults/gjc/skills/ultragoal/SKILL.md +0 -2
  97. package/src/eval/js/shared/runtime.ts +1 -1
  98. package/src/eval/py/index.ts +2 -2
  99. package/src/export/html/template.generated.ts +1 -1
  100. package/src/extensibility/plugins/marketplace/manager.ts +94 -10
  101. package/src/gjc-runtime/deep-interview-recorder.ts +7 -0
  102. package/src/gjc-runtime/deep-interview-runtime.ts +10 -0
  103. package/src/gjc-runtime/deep-interview-state.ts +127 -3
  104. package/src/gjc-runtime/gc-render.ts +19 -1
  105. package/src/gjc-runtime/gc-runtime.ts +68 -3
  106. package/src/gjc-runtime/launch-tmux.ts +61 -6
  107. package/src/gjc-runtime/managed-owner-admission.ts +352 -0
  108. package/src/gjc-runtime/managed-owner-supervisor.ts +162 -0
  109. package/src/gjc-runtime/state-argv.ts +292 -0
  110. package/src/gjc-runtime/state-runtime.ts +80 -222
  111. package/src/gjc-runtime/team-runtime.ts +1 -1
  112. package/src/gjc-runtime/tmux-owner-isolation.ts +117 -0
  113. package/src/gjc-runtime/ultragoal-owner-loss-recovery.ts +328 -0
  114. package/src/gjc-runtime/ultragoal-runtime.ts +14 -0
  115. package/src/harness-control-plane/owner.ts +59 -3
  116. package/src/hindsight/client.ts +65 -2
  117. package/src/internal-urls/agent-protocol.ts +76 -5
  118. package/src/internal-urls/docs-index.generated.ts +7 -6
  119. package/src/internal-urls/local-protocol.ts +416 -18
  120. package/src/lsp/index.ts +4 -88
  121. package/src/main.ts +37 -13
  122. package/src/modes/acp/acp-agent.ts +8 -0
  123. package/src/modes/components/ansi-display-validator.ts +54 -0
  124. package/src/modes/components/custom-editor.ts +103 -32
  125. package/src/modes/components/custom-provider-wizard.ts +26 -1
  126. package/src/modes/components/notifications-settings-editor.ts +26 -2
  127. package/src/modes/components/session-observer-overlay.ts +40 -37
  128. package/src/modes/components/settings-selector.ts +3 -1
  129. package/src/modes/components/tool-transcript-format.ts +393 -0
  130. package/src/modes/components/transcript-viewer-overlay.ts +63 -1
  131. package/src/modes/controllers/goal-mode-controller.ts +20 -1
  132. package/src/modes/controllers/input-controller.ts +98 -37
  133. package/src/modes/controllers/plan-mode-controller.ts +2 -0
  134. package/src/modes/controllers/runtime-mcp-command-controller.ts +3 -0
  135. package/src/modes/controllers/selector-controller.ts +71 -9
  136. package/src/modes/interactive-mode.ts +14 -2
  137. package/src/modes/shared/agent-wire/deep-interview-gate.ts +31 -1
  138. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +17 -1
  139. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +4 -2
  140. package/src/modes/shared/agent-wire/workflow-gate-types.ts +120 -3
  141. package/src/plan-mode/approved-plan.ts +3 -1
  142. package/src/prompts/agents/architect.md +1 -0
  143. package/src/prompts/agents/critic.md +1 -0
  144. package/src/prompts/system/custom-system-prompt.md +1 -1
  145. package/src/prompts/system/system-prompt.md +2 -1
  146. package/src/prompts/tools/lsp.md +3 -3
  147. package/src/runtime-mcp/manager.ts +16 -1
  148. package/src/runtime-mcp/oauth-discovery.ts +116 -26
  149. package/src/sdk/broker/broker.ts +139 -32
  150. package/src/sdk/broker/discovery.ts +125 -0
  151. package/src/sdk/broker/ensure.ts +103 -19
  152. package/src/sdk/broker/internal.ts +10 -0
  153. package/src/sdk/broker/session-index.ts +309 -38
  154. package/src/sdk/broker/state-version.ts +5 -2
  155. package/src/sdk/bus/chat-daemon-cli.ts +72 -10
  156. package/src/sdk/bus/chat-daemon-control.ts +526 -130
  157. package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
  158. package/src/sdk/bus/config-commands.ts +22 -0
  159. package/src/sdk/bus/config.ts +37 -0
  160. package/src/sdk/bus/index.ts +384 -92
  161. package/src/sdk/bus/lifecycle-control-runtime.ts +53 -3
  162. package/src/sdk/bus/notification-service.ts +284 -62
  163. package/src/sdk/bus/recent-activity.ts +14 -5
  164. package/src/sdk/bus/session-control.ts +150 -44
  165. package/src/sdk/bus/telegram-daemon-cli.ts +20 -14
  166. package/src/sdk/bus/telegram-daemon-contract.ts +6 -3
  167. package/src/sdk/bus/telegram-daemon-control.ts +294 -76
  168. package/src/sdk/bus/telegram-daemon.ts +1842 -281
  169. package/src/sdk/protocol/operation-inventory.generated.json +11 -0
  170. package/src/sdk/session.ts +155 -27
  171. package/src/secrets/index.ts +53 -10
  172. package/src/secrets/obfuscator.ts +21 -18
  173. package/src/secrets/regex.ts +2 -0
  174. package/src/session/agent-session.ts +495 -253
  175. package/src/session/artifacts.ts +188 -23
  176. package/src/session/context-estimation.ts +7 -2
  177. package/src/session/internal/managed-session-scope.ts +215 -39
  178. package/src/session/internal/managed-session-storage.ts +1152 -46
  179. package/src/session/session-manager.ts +1055 -148
  180. package/src/session/session-storage.ts +109 -11
  181. package/src/session/streaming-output.ts +6 -0
  182. package/src/task/executor.ts +71 -26
  183. package/src/task/index.ts +63 -20
  184. package/src/tool-discovery/tool-index.ts +18 -0
  185. package/src/tools/ask.ts +329 -57
  186. package/src/tools/bash-allowed-prefixes.ts +79 -29
  187. package/src/tools/bash-skill-urls.ts +14 -3
  188. package/src/tools/bash.ts +2 -2
  189. package/src/tools/browser/launch.ts +3 -1
  190. package/src/tools/browser/readable.ts +1 -1
  191. package/src/tools/browser/screenshot-format.ts +34 -0
  192. package/src/tools/browser/tab-protocol.ts +3 -0
  193. package/src/tools/browser/tab-supervisor.ts +125 -122
  194. package/src/tools/browser/tab-worker-entry.ts +33 -14
  195. package/src/tools/browser/tab-worker-path-resolver.ts +67 -0
  196. package/src/tools/browser/tab-worker-smoke.ts +87 -0
  197. package/src/tools/browser/tab-worker.ts +7 -5
  198. package/src/tools/index.ts +4 -0
  199. package/src/tools/path-utils.ts +42 -35
  200. package/src/tools/plan-mode-guard.ts +1 -0
  201. package/src/tools/read.ts +7 -1
  202. package/src/tools/render-utils.ts +1 -27
  203. package/src/tools/resource-gc.ts +123 -34
  204. package/src/tools/sqlite-reader.ts +3 -2
  205. package/src/tools/subagent.ts +2 -0
  206. package/src/utils/image-loading.ts +85 -34
  207. package/src/utils/image-resize.ts +16 -9
  208. package/src/utils/pasted-image-loading.ts +514 -0
  209. package/src/utils/pasted-image-path.ts +223 -98
  210. package/src/web/scrapers/html-to-markdown.ts +68 -0
  211. package/src/web/scrapers/readthedocs.ts +1 -1
  212. package/src/web/scrapers/types.ts +1 -68
  213. package/src/web/search/providers/openai-compatible.ts +76 -23
@@ -8,12 +8,27 @@ export declare const RESERVED_WORKFLOW_STAGES: readonly string[];
8
8
  export type WorkflowGateKind = "question" | "approval" | "execution";
9
9
  /** "Other (type your own)" sentinel, mirroring the interactive ask tool. */
10
10
  export declare const GATE_OTHER_OPTION = "Other (type your own)";
11
+ /**
12
+ * Structured adapter context queued at interview start. Non-behavioral:
13
+ * `confused_terms` and `references` MUST NOT alter the first question, are never
14
+ * inferred from vocabulary density, and referenced `url`/`excerpt` are inert
15
+ * strings that are never auto-fetched.
16
+ */
17
+ export interface AskGateReference {
18
+ reference_id: string;
19
+ label: string;
20
+ origin: string;
21
+ url?: string;
22
+ excerpt?: string;
23
+ }
11
24
  export interface AskGateDeepInterviewState {
12
25
  round_id?: string;
13
26
  round: number;
14
27
  component: string;
15
28
  dimension: string;
16
29
  ambiguity: number;
30
+ confused_terms?: string[];
31
+ references?: AskGateReference[];
17
32
  }
18
33
  export interface AskGateStageStateInput {
19
34
  id: string;
@@ -26,6 +41,7 @@ export interface AskGateStageStateInput {
26
41
  export interface AskGateSchemaInput {
27
42
  multi?: boolean;
28
43
  allowEmpty?: boolean;
44
+ customMaxLength?: number;
29
45
  }
30
46
  /** Rejects stage state that is not exactly compatible with the generic ask-gate producer. */
31
47
  export declare function validateAskGateStageState(value: unknown): asserts value is Record<string, unknown>;
@@ -43,6 +43,7 @@ interface RenameApprovedPlanFileOptions {
43
43
  planFilePath: string;
44
44
  finalPlanFilePath: string;
45
45
  getArtifactsDir: () => string | null;
46
+ isManagedDestination?: () => boolean;
46
47
  getSessionId: () => string | null;
47
48
  }
48
49
  export declare function renameApprovedPlanFile(options: RenameApprovedPlanFileOptions): Promise<void>;
@@ -64,6 +64,8 @@ export declare class MCPManager {
64
64
  static setInstance(value: MCPManager | undefined): void;
65
65
  /** Reset the process-global instance. Test-only. */
66
66
  static resetForTests(): void;
67
+ sealConnectionSet(): void;
68
+ isConnectionSetSealed(): boolean;
67
69
  constructor(cwd: string, toolCache?: MCPToolCache | null, options?: MCPManagerOptions);
68
70
  isToolsOnly(): boolean;
69
71
  /**
@@ -4,6 +4,7 @@
4
4
  * Automatically detects OAuth requirements from MCP server responses
5
5
  * and extracts authentication endpoints.
6
6
  */
7
+ import type { AddressResolver } from "../web/insane/url-guard";
7
8
  export interface OAuthEndpoints {
8
9
  authorizationUrl: string;
9
10
  tokenUrl: string;
@@ -17,6 +18,15 @@ export interface AuthDetectionResult {
17
18
  authServerUrl?: string;
18
19
  message?: string;
19
20
  }
21
+ interface OAuthDiscoveryOptions {
22
+ fetch?: (input: string | URL | Request, init?: BunFetchRequestInit) => Promise<Response>;
23
+ resolver?: AddressResolver;
24
+ maxRequests?: number;
25
+ maxNodes?: number;
26
+ maxRedirects?: number;
27
+ timeoutMs?: number;
28
+ signal?: AbortSignal;
29
+ }
20
30
  export declare function extractMcpAuthServerUrl(error: Error): string | undefined;
21
31
  /**
22
32
  * Detect if an error indicates authentication is required.
@@ -37,4 +47,5 @@ export declare function analyzeAuthError(error: Error): AuthDetectionResult;
37
47
  * Try to discover OAuth endpoints by querying the server's well-known endpoints.
38
48
  * This is a fallback when error responses don't include OAuth metadata.
39
49
  */
40
- export declare function discoverOAuthEndpoints(serverUrl: string, authServerUrl?: string): Promise<OAuthEndpoints | null>;
50
+ export declare function discoverOAuthEndpoints(serverUrl: string, authServerUrl?: string, options?: OAuthDiscoveryOptions): Promise<OAuthEndpoints | null>;
51
+ export {};
@@ -109,6 +109,7 @@ export declare class Broker {
109
109
  constructor(settings: BrokerSettings);
110
110
  start(): Promise<BrokerDiscovery>;
111
111
  get ownsDiscovery(): boolean;
112
+ get completion(): Promise<void>;
112
113
  status(): RedactedBrokerDiscovery | null;
113
114
  heartbeat(): Promise<void>;
114
115
  stop(): Promise<void>;
@@ -1,5 +1,11 @@
1
1
  import { processIncarnation } from "./process-incarnation";
2
2
  import { SDK_STATE_VERSION } from "./state-version";
3
+ export type BrokerPublicationObservation = "owned" | "absent" | "replaced" | "ambiguous";
4
+ export interface RetainedBrokerDiscovery {
5
+ observe(): BrokerPublicationObservation;
6
+ heartbeat(heartbeatAt: number): Promise<boolean>;
7
+ close(): void;
8
+ }
3
9
  export declare const BROKER_HEARTBEAT_TTL_MS = 15000;
4
10
  export interface BrokerDiscovery {
5
11
  version: typeof SDK_STATE_VERSION;
@@ -26,5 +32,9 @@ export declare const newBrokerToken: () => string;
26
32
  export declare const brokerProcessIncarnation: typeof processIncarnation;
27
33
  export declare function isPidAlive(pid: number): boolean;
28
34
  export declare function writeBrokerDiscovery(agentDir: string, discovery: BrokerDiscoveryWrite): Promise<void>;
35
+ /** Publish once by name, then retain no-follow native authority for recurring heartbeats. */
36
+ export declare function publishBrokerDiscovery(agentDir: string, discovery: BrokerDiscoveryWrite, platform?: NodeJS.Platform): Promise<RetainedBrokerDiscovery>;
37
+ /** Heartbeat through retained authority, or the explicit Windows compatibility path. */
38
+ export declare function heartbeatBrokerDiscoveryRetained(publication: RetainedBrokerDiscovery, heartbeatAt: number): Promise<boolean>;
29
39
  export declare function readBrokerDiscovery(agentDir: string, ttlMs?: number): Promise<BrokerDiscovery | null>;
30
40
  export declare function redactBrokerDiscovery(discovery: BrokerDiscovery): RedactedBrokerDiscovery;
@@ -12,11 +12,28 @@ export interface EnsureBrokerSettings {
12
12
  env?: NodeJS.ProcessEnv;
13
13
  }
14
14
  export interface FixtureBrokerLease {
15
+ /** Backward-compatible fixture cleanup alias for exact child termination. */
15
16
  close(): Promise<void>;
16
17
  }
18
+ export interface ExactFixtureBrokerLease extends FixtureBrokerLease {
19
+ /** Observes the retained child only; it never signals a process. */
20
+ waitForExit(timeoutMs: number): Promise<boolean>;
21
+ /** Signals only the retained ChildProcess, never a discovery-derived PID. */
22
+ terminateExactChild(): Promise<void>;
23
+ }
24
+ export interface FixtureBrokerCommand {
25
+ file: string;
26
+ args: readonly string[];
27
+ cwd?: string;
28
+ env?: NodeJS.ProcessEnv;
29
+ }
30
+ export interface StartedFixtureBrokerCommand {
31
+ lease: ExactFixtureBrokerLease;
32
+ control: NodeJS.WritableStream;
33
+ }
17
34
  export interface StartedFixtureBroker {
18
35
  discovery: BrokerDiscovery;
19
- lease: FixtureBrokerLease;
36
+ lease: ExactFixtureBrokerLease;
20
37
  }
21
38
  interface BrokerOwner {
22
39
  stop(): Promise<void>;
@@ -31,6 +48,12 @@ interface ReapTiming {
31
48
  export declare function ensureBroker(settings: EnsureBrokerSettings): Promise<BrokerDiscovery>;
32
49
  /** Starts one fresh fixture broker and returns its sole exact-child close lease. */
33
50
  export declare function startFixtureBrokerWithLeaseForTest(settings: EnsureBrokerSettings): Promise<StartedFixtureBroker>;
51
+ /**
52
+ * Test-only launch surface for topology fixtures. It accepts an already-resolved
53
+ * command and retains the exact spawned child; no production selection path
54
+ * reaches this function.
55
+ */
56
+ export declare function startFixtureBrokerCommandWithLeaseForTest(command: FixtureBrokerCommand): StartedFixtureBrokerCommand;
34
57
  /** Test hook: returns a stop handle for the detached broker this process spawned. */
35
58
  export declare function brokerOwnerForTest(agentDir: string): BrokerOwner | undefined;
36
59
  /** Test hook: drives the detached-broker reap on a controllable child surface. */
@@ -0,0 +1,3 @@
1
+ import type { Broker } from "./broker";
2
+ /** Wait for broker-local completion, then terminate only the current broker process. */
3
+ export declare function completeBrokerProcess(broker: Broker, exit?: (code: number) => never): Promise<never>;
@@ -36,12 +36,24 @@ export interface SessionList {
36
36
  sessions: IndexedSession[];
37
37
  warnings: string[];
38
38
  }
39
+ export interface SessionIndexDiagnosis {
40
+ status: "healthy" | "corrupt" | "unsupported";
41
+ validPrefixSeq: number;
42
+ snapshotSeq: number;
43
+ reason?: string;
44
+ }
45
+ export interface SessionIndexRepairResult extends SessionIndexDiagnosis {
46
+ repaired: boolean;
47
+ quarantinePath?: string;
48
+ }
39
49
  export declare const sessionIndexChecksum: (event: Omit<SessionIndexEvent, "checksum">) => string;
40
50
  export declare class SessionIndex {
41
51
  #private;
42
52
  constructor(agentDir: string);
43
53
  open(): Promise<this>;
44
54
  replay(): Promise<void>;
55
+ diagnose(): Promise<SessionIndexDiagnosis>;
56
+ repair(): Promise<SessionIndexRepairResult>;
45
57
  refresh(): Promise<void>;
46
58
  get indexSeq(): number;
47
59
  append(input: Omit<SessionIndexEvent, "version" | "indexSeq" | "checksum" | "ts"> & Partial<Pick<SessionIndexEvent, "ts">>): Promise<SessionIndexEvent>;
@@ -3,8 +3,9 @@ export declare const SESSION_INDEX_SNAPSHOT_VERSION = 2;
3
3
  export declare class UnsupportedStateVersionError extends Error {
4
4
  readonly file: string;
5
5
  readonly version: number;
6
+ readonly maximumSupportedVersion: number;
6
7
  readonly code = "unsupported_state_version";
7
- constructor(file: string, version: number);
8
+ constructor(file: string, version: number, maximumSupportedVersion?: number);
8
9
  }
9
10
  export declare function assertSupportedStateVersion(file: string, value: unknown): void;
10
11
  export declare function assertSupportedSnapshotVersion(file: string, value: unknown): void;
@@ -1,4 +1,4 @@
1
- import { type ChatDaemonKind } from "./chat-daemon-control";
1
+ import { type ChatDaemonKind, renewChatDaemonHeartbeat } from "./chat-daemon-control";
2
2
  import { type ChatDaemonRuntimeConfig } from "./chat-daemon-runtime";
3
3
  export interface ChatDaemonRuntimeHandle {
4
4
  start(): Promise<void>;
@@ -8,11 +8,13 @@ export interface ChatDaemonRuntimeHandle {
8
8
  export interface RunChatDaemonInternalDeps {
9
9
  processPid?: number;
10
10
  pidAlive?: (pid: number) => boolean;
11
+ pidIncarnation?: (pid: number) => string | undefined;
11
12
  createRuntime?: (input: {
12
13
  kind: ChatDaemonKind;
13
14
  agentDir: string;
14
15
  config: ChatDaemonConfig;
15
16
  }) => Promise<ChatDaemonRuntimeHandle> | ChatDaemonRuntimeHandle;
17
+ renewHeartbeat?: (input: Parameters<typeof renewChatDaemonHeartbeat>[0]) => Promise<boolean>;
16
18
  setInterval?: typeof setInterval;
17
19
  clearInterval?: typeof clearInterval;
18
20
  }
@@ -2,6 +2,13 @@ import type { Settings } from "../../config/settings";
2
2
  import type { BuiltInDaemonController, DaemonOperationOptions, DaemonOperationResult, DaemonRuntimeInfo, DaemonStatus } from "../../daemon/control-types";
3
3
  export type ChatDaemonKind = "discord" | "slack";
4
4
  export type ChatDaemonAction = "stop" | "reload";
5
+ /**
6
+ * Operational generations of the Discord/Slack daemon lifecycle contracts.
7
+ * These are intentionally separate from per-session endpoint generations.
8
+ * Generation 6 carries the retained managed filesystem authority boundary.
9
+ */
10
+ export declare const CHAT_DAEMON_GENERATIONS: Readonly<Record<ChatDaemonKind, number>>;
11
+ export declare function chatDaemonGeneration(kind: ChatDaemonKind): number;
5
12
  export interface ChatDaemonState {
6
13
  version: 1;
7
14
  kind: ChatDaemonKind;
@@ -12,8 +19,16 @@ export interface ChatDaemonState {
12
19
  startedAt: number;
13
20
  heartbeatAt: number;
14
21
  transportHealthy: boolean;
22
+ generation: number;
15
23
  stoppedAt?: number;
16
24
  }
25
+ /**
26
+ * State files are untrusted persisted input. A record must be completely valid
27
+ * before its PID can be treated as an owner, stopped, or safe to replace.
28
+ */
29
+ /** A legacy owner is recognized only when the sole missing field is generation. */
30
+ export declare function isRecognizedLegacyGeneration(value: unknown): value is undefined;
31
+ export declare function hasSafeChatDaemonStateShape(value: unknown): value is ChatDaemonState;
17
32
  export interface ChatDaemonControlRequest {
18
33
  version: 1;
19
34
  requestId: string;
@@ -23,9 +38,13 @@ export interface ChatDaemonControlRequest {
23
38
  createdAt: number;
24
39
  incarnation: string;
25
40
  }
41
+ export interface ChatDaemonProcessReference {
42
+ incarnation: string;
43
+ signalRoot(signal: NodeJS.Signals): void;
44
+ }
26
45
  export interface ChatDaemonControlDeps {
27
46
  pidAlive?: (pid: number) => boolean;
28
- sendSignal?: (pid: number, signal: NodeJS.Signals) => void;
47
+ processReference?: (pid: number) => ChatDaemonProcessReference | undefined;
29
48
  spawn?: (command: string, args: string[], opts: {
30
49
  detached: boolean;
31
50
  stdio: "ignore";
@@ -36,7 +55,10 @@ export interface ChatDaemonControlDeps {
36
55
  ownerPid?: number;
37
56
  randomId?: () => string;
38
57
  pidIncarnation?: (pid: number) => string | undefined;
58
+ /** Test seam for platform-specific default stable-process authority. */
59
+ platform?: NodeJS.Platform;
39
60
  sleep?: (ms: number) => Promise<void>;
61
+ spawnReadyTimeoutMs?: number;
40
62
  }
41
63
  export declare function chatDaemonPaths(agentDir: string, kind: ChatDaemonKind): {
42
64
  dir: string;
@@ -71,7 +93,15 @@ export declare class ChatDaemonController implements BuiltInDaemonController {
71
93
  ensure(): Promise<EnsureChatDaemonResult>;
72
94
  private operate;
73
95
  private incarnation;
74
- private isLiveState;
96
+ private processReference;
97
+ private isDefinitelyStoppedState;
98
+ private stateHealth;
99
+ private isSignalableMatchingOwner;
100
+ /** A live PID with an invalid ownership record is never safe to overwrite. */
101
+ private isAmbiguouslyLiveState;
102
+ private isHealthyFreshState;
103
+ private classify;
104
+ private isCurrentCompatibleState;
75
105
  private stopForReplacement;
76
106
  private ownsCapturedState;
77
107
  private signalIfOwner;
@@ -80,6 +110,7 @@ export declare class ChatDaemonController implements BuiltInDaemonController {
80
110
  private waitForDeath;
81
111
  private sleep;
82
112
  private spawn;
113
+ private waitForOwnership;
83
114
  }
84
115
  export type EnsureChatDaemonResult = "disabled" | "owner_spawned" | "attached";
85
116
  export declare function ensureDiscordDaemon(settings: Settings, deps?: ChatDaemonControlDeps): Promise<EnsureChatDaemonResult>;
@@ -101,11 +132,15 @@ export declare function renewChatDaemonHeartbeat(input: {
101
132
  pid?: number;
102
133
  incarnation?: string;
103
134
  transportHealthy: boolean;
135
+ pidAlive?: (pid: number) => boolean;
136
+ pidIncarnation?: (pid: number) => string | undefined;
104
137
  }): Promise<boolean>;
105
138
  export declare function releaseChatDaemonOwnership(input: {
106
139
  agentDir: string;
107
140
  kind: ChatDaemonKind;
108
141
  ownerId: string;
109
- pid?: number;
110
- incarnation?: string;
142
+ pid: number;
143
+ incarnation: string;
144
+ pidAlive?: (pid: number) => boolean;
145
+ pidIncarnation?: (pid: number) => string | undefined;
111
146
  }): Promise<void>;
@@ -67,3 +67,11 @@ export declare function parseInThreadConfigCommand(text: string): ConfigCommandC
67
67
  * daemon-locally, so it never becomes a `config_command` frame or a user turn.
68
68
  */
69
69
  export declare function parseRichToggleCommand(text: string): boolean | undefined;
70
+ /**
71
+ * Parse a `/toolactivity on|off` toggle for Telegram tool-activity delivery.
72
+ *
73
+ * This is daemon-local delivery policy rather than a host-session config
74
+ * command, so it works without a connected session and persists globally.
75
+ * Addressed commands are accepted only for the exact current bot username.
76
+ */
77
+ export declare function parseToolActivityToggleCommand(text: string, botUsername?: string): boolean | undefined;
@@ -37,6 +37,12 @@ export interface NotificationSettingsSnapshot {
37
37
  richDraft: {
38
38
  enabled: boolean;
39
39
  };
40
+ toolActivity: {
41
+ enabled: boolean;
42
+ };
43
+ streaming: {
44
+ enabled: boolean;
45
+ };
40
46
  topics: {
41
47
  nameTemplate?: string;
42
48
  };
@@ -109,6 +115,12 @@ export interface NotificationConfig {
109
115
  richDraft: {
110
116
  enabled: boolean;
111
117
  };
118
+ toolActivity: {
119
+ enabled: boolean;
120
+ };
121
+ streaming: {
122
+ enabled: boolean;
123
+ };
112
124
  topics: {
113
125
  /**
114
126
  * Optional Telegram forum-topic name template with `{repo}`, `{branch}`,
@@ -149,6 +161,16 @@ type NotificationConfigFile = z.infer<typeof notificationConfigSchema>;
149
161
  export declare function loadNotificationConfigFile(agentDir: string): LoadResult<NotificationConfigFile>;
150
162
  export declare function notificationConfigFromFile(value: NotificationConfigFile): Pick<NotificationConfig, "enabled" | "discord" | "slack" | "redact" | "verbosity">;
151
163
  export declare function hasNonBlankValue(value: string | undefined): boolean;
164
+ /**
165
+ * Resolve live assistant streaming independently of generic notification
166
+ * lifecycle enablement. Explicit environment values override the durable
167
+ * Telegram preference; otherwise streaming is available only to an active
168
+ * configured Telegram identity.
169
+ */
170
+ export declare function isNotificationStreamingEnabled(input: {
171
+ cfg: NotificationConfig;
172
+ env: NodeJS.ProcessEnv;
173
+ }): boolean;
152
174
  /** Is Telegram configured with usable non-blank boundary credentials? */
153
175
  export declare function isTelegramConfigured(cfg: NotificationConfig): cfg is NotificationConfig & {
154
176
  botToken: string;
@@ -21,8 +21,13 @@ import type { Tool } from "@gajae-code/ai";
21
21
  import { NotificationServer } from "@gajae-code/natives";
22
22
  import { Settings } from "../../config/settings";
23
23
  import type { ExtensionAPI, ExtensionContext } from "../../extensibility/extensions";
24
- import type { WorkflowGateTerminalProof } from "../../modes/shared/agent-wire/workflow-gate-broker";
25
- import type { AskRemoteControl } from "../../tools";
24
+ import { type WorkflowGateEmitter, type WorkflowGateTerminalProof } from "../../modes/shared/agent-wire/workflow-gate-broker";
25
+ import type { AgentSessionEvent } from "../../session/agent-session";
26
+ import type { AskAnswerSourceResult, AskRemoteControl } from "../../tools";
27
+ import { SessionSdkHost } from "../host";
28
+ import { CursorRegistry, RevisionStore } from "../host/query";
29
+ import { type SdkStartupFailure } from "../startup-capability";
30
+ import { type NotificationConfig } from "./config";
26
31
  import { NotificationSessionController } from "./session-control";
27
32
  import { type EnsureDaemonResult } from "./telegram-daemon";
28
33
  /** Where a `session_create` should run. Discriminated by `kind`. */
@@ -182,6 +187,17 @@ export interface SessionReadyFrame {
182
187
  * instead of the worktree directory (e.g. `feat-foo-01047f11`).
183
188
  */
184
189
  export declare function readGitRepoName(cwd: string): string | undefined;
190
+ interface PendingInteractiveAsk {
191
+ resolve: (result: AskAnswerSourceResult) => void;
192
+ options: string[];
193
+ controls: readonly AskRemoteControl[];
194
+ actionId?: string;
195
+ retireForDirectControl: () => RetireStatus;
196
+ reissue: () => boolean;
197
+ complete: (actionId: string) => void;
198
+ completeDirect: () => void;
199
+ fail: (actionId: string) => void;
200
+ }
185
201
  interface UnattendedGatePresentation {
186
202
  gateId: string;
187
203
  sessionId: string;
@@ -260,9 +276,139 @@ export declare class PresentationArbiter {
260
276
  cancel(gateId: string, reason: string): void;
261
277
  dispose(): void;
262
278
  }
279
+ interface SessionRuntime {
280
+ server: NotificationServer;
281
+ host: SessionSdkHost;
282
+ /** Owns stateRoot-backed revisions and removes their spills on terminal shutdown. */
283
+ revisions: RevisionStore;
284
+ /** Releases all snapshot pins before the revision store is closed. */
285
+ cursors: CursorRegistry;
286
+ /** Current endpoint session identity; never re-key an existing host across a switch. */
287
+ id: string;
288
+ idleSeq: number;
289
+ /** Interactive asks awaiting a remote answer, by action id. */
290
+ pendingInteractive: Map<string, PendingInteractiveAsk>;
291
+ /** Deregisters this session's ask answer source. */
292
+ disposeAnswerSource: () => void;
293
+ /** Deregisters this session's Telegram file sink. */
294
+ disposeFileSink: () => void;
295
+ /** Deregisters this session's workflow-gate listener. */
296
+ disposeGateListener: () => void;
297
+ /** Whether notification-only delivery and answer resources are active. */
298
+ notificationsActive: boolean;
299
+ /** Set as soon as terminal teardown is requested, before startup settles. */
300
+ stopping: boolean;
301
+ /** Recreates notification-only resources after `/notify on`. */
302
+ enableNotifications: () => void;
303
+ /** Deregisters canonical workflow-gate terminal cleanup. */
304
+ disposeGateTerminalController: () => void;
305
+ disposeAckRecoveryParticipant: () => void;
306
+ disposeGateEmitterListener: () => void;
307
+ /** Aborts and fences side turns while notification delivery is disabled. */
308
+ disableEphemeralTurns: () => void;
309
+ waitForGateResolutionQuiescence: () => Promise<void>;
310
+ trackGateResolution: <T>(resolution: Promise<T>) => Promise<T>;
311
+ workflowGate?: WorkflowGateEmitter;
312
+ gatePresentations?: PresentationArbiter;
313
+ redact: boolean;
314
+ /** Last stable policy's redaction state, retained while provisional policy is held. */
315
+ committedRedact: boolean;
316
+ /** Provisional policy suppresses delivery without changing committed-side effects. */
317
+ policySuspended: boolean;
318
+ /** Monotonic policy epoch fences asynchronous notification delivery. */
319
+ policyGeneration: number;
320
+ /** True only after the exact host generation was registered with the broker index. */
321
+ brokerRegistrationActive: boolean;
322
+ /** Terminal cleanup proof retained across retries; each owner is released at most once after proof. */
323
+ hostStopped: boolean;
324
+ serverStopped: boolean;
325
+ brokerRegistrationReleased: boolean;
326
+ verbosity: "lean" | "verbose";
327
+ sessionTag: string;
328
+ /** Whether the agent loop is currently running (drives the typing indicator). */
329
+ busy: boolean;
330
+ /** Prompt command/turn identities awaiting their corresponding agent_start. */
331
+ pendingPromptCorrelations: Array<{
332
+ commandId: string;
333
+ turnId: string;
334
+ }>;
335
+ /** Identity bound to the agent lifecycle currently in flight. */
336
+ activePromptCorrelation?: {
337
+ commandId: string;
338
+ turnId: string;
339
+ };
340
+ /** Records a correlated prompt terminal boundary after agent unwind. */
341
+ /** Atomically claims a correlated prompt terminal boundary after agent unwind. */
342
+ recordPromptTerminal: (correlation: {
343
+ commandId: string;
344
+ turnId: string;
345
+ } | undefined) => boolean;
346
+ /** Records correlated lifecycle frames for replay and delivers them only to the accepted requester after acknowledgement. */
347
+ emitPromptLifecycle: (correlation: {
348
+ commandId: string;
349
+ turnId: string;
350
+ } | undefined, frame: {
351
+ type: "agent_start" | "agent_end";
352
+ sessionId: string;
353
+ commandId?: string;
354
+ turnId?: string;
355
+ } | {
356
+ type: "agent_failed";
357
+ sessionId: string;
358
+ commandId: string;
359
+ turnId: string;
360
+ error: {
361
+ code: string;
362
+ message: string;
363
+ };
364
+ }) => void;
365
+ /** Publishes one canonical agent-wire event to the client that owns the active prompt. */
366
+ emitPromptEvent: (event: AgentSessionEvent) => void;
367
+ /** Inbound Telegram update ids injected but not yet consumed by a turn. */
368
+ pendingInbound: Set<number>;
369
+ /** Latest assistant text of the in-flight turn (from message_update). */
370
+ currentTurnText?: string;
371
+ /** Assistant text already flushed before an ask this turn (turn-scoped dedupe
372
+ * so turn_end does not re-emit the pre-ask lead-in). Reset each turn. */
373
+ preAskFlushedText?: string;
374
+ /** Live streaming: opt-in flag, monotonic per-turn ref, and emit throttle state. */
375
+ stream: boolean;
376
+ turnSeq?: number;
377
+ liveRef?: string;
378
+ lastLiveAt?: number;
379
+ lastLiveText?: string;
380
+ /** True between turn_end and the next turn_start: drops late async message_update
381
+ * frames so a stale live edit can never be emitted after the finalized turn. */
382
+ turnClosed?: boolean;
383
+ /** Finalized while provisional policy was held; flush exactly once on stable activation. */
384
+ pendingFinal?: {
385
+ text?: string;
386
+ messageRef?: string;
387
+ };
388
+ /** Durable gates emitted while ownership is provisional; presented only after stable activation. */
389
+ deferredGatePresentations: Array<() => void>;
390
+ /** SDK control frames received during provisional ownership; replayed only after stable activation. */
391
+ deferredInboundControls: Array<() => void>;
392
+ /** Started tool calls awaiting a terminal activity frame, keyed by tool call id. */
393
+ inFlightTools: Map<string, {
394
+ toolName: string;
395
+ args: unknown;
396
+ }>;
397
+ /** Cancels the postmortem cleanup that emits `session_closed` on process teardown. */
398
+ cancelPostmortemCleanup: () => void;
399
+ /** Disposes side-turn resources when their owning logical session becomes unavailable. */
400
+ abortEphemeralTurns: () => void;
401
+ }
263
402
  /** Stable projection of the tool-owned safe-display seam (never the full Tool surface). */
264
403
  type SafeSummaryTool = Pick<Tool, "safeSummary" | "safeSummaryFields">;
265
404
  export declare function projectToolSummary(tool: SafeSummaryTool | undefined, kind: "args" | "result", value: unknown): string | undefined;
405
+ type SessionStartStatus = "started" | "already" | "disabled" | "failed";
406
+ type SessionStartResult = {
407
+ status: SessionStartStatus;
408
+ runtime?: SessionRuntime;
409
+ failure?: SdkStartupFailure;
410
+ suppressExtensionError?: boolean;
411
+ };
266
412
  export declare function notificationsEnabled(): boolean;
267
413
  /** Workflow-gate answer shape. */
268
414
  interface GateAnswer {
@@ -328,6 +474,12 @@ export declare class EphemeralTurnHost {
328
474
  /** Testable event-ring eviction boundary; tombstones remain idempotency authority. */
329
475
  evictTerminalEvents(): void;
330
476
  }
477
+ /**
478
+ * Ensures every configured chat-provider daemon is ready before the SDK
479
+ * publishes session identity. A rejected ensure is startup-fatal: presenting
480
+ * an identity for a transport that never became available is false success.
481
+ */
482
+ export declare function ensureConfiguredProviderDaemons(settings: Settings, cfg: NotificationConfig, ensureProviderDaemon?: (provider: "discord" | "slack", settings: Settings) => Promise<unknown>): Promise<void>;
331
483
  export declare function createNotificationsExtension(api: ExtensionAPI, options?: {
332
484
  settings?: Settings;
333
485
  ensureTelegramDaemon?: (input: {
@@ -335,6 +487,7 @@ export declare function createNotificationsExtension(api: ExtensionAPI, options?
335
487
  cwd: string;
336
488
  sessionId: string;
337
489
  }) => Promise<EnsureDaemonResult>;
490
+ ensureProviderDaemon?: (provider: "discord" | "slack", settings: Settings) => Promise<unknown>;
338
491
  /** Suppress auto-delivery for a GJC-spawned child under `sessionScope=primary`. */
339
492
  spawnedByGjc?: boolean;
340
493
  controller?: NotificationSessionController;
@@ -344,5 +497,12 @@ export declare function createNotificationsExtension(api: ExtensionAPI, options?
344
497
  runEphemeralTurn?: (promptText: string, signal: AbortSignal) => Promise<{
345
498
  replyText: string;
346
499
  }>;
500
+ /** Observes settlement of optional session-branch startup after reconciliation completes. */
501
+ onBranchStartupSettled?: (receipt: {
502
+ sessionId: string;
503
+ status: SessionStartResult["status"];
504
+ }) => void;
505
+ readNotificationFile?: (path: string) => Promise<Buffer>;
506
+ readNotificationDiffStat?: (cwd: string) => Promise<string | undefined>;
347
507
  }): void;
348
508
  export {};