@zq-silk/yui 0.15.7 → 0.15.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 (281) hide show
  1. package/ARCHITECTURE.md +192 -399
  2. package/README.md +127 -1149
  3. package/dist/agent/adapterCatalog.js +15 -2
  4. package/dist/agent/agent.js +23 -3
  5. package/dist/agent/argumentPolicy.js +7 -1
  6. package/dist/agent/connectionPlan.js +62 -0
  7. package/dist/agent/executionComponents.js +158 -0
  8. package/dist/agent/launchEnvironment.js +31 -3
  9. package/dist/agent/managedRuntimeEnvironment.js +3 -5
  10. package/dist/{turn/turn.js → agentRun/agentRun.js} +166 -109
  11. package/dist/{turn/turnIdentity.js → agentRun/runIdentity.js} +4 -4
  12. package/dist/brief/taskBrief.js +12 -0
  13. package/dist/cli/agentConfigurationPicker.js +13 -0
  14. package/dist/cli/commandCatalog.js +157 -70
  15. package/dist/cli/interactionCandidates.js +5 -5
  16. package/dist/cli/interactionPolicy.js +38 -8
  17. package/dist/cli/invocationRouter.js +1 -1
  18. package/dist/cli/managedDiagnostics.js +28 -0
  19. package/dist/cli/operatorWizard.js +1 -7
  20. package/dist/cli/roleOptionOrder.js +27 -0
  21. package/dist/cli/roleWizard.js +50 -14
  22. package/dist/cli/updateOrchestrator.js +1 -1
  23. package/dist/cli/updatePorts.js +3 -4
  24. package/dist/cli.js +178 -95
  25. package/dist/commands/agentCommands.js +72 -14
  26. package/dist/commands/capabilityCommands.js +9 -6
  27. package/dist/commands/configCommands.js +20 -20
  28. package/dist/commands/deliveryGuardPreflight.js +2 -2
  29. package/dist/commands/executionAuditCommands.js +24 -24
  30. package/dist/commands/globalRoleCommands.js +1 -1
  31. package/dist/commands/grantCommands.js +4 -4
  32. package/dist/commands/operatorCommands.js +1 -7
  33. package/dist/commands/projectCommands.js +4 -4
  34. package/dist/commands/resourcesCommands.js +2 -2
  35. package/dist/commands/roleConfiguration.js +25 -5
  36. package/dist/commands/roleRuntimeGuard.js +4 -5
  37. package/dist/commands/sessionCommands.js +3 -7
  38. package/dist/commands/taskActivationCommands.js +259 -0
  39. package/dist/commands/taskActor.js +28 -49
  40. package/dist/commands/taskCommands.js +1188 -710
  41. package/dist/commands/taskContextCommand.js +39 -583
  42. package/dist/commands/taskExecutionCommands.js +32 -32
  43. package/dist/commands/taskInputCommands.js +40 -104
  44. package/dist/commands/taskIntegrationCommands.js +3 -2
  45. package/dist/commands/taskIntegrationQueueCommands.js +1 -1
  46. package/dist/commands/taskNextActionCommand.js +8 -8
  47. package/dist/commands/taskOverviewCommand.js +33 -45
  48. package/dist/commands/taskRemoteDeliveryCommand.js +2 -2
  49. package/dist/commands/taskRoleRuntimeStatus.js +133 -102
  50. package/dist/commands/telemetryCommands.js +36 -38
  51. package/dist/config/configCatalog.js +4 -4
  52. package/dist/config/yuiConfig.js +8 -8
  53. package/dist/context/contextSnapshot.js +10 -10
  54. package/dist/context/dispatchContext.js +11 -11
  55. package/dist/context/roleSessionContext.js +6 -3
  56. package/dist/context/{turnContextPack.js → runContextPack.js} +146 -81
  57. package/dist/context/{turnInputContract.js → runInputContract.js} +73 -60
  58. package/dist/context/sessionBootstrapManifest.js +21 -2
  59. package/dist/context/sourceRunContext.js +30 -0
  60. package/dist/context/taskContext.js +458 -0
  61. package/dist/context/wakeNotification.js +27 -27
  62. package/dist/controller/agentRuntimeObserver.js +21 -24
  63. package/dist/controller/capabilityBridge.js +17 -6
  64. package/dist/controller/clientRuntime.js +65 -92
  65. package/dist/controller/controller.js +114 -188
  66. package/dist/controller/fileSchedulerStoreAdapter.js +787 -887
  67. package/dist/controller/jobControl.js +54 -85
  68. package/dist/controller/resourceInventory.js +8 -27
  69. package/dist/controller/resourceInventoryLinux.js +12 -13
  70. package/dist/controller/runtime.js +529 -479
  71. package/dist/controller/runtimeEventInbox.js +55 -25
  72. package/dist/controller/runtimeEventProcessor.js +22 -31
  73. package/dist/controller/{runtimeHookTurnFence.js → runtimeHookRunFence.js} +91 -115
  74. package/dist/controller/runtimeLaunchCoordinator.js +80 -426
  75. package/dist/controller/runtimeObservationHook.js +14 -18
  76. package/dist/controller/sessionNotify.js +16 -24
  77. package/dist/controller/sessionOwnerReconciliation.js +168 -50
  78. package/dist/controller/structuredProviderObservation.js +138 -99
  79. package/dist/coordination/workMailbox.js +3 -3
  80. package/dist/coordination/workMailboxQueue.js +36 -33
  81. package/dist/core/boundedRpc.js +8 -1
  82. package/dist/core/controllerClient.js +20 -1
  83. package/dist/core/controllerServer.js +4 -4
  84. package/dist/doctor/doctor.js +13 -2
  85. package/dist/domain/agentResultTransport.js +9 -9
  86. package/dist/execution/codexThreadNaming.js +2 -8
  87. package/dist/execution/executionHealth.js +51 -63
  88. package/dist/execution/reviewMainRun.js +137 -0
  89. package/dist/execution/workItemExecution.js +28 -29
  90. package/dist/execution/workItemExecutionProjection.js +99 -107
  91. package/dist/execution/workItemMainRun.js +141 -0
  92. package/dist/executor/agentAdapter.js +227 -20
  93. package/dist/executor/agentConfigurationCatalog.js +126 -4
  94. package/dist/executor/agentConfigurationProbe.js +162 -4
  95. package/dist/executor/agentExecutor.js +79 -78
  96. package/dist/executor/effectiveLaunch.js +105 -18
  97. package/dist/executor/executorRegistry.js +29 -44
  98. package/dist/executor/fileRoleLaunchPlanner.js +229 -154
  99. package/dist/executor/workspacePreflightClassification.js +16 -16
  100. package/dist/grant/capabilityGrant.js +6 -3
  101. package/dist/input/inputRequest.js +12 -10
  102. package/dist/integration/gitIntegrationService.js +4 -11
  103. package/dist/integration/integrationQueueService.js +4 -4
  104. package/dist/interaction/operatorPresentation.js +1 -1
  105. package/dist/kernel/builtinCapabilities.js +247 -12
  106. package/dist/kernel/capabilityRegistry.js +64 -18
  107. package/dist/kernel/instanceHost.js +12 -1
  108. package/dist/kernel/kernelPorts.js +2 -2
  109. package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
  110. package/dist/lifecycle/exactRunTerminalization.js +449 -0
  111. package/dist/message/message.js +62 -6
  112. package/dist/message/messageContinuation.js +204 -0
  113. package/dist/observability/executionAudit.js +70 -72
  114. package/dist/observability/faultClassification.js +2 -2
  115. package/dist/observability/orchestrationMetrics.js +8 -8
  116. package/dist/operator/operatorSessionHistory.js +1 -7
  117. package/dist/output/agentConfigurationPresentation.js +8 -3
  118. package/dist/output/agentRunConfigurationPresentation.js +128 -0
  119. package/dist/output/rolePresentation.js +54 -3
  120. package/dist/plugins/pluginChild.js +104 -0
  121. package/dist/plugins/pluginIntent.js +26 -0
  122. package/dist/plugins/pluginInterpreter.js +43 -0
  123. package/dist/plugins/pluginPackage.js +101 -0
  124. package/dist/plugins/pluginProcess.js +112 -0
  125. package/dist/plugins/pluginService.js +380 -0
  126. package/dist/profile/agentProfile.js +1 -1
  127. package/dist/repository/gitWorkspace.js +26 -4
  128. package/dist/repository/project.js +19 -4
  129. package/dist/repository/taskBaseFreshness.js +13 -13
  130. package/dist/repository/taskWorkspaceCoordinator.js +20 -27
  131. package/dist/repository/taskWorkspacePreparer.js +344 -83
  132. package/dist/resources/autoResourceGc.js +3 -3
  133. package/dist/resources/liveReferences.js +3 -3
  134. package/dist/resources/projectResource.js +123 -0
  135. package/dist/resources/projectResourceService.js +421 -0
  136. package/dist/resources/resourceDiscovery.js +6 -6
  137. package/dist/resources/resourceGc.js +1 -1
  138. package/dist/resources/resourceRegistrar.js +1 -1
  139. package/dist/resources/resourceTypes.js +1 -1
  140. package/dist/review/deltaRecheck.js +3 -3
  141. package/dist/review/reviewAcceptance.js +16 -16
  142. package/dist/review/reviewDecision.js +7 -7
  143. package/dist/review/reviewRound.js +21 -20
  144. package/dist/review/reviewerAvailability.js +2 -2
  145. package/dist/role/role.js +51 -7
  146. package/dist/role/taskRoleUpdate.js +30 -0
  147. package/dist/runtime/acpProtocol.js +425 -0
  148. package/dist/runtime/acpSession.js +731 -0
  149. package/dist/runtime/acpSessionConfiguration.js +260 -0
  150. package/dist/runtime/agentDriver.js +30 -11
  151. package/dist/runtime/agentEndpoint.js +278 -0
  152. package/dist/runtime/agentEndpointIdentity.js +86 -0
  153. package/dist/runtime/agentEndpointOwnership.js +239 -0
  154. package/dist/runtime/agentError.js +2 -10
  155. package/dist/runtime/agentHost.js +565 -314
  156. package/dist/runtime/agentRunConfiguration.js +258 -0
  157. package/dist/runtime/builtinAgentDrivers.js +134 -18
  158. package/dist/runtime/builtinAgentErrorMappers.js +55 -3
  159. package/dist/runtime/builtinTranscriptUsage.js +1 -1
  160. package/dist/runtime/claude-process-owner +0 -0
  161. package/dist/runtime/codexAppServerRuntime.js +38 -30
  162. package/dist/runtime/codexInteractiveHost.js +41 -6
  163. package/dist/runtime/continuationManager.js +2 -6
  164. package/dist/runtime/executionEnvironment.js +30 -0
  165. package/dist/runtime/firstProgressAdvisory.js +11 -11
  166. package/dist/runtime/index.js +4 -3
  167. package/dist/runtime/jsonLineChannel.js +109 -0
  168. package/dist/runtime/launchBroker.js +91 -16
  169. package/dist/runtime/launchDiagnostics.js +2 -2
  170. package/dist/runtime/lifecycleReservation.js +10 -18
  171. package/dist/runtime/managedCaller.js +61 -17
  172. package/dist/runtime/nativeSessionControl.js +102 -0
  173. package/dist/runtime/ports.js +6 -21
  174. package/dist/runtime/processExitObservation.js +8 -7
  175. package/dist/runtime/promptEnvelope.js +17 -6
  176. package/dist/runtime/providerContinuation.js +3 -9
  177. package/dist/runtime/providerContinuationReconciliationService.js +4 -13
  178. package/dist/runtime/providerControl.js +2 -7
  179. package/dist/runtime/providerRuntimeIdentity.js +110 -222
  180. package/dist/runtime/providerRuntimeReconciler.js +5 -9
  181. package/dist/runtime/runtimeBinding.js +0 -1
  182. package/dist/runtime/runtimeContinuationProjection.js +4 -7
  183. package/dist/runtime/runtimeDeadlines.js +9 -0
  184. package/dist/runtime/runtimeHealthPolicy.js +1 -1
  185. package/dist/runtime/runtimeObservation.js +29 -65
  186. package/dist/runtime/runtimeProjection.js +43 -51
  187. package/dist/runtime/runtimeSessionCandidate.js +1 -3
  188. package/dist/runtime/sessionLaunchRequest.js +3 -7
  189. package/dist/runtime/sessionOwnerIdentity.js +7 -54
  190. package/dist/runtime/sessionOwnerRegistry.js +22 -17
  191. package/dist/runtime/sessionReconciliation.js +4 -8
  192. package/dist/runtime/sessionTerminationGuard.js +70 -259
  193. package/dist/runtime/sessionTokenMetrics.js +5 -16
  194. package/dist/runtime/structuredProviderHost.js +237 -117
  195. package/dist/runtime/taskRuntimeIsolation.js +39 -122
  196. package/dist/runtime/tmuxAdapters.js +39 -86
  197. package/dist/scheduler/activeRoleRunDelivery.js +354 -0
  198. package/dist/scheduler/leaderWakeupProcessor.js +75 -266
  199. package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
  200. package/dist/scheduler/ports.js +80 -9
  201. package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
  202. package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
  203. package/dist/scheduler/taskExecutionProjection.js +120 -124
  204. package/dist/scheduler/taskObservabilityProjection.js +29 -29
  205. package/dist/scheduler/taskWake.js +11 -4
  206. package/dist/scheduler/wakeReason.js +9 -1
  207. package/dist/setup/setupCommand.js +1 -0
  208. package/dist/storage/migrations/agentRunContract.js +159 -0
  209. package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
  210. package/dist/storage/sqliteSchema.js +431 -5
  211. package/dist/storage/sqliteStore.js +375 -220
  212. package/dist/storage/storageVersions.js +1 -1
  213. package/dist/storage/storeRpc.js +10 -5
  214. package/dist/storage/taskStore.js +13 -11
  215. package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
  216. package/dist/surface/surfaceContributions.js +102 -0
  217. package/dist/task/completionReadiness.js +32 -6
  218. package/dist/task/deliveryGuard.js +16 -16
  219. package/dist/task/draftPlan.js +72 -12
  220. package/dist/task/nextAction.js +144 -128
  221. package/dist/task/remoteDelivery.js +6 -6
  222. package/dist/task/task.js +184 -18
  223. package/dist/task/taskActivation.js +301 -0
  224. package/dist/task/taskActivationService.js +392 -0
  225. package/dist/task/taskRecordReference.js +5 -4
  226. package/dist/task/taskRecordRetirement.js +1 -1
  227. package/dist/telemetry/sqliteTelemetryStore.js +55 -68
  228. package/dist/telemetry/telemetryConfig.js +14 -14
  229. package/dist/telemetry/telemetryWiring.js +2 -2
  230. package/dist/web/assets/assetManifest.js +2 -0
  231. package/dist/web/assets/client/app.js +120 -20
  232. package/dist/web/assets/client/components.js +87 -54
  233. package/dist/web/assets/client/i18n.js +83 -41
  234. package/dist/web/assets/client/markdown.js +1 -1
  235. package/dist/web/assets/client/taskSurface.js +353 -0
  236. package/dist/web/assets/client/view.js +49 -44
  237. package/dist/web/assets/shell.js +1 -1
  238. package/dist/web/assets/styles/cards.js +22 -4
  239. package/dist/web/controllerWeb.js +60 -0
  240. package/dist/web/webMutation.js +28 -0
  241. package/dist/web/webServer.js +118 -8
  242. package/dist/web/webSnapshot.js +81 -74
  243. package/dist/web/webTaskSurface.js +64 -0
  244. package/dist/workItem/dependencyGate.js +1 -1
  245. package/dist/workItem/workItem.js +80 -48
  246. package/dist/workspace/workItemChangeSetManager.js +16 -9
  247. package/docs/agent-result-consumption.md +94 -0
  248. package/docs/agent-runtime-drivers.md +91 -0
  249. package/docs/architecture/README.md +38 -0
  250. package/docs/architecture/capabilities-and-resources.md +79 -0
  251. package/docs/managed-turn-and-session-runtime.md +222 -0
  252. package/docs/observability/README.md +81 -0
  253. package/docs/plugin-sdk.md +290 -0
  254. package/docs/provider-runtime.md +163 -0
  255. package/docs/release-workflow.md +303 -0
  256. package/docs/roles-and-configuration.md +113 -0
  257. package/docs/sqlite-control-plane-design.md +76 -0
  258. package/docs/task-dag-semantics.md +57 -0
  259. package/docs/task-delivery.md +103 -0
  260. package/docs/task-local-identity.md +6 -6
  261. package/docs/testing/verification-levels.md +86 -0
  262. package/i18n/README.zh-CN.md +98 -739
  263. package/package.json +2 -2
  264. package/skills/yui-leader/SKILL.md +130 -103
  265. package/skills/yui-leader/references/integration.md +39 -0
  266. package/skills/yui-leader/references/replicated-execution.md +42 -0
  267. package/skills/yui-leader/references/task-plugins.md +33 -0
  268. package/skills/yui-operator/SKILL.md +30 -59
  269. package/skills/yui-reviewer/SKILL.md +35 -36
  270. package/skills/yui-runtime/SKILL.md +88 -24
  271. package/skills/yui-runtime/references/publication.md +22 -0
  272. package/skills/yui-runtime/references/recovery.md +64 -0
  273. package/skills/yui-worker/SKILL.md +37 -39
  274. package/dist/cli/roleOptionCatalog.js +0 -68
  275. package/dist/context/sourceTurnContext.js +0 -30
  276. package/dist/execution/reviewMainTurn.js +0 -161
  277. package/dist/execution/workItemMainTurn.js +0 -164
  278. package/dist/lifecycle/exactTurnTerminalization.js +0 -407
  279. package/dist/runtime/preallocatedNativeSession.js +0 -13
  280. package/dist/runtime/runtimeStopReceipt.js +0 -42
  281. package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
