@gajae-code/coding-agent 0.11.9 → 0.11.11

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 (150) hide show
  1. package/CHANGELOG.md +56 -1
  2. package/dist/types/cli.d.ts +8 -1
  3. package/dist/types/config/model-profile-activation.d.ts +1 -0
  4. package/dist/types/config/model-profile-contract.d.ts +2 -0
  5. package/dist/types/config/model-registry.d.ts +2 -0
  6. package/dist/types/config/settings-schema.d.ts +57 -2
  7. package/dist/types/config/settings.d.ts +1 -0
  8. package/dist/types/extensibility/extensions/types.d.ts +21 -0
  9. package/dist/types/gjc-runtime/linux-proc.d.ts +22 -14
  10. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +60 -0
  11. package/dist/types/gjc-runtime/state-runtime.d.ts +3 -1
  12. package/dist/types/gjc-runtime/state-writer.d.ts +1 -0
  13. package/dist/types/modes/acp/acp-agent.d.ts +14 -9
  14. package/dist/types/modes/components/queue-pane.d.ts +8 -0
  15. package/dist/types/modes/components/queued-message-selector.d.ts +6 -0
  16. package/dist/types/modes/components/welcome.d.ts +1 -0
  17. package/dist/types/modes/controllers/selector-controller.d.ts +16 -8
  18. package/dist/types/modes/interactive-mode.d.ts +5 -1
  19. package/dist/types/runtime/memory-domain.d.ts +9 -0
  20. package/dist/types/runtime/memory-guard-contract.d.ts +71 -0
  21. package/dist/types/runtime/memory-guard.d.ts +39 -0
  22. package/dist/types/runtime/memory-limit.d.ts +11 -0
  23. package/dist/types/runtime-mcp/manager.d.ts +8 -0
  24. package/dist/types/sdk/acp/final-text.d.ts +19 -0
  25. package/dist/types/sdk/acp/mcp.d.ts +23 -0
  26. package/dist/types/sdk/broker/lifecycle.d.ts +2 -0
  27. package/dist/types/sdk/bus/chat-daemon-control.d.ts +2 -1
  28. package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
  29. package/dist/types/sdk/bus/index.d.ts +11 -2
  30. package/dist/types/sdk/bus/operator-runtime.d.ts +1 -0
  31. package/dist/types/sdk/bus/rate-limit-pool.d.ts +2 -0
  32. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +14 -7
  33. package/dist/types/sdk/bus/telegram-daemon.d.ts +97 -8
  34. package/dist/types/sdk/host/control/operations.d.ts +1 -0
  35. package/dist/types/sdk/lifecycle-session.d.ts +10 -1
  36. package/dist/types/sdk/session.d.ts +7 -0
  37. package/dist/types/sdk/startup-capability.d.ts +6 -0
  38. package/dist/types/session/agent-session.d.ts +11 -11
  39. package/dist/types/session/fallback-chain-controller.d.ts +18 -2
  40. package/dist/types/session/internal/managed-session-scope.d.ts +28 -1
  41. package/dist/types/session/session-manager.d.ts +34 -0
  42. package/dist/types/task/executor.d.ts +6 -0
  43. package/dist/types/task/provider-retry-status.d.ts +13 -0
  44. package/dist/types/task/types.d.ts +39 -0
  45. package/dist/types/task/ultragoal-redteam-activation.d.ts +33 -0
  46. package/dist/types/tools/index.d.ts +3 -1
  47. package/dist/types/tools/resource-gc.d.ts +19 -0
  48. package/package.json +8 -8
  49. package/scripts/generate-sdk-operation-inventory.ts +3 -0
  50. package/scripts/run-test-manifest.ts +6 -4
  51. package/src/cli/args.ts +14 -8
  52. package/src/cli/fast-help.ts +1 -1
  53. package/src/cli/notify-cli.ts +1 -0
  54. package/src/cli.ts +48 -2
  55. package/src/commands/sdk.ts +91 -7
  56. package/src/config/model-profile-activation.ts +1 -0
  57. package/src/config/model-profile-contract.ts +13 -0
  58. package/src/config/model-profiles.ts +31 -7
  59. package/src/config/model-registry.ts +4 -2
  60. package/src/config/settings-schema.ts +61 -2
  61. package/src/config/settings.ts +8 -0
  62. package/src/defaults/gjc/skills/ralplan/SKILL.md +21 -2
  63. package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
  64. package/src/eval/js/tool-bridge.ts +1 -1
  65. package/src/extensibility/extensions/runner.ts +4 -0
  66. package/src/extensibility/extensions/types.ts +14 -0
  67. package/src/gjc-runtime/deep-interview-ambiguity.ts +16 -2
  68. package/src/gjc-runtime/deep-interview-draft.ts +2 -1
  69. package/src/gjc-runtime/deep-interview-recorder.ts +16 -1
  70. package/src/gjc-runtime/deep-interview-state.ts +25 -3
  71. package/src/gjc-runtime/linux-proc.ts +70 -36
  72. package/src/gjc-runtime/ralplan-runtime.ts +252 -1
  73. package/src/gjc-runtime/state-runtime.ts +48 -11
  74. package/src/gjc-runtime/state-writer.ts +1 -1
  75. package/src/hooks/skill-state.ts +23 -1
  76. package/src/internal-urls/docs-index.generated.ts +7 -7
  77. package/src/internal-urls/local-protocol.ts +23 -4
  78. package/src/modes/acp/acp-agent.ts +554 -60
  79. package/src/modes/acp/acp-event-mapper.ts +93 -6
  80. package/src/modes/components/model-selector.ts +15 -1
  81. package/src/modes/components/notifications-settings-editor.ts +1 -1
  82. package/src/modes/components/queue-pane.ts +55 -9
  83. package/src/modes/components/queued-message-selector.ts +53 -10
  84. package/src/modes/components/tool-status-header.ts +1 -4
  85. package/src/modes/components/welcome.ts +18 -3
  86. package/src/modes/controllers/command-controller.ts +4 -0
  87. package/src/modes/controllers/extension-ui-controller.ts +4 -10
  88. package/src/modes/controllers/input-controller.ts +44 -3
  89. package/src/modes/controllers/selector-controller.ts +38 -8
  90. package/src/modes/interactive-mode.ts +65 -26
  91. package/src/modes/runtime-init.ts +1 -0
  92. package/src/prompts/agent-fragments/restricted-bash.md +1 -1
  93. package/src/prompts/agents/architect.md +8 -1
  94. package/src/prompts/agents/critic.md +8 -1
  95. package/src/prompts/agents/executor.md +1 -1
  96. package/src/prompts/agents/planner.md +8 -1
  97. package/src/runtime/memory-domain.ts +66 -0
  98. package/src/runtime/memory-guard-contract.ts +73 -0
  99. package/src/runtime/memory-guard.ts +292 -0
  100. package/src/runtime/memory-limit.ts +50 -0
  101. package/src/runtime-mcp/manager.ts +26 -6
  102. package/src/sdk/acp/adapter.ts +8 -1
  103. package/src/sdk/acp/final-text.ts +40 -0
  104. package/src/sdk/acp/mcp.ts +26 -0
  105. package/src/sdk/broker/identity.ts +22 -12
  106. package/src/sdk/broker/lifecycle.ts +82 -1
  107. package/src/sdk/bus/chat-daemon-cli.ts +2 -2
  108. package/src/sdk/bus/chat-daemon-control.ts +4 -3
  109. package/src/sdk/bus/config.ts +1 -1
  110. package/src/sdk/bus/daemon-paths.ts +2 -0
  111. package/src/sdk/bus/index.ts +222 -27
  112. package/src/sdk/bus/notification-service.ts +19 -5
  113. package/src/sdk/bus/operator-runtime.ts +31 -5
  114. package/src/sdk/bus/rate-limit-pool.ts +8 -0
  115. package/src/sdk/bus/telegram-cli.ts +6 -13
  116. package/src/sdk/bus/telegram-daemon-cli.ts +8 -3
  117. package/src/sdk/bus/telegram-daemon-contract.ts +15 -7
  118. package/src/sdk/bus/telegram-daemon-control.ts +14 -5
  119. package/src/sdk/bus/telegram-daemon.ts +1191 -164
  120. package/src/sdk/host/control/dispatch.ts +2 -0
  121. package/src/sdk/host/control/operations.ts +1 -0
  122. package/src/sdk/host/host.ts +2 -2
  123. package/src/sdk/lifecycle-session.ts +19 -3
  124. package/src/sdk/protocol/operation-inventory.generated.json +58 -0
  125. package/src/sdk/protocol/operation-registry.ts +1 -0
  126. package/src/sdk/session.ts +24 -1
  127. package/src/sdk/startup-capability.ts +6 -0
  128. package/src/session/agent-session.ts +290 -132
  129. package/src/session/fallback-chain-controller.ts +47 -8
  130. package/src/session/internal/managed-session-scope.ts +173 -127
  131. package/src/session/internal/native-publish-outcome.ts +8 -3
  132. package/src/session/session-manager.ts +608 -25
  133. package/src/skill-state/workflow-mutation-guard.ts +41 -7
  134. package/src/task/executor.ts +152 -42
  135. package/src/task/index.ts +2 -0
  136. package/src/task/provider-retry-status.ts +88 -0
  137. package/src/task/render.ts +45 -26
  138. package/src/task/types.ts +25 -11
  139. package/src/task/ultragoal-redteam-activation.ts +75 -0
  140. package/src/tools/bash-allowed-prefixes.ts +45 -1
  141. package/src/tools/index.ts +3 -1
  142. package/src/tools/resource-gc.ts +496 -120
  143. package/src/tools/subagent-render.ts +74 -16
  144. package/src/tools/subagent.ts +2 -0
  145. package/src/workflow/workflow-intent-diff.ts +4 -1
  146. package/vendor/insane-search/MANIFEST.json +4 -1
  147. package/vendor/insane-search/engine/bias_check.py +5 -0
  148. package/vendor/insane-search/engine/fetch_chain.py +67 -1
  149. package/vendor/insane-search/engine/transport.py +13 -2
  150. package/vendor/insane-search/engine/validators.py +4 -1
