@gajae-code/coding-agent 0.18.6 → 0.18.8

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 (302) hide show
  1. package/CHANGELOG.md +318 -1
  2. package/dist/types/async/job-manager.d.ts +1 -1
  3. package/dist/types/capability/mcp.d.ts +2 -0
  4. package/dist/types/capability/skill.d.ts +2 -0
  5. package/dist/types/capability/types.d.ts +6 -0
  6. package/dist/types/cli/public-command-errors.d.ts +3 -1
  7. package/dist/types/cli/setup-cli.d.ts +1 -1
  8. package/dist/types/commands/deep-interview.d.ts +3 -0
  9. package/dist/types/config/autorouting-tier-map.d.ts +348 -9
  10. package/dist/types/config/file-lock.d.ts +1 -0
  11. package/dist/types/config/model-bindings-applier.d.ts +2 -0
  12. package/dist/types/config/model-profile-activation.d.ts +11 -3
  13. package/dist/types/config/model-registry.d.ts +4 -9
  14. package/dist/types/config/settings.d.ts +4 -0
  15. package/dist/types/config/skill-settings-defaults.d.ts +2 -0
  16. package/dist/types/cursor-delete-path.d.ts +1 -0
  17. package/dist/types/cursor-mcp-name.d.ts +8 -0
  18. package/dist/types/customization/inventory.d.ts +2 -0
  19. package/dist/types/debug/report-bundle-parent.d.ts +2 -0
  20. package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.d.ts +1 -0
  21. package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.d.ts +31 -0
  22. package/dist/types/defaults/gjc-skills.generated.d.ts +5 -6
  23. package/dist/types/discovery/helpers.d.ts +8 -3
  24. package/dist/types/export/html/css-color.d.ts +2 -0
  25. package/dist/types/export/html/template.generated.d.ts +1 -1
  26. package/dist/types/extensibility/extensions/types.d.ts +7 -0
  27. package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +14 -1
  28. package/dist/types/extensibility/plugins/marketplace/cache.d.ts +2 -0
  29. package/dist/types/extensibility/plugins/plugin-link-path.d.ts +2 -0
  30. package/dist/types/extensibility/runtime-skill-discovery.d.ts +3 -1
  31. package/dist/types/extensibility/skill-management.d.ts +3 -1
  32. package/dist/types/extensibility/skills.d.ts +2 -0
  33. package/dist/types/gjc-runtime/deep-interview-crystallize.d.ts +74 -0
  34. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +11 -0
  35. package/dist/types/gjc-runtime/gc-runtime.d.ts +5 -0
  36. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +0 -5
  37. package/dist/types/gjc-runtime/state-argv.d.ts +1 -1
  38. package/dist/types/gjc-runtime/state-migrations.d.ts +8 -0
  39. package/dist/types/gjc-runtime/state-runtime.d.ts +95 -0
  40. package/dist/types/gjc-runtime/state-writer.d.ts +11 -1
  41. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -0
  42. package/dist/types/internal-urls/skill-path.d.ts +1 -0
  43. package/dist/types/lsp/workspace-path.d.ts +1 -0
  44. package/dist/types/modes/acp/acp-agent.d.ts +7 -0
  45. package/dist/types/modes/components/custom-editor.d.ts +6 -0
  46. package/dist/types/modes/components/customization/customization-dashboard.d.ts +1 -0
  47. package/dist/types/modes/components/extensions/state-manager.d.ts +4 -3
  48. package/dist/types/modes/controllers/input-controller.d.ts +9 -0
  49. package/dist/types/modes/interactive-mode.d.ts +1 -0
  50. package/dist/types/modes/utils/interrupt-ownership.d.ts +3 -0
  51. package/dist/types/modes/utils/keybinding-matchers.d.ts +1 -0
  52. package/dist/types/modes/utils/macos-option-forwarding.d.ts +17 -0
  53. package/dist/types/progress/collect-project-progress.d.ts +38 -0
  54. package/dist/types/progress/progress-contract.d.ts +154 -0
  55. package/dist/types/progress/progress-snapshot.d.ts +11 -0
  56. package/dist/types/progress/project-progress.d.ts +141 -0
  57. package/dist/types/progress/render-progress.d.ts +28 -0
  58. package/dist/types/runtime-mcp/elicitation.d.ts +12 -0
  59. package/dist/types/runtime-mcp/oauth-public-url.d.ts +1 -0
  60. package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +1 -0
  61. package/dist/types/runtime-mcp/smithery-registry.d.ts +24 -0
  62. package/dist/types/runtime-mcp/types.d.ts +6 -0
  63. package/dist/types/sdk/acp/adapter.d.ts +1 -1
  64. package/dist/types/sdk/broker/broker-exit.d.ts +6 -2
  65. package/dist/types/sdk/broker/broker.d.ts +18 -1
  66. package/dist/types/sdk/broker/lifecycle.d.ts +9 -0
  67. package/dist/types/sdk/broker/session-index.d.ts +12 -6
  68. package/dist/types/sdk/broker/task-artifact-owner-validation.d.ts +55 -0
  69. package/dist/types/sdk/bus/index.d.ts +12 -1
  70. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +6 -1
  71. package/dist/types/sdk/bus/telegram-daemon.d.ts +3 -2
  72. package/dist/types/sdk/client/client.d.ts +2 -0
  73. package/dist/types/sdk/host/host.d.ts +6 -0
  74. package/dist/types/sdk/host/query/handlers.d.ts +3 -0
  75. package/dist/types/sdk/index.d.ts +1 -0
  76. package/dist/types/sdk/router/session-router.d.ts +9 -0
  77. package/dist/types/sdk/session-list.d.ts +1 -1
  78. package/dist/types/sdk/session.d.ts +8 -0
  79. package/dist/types/session/agent-session.d.ts +38 -9
  80. package/dist/types/session/artifacts.d.ts +2 -2
  81. package/dist/types/session/internal/managed-gc-retirement-codec.d.ts +32 -0
  82. package/dist/types/session/internal/managed-session-scope.d.ts +79 -2
  83. package/dist/types/session/internal/managed-session-storage.d.ts +36 -1
  84. package/dist/types/session/internal/managed-task-owner-cleanup.d.ts +62 -0
  85. package/dist/types/session/internal/task-artifact-owner-access.d.ts +19 -0
  86. package/dist/types/session/internal/task-artifact-owner-transcript.d.ts +11 -0
  87. package/dist/types/session/session-manager.d.ts +31 -5
  88. package/dist/types/session/session-retirement.d.ts +71 -0
  89. package/dist/types/session/session-storage.d.ts +62 -48
  90. package/dist/types/session/session-transcript-header.d.ts +2 -0
  91. package/dist/types/session/task-artifact-owner-codec.d.ts +109 -0
  92. package/dist/types/session/task-artifact-owner-retirement.d.ts +7 -0
  93. package/dist/types/session/task-artifact-owner.d.ts +10 -0
  94. package/dist/types/setup/credential-auto-import.d.ts +1 -1
  95. package/dist/types/setup/credential-import.d.ts +6 -4
  96. package/dist/types/skill-state/active-state.d.ts +38 -0
  97. package/dist/types/slash-commands/helpers/progress-report.d.ts +8 -0
  98. package/dist/types/task/executor.d.ts +3 -0
  99. package/dist/types/tools/bash-skill-urls.d.ts +1 -1
  100. package/dist/types/tools/index.d.ts +3 -0
  101. package/dist/types/tools/python.d.ts +9 -1
  102. package/dist/types/tools/recipe/recipe-guard.d.ts +7 -0
  103. package/dist/types/tools/restricted-cwd.d.ts +1 -0
  104. package/dist/types/tools/todo-write.d.ts +6 -0
  105. package/dist/types/utils/tools-checksum.d.ts +7 -0
  106. package/package.json +7 -7
  107. package/scripts/generate-sdk-operation-inventory.ts +21 -0
  108. package/scripts/resident-memory-bench.ts +174 -20
  109. package/scripts/verify-managed-empty-stop.ts +28 -0
  110. package/src/async/job-manager.ts +228 -122
  111. package/src/capability/index.ts +18 -0
  112. package/src/capability/mcp.ts +2 -0
  113. package/src/capability/skill.ts +2 -0
  114. package/src/capability/types.ts +6 -0
  115. package/src/cli/auth-broker-cli.ts +1 -1
  116. package/src/cli/config-cli.ts +8 -18
  117. package/src/cli/customize-doctor.ts +15 -2
  118. package/src/cli/public-command-errors.ts +21 -1
  119. package/src/cli/setup-cli.ts +4 -4
  120. package/src/cli/skills-cli.ts +5 -0
  121. package/src/cli-main.ts +7 -8
  122. package/src/commands/deep-interview.ts +47 -8
  123. package/src/commands/sdk.ts +140 -29
  124. package/src/config/autorouting-tier-map.ts +117 -7
  125. package/src/config/file-lock.ts +307 -68
  126. package/src/config/mcp-schema.json +4 -0
  127. package/src/config/model-bindings-applier.ts +20 -0
  128. package/src/config/model-profile-activation.ts +240 -46
  129. package/src/config/model-registry.ts +47 -153
  130. package/src/config/settings.ts +44 -4
  131. package/src/config/skill-settings-defaults.ts +7 -0
  132. package/src/coordinator-mcp/policy.ts +3 -2
  133. package/src/cursor-delete-path.ts +10 -0
  134. package/src/cursor-mcp-name.ts +15 -0
  135. package/src/cursor.ts +13 -2
  136. package/src/customization/inventory.ts +3 -0
  137. package/src/debug/report-bundle-parent.ts +22 -0
  138. package/src/debug/report-bundle.ts +3 -0
  139. package/src/debug/system-info.ts +13 -1
  140. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.ts +67 -4
  141. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.ts +80 -0
  142. package/src/defaults/gjc/skills/deep-interview/SKILL.md +105 -10
  143. package/src/defaults/gjc/skills/ralplan/SKILL.md +6 -4
  144. package/src/defaults/gjc-defaults.test.ts +18 -1
  145. package/src/defaults/gjc-defaults.ts +3 -0
  146. package/src/defaults/gjc-skills.generated.ts +58 -36
  147. package/src/discovery/agents.ts +6 -1
  148. package/src/discovery/builtin.ts +10 -0
  149. package/src/discovery/helpers.ts +168 -23
  150. package/src/discovery/mcp-json.ts +6 -0
  151. package/src/discovery/ssh.ts +9 -4
  152. package/src/discovery/substitute-plugin-root.ts +3 -1
  153. package/src/edit/file-read-cache.ts +1 -1
  154. package/src/eval/py/executor.ts +380 -120
  155. package/src/export/html/css-color.ts +9 -0
  156. package/src/export/html/index.ts +5 -4
  157. package/src/export/html/template.generated.ts +1 -1
  158. package/src/extensibility/extensions/runner.ts +4 -0
  159. package/src/extensibility/extensions/types.ts +7 -0
  160. package/src/extensibility/gjc-plugins/runtime-adapters.ts +73 -8
  161. package/src/extensibility/plugins/manager.ts +3 -2
  162. package/src/extensibility/plugins/marketplace/cache.ts +15 -0
  163. package/src/extensibility/plugins/marketplace/manager.ts +11 -3
  164. package/src/extensibility/plugins/plugin-link-path.ts +12 -0
  165. package/src/extensibility/runtime-skill-discovery.ts +20 -2
  166. package/src/extensibility/skill-management.ts +6 -2
  167. package/src/extensibility/skills.ts +6 -1
  168. package/src/gjc-runtime/deep-interview-crystallize.ts +1814 -0
  169. package/src/gjc-runtime/deep-interview-recorder.ts +20 -2
  170. package/src/gjc-runtime/deep-interview-runtime.ts +1415 -13
  171. package/src/gjc-runtime/deep-interview-stage.ts +98 -21
  172. package/src/gjc-runtime/gc-runtime.ts +206 -8
  173. package/src/gjc-runtime/launch-worktree.ts +14 -4
  174. package/src/gjc-runtime/ralplan-runtime.ts +447 -52
  175. package/src/gjc-runtime/state-argv.ts +2 -0
  176. package/src/gjc-runtime/state-migrations.ts +91 -29
  177. package/src/gjc-runtime/state-runtime.ts +3716 -135
  178. package/src/gjc-runtime/state-writer.ts +83 -8
  179. package/src/gjc-runtime/ultragoal-runtime.ts +16 -4
  180. package/src/gjc-runtime/workflow-manifest.generated.json +70 -42
  181. package/src/gjc-runtime/workflow-manifest.ts +54 -21
  182. package/src/harness-control-plane/operate.ts +12 -4
  183. package/src/harness-control-plane/owner.ts +5 -1
  184. package/src/hashline/parser.ts +48 -9
  185. package/src/hashline/recovery.ts +13 -4
  186. package/src/hindsight/config.ts +9 -3
  187. package/src/internal-urls/docs-index.generated.ts +19 -18
  188. package/src/internal-urls/skill-path.ts +19 -0
  189. package/src/internal-urls/skill-protocol.ts +2 -0
  190. package/src/lsp/edits.ts +6 -0
  191. package/src/lsp/workspace-path.ts +51 -0
  192. package/src/main.ts +195 -31
  193. package/src/modes/acp/acp-agent.ts +163 -7
  194. package/src/modes/components/custom-editor.ts +14 -0
  195. package/src/modes/components/customization/customization-dashboard.ts +12 -0
  196. package/src/modes/components/extensions/extension-dashboard.ts +2 -2
  197. package/src/modes/components/extensions/state-manager.ts +15 -5
  198. package/src/modes/components/model-selector.ts +1 -4
  199. package/src/modes/components/provider-onboarding-selector.ts +1 -1
  200. package/src/modes/components/status-line/segments.ts +4 -0
  201. package/src/modes/controllers/event-controller.ts +11 -4
  202. package/src/modes/controllers/input-controller.ts +74 -29
  203. package/src/modes/controllers/runtime-mcp-command-controller.ts +8 -3
  204. package/src/modes/controllers/selector-controller.ts +28 -15
  205. package/src/modes/interactive-mode.ts +4 -0
  206. package/src/modes/runtime-init.ts +4 -0
  207. package/src/modes/utils/abort-message.ts +3 -1
  208. package/src/modes/utils/interrupt-ownership.ts +12 -0
  209. package/src/modes/utils/keybinding-matchers.ts +4 -0
  210. package/src/modes/utils/macos-option-forwarding.ts +80 -0
  211. package/src/progress/collect-project-progress.ts +153 -0
  212. package/src/progress/progress-contract.ts +172 -0
  213. package/src/progress/progress-snapshot.ts +140 -0
  214. package/src/progress/project-progress.ts +446 -0
  215. package/src/progress/render-progress.ts +209 -0
  216. package/src/prompts/system/master-mode.md +1 -0
  217. package/src/prompts/tools/skill-discovery.md +1 -1
  218. package/src/runtime-mcp/client.ts +13 -4
  219. package/src/runtime-mcp/config-writer.ts +10 -6
  220. package/src/runtime-mcp/config.ts +1 -0
  221. package/src/runtime-mcp/elicitation.ts +142 -0
  222. package/src/runtime-mcp/oauth-flow.ts +5 -0
  223. package/src/runtime-mcp/oauth-public-url.ts +8 -0
  224. package/src/runtime-mcp/plugin-network-boundary.ts +4 -0
  225. package/src/runtime-mcp/smithery-registry.ts +22 -3
  226. package/src/runtime-mcp/transports/http.ts +2 -2
  227. package/src/runtime-mcp/types.ts +6 -0
  228. package/src/sdk/acp/adapter.ts +93 -8
  229. package/src/sdk/broker/broker-exit.ts +52 -23
  230. package/src/sdk/broker/broker.ts +83 -7
  231. package/src/sdk/broker/ensure.ts +2 -0
  232. package/src/sdk/broker/lifecycle.ts +820 -73
  233. package/src/sdk/broker/session-index.ts +191 -81
  234. package/src/sdk/broker/task-artifact-owner-validation.ts +259 -0
  235. package/src/sdk/bus/chat-daemon-cli.ts +38 -1
  236. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  237. package/src/sdk/bus/chat-daemon-runtime.ts +3 -0
  238. package/src/sdk/bus/index.ts +241 -46
  239. package/src/sdk/bus/telegram-daemon-contract.ts +6 -1
  240. package/src/sdk/bus/telegram-daemon.ts +4 -2
  241. package/src/sdk/cli/session-cli.ts +17 -3
  242. package/src/sdk/client/client.ts +28 -8
  243. package/src/sdk/host/host.ts +6 -0
  244. package/src/sdk/host/query/handlers.ts +9 -1
  245. package/src/sdk/host/session-runtime.test.ts +2805 -411
  246. package/src/sdk/host/session-runtime.ts +428 -111
  247. package/src/sdk/host/surface-policy.ts +1 -0
  248. package/src/sdk/index.ts +8 -0
  249. package/src/sdk/lifecycle-session.ts +3 -1
  250. package/src/sdk/mcp/server.ts +15 -3
  251. package/src/sdk/prompt-deadline-manager.ts +15 -0
  252. package/src/sdk/protocol/operation-inventory.generated.json +146 -0
  253. package/src/sdk/protocol/operation-registry.ts +9 -2
  254. package/src/sdk/router/session-router.ts +94 -14
  255. package/src/sdk/session-list.ts +1 -0
  256. package/src/sdk/session.ts +81 -38
  257. package/src/session/agent-session.ts +674 -224
  258. package/src/session/artifacts.ts +174 -70
  259. package/src/session/internal/managed-gc-retirement-codec.ts +319 -0
  260. package/src/session/internal/managed-session-scope.ts +3457 -462
  261. package/src/session/internal/managed-session-storage.ts +482 -61
  262. package/src/session/internal/managed-task-owner-cleanup.ts +473 -0
  263. package/src/session/internal/task-artifact-owner-access.ts +245 -0
  264. package/src/session/internal/task-artifact-owner-transcript.ts +614 -0
  265. package/src/session/session-manager.ts +939 -133
  266. package/src/session/session-retirement.ts +714 -0
  267. package/src/session/session-storage.ts +418 -174
  268. package/src/session/session-transcript-header.ts +17 -0
  269. package/src/session/task-artifact-owner-codec.ts +641 -0
  270. package/src/session/task-artifact-owner-retirement.ts +477 -0
  271. package/src/session/task-artifact-owner.ts +289 -0
  272. package/src/setup/credential-auto-import.ts +12 -3
  273. package/src/setup/credential-import.ts +176 -5
  274. package/src/setup/paseo/announce.ts +6 -1
  275. package/src/skill-state/active-state.ts +132 -2
  276. package/src/slash-commands/builtin-registry.ts +39 -9
  277. package/src/slash-commands/helpers/progress-report.ts +23 -0
  278. package/src/stt/setup.ts +3 -5
  279. package/src/task/commands.ts +3 -1
  280. package/src/task/executor.ts +4 -0
  281. package/src/task/index.ts +6 -0
  282. package/src/tools/ask.ts +205 -6
  283. package/src/tools/ast-edit.ts +4 -0
  284. package/src/tools/bash-allowed-prefixes.ts +15 -0
  285. package/src/tools/bash-skill-urls.ts +56 -3
  286. package/src/tools/bash.ts +48 -79
  287. package/src/tools/descriptors.ts +5 -1
  288. package/src/tools/eval.ts +56 -36
  289. package/src/tools/image-gen.ts +1 -1
  290. package/src/tools/index.ts +3 -0
  291. package/src/tools/python.ts +187 -66
  292. package/src/tools/recipe/index.ts +9 -0
  293. package/src/tools/recipe/recipe-guard.ts +19 -0
  294. package/src/tools/restricted-cwd.ts +10 -0
  295. package/src/tools/skill-discovery.ts +5 -0
  296. package/src/tools/skill.ts +28 -1
  297. package/src/tools/todo-write.ts +10 -1
  298. package/src/tools/tool-catalog.generated.ts +1 -1
  299. package/src/tools/write.ts +1 -0
  300. package/src/utils/tools-checksum.ts +34 -0
  301. package/src/utils/tools-manager.ts +24 -6
  302. package/src/web/search/providers/codex.ts +3 -2