@@ -0,0 +1,86 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFileSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
4
+ import { detectRunningRelease } from "../release/runtimeRelease.js";
5
+ import { isAgentAdapterId } from "../agent/adapterCatalog.js";
6
+ /**
7
+ * The generation of the Endpoint code this process is actually executing.
8
+ *
9
+ * Resolved once, at module load, from the immutable release the running module
10
+ * belongs to — the same idiom the Controller, the handover candidate and the CLI
11
+ * Home fence already use. A release directory is content-addressed
12
+ * (`<version>-<packageDigest>`) and byte-verified on install, so its digest
13
+ * covers every shipped file rather than a hand-picked few, and cannot drift
14
+ * under a live process: publishing a new release writes a new directory instead
15
+ * of mutating this one.
16
+ *
17
+ * Resolving at load rather than on first use is the point. A digest computed
18
+ * lazily would read whatever is on disk when the first Session happens to pin,
19
+ * and could label already-loaded code A with the identity of a newer B.
20
+ *
21
+ * A development checkout has no immutable release, and mutable files have no
22
+ * honest generation: editing a module in place would keep claiming the previous
23
+ * bytes. So a checkout gets a digest of its loaded Endpoint modules, explicitly
24
+ * marked `checkout-`, which never compares equal to a release generation. It is
25
+ * a development identity and is not claimed to be reproducible from a release.
26
+ */
27
+ const ENDPOINT_CHECKOUT_MODULES = Object.freeze([
28
+ "agentEndpoint.js",
29
+ "agentEndpointIdentity.js",
30
+ "structuredProviderHost.js",
31
+ "claude-process-owner",
32
+ "codexAppServerRuntime.js",
33
+ "acpSession.js",
34
+ "acpProtocol.js",
35
+ "acpSessionConfiguration.js",
36
+ "agentRunConfiguration.js",
37
+ "jsonLineChannel.js"
38
+ ]);
39
+ function resolveEndpointGeneration() {
40
+ const running = detectRunningRelease(fileURLToPath(import.meta.url));
41
+ // The release digest already covers these modules' bytes, so an installed
42
+ // release needs no separate file list to be exact.
43
+ if (running !== null)
44
+ return running.manifest.packageDigest.slice(0, 32);
45
+ const hash = createHash("sha256");
46
+ for (const module of ENDPOINT_CHECKOUT_MODULES) {
47
+ // An unreadable module is a broken installation, not a reason to fall back
48
+ // to an identity that would silently match a different build.
49
+ hash.update(module).update("\0").update(readFileSync(new URL(module, import.meta.url))).update("\0");
50
+ }
51
+ return `checkout-${hash.digest("hex").slice(0, 23)}`;
52
+ }
53
+ const ENDPOINT_GENERATION = resolveEndpointGeneration();
54
+ /**
55
+ * Built-in Endpoint identity under the existing ImplementationRef contract.
56
+ * Uses the adopted release/checkout identity; matching it does not by itself
57
+ * prove that the Provider can recover its native Session.
58
+ */
59
+ export function builtinAgentEndpointImplementation(adapterId) {
60
+ // Every catalogued adapter has a managed Endpoint. Re-listing the adapter
61
+ // names here would let the two lists drift, so the catalog is the only source.
62
+ if (!isAgentAdapterId(adapterId)) {
63
+ throw new Error(`No managed Endpoint implementation for adapter: ${adapterId}.`);
64
+ }
65
+ return Object.freeze({
66
+ id: `yui.agent-endpoint.${adapterId}`,
67
+ generation: ENDPOINT_GENERATION
68
+ });
69
+ }
70
+ export function validateAgentEndpointImplementation(ref) {
71
+ if (ref === null || typeof ref !== "object"
72
+ || typeof ref.id !== "string" || !ref.id.trim() || ref.id.includes("\0")
73
+ || typeof ref.generation !== "string" || !ref.generation.trim() || ref.generation.includes("\0")) {
74
+ throw new Error("Session Endpoint implementation identity is invalid.");
75
+ }
76
+ return ref;
77
+ }
78
+ /** Missing old code is an explicit inability to resume, never a Provider fallback. */
79
+ export function requireBuiltinAgentEndpointImplementation(adapterId, ref) {
80
+ validateAgentEndpointImplementation(ref);
81
+ const current = builtinAgentEndpointImplementation(adapterId);
82
+ if (ref.id !== current.id || ref.generation !== current.generation) {
83
+ throw new Error(`Session Endpoint ${ref.id}@${ref.generation} is unavailable; explicitly select a new Session.`);
84
+ }
85
+ return ref;
86
+ }
@@ -0,0 +1,239 @@
1
+ import { InstanceHost } from "../kernel/instanceHost.js";
2
+ import { builtinAgentEndpointImplementation, requireBuiltinAgentEndpointImplementation } from "./agentEndpointIdentity.js";
3
+ import { createAgentEndpointFactory } from "./agentEndpoint.js";
4
+ /**
5
+ * Process-local ownership of the Endpoint implementation this Agent Host is
6
+ * executing. Reuses the one Instance Host primitive; it is not a second
7
+ * registry, a capability directory or a durable reference table. The Controller
8
+ * owns its own Host in its own process and never holds an Endpoint client, so
9
+ * the reference facts for a Session live where the Session actually runs.
10
+ *
11
+ * Only the running code can be attached here. Selecting between generations is
12
+ * the launch decision recorded in the durable Session; this owner proves the
13
+ * chosen generation is really held and really released.
14
+ */
15
+ export function createAgentEndpointOwner(factory = createAgentEndpointFactory()) {
16
+ const host = new InstanceHost();
17
+ const attached = new Map();
18
+ const live = new Map();
19
+ const implementationFor = (adapterId) => {
20
+ const current = builtinAgentEndpointImplementation(adapterId);
21
+ const existing = attached.get(current.id);
22
+ if (existing !== undefined)
23
+ return existing;
24
+ // The disposer owns the opener, not the clients: a Session's client is
25
+ // terminated by that Session's detach. Dropping the opener stops a leaked
26
+ // reference from starting new work on a generation that is already gone.
27
+ const ref = host.attach(current, factory, [
28
+ () => { live.delete(current.id); }
29
+ ]);
30
+ attached.set(current.id, ref);
31
+ live.set(current.id, new Set());
32
+ return ref;
33
+ };
34
+ /**
35
+ * Hand the reference back only when the Session asked to end *and* it has no
36
+ * client running *and* no handshake in flight. A client that never proves exit
37
+ * keeps this hold, so the drain below reports a real dependency instead of an
38
+ * empty list; so does an opener that has not answered yet, whose client may
39
+ * still be about to attach.
40
+ */
41
+ const settle = async (holders, holder) => {
42
+ if (holder.settled || !holder.releaseRequested)
43
+ return;
44
+ if (holder.current !== undefined || holder.opening > 0)
45
+ return;
46
+ holder.settled = true;
47
+ holders.delete(holder);
48
+ await holder.handle.release();
49
+ };
50
+ /**
51
+ * Pin the implementation for one Session. A pinned reference from the durable
52
+ * Session must name this exact code; a mismatch is an explicit inability to
53
+ * resume, never a silent start on a different generation.
54
+ */
55
+ const pin = (adapterId, pinned) => {
56
+ if (pinned !== undefined)
57
+ requireBuiltinAgentEndpointImplementation(adapterId, pinned);
58
+ const ref = implementationFor(adapterId);
59
+ const handle = host.acquire(ref);
60
+ const holders = live.get(ref.id);
61
+ // One entry per Session hold, reporting the client it currently has. A
62
+ // Session may reattach a replacement client for the same conversation; that
63
+ // succession is one hold, not two, so a drain never double-counts it.
64
+ const holder = { handle, opening: 0, releaseRequested: false, settled: false };
65
+ holders.add(holder);
66
+ const track = async (opened) => {
67
+ // Counted before the handshake is awaited, so a stop that lands while the
68
+ // client is still coming up sees this Session as a real holder.
69
+ holder.opening += 1;
70
+ let result;
71
+ try {
72
+ result = await opened;
73
+ }
74
+ catch (error) {
75
+ // A handshake that failed owes nothing: no client attached, so the hold
76
+ // ends on the real dependency rather than waiting for an exit that can
77
+ // never come.
78
+ holder.opening -= 1;
79
+ void settle(holders, holder).catch(() => undefined);
80
+ throw error;
81
+ }
82
+ holder.current = result.session;
83
+ holder.opening -= 1;
84
+ // Only a resolved exit proves the client stopped. An exit that never
85
+ // settles, or that fails, leaves this hold in place on purpose: the drain
86
+ // must be able to say what is still running.
87
+ void result.session.waitForExit().then(() => {
88
+ if (holder.current !== result.session)
89
+ return;
90
+ holder.current = undefined;
91
+ void settle(holders, holder).catch(() => undefined);
92
+ }, () => { });
93
+ // A stop may already have been requested while this handshake was in
94
+ // flight. The client is real and attached, so it enters the same controlled
95
+ // exit tracking instead of being handed back as an untracked leak: ask it to
96
+ // exit and let its proven exit release the hold.
97
+ if (holder.releaseRequested)
98
+ result.session.detach();
99
+ return result;
100
+ };
101
+ const start = (call) => {
102
+ // An acquired handle keeps its captured opener even after the generation is
103
+ // disposed, so a released lease must refuse to start new work rather than
104
+ // run on code the Session has already given up.
105
+ if (holder.releaseRequested) {
106
+ return Promise.reject(new Error("Session Endpoint lease is released; it cannot start new work."));
107
+ }
108
+ return track(call(handle.value));
109
+ };
110
+ return Object.freeze({
111
+ implementation: handle.implementation,
112
+ open: (payload) => start((value) => value.open(payload)),
113
+ resume: (payload) => start((value) => value.resume(payload)),
114
+ release: async () => {
115
+ // Idempotent, and never blocking: a client that has not exited keeps the
116
+ // reference, and `stop` is what bounds and reports that wait. A hold that
117
+ // never opened a client (a failed start) owes nothing and settles here.
118
+ holder.releaseRequested = true;
119
+ await settle(holders, holder);
120
+ }
121
+ });
122
+ };
123
+ /** Actual reference and request records, never a status label. */
124
+ const inspectImplementation = (implementationId, waited) => {
125
+ const instances = host.inspect(implementationId);
126
+ const references = instances.reduce((total, instance) => total + instance.references, 0);
127
+ const holders = [...live.get(implementationId) ?? []];
128
+ const opening = holders.reduce((total, holder) => total + holder.opening, 0);
129
+ const sessions = holders.flatMap((holder) => {
130
+ const endpoint = holder.current;
131
+ // A hold between clients has nothing attached to report. Its hold is
132
+ // still counted in `references`, so it cannot be mistaken for quiescence.
133
+ if (endpoint === undefined)
134
+ return [];
135
+ const state = endpoint.inspect();
136
+ return [Object.freeze({
137
+ nativeSessionId: endpoint.nativeSessionId,
138
+ processInstanceId: endpoint.processInstanceId,
139
+ attachment: state.attachment,
140
+ cancellation: state.cancellation,
141
+ resources: state.resources,
142
+ releaseAwaitingExit: holder.releaseRequested,
143
+ pending: Object.freeze(state.submissions
144
+ .filter((submission) => submission.disposition.status === "pending"
145
+ || submission.disposition.status === "unknown")
146
+ .map((submission) => Object.freeze({
147
+ attemptId: submission.attemptId,
148
+ inputRef: submission.inputRef,
149
+ status: submission.disposition.status
150
+ })))
151
+ })];
152
+ });
153
+ return Object.freeze({
154
+ // Quiescent means nothing holds the implementation, no handshake is still
155
+ // in flight, and no owned client is still attached. Holds are dropped by
156
+ // proven exit, so an unreleased Session, an opening client or a client that
157
+ // never exited keeps this false.
158
+ quiescent: references === 0
159
+ && opening === 0
160
+ && sessions.every((session) => session.attachment === "exited" && session.pending.length === 0),
161
+ references,
162
+ opening,
163
+ waitedMs: waited.waitedMs,
164
+ timedOut: waited.timedOut,
165
+ sessions: Object.freeze(sessions)
166
+ });
167
+ };
168
+ const inspectWith = (adapterId, waited) => inspectImplementation(builtinAgentEndpointImplementation(adapterId).id, waited);
169
+ const inspect = (adapterId) => inspectWith(adapterId, { waitedMs: 0, timedOut: false });
170
+ /**
171
+ * Wait a bounded time for one already-detached drain, and report whether the
172
+ * bound ran out. The timer keeps the process alive for the window, or a caller
173
+ * with nothing else pending would exit before reporting what is still in use,
174
+ * and is cleared as soon as the drain settles so a released implementation
175
+ * never delays shutdown until the deadline.
176
+ */
177
+ const awaitDrained = async (drained, timeoutMs) => {
178
+ const startedAt = Date.now();
179
+ let timedOut = false;
180
+ if (timeoutMs > 0) {
181
+ let expire;
182
+ try {
183
+ timedOut = !await Promise.race([
184
+ drained,
185
+ new Promise((resolve) => { expire = setTimeout(() => resolve(false), timeoutMs); })
186
+ ]);
187
+ }
188
+ finally {
189
+ if (expire !== undefined)
190
+ clearTimeout(expire);
191
+ }
192
+ }
193
+ else {
194
+ await Promise.resolve();
195
+ }
196
+ return Object.freeze({ waitedMs: Date.now() - startedAt, timedOut });
197
+ };
198
+ /**
199
+ * Ordinary stop: no new independent acquisition, while an already-acquired
200
+ * Session ends bounded. Resolves with the drain facts once every reference is
201
+ * released, or with what is still in use when the wait runs out.
202
+ */
203
+ const stop = async (adapterId, timeoutMs = 0) => {
204
+ const ref = attached.get(builtinAgentEndpointImplementation(adapterId).id);
205
+ if (ref === undefined) {
206
+ return Object.freeze({
207
+ quiescent: true, references: 0, opening: 0, waitedMs: 0, timedOut: false, sessions: []
208
+ });
209
+ }
210
+ // A disposer failure still ends acquisition; the drain facts below, not the
211
+ // settle reason, decide whether this is actually quiescent.
212
+ const drained = host.detach(ref).then(() => true, () => true);
213
+ return inspectWith(adapterId, await awaitDrained(drained, timeoutMs));
214
+ };
215
+ /**
216
+ * Final cleanup, bounded by construction. Every attached implementation is
217
+ * detached so nothing can acquire again, and the wait for their drains shares
218
+ * one deadline. `InstanceHost.close()` resolves only after every reference is
219
+ * handed back, which a client that never proves exit will never do; awaiting it
220
+ * here would block the Host's own shutdown after a bounded `stop` already
221
+ * reported that dependency, leaving the control socket unclosed.
222
+ *
223
+ * So this returns on the deadline and says what is still held, rather than
224
+ * releasing a reference it cannot prove or killing a client it does not own.
225
+ * The still-live implementations stay detached and undisposed on purpose: their
226
+ * facts remain readable, and the caller decides what to do about them.
227
+ */
228
+ const close = async (timeoutMs = 0) => {
229
+ const drains = [...attached.values()].map((ref) => Object.freeze({
230
+ implementationId: ref.id,
231
+ // Detaching cannot throw here: these refs are exactly what was attached,
232
+ // and detach is idempotent for an already-detached instance.
233
+ drained: host.detach(ref).then(() => true, () => true)
234
+ }));
235
+ const waited = await awaitDrained(Promise.all(drains.map((entry) => entry.drained)).then(() => true, () => true), timeoutMs);
236
+ return Object.freeze(drains.map((entry) => inspectImplementation(entry.implementationId, waited)));
237
+ };
238
+ return Object.freeze({ pin, stop, inspect, close });
239
+ }
@@ -69,8 +69,6 @@ export function providerDeliveryFailureFacts(failure) {
69
69
  ...(failure.errorName === undefined ? {} : { errorName: failure.errorName }),
70
70
  ...(failure.causeName === undefined ? {} : { causeName: failure.causeName }),
71
71
  ...(failure.hostState === undefined ? {} : { hostState: failure.hostState }),
72
- ...(failure.expectedRuntimeGenerationId === undefined ? {} : { expectedRuntimeGenerationId: failure.expectedRuntimeGenerationId }),
73
- ...(failure.observedRuntimeGenerationId === undefined ? {} : { observedRuntimeGenerationId: failure.observedRuntimeGenerationId }),
74
72
  ...(failure.attemptId === undefined ? {} : { attemptId: failure.attemptId })
75
73
  };