@@ -5,7 +5,7 @@ import type { InteractiveModeContext, OAuthSelectorOptions } from "../../modes/t
5
5
  import { getNotificationConfig, maskToken } from "../../sdk/bus/config";
6
6
  import { proposedTelegramIdentity, reconcileCommittedTelegramConfiguration, removeTelegramConfiguration, saveTelegramInactive } from "../../sdk/bus/notification-orchestration";
7
7
  import { buildNotificationStatusReport, checkNotificationHealth, recoverNotifications, sanitizeDiagnostic, sendNotificationTest } from "../../sdk/bus/notification-service";
8
- import { ensureTelegramDaemonRunningDetailed, resolveTelegramSetupPreflight, unregisterNotificationRoot } from "../../sdk/bus/telegram-daemon";
8
+ import { ensureTelegramDaemonRunningDetailed, readNotificationRootRegistration, resolveTelegramSetupPreflight, unregisterNotificationRoot } from "../../sdk/bus/telegram-daemon";
9
9
  import { runTelegramSetup } from "../../sdk/bus/telegram-setup";
10
10
  import { type CredentialAutoImportStateStore } from "../../setup/credential-auto-import";
11
11
  import { type CommandPaletteAction } from "../components/command-palette";
@@ -28,6 +28,13 @@ export interface NotificationsEditorAdapterContext {
28
28
  sessionManager: Pick<InteractiveModeContext["sessionManager"], "getCwd" | "getSessionId">;
29
29
  notifyConfigChanged?: () => Promise<void> | void;
30
30
  }