@@ -69,6 +69,7 @@ const QUERY_BINDINGS: Readonly<Record<string, string | undefined>> = {
69
69
  "config.list/get": "getConfigItems",
70
70
  "session.branch_candidates": "getBranchCandidates",
71
71
  "extensions.list": "getExtensions",
72
+ "session.progress": "getProjectProgress",
72
73
  };
73
74
 
74
75
  export interface SdkSurfacePolicy {
package/src/sdk/index.ts CHANGED
@@ -9,6 +9,14 @@ export {
9
9
  type UnknownModelProfileDetails,
10
10
  UnknownModelProfileError,
11
11
  } from "../config/model-profile-contract";
12
+ export {
13
+ PROJECT_PROGRESS_SNAPSHOT_SCHEMA,
14
+ type ProgressSnapshotAttention,
15
+ type ProgressSnapshotStory,
16
+ type ProgressSnapshotTodo,
17
+ type ProgressSnapshotWorkflow,
18
+ type ProjectProgressSnapshot,
19
+ } from "../progress/progress-contract";
12
20
  export type {
13
21
  QueuedInputAdmission,
14
22
  QueuedInputDelivery,
@@ -117,7 +117,9 @@ export async function createLifecycleAgentSession(
117
117
  // Explicit model pin (#4707): resolve through the staged selector
118
118
  // resolver after extension providers register (modelPattern), so the
119
119
  // pin matches CLI `--model` semantics instead of bypassing them.
120
- ...(modelId !== undefined ? { modelPattern: modelId } : {}),
120
+ // Defer startup profile activation so pin validation happens first,
121
+ // before the default profile could be activated in place of the pin.
122
+ ...(modelId !== undefined ? { modelPattern: modelId, deferModelProfileActivation: true } : {}),
121
123
  // Memory startup (rollout summarisation) issues one LLM request per
122
124
  // claimed rollout, so its duration scales with the backlog. Keeping it
123
125
  // inside the broker's readiness window is what kills the child at the
@@ -1,4 +1,4 @@
1
- import { getAgentDir } from "@gajae-code/utils";
1
+ import { getAgentDir, VERSION } from "@gajae-code/utils";
2
2
  import { ensureBroker } from "../broker/ensure";
3
3
  import { lifecycleRequestTimeoutMs } from "../broker/startup-budget";
4
4
  import { SdkClientError } from "../client/client";
@@ -14,6 +14,8 @@ import { type SessionAttachment, SessionRouter, SessionRouterError } from "../ro
14
14
  import { SessionListTraversalError, sessionListPageFromResponse, traverseSessionList } from "../session-list";
15
15
 
16
16
  const PROTOCOL_VERSION = "2024-11-05";
17
+ const SUPPORTED_PROTOCOL_VERSIONS = [PROTOCOL_VERSION, "2025-03-26", "2025-06-18"] as const;
18
+ const NEWEST_PROTOCOL_VERSION = SUPPORTED_PROTOCOL_VERSIONS[SUPPORTED_PROTOCOL_VERSIONS.length - 1];
17
19
  const SERVER_NAME = "gjc-sdk-mcp";
18
20
  const ENDPOINT_CREDENTIAL_OPERATION = "session.get_endpoint";
19
21
 
@@ -107,6 +109,16 @@ function isObject(value: unknown): value is Arguments {
107
109
  return typeof value === "object" && value !== null && !Array.isArray(value);
108
110
  }
109
111
 
112
+ function negotiatedProtocolVersion(params: unknown): string {
113
+ const requestedProtocolVersion = isObject(params) ? params.protocolVersion : undefined;
114
+ if (
115
+ typeof requestedProtocolVersion === "string" &&
116
+ (SUPPORTED_PROTOCOL_VERSIONS as readonly string[]).includes(requestedProtocolVersion)
117
+ )
118
+ return requestedProtocolVersion;
119
+ return NEWEST_PROTOCOL_VERSION;
120
+ }
121
+
110
122
  function asString(args: Arguments, name: string): string | null {
111
123
  return typeof args[name] === "string" && args[name] ? (args[name] as string) : null;
112
124
  }
@@ -389,9 +401,9 @@ export function createSdkMcpServer(options: SdkMcpServerOptions = {}) {
389
401
  jsonrpc: "2.0",
390
402
  id,
391
403
  result: {
392
- protocolVersion: PROTOCOL_VERSION,
404
+ protocolVersion: negotiatedProtocolVersion(request.params),
393
405
  capabilities: { tools: {} },
394
- serverInfo: { name: SERVER_NAME },
406
+ serverInfo: { name: SERVER_NAME, version: VERSION },
395
407
  },
396
408
  };
397
409
  if (request.method === "tools/list")
@@ -347,6 +347,21 @@ export class PromptDeadlineManager {
347
347
  } catch {
348
348
  // claim may fail if already claimed (e.g., cancellation won); ignore.
349
349
  }
350
+ // The claim and the first lookup are separated by an await. A real
351
+ // agent_end can therefore commit terminal_ok while the deadline path is
352
+ // still preparing its synthetic failure. Re-read the durable state before
353
+ // invoking terminalization so a completed turn cannot be reported later as
354
+ // prompt_deadline_exceeded.
355
+ try {
356
+ const settled = this.#reconciliation.lookup("prompt", correlation) as { status: string };
357
+ if (settled.status === "terminal_ok" || settled.status === "failed") {
358
+ this.clear(correlation);
359
+ return;
360
+ }
361
+ } catch {
362
+ // Keep the existing uncertainty recovery path below when the durable
363
+ // read is unavailable.
364
+ }
350
365
  // A real terminal may win between lookup and this claim. A diagnostic-only
351
366
  // failure is not terminal evidence; preserve it privately until the host hook
352
367
  // proves the exact run/tool settlement and captures its correlated agent_end.
@@ -1673,6 +1673,24 @@
1673
1673
  "packages/coding-agent/test/sdk-operation-inventory.test.ts"
1674
1674
  ]
1675
1675
  },
1676
+ {
1677
+ "sourceId": "registry:Q32",
1678
+ "sourceFile": "packages/coding-agent/src/sdk/protocol/operation-registry.ts",
1679
+ "sourceKind": "registry",
1680
+ "decision": "include",
1681
+ "sdkId": "session.progress",
1682
+ "adapterMappings": {
1683
+ "telegram": "prohibited",
1684
+ "discord": "prohibited",
1685
+ "slack": "prohibited",
1686
+ "mcp": "generic_safe",
1687
+ "acp": "generic_safe",
1688
+ "daemonCli": "generic_safe"
1689
+ },
1690
+ "testIds": [
1691
+ "packages/coding-agent/test/sdk-operation-inventory.test.ts"
1692
+ ]
1693
+ },
1676
1694
  {
1677
1695
  "sourceId": "registry:R01",
1678
1696
  "sourceFile": "packages/coding-agent/src/sdk/protocol/operation-registry.ts",
@@ -2053,6 +2071,24 @@
2053
2071
  "packages/coding-agent/test/sdk-operation-inventory.test.ts"
2054
2072
  ]
2055
2073
  },