76
74
  }
@@ -111,7 +109,7 @@ function errorMessageText(error) {
111
109
  return String(error ?? "unknown error");
112
110
  }
113
111
  /**
114
- * Renders a delivery failure as one readable line for a Turn summary. The
112
+ * Renders a delivery failure as one readable line for a AgentRun summary. The
115
113
  * complete record stays available on `runtime.agent-error`; this is the
116
114
  * bounded projection, never a replacement for the original cause.
117
115
  */
@@ -126,12 +124,6 @@ export function formatProviderDeliveryFailure(failure) {
126
124
  fields.push(`error=${failure.errorName}`);
127
125
  if (failure.causeName !== undefined)
128
126
  fields.push(`cause=${failure.causeName}`);
129
- if (failure.expectedRuntimeGenerationId !== undefined) {
130
- fields.push(`expectedGeneration=${failure.expectedRuntimeGenerationId}`);
131
- }
132
- if (failure.observedRuntimeGenerationId !== undefined) {
133
- fields.push(`observedGeneration=${failure.observedRuntimeGenerationId}`);
134
- }
135
127
  if (failure.attemptId !== undefined)
136
128
  fields.push(`attemptId=${failure.attemptId}`);
137
129
  if (failure.registrationDisposition !== undefined) {
@@ -225,7 +217,7 @@ function rawPayloadText(value) {
225
217
  try {
226
218
  const seen = new WeakSet();
227
219
  const serialized = JSON.stringify(value, (key, member) => {
228
- // Turn input is the Agent's prompt: Task context, quoted files, whatever
220
+ // AgentRun input is the Agent's prompt: Task context, quoted files, whatever
229
221
  // the Role was told. It is not a failure fact, and it reaches the same
230
222
  // durable, publicly-readable record as the rest of this payload. A
231
223
  // transport client that echoes its own request into the thrown error