31
+ type TelegramDaemonStopResult = {
32
+ ok: boolean;
33
+ message: string;
34
+ before?: {
35
+ health?: string;
36
+ };
37
+ };
31
38
  export interface NotificationsEditorOperationDependencies {
32
39
  getNotificationConfig: typeof getNotificationConfig;
33
40
  maskToken: typeof maskToken;
@@ -43,7 +50,13 @@ export interface NotificationsEditorOperationDependencies {
43
50
  reconcileCommittedTelegramConfiguration: typeof reconcileCommittedTelegramConfiguration;
44
51
  saveTelegramInactive: typeof saveTelegramInactive;
45
52
  removeTelegramConfiguration: typeof removeTelegramConfiguration;
53
+ readNotificationRootRegistration: typeof readNotificationRootRegistration;
46
54
  unregisterNotificationRoot: typeof unregisterNotificationRoot;
55
+ stopTelegramDaemonIfRootRegistryFenceMatches(input: {
56
+ settings: Settings;
57
+ registryFingerprint: string;
58
+ stop: () => Promise<TelegramDaemonStopResult>;
59
+ }): Promise<boolean>;
47
60
  reloadTelegramDaemon(settings: Settings): Promise<{
48
61
  ok: boolean;
49
62
  message: string;
@@ -52,13 +65,7 @@ export interface NotificationsEditorOperationDependencies {
52
65
  ok: boolean;
53
66
  message: string;
54
67
  }>;
55
- stopTelegramDaemon(settings: Settings): Promise<{
56
- ok: boolean;
57
- message: string;
58
- before?: {
59
- health?: string;
60
- };
61
- }>;
68
+ stopTelegramDaemon(settings: Settings): Promise<TelegramDaemonStopResult>;
62
69
  }
63
70
  /**
64
71
  * Concrete service adapter for the direct Notifications settings tab. Secrets remain in this closure's
@@ -128,3 +135,4 @@ export declare class SelectorController {
128
135
  showJobsOverlay(observer: JobsObserver): void;
129
136
  showTasksPane(aggregator: TasksAggregator): void;
130
137
  }
138
+ export {};
@@ -34,8 +34,12 @@ import { PromptSuggestionController } from "./prompt-suggestion-controller";
34
34
  import type { Theme } from "./theme/theme";
35
35
  import { type CompactionQueuedMessage, type ComposerSubmissionOptions, type InteractiveModeContext, type IrcArrivalSnapshot, type SubmittedUserInput, type TodoItem, type TodoPhase, type TranscriptRebuildPolicy } from "./types";
36
36
  import type { ParsedIrcMessage } from "./utils/irc-message";
37
- export declare function getDefaultComposerPlaceholder(context?: KeyDisplayContext): string;
37
+ export declare function getDefaultComposerPlaceholder(context?: KeyDisplayContext, keybindings?: Pick<KeybindingsManager, "getDisplayString">): string;
38
38
  export declare const DEFAULT_COMPOSER_PLACEHOLDER: string;
39
+ export declare function getComposerPlaceholder(keybindings: Pick<KeybindingsManager, "getDisplayString">, context: KeyDisplayContext, options: {
40
+ readonly busy: boolean;
41
+ readonly busyPromptMode: "steer" | "queue";
42
+ }): string;
39
43
  export declare function getWelcomeTranscriptReservedRows(chatContainer: Container, width: number): number;
40
44
  export type WelcomeBannerSettingMode = "auto" | "unicode" | "square" | "ascii";
41
45
  export declare function resolveWelcomeLogoMode(mode: WelcomeBannerSettingMode, env?: Record<string, string | undefined>, platform?: NodeJS.Platform): WelcomeLogoMode;
@@ -0,0 +1,9 @@
1
+ import type { MemoryGuardDomainSnapshot, MemoryGuardWorkerSample } from "./memory-guard-contract";
2
+ export interface MemoryGuardDomainInput {
3
+ effectiveLimitBytes: number;
4
+ totalUsageBytes: number;
5
+ parentBytes: number;
6
+ parentReserveBytes: number;
7
+ workers: readonly MemoryGuardWorkerSample[];
8
+ }
9
+ export declare function computeMemoryGuardDomain(input: MemoryGuardDomainInput): MemoryGuardDomainSnapshot;
@@ -0,0 +1,71 @@
1
+ export interface MemoryGuardPolicy {
2
+ enabled: boolean;
3
+ checkIntervalMs: number;
4
+ gcThresholdRatio: number;
5
+ restartThresholdRatio: number;
6
+ restartThresholdWindowMs: number;
7
+ cooldownMs: number;
8
+ parentReserveBytes: number;
9
+ policyLimitBytes: number | null;
10
+ }
11
+ export interface MemoryGuardWorkerSample {
12
+ workerId: string;
13
+ bytes: number;
14
+ accepted?: boolean;
15
+ }
16
+ export interface MemoryGuardWorkerAccounting {
17
+ workerId: string;
18
+ bytes: number;
19
+ accepted: boolean;
20
+ allowanceBytes: number;
21
+ excessBytes: number;
22
+ }
23
+ export interface MemoryGuardDomainSnapshot {
24
+ effectiveLimitBytes: number;
25
+ totalUsageBytes: number;
26
+ parentBytes: number;
27
+ parentReserveBytes: number;
28
+ totalWorkerBytes: number;
29
+ acceptedWorkerCount: number;
30
+ unmanagedBytes: number;
31
+ headroomBytes: number;
32
+ workerBudgetBytes: number;
33
+ perWorkerAllowanceBytes: number;
34
+ hostExcessBytes: number;
35
+ workers: MemoryGuardWorkerAccounting[];
36
+ }
37
+ export interface MemoryGuardHostTarget {
38
+ kind: "host";
39
+ excessBytes: number;
40
+ }
41
+ export interface MemoryGuardWorkerTarget {
42
+ kind: "worker";
43
+ workerId: string;
44
+ excessBytes: number;
45
+ }
46
+ export type MemoryGuardActionTarget = MemoryGuardHostTarget | MemoryGuardWorkerTarget;
47
+ export type MemoryGuardNoopReason = "memory_guard_action_noop_unmanaged_or_within_allowance" | "memory_guard_action_noop_unsupported";
48
+ export type MemoryGuardDecision = {
49
+ kind: "execute";
50
+ target: MemoryGuardActionTarget;
51
+ } | {
52
+ kind: "noop";
53
+ reason: MemoryGuardNoopReason;
54
+ } | {
55
+ kind: "revalidated_out";
56
+ reason: "memory_guard_action_revalidated_out";
57
+ };
58
+ export interface MemoryGuardSchedulerState {
59
+ timerActive: boolean;
60
+ registrationCount: number;
61
+ inProgress: boolean;
62
+ generation: number;
63
+ pendingDeadline: number | null;
64
+ pendingOwner: {
65
+ generation: number;
66
+ token: number;
67
+ } | null;
68
+ deferredDeadline: number | null;
69
+ deferredGeneration: number | null;
70
+ activeGeneration: number | null;
71
+ }
@@ -0,0 +1,39 @@
1
+ import type { Settings } from "../config/settings";
2
+ import type { MemoryGuardDecision, MemoryGuardDomainSnapshot, MemoryGuardPolicy, MemoryGuardSchedulerState } from "./memory-guard-contract";
3
+ type WorkOwner = {
4
+ generation: number;
5
+ source: "timer" | "external";
6
+ };
7
+ export interface MemoryGuardHostRegistration {
8
+ ownerId: string;
9
+ intervalMs: number;
10
+ }
11
+ export interface MemoryGuardHostOptions {
12
+ run: () => Promise<void>;
13
+ logDebug?: (message: string, meta?: Record<string, unknown>) => void;
14
+ schedulerNow?: () => number;
15
+ }
16
+ export declare function resolveMemoryGuardPolicy(settings: Settings): MemoryGuardPolicy;
17
+ export declare function chooseMemoryGuardAction(input: {
18
+ domain: MemoryGuardDomainSnapshot;
19
+ hostSupported: boolean;
20
+ workerSupported: (workerId: string) => boolean;
21
+ }): MemoryGuardDecision;
22
+ export declare function revalidateMemoryGuardAction(previous: Extract<MemoryGuardDecision, {
23
+ kind: "execute";
24
+ }>, revalidated: MemoryGuardDecision): MemoryGuardDecision;
25
+ export declare class MemoryGuardHost {
26
+ #private;
27
+ constructor(options: MemoryGuardHostOptions);
28
+ register(registration: MemoryGuardHostRegistration): () => void;
29
+ updateInterval(ownerId: string, intervalMs: number): void;
30
+ runTick(generation?: number, source?: WorkOwner["source"]): Promise<void>;
31
+ runTimerCallbackForTest(owner: {
32
+ generation: number;
33
+ token: number;
34
+ }, deadline: number): Promise<void>;
35
+ setSchedulerNowForTest(now: () => number): void;
36
+ getStateForTest(): MemoryGuardSchedulerState;
37
+ resetForTest(): void;
38
+ }
39
+ export {};
@@ -0,0 +1,11 @@
1
+ export interface EffectiveMemoryLimitInput {
2
+ hardCapBytes?: number | null;
3
+ policyLimitBytes?: number | null;
4
+ }
5
+ export interface EffectiveMemoryLimit {
6
+ hardCapBytes: number | null;
7
+ policyLimitBytes: number | null;
8
+ effectiveBytes: number | null;
9
+ source: "none" | "hard_cap" | "policy_limit" | "hard_cap_and_policy_limit";
10
+ }
11
+ export declare function resolveEffectiveMemoryLimit(input: EffectiveMemoryLimitInput): EffectiveMemoryLimit;
@@ -5,6 +5,7 @@ import type { AuthStorage } from "../session/auth-storage";
5
5
  import type { MCPToolDetails } from "./tool-bridge";
6
6
  import type { MCPToolCache } from "./tool-cache";
7
7
  import type { MCPGetPromptResult, MCPPrompt, MCPRequestOptions, MCPResource, MCPResourceReadResult, MCPResourceTemplate, MCPServerConfig, MCPServerConnection } from "./types";
8
+ export declare function resolveStartupTimeoutMs(configs: MCPServerConfig[], maxStartupTimeoutMs?: number): number;
8
9
  /**
9
10
  * Stable, total ordering on MCP tools by name.
10
11
  *
@@ -48,6 +49,13 @@ export interface MCPDiscoverOptions {
48
49
  export interface MCPManagerOptions {
49
50
  /** Restrict this instance to tools from an explicit MCP config. */
50
51
  toolsOnly?: boolean;
52
+ /**
53
+ * Ceiling for the startup wait, in milliseconds. Only ACP lifecycle launches
54
+ * set this, so a slow ACP MCP handshake gets the readiness budget while every
55
+ * other consumer keeps the short default. Non-positive or non-finite values
56
+ * are ignored and the default applies.
57
+ */
58
+ maxStartupTimeoutMs?: number;
51
59
  }
52
60
  /**
53
61
  * MCP Server Manager.
@@ -0,0 +1,19 @@
1
+ export declare const ACP_FINAL_TEXT_LIMIT = 100000;
2
+ export interface BoundedAcpFinalText {
3
+ text: string;
4
+ truncated: boolean;
5
+ }
6
+ export type AcpFinalTextResolution = {
7
+ kind: "none";
8
+ final: BoundedAcpFinalText;
9
+ } | {
10
+ kind: "emit";
11
+ final: BoundedAcpFinalText;
12
+ text: string;
13
+ } | {
14
+ kind: "divergent";
15
+ final: BoundedAcpFinalText;
16
+ };
17
+ export declare function boundAcpFinalText(value: string): BoundedAcpFinalText;
18
+ export declare function acpFinalTextFromMessage(message: unknown): BoundedAcpFinalText;
19
+ export declare function resolveAcpFinalText(streamed: string, finalText: string): AcpFinalTextResolution;
@@ -0,0 +1,23 @@
1
+ export declare const ACP_MCP_REQUEST_TIMEOUT_MS = 30000;
2
+ export declare const ACP_MCP_LIFECYCLE_TIMEOUT_MS: number;
3
+ /**
4
+ * Slice of the readiness budget reserved for the work that follows MCP startup
5
+ * (session wiring, marker publication). The ACP MCP startup ceiling is the
6
+ * remaining time to `semanticReadyDeadlineAt` minus this headroom, so a slow
7
+ * MCP handshake cannot consume the whole readiness window.
8
+ */
9
+ export declare const ACP_MCP_STARTUP_HEADROOM_MS = 250;
10
+ export interface SessionLifecycleMcpStdioServer {
11
+ type?: "stdio";
12
+ name: string;
13
+ command: string;
14
+ args: string[];
15
+ env?: Record<string, string>;
16
+ }
17
+ export interface SessionLifecycleMcpRemoteServer {
18
+ type: "http" | "sse";
19
+ name: string;
20
+ url: string;
21
+ headers?: Record<string, string>;
22
+ }
23
+ export type SessionLifecycleMcpServer = SessionLifecycleMcpStdioServer | SessionLifecycleMcpRemoteServer;
@@ -1,3 +1,4 @@
1
+ import type { SessionLifecycleMcpServer } from "../acp/mcp";
1
2
  import type { SdkStartupFailure, SdkStartupRollbackResult } from "../startup-capability";
2
3
  import type { Broker, BrokerCleanupEvidence, BrokerResponse } from "./broker";
3
4
  import type { LifecycleDurableEffectsReceipt, LifecycleStartupFailureReceipt } from "./lifecycle-ledger";
@@ -61,6 +62,7 @@ export interface SessionLifecycleLaunchRequest {
61
62
  /** Broker-issued effect marker which the child echoes only after host readiness. */
62
63
  effectMarker?: string;
63
64
  modelPreset?: string;
65
+ mcpServers?: SessionLifecycleMcpServer[];
64
66
  worktree?: SessionLifecycleWorktreeTarget;
65
67
  receivedAt: number;
66
68
  requestedReadinessTimeoutMs: number;
@@ -15,7 +15,8 @@ export type ChatDaemonAction = "stop" | "reload";
15
15
  * concrete detached quarantine plus a proven-absent canonical lock pathname —
16
16
  * when deleting an observed owner-lock lease. Generation 12 refreshes retained
17
17
  * native path and process authority semantics. Generation 13 rejects special
18
- * files before retained native authority opens.
18
+ * files before retained native authority opens. Generation 14 reloads shared
19
+ * chat daemons after notification configuration parsing changes.
19
20
  */
20
21
  export declare const CHAT_DAEMON_GENERATIONS: Readonly<Record<ChatDaemonKind, number>>;
21
22
  export declare function chatDaemonGeneration(kind: ChatDaemonKind): number;
@@ -9,6 +9,7 @@ export interface DaemonPaths {
9
9
  dir: string;
10
10
  lock: string;
11
11
  state: string;
12
+ heartbeat: string;
12
13
  ownership: string;
13
14
  roots: string;
14
15
  steal: string;
@@ -29,7 +29,7 @@ import { CursorRegistry, RevisionStore } from "../host/query";
29
29
  import { type SdkStartupFailure } from "../startup-capability";
30
30
  import { type NotificationConfig } from "./config";
31
31
  import { NotificationSessionController } from "./session-control";
32
- import { type EnsureDaemonResult } from "./telegram-daemon";
32
+ import { type EnsureDaemonResult, type RegisterNotificationRootResult } from "./telegram-daemon";
33
33
  /** Where a `session_create` should run. Discriminated by `kind`. */
34
34
  export type SessionCreateTarget = {
35
35
  kind: "existing_path";
@@ -324,6 +324,12 @@ interface SessionRuntime {
324
324
  hostStopped: boolean;
325
325
  serverStopped: boolean;
326
326
  brokerRegistrationReleased: boolean;
327
+ /** Managed Telegram root registration released during terminal teardown. */
328
+ notificationRootRegistration?: {
329
+ settings: Settings;
330
+ cwd: string;
331
+ registrationToken?: string;
332
+ };
327
333
  verbosity: "lean" | "verbose";
328
334
  sessionTag: string;
329
335
  /** Whether the agent loop is currently running (drives the typing indicator). */
@@ -368,6 +374,7 @@ interface SessionRuntime {
368
374
  sessionId: string;
369
375
  commandId?: string;
370
376
  turnId?: string;
377
+ finalText?: string;
371
378
  } | {
372
379
  type: "agent_failed";
373
380
  sessionId: string;
@@ -417,7 +424,8 @@ interface SessionRuntime {
417
424
  /** Started tool calls awaiting a terminal activity frame, keyed by tool call id. */
418
425
  inFlightTools: Map<string, {
419
426
  toolName: string;
420
- args: unknown;
427
+ args?: unknown;
428
+ pendingPhase?: "completed" | "failed" | "cancelled";
421
429
  }>;
422
430
  /** Cancels the postmortem cleanup that emits `session_closed` on process teardown. */
423
431
  cancelPostmortemCleanup: () => void;
@@ -511,6 +519,7 @@ export declare function createNotificationsExtension(api: ExtensionAPI, options?
511
519
  settings: Settings;
512
520
  cwd: string;
513
521
  sessionId: string;
522
+ onRegistered?: (registration: RegisterNotificationRootResult) => void;
514
523
  }) => Promise<EnsureDaemonResult>;
515
524
  ensureProviderDaemon?: (provider: "discord" | "slack", settings: Settings) => Promise<unknown>;
516
525
  /** Suppress auto-delivery for a GJC-spawned child under `sessionScope=primary`. */
@@ -47,6 +47,7 @@ export declare class NotificationOperatorRuntime {
47
47
  stopInterval(name: string): void;
48
48
  stopAllIntervals(): void;
49
49
  runExclusive(name: string, fn: () => Promise<void>): Promise<void>;
50
+ joinExclusive(name: string, timeoutMs: number): Promise<boolean>;
50
51
  sleep(ms: number, signal?: AbortSignal): Promise<void>;
51
52
  now(): number;
52
53
  }
@@ -84,6 +84,8 @@ export declare class RateLimitPool<T = unknown> {
84
84
  constructor(options?: RateLimitPoolOptions);
85
85
  /** Number of items currently queued across all lanes. */
86
86
  get pending(): number;
87
+ /** Whether any queued item currently matches the predicate. */
88
+ someQueued(predicate: (item: RateLimitItem<T>) => boolean): boolean;
87
89
  /** Current available token count (after refill at `now`). */
88
90
  availableTokens(nowMs?: number): number;
89
91
  /**
@@ -5,12 +5,9 @@
5
5
  /** Protocol version the daemon advertises in its ClientHello. */
6
6
  export declare const NOTIFICATION_PROTOCOL_VERSION = 3;
7
7
  /**
8
- * Operational generation the current daemon build speaks. Decoupled from
9
- * {@link NOTIFICATION_PROTOCOL_VERSION} (#2304): additive `tool_activity` /
10
- * `reasoning_summary` frames do not bump the wire protocol version, but a
11
- * freshly-upgraded host must still recognize an older, still-live daemon that
12
- * predates capability-gated frame enforcement and trigger a reload. Bump this
13
- * on every daemon-behavior change independent of the wire version.
8
+ * Guarded behavior-inventory version for the current daemon build. Bump this
9
+ * on every guarded daemon-behavior change independent of the wire version; it
10
+ * does not force a live daemon reload by itself.
14
11
  * The current development baseline already includes #2299's generation 4,
15
12
  * incarnation fencing in generation 5, owner-lock authority in generation 6,
16
13
  * identity-atomic transition markers in generation 7, stable signaling plus
@@ -38,5 +35,15 @@ export declare const NOTIFICATION_PROTOCOL_VERSION = 3;
38
35
  * cooldown and lazy Telegram topic lifecycle safeguards (#2956, #2960, #2984).
39
36
  * Generation 27 refreshes retained native path and process authority semantics.
40
37
  * Generation 28 rejects special files before retained native authority opens.
38
+ * Generation 29 adds serving-epoch compatibility, sidecar heartbeat, root GC,
39
+ * and Bot API cooldown structural fixes (#2956, #2960, #3048).
40
+ * Generation 30 adds opt-in tool activity delivery, closed lifecycle phases,
41
+ * and capability-versioned mixed-host compatibility.
41
42
  */
42
- export declare const DAEMON_GENERATION = 28;
43
+ export declare const DAEMON_GENERATION = 30;
44
+ /**
45
+ * Serving-compatibility boundary for daemon lifecycle requests. Epoch 1 covers
46
+ * all builds published before this field existed; epoch 2 covered generation 29;
47
+ * bump this to force serving convergence and reload of compatible live predecessors.
48
+ */
49
+ export declare const SERVING_EPOCH = 3;
@@ -5,10 +5,10 @@ import { HEARTBEAT_TTL_MS } from "./daemon-paths";
5
5
  import { type DaemonTransitionLock, type NotificationEndpointFile, type NotificationEndpointFileIdentity, type NotificationExactUnlinkResult } from "./notification-service";
6
6
  import { type DaemonProcessReference } from "./telegram-daemon-control";
7
7
  import { type TelegramSetupPreflight } from "./telegram-setup";
8
- export { DAEMON_GENERATION, NOTIFICATION_PROTOCOL_VERSION } from "./telegram-daemon-contract";
8
+ export { DAEMON_GENERATION, NOTIFICATION_PROTOCOL_VERSION, SERVING_EPOCH } from "./telegram-daemon-contract";
9
9
  import { type ControlServerLike, type LifecycleControlServerFactory } from "./lifecycle-control-runtime";
10
10
  import type { OrchestratorDeps } from "./lifecycle-orchestrator";
11
- import { NotificationOperatorRuntime, OperatorBackoffPolicy } from "./operator-runtime";
11
+ import { NotificationOperatorRuntime } from "./operator-runtime";
12
12
  import { type AliasTable, type CallbackRoute } from "./telegram-reference";
13
13
  import { type TopicEndpointBinding } from "./topic-registry";
14
14
  export type EnsureDaemonResult = "owner_spawned" | "attached" | "disabled" | "blocked";
@@ -41,6 +41,8 @@ export interface DaemonState {
41
41
  * notification wire protocol version. Absent on pre-generation state.
42
42
  */
43
43
  generation?: number;
44
+ /** Lifecycle-serving compatibility epoch; absent pre-epoch records are epoch 1. */
45
+ servingEpoch?: number;
44
46
  stoppedAt?: number;
45
47
  }
46
48
  export interface TelegramDaemonFs {
@@ -105,8 +107,10 @@ export declare const CLIENT_PING_PONG_CAPABILITY = "client_ping_pong";
105
107
  /** Capability required for typed controls and semantic Selected acknowledgement frames. */
106
108
  export declare const ASK_SELECTED_ACK_CAPABILITY = "ask_selected_ack_v1";
107
109
  export declare const ASK_CONTROLS_CAPABILITY = "ask_controls_v1";
108
- /** Capability required for tool lifecycle and reasoning-summary frames. */
109
- export declare const TOOL_ACTIVITY_CAPABILITY = "tool_activity_v1";
110
+ /** Capability for the closed tool phase set: started, completed, failed, and cancelled. */
111
+ export declare const TOOL_ACTIVITY_CAPABILITY = "tool_activity_v2";
112
+ /** Receive-only compatibility capability for pre-v2 hosts. */
113
+ export declare const LEGACY_TOOL_ACTIVITY_CAPABILITY = "tool_activity_v1";
110
114
  /**
111
115
  * File-lock options whose acquisition budget covers the full reload-reservation
112
116
  * critical section: the in-lock freshness poll plus the controller's
@@ -201,15 +205,59 @@ export declare function liveOwnershipLockDecision(input: {
201
205
  attached: false;
202
206
  provisional: true;
203
207
  } | undefined;
208
+ type OwnerHeartbeatSidecar = {
209
+ pid: number;
210
+ incarnation: string;
211
+ ownerId: string;
212
+ acquisitionId: string;
213
+ heartbeatAt: number;
214
+ };
215
+ export interface OwnerFreshnessSnapshot {
216
+ ownerTag: Pick<OwnerHeartbeatSidecar, "pid" | "incarnation" | "ownerId" | "acquisitionId"> | null;
217
+ effectiveHeartbeatAt: number | undefined;
218
+ legacyEmbedded: boolean;
219
+ state: DaemonState | undefined;
220
+ }
221
+ export declare function readOwnerFreshnessSnapshot(input: {
222
+ settings: Settings;
223
+ fs?: TelegramDaemonFs;
224
+ }): Promise<OwnerFreshnessSnapshot>;
225
+ /** Marker-free steady heartbeat renewal. The final lock reread fences a stale writer. */
226
+ export declare function renewOwnerHeartbeatSidecar(input: {
227
+ settings: Settings;
228
+ ownerId: string;
229
+ acquisitionId?: string;
230
+ fs?: TelegramDaemonFs;
231
+ now?: () => number;
232
+ pid?: number;
233
+ pidIncarnation?: (pid: number) => string | undefined;
234
+ }): Promise<boolean>;
235
+ export interface NotificationRootRegistration {
236
+ root?: string;
237
+ managed?: boolean;
238
+ token?: string;
239
+ }
240
+ export declare function readNotificationRootRegistration(input: {
241
+ settings: Settings;
242
+ sessionId: string;
243
+ fs?: TelegramDaemonFs;
244
+ }): Promise<NotificationRootRegistration>;
245
+ export interface RegisterNotificationRootResult {
246
+ root: string;
247
+ /** Per-registration ownership token fencing a stale same-session cleanup from deleting a live replacement registration. */
248
+ token: string;
249
+ }
204
250
  export declare function registerNotificationRoot(input: {
205
251
  settings: Settings;
206
252
  cwd: string;
207
253
  sessionId: string;
208
254
  fs?: TelegramDaemonFs;
209
- }): Promise<string>;
255
+ }): Promise<RegisterNotificationRootResult>;
210
256
  export interface UnregisterNotificationRootResult {
211
257
  root: string;
212
258
  remainingRoots: number;
259
+ /** Opaque fingerprint of the exact registry written by this successful unregister. */
260
+ registryFingerprint?: string;
213
261
  }
214
262
  /** Remove one session's Telegram scan root without disturbing other live session roots. */
215
263
  export declare function unregisterNotificationRoot(input: {
@@ -217,7 +265,16 @@ export declare function unregisterNotificationRoot(input: {
217
265
  cwd: string;
218
266
  sessionId: string;
219
267
  fs?: TelegramDaemonFs;
268
+ /** Ownership token minted by this runtime's own registration; a stale cleanup presenting an older token never deletes a replacement registration. */
269
+ registrationToken?: string;
220
270
  }): Promise<UnregisterNotificationRootResult>;
271
+ /** Run an action while the roots registry lock excludes any registration or unregister. */
272
+ export declare function withNotificationRootRegistryFence(input: {
273
+ settings: Settings;
274
+ registryFingerprint: string;
275
+ action: () => Promise<void>;
276
+ fs?: TelegramDaemonFs;
277
+ }): Promise<boolean>;
221
278
  /**
222
279
  * Leak artifact prefixes left when native exact-unlink cleanup is retained
223
280
  * (#2956). Nothing previously reaped these; they accumulate in the notifications
@@ -319,6 +376,7 @@ export declare function isFreshLiveOwner(input: {
319
376
  chatId: string;
320
377
  pidAlive: (pid: number) => boolean;
321
378
  pidIncarnation?: (pid: number) => string | undefined;
379
+ effectiveHeartbeatAt?: number;
322
380
  }): boolean;
323
381
  /** True only when a physically live matching owner can serve this build's daemon lifecycle contract. */
324
382
  export declare function isCurrentCompatibleOwner(input: {
@@ -328,6 +386,7 @@ export declare function isCurrentCompatibleOwner(input: {
328
386
  chatId: string;
329
387
  pidAlive: (pid: number) => boolean;
330
388
  pidIncarnation?: (pid: number) => string | undefined;
389
+ effectiveHeartbeatAt?: number;
331
390
  }): boolean;
332
391
  export declare function acquireDaemonOwnership(input: {
333
392
  settings: Settings;
@@ -399,7 +458,7 @@ export declare function retireProvisionalDaemonOwnership(input: {
399
458
  /** Only no-child confirmation may retire a ready-like launcher publication. */
400
459
  allowReadyWithoutChildPid?: boolean;
401
460
  }): Promise<boolean>;
402
- /** Wait for a matching current-generation daemon to publish a ready state. */
461
+ /** Wait for a matching compatible owner to publish a ready state. Readiness is serving-epoch gated (same-epoch cross-generation owners attach, per isCurrentCompatibleOwner); generation is inventory-only here. Mutation paths still require exact current-generation equality. */
403
462
  export declare function waitForTelegramDaemonReady(input: {
404
463
  settings: Settings;
405
464
  ownerId?: string;
@@ -548,6 +607,9 @@ export declare function ensureTelegramDaemonRunningDetailed(input: {
548
607
  settings: Settings;
549
608
  cwd: string;
550
609
  sessionId: string;
610
+ registerRoot?: boolean;
611
+ /** Receives each registration this ensure operation minted so the caller can fence its own later cleanup. */
612
+ onRegistered?: (registration: RegisterNotificationRootResult) => void;
551
613
  }, deps?: TelegramDaemonDeps): Promise<EnsureTelegramDaemonDetailedResult>;
552
614
  /**
553
615
  * Legacy compatibility mapping for callers that only distinguish ownership from
@@ -600,7 +662,10 @@ export type TelegramPollResult = {
600
662
  export interface TelegramUpdatePollerOptions {
601
663
  botApi: BotApi;
602
664
  runtime: NotificationOperatorRuntime;
603
- backoff: OperatorBackoffPolicy;
665
+ backoff: {
666
+ next(): number;
667
+ reset(): void;
668
+ };
604
669
  processUpdate: (update: unknown) => Promise<TelegramUpdateOutcome>;
605
670
  health?: TelegramPollHealth;
606
671
  }
@@ -689,7 +754,7 @@ export interface TelegramDaemonOptions {
689
754
  richDraft?: {
690
755
  enabled: boolean;
691
756
  };
692
- /** Tool start/completion messages (enabled by default). */
757
+ /** Tool start/completion messages (off by default; explicit opt-in only). */
693
758
  toolActivity?: {
694
759
  enabled: boolean;
695
760
  };
@@ -723,6 +788,8 @@ interface SessionSocket {
723
788
  /** True once the server advertised the `client_ping_pong` capability. */
724
789
  capable: boolean;
725
790
  ephemeralCapable: boolean;
791
+ /** Tool activity contract advertised by the connected host. */
792
+ toolActivityCapability?: "v1" | "v2";
726
793
  /** Timestamp (via opts.now) of the last received pong; seeds the TTL window. */
727
794
  lastPongAt: number;
728
795
  /** Nonce of the most recent in-flight ping, if any. */
@@ -752,6 +819,9 @@ export declare class TelegramNotificationDaemon {
752
819
  /** Endpoint-bound ownership for visible or dispatching tool bubbles. */
753
820
  private readonly toolActivityOwners;
754
821
  private readonly revokedToolEndpoints;
822
+ /** Exact settlement of each admitted legacy-v1 start; retained only while visible. */
823
+ private readonly legacyToolStarts;
824
+ private nextLegacyToolStartId;
755
825
  private readonly unresolvedToolTerminalizations;
756
826
  private toolTerminalizationChain;
757
827
  private toolActivityPolicyEpoch;
@@ -785,6 +855,9 @@ export declare class TelegramNotificationDaemon {
785
855
  private readonly pool;
786
856
  private readonly poller;
787
857
  private readonly dispatchState;
858
+ /** Bot-wide flood-control window; inbound polling remains eligible during it. */
859
+ private botCooldownUntil;
860
+ private warnedBotCooldownUntil;
788
861
  /** Original markdown of rich messages we sent (chat+message_id), for restoring reply context on inbound replies. */
789
862
  private readonly replyStore;
790
863
  /** Per-session debounce + monotonic draft-id state for opt-in draft streaming. */
@@ -871,6 +944,9 @@ export declare class TelegramNotificationDaemon {
871
944
  private refreshBotIdentity;
872
945
  /** Map a lifecycle response/error to a user-facing message (G010 surfacing). */
873
946
  private formatLifecycleResponse;
947
+ private callBotApi;
948
+ private readonly callBotApiClassified;
949
+ private botApiWithOutcomeCollector;
874
950
  constructor(opts: TelegramDaemonOptions);
875
951
  private createSessionRouter;
876
952
  loadAliases(): Promise<void>;
@@ -917,8 +993,21 @@ export declare class TelegramNotificationDaemon {
917
993
  private topicIdentityKey;
918
994
  private topicIdentityBase;
919
995
  private topicOwnerForIdentity;
996
+ private admitLegacyToolStart;
997
+ private legacyToolStartForTerminal;
998
+ private settleLegacyToolStart;
999
+ private cancelUnsentLegacyToolStart;
1000
+ private failLegacyToolStart;
1001
+ private settleRejectedLegacyToolSubmission;
1002
+ private cancelLegacyToolStartsForSession;
1003
+ private cleanLegacyToolStartsForCapabilityUpgrade;
1004
+ private cancelLegacyToolStartsForPolicyTransition;
920
1005
  private toolActivityOwner;
1006
+ private renderThreadedFrame;
1007
+ private toolActivityFrameWithoutSummaries;
1008
+ private toolActivitySummariesAreCurrent;
921
1009
  private toolActivityAuthorityIsCurrent;
1010
+ private toolActivityDeliveryIsCurrent;
922
1011
  private submitThreadedFrame;
923
1012
  private existingTopicForPrivateChat;
924
1013
  private topicAuthorityLease;
@@ -18,6 +18,7 @@ export interface ControlSurface {
18
18
  operateGoal(op: string, objective?: string): Promise<ControlValue> | ControlValue;
19
19
  replaceTodo(items: ControlValue): Promise<ControlValue> | ControlValue;
20
20
  setModel(id: string, thinkingLevel?: ControlValue): Promise<ControlValue> | ControlValue;
21
+ setModelProfile(id: string): Promise<ControlValue> | ControlValue;
21
22
  cycleModel(): Promise<ControlValue> | ControlValue;
22
23
  setThinking(level: ControlValue): Promise<ControlValue> | ControlValue;
23
24
  cycleThinking(): Promise<ControlValue> | ControlValue;
@@ -10,5 +10,14 @@ export type CreateLifecycleAgentSessionResult = {
10
10
  rollback: SdkStartupRollbackTracker;
11
11
  failure: SdkStartupFailure;
12
12
  };
13
+ /** Options accepted by lifecycle-only session construction. */
14
+ export type CreateLifecycleAgentSessionOptions = CreateAgentSessionOptions & {
15
+ /**
16
+ * Startup budget for ACP lifecycle MCP launches, in milliseconds. Set only
17
+ * when the lifecycle request supplies `mcpServers`; ordinary consumers keep
18
+ * the manager's short default ceiling.
19
+ */
20
+ mcpStartupTimeoutMs?: number;
21
+ };
13
22
  /** Internal lifecycle-only session construction with an owner-bound SDK startup result. */
14
- export declare function createLifecycleAgentSession(options?: CreateAgentSessionOptions): Promise<CreateLifecycleAgentSessionResult>;
23
+ export declare function createLifecycleAgentSession(options?: CreateLifecycleAgentSessionOptions): Promise<CreateLifecycleAgentSessionResult>;