2074
+ {
2075
+ "sourceId": "slash_command:progress",
2076
+ "sourceFile": "packages/coding-agent/src/slash-commands/builtin-registry.ts",
2077
+ "sourceKind": "slash_command",
2078
+ "decision": "include",
2079
+ "sdkId": "session.progress",
2080
+ "adapterMappings": {
2081
+ "telegram": "prohibited",
2082
+ "discord": "prohibited",
2083
+ "slack": "prohibited",
2084
+ "mcp": "generic_safe",
2085
+ "acp": "generic_safe",
2086
+ "daemonCli": "generic_safe"
2087
+ },
2088
+ "testIds": [
2089
+ "packages/coding-agent/test/sdk-operation-inventory.test.ts"
2090
+ ]
2091
+ },
2056
2092
  {
2057
2093
  "sourceId": "slash_command:usage",
2058
2094
  "sourceFile": "packages/coding-agent/src/slash-commands/builtin-registry.ts",
@@ -2844,6 +2880,17 @@
2844
2880
  "packages/coding-agent/test/sdk-operation-inventory.test.ts"
2845
2881
  ]
2846
2882
  },
2883
+ {
2884
+ "sourceId": "agent_session:getSubagentLifecycleStatuses",
2885
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
2886
+ "sourceKind": "agent_session",
2887
+ "decision": "exclude",
2888
+ "rationale": "internal read-only subagent status projection consumed through session.progress (Q32), not a separate SDK seam",
2889
+ "exclusionMetadata": {
2890
+ "adapterMappings": "not_applicable",
2891
+ "testIds": "not_applicable"
2892
+ }
2893
+ },
2847
2894
  {
2848
2895
  "sourceId": "agent_session:emitNotice",
2849
2896
  "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
@@ -3844,6 +3891,28 @@
3844
3891
  "packages/coding-agent/test/sdk-operation-inventory.test.ts"
3845
3892
  ]
3846
3893
  },
3894
+ {
3895
+ "sourceId": "agent_session:resolvePromptSkillInvocation",
3896
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
3897
+ "sourceKind": "agent_session",
3898
+ "decision": "exclude",
3899
+ "rationale": "internal prompt-dispatch classifier shared with interactive title seeding, not a user-facing control seam",
3900
+ "exclusionMetadata": {
3901
+ "adapterMappings": "not_applicable",
3902
+ "testIds": "not_applicable"
3903
+ }
3904
+ },
3905
+ {
3906
+ "sourceId": "agent_session:isLocallyHandledSlashCommand",
3907
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
3908
+ "sourceKind": "agent_session",
3909
+ "decision": "exclude",
3910
+ "rationale": "internal slash-command classifier that keeps command text out of title seeding, not a user-facing control seam",
3911
+ "exclusionMetadata": {
3912
+ "adapterMappings": "not_applicable",
3913
+ "testIds": "not_applicable"
3914
+ }
3915
+ },
3847
3916
  {
3848
3917
  "sourceId": "agent_session:promptCustomMessage",
3849
3918
  "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
@@ -4277,6 +4346,28 @@
4277
4346
  "testIds": "not_applicable"
4278
4347
  }
4279
4348
  },
4349
+ {
4350
+ "sourceId": "agent_session:getTerminalRunOwnerForEvent",
4351
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
4352
+ "sourceKind": "agent_session",
4353
+ "decision": "exclude",
4354
+ "rationale": "internal Agent-claimed event ownership proof, read only through the terminalAbortSeams bus capability; not a public SDK operation",
4355
+ "exclusionMetadata": {
4356
+ "adapterMappings": "not_applicable",
4357
+ "testIds": "not_applicable"
4358
+ }
4359
+ },
4360
+ {
4361
+ "sourceId": "agent_session:getRunOwnerDomain",
4362
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
4363
+ "sourceKind": "agent_session",
4364
+ "decision": "exclude",
4365
+ "rationale": "internal run-resource ledger domain lookup for exact consuming-run ownership; not a public SDK operation",
4366
+ "exclusionMetadata": {
4367
+ "adapterMappings": "not_applicable",
4368
+ "testIds": "not_applicable"
4369
+ }
4370
+ },
4280
4371
  {
4281
4372
  "sourceId": "agent_session:pendingToolExecutions",
4282
4373
  "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
@@ -4422,6 +4513,61 @@
4422
4513
  "testIds": "not_applicable"
4423
4514
  }
4424
4515
  },
4516
+ {
4517
+ "sourceId": "agent_session:setUnavailableModelProfile",
4518
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
4519
+ "sourceKind": "agent_session",
4520
+ "decision": "exclude",
4521
+ "rationale": "internal session-scoped unavailable profile tracking; mutated by the session lifecycle on model-load failure, not a public SDK control seam",
4522
+ "exclusionMetadata": {
4523
+ "adapterMappings": "not_applicable",
4524
+ "testIds": "not_applicable"
4525
+ }
4526
+ },
4527
+ {
4528
+ "sourceId": "agent_session:getUnavailableModelProfile",
4529
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
4530
+ "sourceKind": "agent_session",
4531
+ "decision": "exclude",
4532
+ "rationale": "internal session-scoped unavailable profile query for UI status rendering; not a public SDK operation",
4533
+ "exclusionMetadata": {
4534
+ "adapterMappings": "not_applicable",
4535
+ "testIds": "not_applicable"
4536
+ }
4537
+ },
4538
+ {
4539
+ "sourceId": "agent_session:getUserModelSelectionRevision",
4540
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
4541
+ "sourceKind": "agent_session",
4542
+ "decision": "exclude",
4543
+ "rationale": "internal session-scoped model selection revision tracking behind the reviewed model.set seam, not an independent public SDK operation",
4544
+ "exclusionMetadata": {
4545
+ "adapterMappings": "not_applicable",
4546
+ "testIds": "not_applicable"
4547
+ }
4548
+ },
4549
+ {
4550
+ "sourceId": "agent_session:getUserCanonicalVariantSelection",
4551
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
4552
+ "sourceKind": "agent_session",
4553
+ "decision": "exclude",
4554
+ "rationale": "internal session-scoped model variant selection state behind the reviewed model.set seam, not an independent public SDK operation",
4555
+ "exclusionMetadata": {
4556
+ "adapterMappings": "not_applicable",
4557
+ "testIds": "not_applicable"
4558
+ }
4559
+ },
4560
+ {
4561
+ "sourceId": "agent_session:markUserModelSelection",
4562
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
4563
+ "sourceKind": "agent_session",
4564
+ "decision": "exclude",
4565
+ "rationale": "internal session-scoped model selection revision marker behind the reviewed model.set seam, not an independent public SDK operation",
4566
+ "exclusionMetadata": {
4567
+ "adapterMappings": "not_applicable",
4568
+ "testIds": "not_applicable"
4569
+ }
4570
+ },
4425
4571
  {
4426
4572
  "sourceId": "agent_session:syncEagerDelegation",
4427
4573
  "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
@@ -174,6 +174,10 @@ const queries = [
174
174
  ["providers.list/active", "List active providers."],
175
175
  ["session.checkpoint", "Resolve a durable transcript checkpoint into a connection-owned replay cursor."],
176
176
  ["turn.steer_status", "Read the durable acknowledgement status of a correlated steer by clientRef."],
177
+ [
178
+ "session.progress",
179
+ "Read the read-only project progress snapshot (gjc.project_progress.v1) derived from durable session state.",
180
+ ],
177
181
  ] as const;
178
182
 
179
183
  // Q28 was folded into Q26; preserve the independent Q29/Q30 query identities.
@@ -208,6 +212,7 @@ const queryIds = [
208
212
  "Q29",
209
213
  "Q30",
210
214
  "Q31",
215
+ "Q32",
211
216
  ] as const;
212
217
 
213
218
  function queryId(index: number): string {
@@ -311,7 +316,7 @@ function queryContinuityClass(id: string): QueryContinuityClass {
311
316
  }
312
317
 
313
318
  function queryDisposition(id: string): Record<Adapter, AdapterDisposition> {
314
- if (["Q23", "Q24", "Q25", "Q26", "Q27", "Q29", "Q30", "Q31"].includes(id))
319
+ if (["Q23", "Q24", "Q25", "Q26", "Q27", "Q29", "Q30", "Q31", "Q32"].includes(id))
315
320
  return dispositions({ telegram: "prohibited", discord: "prohibited", slack: "prohibited" });
316
321
  return dispositions();
317
322
  }
@@ -398,7 +403,9 @@ export const OPERATIONS: readonly Operation[] = [
398
403
  ? ["invalid_request", "resource_gone", "internal"]
399
404
  : id === "Q27"
400
405
  ? ["invalid_request", "resource_gone", "model_profile_registry_error"]
401
- : ["invalid_request", "resource_gone"],
406
+ : id === "Q32"
407
+ ? ["invalid_request", "resource_gone", "unavailable"]
408
+ : ["invalid_request", "resource_gone"],
402
409
  continuityClass: queryContinuityClass(id),
403
410
  ...(queryAliases[id] === undefined ? {} : { aliases: queryAliases[id] }),
404
411
  adapterDispositions: queryDisposition(id),
@@ -25,7 +25,11 @@ import {
25
25
  readSdkSessionEndpoint,
26
26
  type SdkSessionEndpoint,
27
27
  } from "../client/discovery";
28
- import { SESSION_HOST_OBSERVER_CAPABILITY, TURN_STREAM_CAPABILITY } from "../host/host";
28
+ import {
29
+ POSITIONED_NOTIFICATION_EFFECTS_CAPABILITY,
30
+ SESSION_HOST_OBSERVER_CAPABILITY,
31
+ TURN_STREAM_CAPABILITY,
32
+ } from "../host/host";
29
33
  import {
30
34
  type ActivatedPreparedSession,
31
35
  type PreparedSessionActivationClient,
@@ -199,6 +203,7 @@ export interface SessionRouterClient {
199
203
  frame: Record<string, unknown>,
200
204
  options?: {
201
205
  timeoutMs?: number;
206
+ deadline?: number;
202
207
  connectedOnly?: boolean;
203
208
  /** Synchronous pre-send observer; a throw aborts the dispatch before the wire. */
204
209
  beforeDispatch?: (context: SdkDispatchContext) => void;
@@ -291,6 +296,13 @@ export interface SessionRouterOptions {
291
296
  attachFilter?: (sessionId: string) => boolean;
292
297
  /** Marks default SDK clients as notification-only observers; demanding by default. */
293
298
  observer?: boolean;
299
+ /**
300
+ * Negotiates positioned-only notification effects on default SDK clients, so the
301
+ * host stops sending them the raw native copy of frames whose positioned
302
+ * envelope already reached them. Only notification-effect publishers opt in;
303
+ * ordinary SDK observers keep both public surfaces.
304
+ */
305
+ positionedNotificationEffects?: boolean;
294
306
  deps?: SessionRouterDeps;
295
307
  /** Runtime-specific identity validation; Router supplies a conservative fallback. */
296
308
  correlateFrame?: SessionRouterFrameCorrelator;
@@ -619,6 +631,7 @@ export class SessionRouter {
619
631
  readonly #sessionIds: ReadonlySet<string> | undefined;
620
632
  readonly #attachFilter: ((sessionId: string) => boolean) | undefined;
621
633
  readonly #observer: boolean;
634
+ readonly #positionedNotificationEffects: boolean;
622
635
  readonly #deps: SessionRouterDeps;
623
636
  readonly #correlateFrame: SessionRouterFrameCorrelator;
624
637
  readonly #index: SessionIndex;
@@ -662,6 +675,7 @@ export class SessionRouter {
662
675
  this.#sessionIds = options.sessionIds === undefined ? undefined : new Set(options.sessionIds);
663
676
  this.#attachFilter = options.attachFilter;
664
677
  this.#observer = options.observer === true;
678
+ this.#positionedNotificationEffects = options.positionedNotificationEffects === true;
665
679
  this.#deps = options.deps ?? {};
666
680
  this.#correlateFrame = options.correlateFrame ?? fallbackCorrelation;
667
681
  this.#index = this.#deps.createIndex?.(options.agentDir) ?? new DefaultSessionIndex(options.agentDir);
@@ -840,7 +854,7 @@ export class SessionRouter {
840
854
  const capability = current?.capability;
841
855
  if (!attached || !current || !capability)
842
856
  throw new SessionRouterError("pre_send", "Broker session endpoint could not be attached.");
843
- const listing = this.#index.listSessions();
857
+ const listing = this.#index.listSessions(undefined, new Set([sessionId]));
844
858
  const indexedCurrent = listing.warnings.some(warning => warningAffectsSession(warning, sessionId))
845
859
  ? undefined
846
860
  : listing.sessions.find(item => item.sessionId === sessionId);
@@ -941,18 +955,47 @@ export class SessionRouter {
941
955
  expectedAttachment?: SessionAttachment,
942
956
  options?: {
943
957
  timeoutMs?: number;
958
+ deadline?: number;
944
959
  beforeDispatch?: (context: SdkDispatchContext) => void;
945
960
  onDispatch?: SdkDispatchHandler;
946
961
  dispatchFence?: (dispatch: () => Promise<Record<string, unknown>>) => Promise<Record<string, unknown>>;
947
962
  },
948
963
  ): Promise<Record<string, unknown>> {
964
+ const { deadline, beforeDispatch, onDispatch, dispatchFence, ...requestOptions } = options ?? {};
965
+ const remainingDeadlineMs = (): number =>
966
+ deadline === undefined ? Number.POSITIVE_INFINITY : Math.max(0, deadline - Date.now());
967
+ const reconcileWithinDeadline = async (): Promise<void> => {
968
+ if (deadline === undefined) {
969
+ await this.#serialReconcile(this.#runEpoch, true, true);
970
+ return;
971
+ }
972
+ const remaining = remainingDeadlineMs();
973
+ if (remaining <= 0)
974
+ throw new SessionRouterError("pre_send", "SDK session request deadline elapsed during router preparation.");
975
+ const reconciliation = this.#serialReconcile(this.#runEpoch, true, true);
976
+ const expired = Promise.withResolvers<never>();
977
+ const timer = setTimeout(
978
+ () =>
979
+ expired.reject(
980
+ new SessionRouterError("pre_send", "SDK session request deadline elapsed during router preparation."),
981
+ ),
982
+ remaining,
983
+ );
984
+ try {
985
+ await Promise.race([reconciliation, expired.promise]);
986
+ } finally {
987
+ clearTimeout(timer);
988
+ }
989
+ };
949
990
  const matchesExpectedAuthority = (attachment: SessionAttachment): boolean =>
950
991
  expectedAttachment === undefined ||
951
992
  attachment === expectedAttachment ||
952
993
  (expectedAttachment.authorityId !== undefined && attachment.authorityId === expectedAttachment.authorityId);
953
994
  const publishing = this.#sessions.get(sessionId);
954
995
  if (!publishing || !matchesExpectedAuthority(publishing.capability) || !publishing.initializingPublication)
955
- await this.#serialReconcile(this.#runEpoch, true, true);
996
+ await reconcileWithinDeadline();
997
+ if (remainingDeadlineMs() <= 0)
998
+ throw new SessionRouterError("pre_send", "SDK session request deadline elapsed during router preparation.");
956
999
  const attached = this.#sessions.get(sessionId);
957
1000
  if (!attached || !this.#attachmentPublished(attached))
958
1001
  throw new SessionRouterError("pre_send", "SDK session attachment is unavailable: session not published.");
@@ -981,20 +1024,44 @@ export class SessionRouter {
981
1024
  // token: the wire frame alone carries credentials, and the observer
982
1025
  // context is a deep-frozen, token-redacted copy (#4640 review).
983
1026
  const wireFrame = this.#prepareFrame(attached, frame);
984
- const { beforeDispatch, onDispatch, dispatchFence, ...requestOptions } = options ?? {};
1027
+ if (remainingDeadlineMs() <= 0) throw new SessionRouterError("pre_send", "SDK session request deadline elapsed.");
985
1028
  try {
986
- await attached.client.connect?.();
1029
+ const connecting = attached.client.connect?.();
1030
+ if (connecting) {
1031
+ if (deadline === undefined) await connecting;
1032
+ else {
1033
+ const expired = Promise.withResolvers<never>();
1034
+ const timer = setTimeout(
1035
+ () =>
1036
+ expired.reject(
1037
+ new SessionRouterError(
1038
+ "pre_send",
1039
+ "SDK session request deadline elapsed during transport preparation.",
1040
+ ),
1041
+ ),
1042
+ remainingDeadlineMs(),
1043
+ );
1044
+ try {
1045
+ await Promise.race([connecting, expired.promise]);
1046
+ } finally {
1047
+ clearTimeout(timer);
1048
+ }
1049
+ }
1050
+ }
987
1051
  } catch (error) {
988
1052
  if (error instanceof SdkClientError) throw new SdkPreparedDispatchError(error);
989
1053
  throw error;
990
1054
  }
991
1055
  if (!this.#attachmentPublished(attached))
992
1056
  throw new SessionRouterError("pre_send", "SDK session attachment changed during transport preparation.");
993
- const dispatch = () =>
994
- attached.client.request(wireFrame, {
1057
+ const dispatch = () => {
1058
+ const dispatchRemaining = remainingDeadlineMs();
1059
+ if (dispatchRemaining <= 0)
1060
+ throw new SessionRouterError("pre_send", "SDK session request deadline elapsed before dispatch.");
1061
+ return attached.client.request(wireFrame, {
995
1062
  ...requestOptions,
996
1063
  connectedOnly: true,
997
- timeoutMs: requestOptions.timeoutMs ?? SESSION_REQUEST_TIMEOUT_MS,
1064
+ timeoutMs: Math.min(requestOptions.timeoutMs ?? SESSION_REQUEST_TIMEOUT_MS, dispatchRemaining),
998
1065
  ...(beforeDispatch
999
1066
  ? {
1000
1067
  beforeDispatch: (context: SdkDispatchContext) =>
@@ -1008,7 +1075,16 @@ export class SessionRouter {
1008
1075
  }
1009
1076
  : {}),
1010
1077
  });
1078
+ };
1011
1079
  const response = await (dispatchFence ? dispatchFence(dispatch) : dispatch());
1080
+ // A late acknowledgement cannot activate a provider after the caller's budget.
1081
+ // Keep the sent identity for reconciliation: expiry does not undo registration.
1082
+ if (remainingDeadlineMs() <= 0)
1083
+ throw new SdkClientError("uncertain_after_send", "SDK session request deadline elapsed after dispatch.", {
1084
+ id: wireFrame.id,
1085
+ operation: wireFrame.operation ?? wireFrame.type,
1086
+ idempotencyKey: wireFrame.idempotencyKey,
1087
+ });
1012
1088
  const settled = this.#sessions.get(sessionId);
1013
1089
  if (
1014
1090
  !settled ||
@@ -1027,7 +1103,7 @@ export class SessionRouter {
1027
1103
  let indexed: IndexedSession | undefined;
1028
1104
  try {
1029
1105
  await this.#index.refresh();
1030
- const listing = this.#index.listSessions();
1106
+ const listing = this.#index.listSessions(undefined, new Set([sessionId]));
1031
1107
  if (listing.warnings.some(warning => warningAffectsSession(warning, sessionId))) return undefined;
1032
1108
  indexed = listing.sessions.find(candidate => candidate.sessionId === sessionId);
1033
1109
  } catch {
@@ -1101,7 +1177,7 @@ export class SessionRouter {
1101
1177
  try {
1102
1178
  await this.#index.open();
1103
1179
  await this.#index.refresh();
1104
- const listing = this.#index.listSessions();
1180
+ const listing = this.#index.listSessions(undefined, new Set([sessionId]));
1105
1181
  if (listing.warnings.some(warning => warningAffectsSession(warning, sessionId)))
1106
1182
  throw new SessionActivationError(
1107
1183
  "session_not_live",
@@ -1292,7 +1368,7 @@ export class SessionRouter {
1292
1368
  for (const attached of this.#sessions.values()) this.#reviveTransport(attached);
1293
1369
  return;
1294
1370
  }
1295
- const indexed = this.#index.listSessions();
1371
+ const indexed = this.#index.listSessions(undefined, this.#sessionIds);
1296
1372
  const live = indexed.sessions.filter(
1297
1373
  session =>
1298
1374
  !indexed.warnings.some(warning => warningAffectsSession(warning, session.sessionId)) &&
@@ -1500,7 +1576,7 @@ export class SessionRouter {
1500
1576
  )
1501
1577
  return null;
1502
1578
  await this.#index.refresh();
1503
- const listing = this.#index.listSessions();
1579
+ const listing = this.#index.listSessions(undefined, new Set([indexed.sessionId]));
1504
1580
  if (listing.warnings.some(warning => warningAffectsSession(warning, indexed.sessionId))) return null;
1505
1581
  const current = listing.sessions.find(session => session.sessionId === indexed.sessionId);
1506
1582
  if (!current || !sameIndexedAuthority(indexed, current)) return null;
@@ -1530,9 +1606,13 @@ export class SessionRouter {
1530
1606
  endpointMtimeMs,
1531
1607
  });
1532
1608
  } else {
1609
+ const capabilities = [
1610
+ ...(this.#observer ? [SESSION_HOST_OBSERVER_CAPABILITY, TURN_STREAM_CAPABILITY] : []),
1611
+ ...(this.#positionedNotificationEffects ? [POSITIONED_NOTIFICATION_EFFECTS_CAPABILITY] : []),
1612
+ ];
1533
1613
  const defaultClient = new SdkClient(endpoint.url, endpoint.token, {
1534
1614
  ...ACP_SESSION_RECONNECT,
1535
- ...(this.#observer ? { capabilities: [SESSION_HOST_OBSERVER_CAPABILITY, TURN_STREAM_CAPABILITY] } : {}),
1615
+ ...(capabilities.length > 0 ? { capabilities } : {}),
1536
1616
  });
1537
1617
  transport = defaultClient;
1538
1618
  connection = defaultClient.connect().then(() => defaultClient);
@@ -2187,7 +2267,7 @@ export class SessionRouter {
2187
2267
  try {
2188
2268
  await this.#index.refresh();
2189
2269
  const current = this.#index
2190
- .listSessions()
2270
+ .listSessions(undefined, new Set([attached.sessionId]))
2191
2271
  .sessions.find(session => session.sessionId === attached.sessionId);
2192
2272
  if (
2193
2273
  current?.live &&
@@ -17,6 +17,7 @@ export const SESSION_LIST_SAVED_SESSION_OMISSION_DETAIL_CODES = [
17
17
  "binding_conflict",
18
18
  "binding_invalid",
19
19
  "migration_busy",
20
+ "managed_gc_journal_capacity_exceeded",
20
21
  "atomic_unavailable",
21
22
  "invalid_request",
22
23
  "durability_failed",