@zq-silk/yui 0.15.7 → 0.15.9
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.
- package/ARCHITECTURE.md +194 -399
- package/ARCHITECTURE.zh-CN.md +151 -0
- package/README.md +306 -1131
- package/dist/agent/adapterCatalog.js +15 -2
- package/dist/agent/agent.js +23 -3
- package/dist/agent/argumentPolicy.js +7 -1
- package/dist/agent/connectionPlan.js +62 -0
- package/dist/agent/executionComponents.js +158 -0
- package/dist/agent/launchEnvironment.js +31 -3
- package/dist/agent/managedRuntimeEnvironment.js +3 -5
- package/dist/{turn/turn.js → agentRun/agentRun.js} +166 -109
- package/dist/{turn/turnIdentity.js → agentRun/runIdentity.js} +4 -4
- package/dist/artifacts/artifactCapability.js +74 -0
- package/dist/artifacts/artifactCommitLock.js +249 -0
- package/dist/artifacts/artifactPaths.js +151 -0
- package/dist/artifacts/gitArtifactRef.js +146 -0
- package/dist/artifacts/managedGit.js +332 -0
- package/dist/artifacts/taskArtifactRepository.js +277 -0
- package/dist/brief/taskBrief.js +12 -0
- package/dist/cli/agentConfigurationPicker.js +13 -0
- package/dist/cli/commandCatalog.js +165 -74
- package/dist/cli/interactionCandidates.js +5 -5
- package/dist/cli/interactionPolicy.js +38 -8
- package/dist/cli/invocationRouter.js +1 -1
- package/dist/cli/managedDiagnostics.js +28 -0
- package/dist/cli/operatorWizard.js +1 -7
- package/dist/cli/roleOptionOrder.js +27 -0
- package/dist/cli/roleWizard.js +50 -14
- package/dist/cli/updateOrchestrator.js +1 -1
- package/dist/cli/updatePorts.js +3 -4
- package/dist/cli.js +245 -95
- package/dist/commands/agentCommands.js +72 -14
- package/dist/commands/capabilityCommands.js +9 -6
- package/dist/commands/configCommands.js +20 -20
- package/dist/commands/deliveryGuardPreflight.js +2 -2
- package/dist/commands/executionAuditCommands.js +24 -24
- package/dist/commands/globalRoleCommands.js +1 -1
- package/dist/commands/grantCommands.js +4 -4
- package/dist/commands/operatorCommands.js +34 -9
- package/dist/commands/projectCommands.js +4 -4
- package/dist/commands/resourcesCommands.js +2 -2
- package/dist/commands/roleConfiguration.js +25 -5
- package/dist/commands/roleRuntimeGuard.js +4 -5
- package/dist/commands/sessionCommands.js +3 -7
- package/dist/commands/taskActivationCommands.js +281 -0
- package/dist/commands/taskActor.js +28 -49
- package/dist/commands/taskCommands.js +1461 -720
- package/dist/commands/taskContextCommand.js +39 -583
- package/dist/commands/taskExecutionCommands.js +32 -32
- package/dist/commands/taskInputCommands.js +40 -104
- package/dist/commands/taskIntegrationCommands.js +3 -2
- package/dist/commands/taskIntegrationQueueCommands.js +1 -1
- package/dist/commands/taskNextActionCommand.js +8 -8
- package/dist/commands/taskOverviewCommand.js +33 -45
- package/dist/commands/taskRemoteDeliveryCommand.js +2 -2
- package/dist/commands/taskRoleRuntimeStatus.js +133 -102
- package/dist/commands/telemetryCommands.js +36 -38
- package/dist/config/configCatalog.js +4 -4
- package/dist/config/yuiConfig.js +8 -8
- package/dist/context/contextSnapshot.js +10 -10
- package/dist/context/dispatchContext.js +11 -11
- package/dist/context/roleSessionContext.js +6 -3
- package/dist/context/{turnContextPack.js → runContextPack.js} +158 -81
- package/dist/context/{turnInputContract.js → runInputContract.js} +73 -60
- package/dist/context/sessionBootstrapManifest.js +21 -2
- package/dist/context/sourceRunContext.js +30 -0
- package/dist/context/taskContext.js +481 -0
- package/dist/context/wakeNotification.js +27 -27
- package/dist/controller/agentRuntimeObserver.js +21 -24
- package/dist/controller/capabilityBridge.js +17 -6
- package/dist/controller/clientRuntime.js +65 -92
- package/dist/controller/controller.js +120 -188
- package/dist/controller/fileSchedulerStoreAdapter.js +787 -887
- package/dist/controller/jobControl.js +54 -85
- package/dist/controller/resourceInventory.js +8 -27
- package/dist/controller/resourceInventoryLinux.js +12 -13
- package/dist/controller/runtime.js +529 -479
- package/dist/controller/runtimeEventInbox.js +55 -25
- package/dist/controller/runtimeEventProcessor.js +22 -31
- package/dist/controller/{runtimeHookTurnFence.js → runtimeHookRunFence.js} +91 -115
- package/dist/controller/runtimeLaunchCoordinator.js +80 -426
- package/dist/controller/runtimeObservationHook.js +14 -18
- package/dist/controller/sessionNotify.js +16 -24
- package/dist/controller/sessionOwnerReconciliation.js +168 -50
- package/dist/controller/structuredProviderObservation.js +138 -99
- package/dist/coordination/workMailbox.js +3 -3
- package/dist/coordination/workMailboxQueue.js +36 -33
- package/dist/core/boundedRpc.js +8 -1
- package/dist/core/controllerClient.js +20 -1
- package/dist/core/controllerServer.js +4 -4
- package/dist/doctor/doctor.js +13 -2
- package/dist/domain/agentResultTransport.js +9 -9
- package/dist/execution/codexThreadNaming.js +2 -8
- package/dist/execution/executionHealth.js +51 -63
- package/dist/execution/reviewMainRun.js +137 -0
- package/dist/execution/workItemExecution.js +28 -29
- package/dist/execution/workItemExecutionProjection.js +99 -107
- package/dist/execution/workItemMainRun.js +141 -0
- package/dist/executor/agentAdapter.js +227 -20
- package/dist/executor/agentConfigurationCatalog.js +126 -4
- package/dist/executor/agentConfigurationProbe.js +162 -4
- package/dist/executor/agentExecutor.js +79 -78
- package/dist/executor/effectiveLaunch.js +105 -18
- package/dist/executor/executorRegistry.js +29 -44
- package/dist/executor/fileRoleLaunchPlanner.js +229 -154
- package/dist/executor/workspacePreflightClassification.js +16 -16
- package/dist/grant/capabilityGrant.js +6 -3
- package/dist/input/inputRequest.js +12 -10
- package/dist/integration/gitIntegrationService.js +4 -11
- package/dist/integration/integrationQueueService.js +4 -4
- package/dist/interaction/operatorPresentation.js +1 -1
- package/dist/kernel/builtinCapabilities.js +255 -12
- package/dist/kernel/capabilityRegistry.js +64 -18
- package/dist/kernel/instanceHost.js +12 -1
- package/dist/kernel/kernelPorts.js +2 -2
- package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
- package/dist/lifecycle/exactRunTerminalization.js +449 -0
- package/dist/message/message.js +118 -6
- package/dist/message/messageContinuation.js +204 -0
- package/dist/observability/executionAudit.js +70 -72
- package/dist/observability/faultClassification.js +2 -2
- package/dist/observability/orchestrationMetrics.js +8 -8
- package/dist/operator/operatorSessionHistory.js +1 -7
- package/dist/output/agentConfigurationPresentation.js +8 -3
- package/dist/output/agentRunConfigurationPresentation.js +128 -0
- package/dist/output/rolePresentation.js +54 -3
- package/dist/plugins/pluginChild.js +104 -0
- package/dist/plugins/pluginIntent.js +26 -0
- package/dist/plugins/pluginInterpreter.js +43 -0
- package/dist/plugins/pluginPackage.js +101 -0
- package/dist/plugins/pluginProcess.js +112 -0
- package/dist/plugins/pluginService.js +388 -0
- package/dist/profile/agentProfile.js +1 -1
- package/dist/repository/gitWorkspace.js +26 -4
- package/dist/repository/project.js +19 -4
- package/dist/repository/taskBaseFreshness.js +13 -13
- package/dist/repository/taskWorkspaceCoordinator.js +20 -27
- package/dist/repository/taskWorkspacePreparer.js +344 -83
- package/dist/resources/autoResourceGc.js +3 -3
- package/dist/resources/liveReferences.js +3 -3
- package/dist/resources/projectResource.js +75 -0
- package/dist/resources/projectResourceService.js +343 -0
- package/dist/resources/resourceDiscovery.js +6 -6
- package/dist/resources/resourceGc.js +1 -1
- package/dist/resources/resourceRegistrar.js +1 -1
- package/dist/resources/resourceTypes.js +1 -1
- package/dist/review/deltaRecheck.js +3 -3
- package/dist/review/reviewAcceptance.js +16 -16
- package/dist/review/reviewDecision.js +7 -7
- package/dist/review/reviewRound.js +21 -20
- package/dist/review/reviewerAvailability.js +2 -2
- package/dist/role/role.js +51 -7
- package/dist/role/taskRoleUpdate.js +30 -0
- package/dist/runtime/acpProtocol.js +425 -0
- package/dist/runtime/acpSession.js +731 -0
- package/dist/runtime/acpSessionConfiguration.js +260 -0
- package/dist/runtime/agentDriver.js +30 -11
- package/dist/runtime/agentEndpoint.js +278 -0
- package/dist/runtime/agentEndpointIdentity.js +86 -0
- package/dist/runtime/agentEndpointOwnership.js +239 -0
- package/dist/runtime/agentError.js +2 -10
- package/dist/runtime/agentHost.js +565 -314
- package/dist/runtime/agentRunConfiguration.js +258 -0
- package/dist/runtime/builtinAgentDrivers.js +134 -18
- package/dist/runtime/builtinAgentErrorMappers.js +55 -3
- package/dist/runtime/builtinTranscriptUsage.js +1 -1
- package/dist/runtime/claude-process-owner +0 -0
- package/dist/runtime/codexAppServerRuntime.js +38 -30
- package/dist/runtime/codexInteractiveHost.js +41 -6
- package/dist/runtime/continuationManager.js +2 -6
- package/dist/runtime/executionEnvironment.js +30 -0
- package/dist/runtime/firstProgressAdvisory.js +11 -11
- package/dist/runtime/index.js +4 -3
- package/dist/runtime/jsonLineChannel.js +109 -0
- package/dist/runtime/launchBroker.js +91 -16
- package/dist/runtime/launchDiagnostics.js +2 -2
- package/dist/runtime/lifecycleReservation.js +10 -18
- package/dist/runtime/managedCaller.js +61 -17
- package/dist/runtime/nativeSessionControl.js +102 -0
- package/dist/runtime/ports.js +6 -21
- package/dist/runtime/processExitObservation.js +8 -7
- package/dist/runtime/promptEnvelope.js +17 -6
- package/dist/runtime/providerContinuation.js +3 -9
- package/dist/runtime/providerContinuationReconciliationService.js +4 -13
- package/dist/runtime/providerControl.js +2 -7
- package/dist/runtime/providerRuntimeIdentity.js +110 -222
- package/dist/runtime/providerRuntimeReconciler.js +5 -9
- package/dist/runtime/runtimeBinding.js +0 -1
- package/dist/runtime/runtimeContinuationProjection.js +4 -7
- package/dist/runtime/runtimeDeadlines.js +9 -0
- package/dist/runtime/runtimeHealthPolicy.js +1 -1
- package/dist/runtime/runtimeObservation.js +29 -65
- package/dist/runtime/runtimeProjection.js +43 -51
- package/dist/runtime/runtimeSessionCandidate.js +1 -3
- package/dist/runtime/sessionLaunchRequest.js +3 -7
- package/dist/runtime/sessionOwnerIdentity.js +7 -54
- package/dist/runtime/sessionOwnerRegistry.js +22 -17
- package/dist/runtime/sessionReconciliation.js +4 -8
- package/dist/runtime/sessionTerminationGuard.js +70 -259
- package/dist/runtime/sessionTokenMetrics.js +5 -16
- package/dist/runtime/structuredProviderHost.js +237 -117
- package/dist/runtime/taskRuntimeIsolation.js +39 -122
- package/dist/runtime/tmuxAdapters.js +39 -86
- package/dist/scheduler/activeRoleRunDelivery.js +354 -0
- package/dist/scheduler/leaderWakeupProcessor.js +75 -266
- package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
- package/dist/scheduler/ports.js +80 -9
- package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
- package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
- package/dist/scheduler/taskExecutionProjection.js +120 -124
- package/dist/scheduler/taskObservabilityProjection.js +29 -29
- package/dist/scheduler/taskWake.js +11 -4
- package/dist/scheduler/wakeReason.js +9 -1
- package/dist/setup/setupCommand.js +3 -7
- package/dist/storage/migrations/agentRunContract.js +159 -0
- package/dist/storage/migrations/artifactsToGit.js +338 -0
- package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
- package/dist/storage/migrations/submitIntent.js +126 -0
- package/dist/storage/sqliteSchema.js +467 -7
- package/dist/storage/sqliteStore.js +355 -220
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/storeRpc.js +10 -5
- package/dist/storage/taskStore.js +13 -11
- package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
- package/dist/surface/surfaceContributions.js +102 -0
- package/dist/task/completionReadiness.js +32 -6
- package/dist/task/deliveryGuard.js +16 -16
- package/dist/task/draftPlan.js +72 -12
- package/dist/task/nextAction.js +144 -128
- package/dist/task/remoteDelivery.js +6 -6
- package/dist/task/task.js +184 -18
- package/dist/task/taskActivation.js +327 -0
- package/dist/task/taskActivationService.js +408 -0
- package/dist/task/taskRecordReference.js +5 -4
- package/dist/task/taskRecordRetirement.js +1 -1
- package/dist/task/taskSubmission.js +236 -0
- package/dist/telemetry/sqliteTelemetryStore.js +55 -68
- package/dist/telemetry/telemetryConfig.js +14 -14
- package/dist/telemetry/telemetryWiring.js +2 -2
- package/dist/web/assets/assetManifest.js +2 -0
- package/dist/web/assets/client/app.js +121 -20
- package/dist/web/assets/client/components.js +87 -54
- package/dist/web/assets/client/i18n.js +83 -41
- package/dist/web/assets/client/markdown.js +1 -1
- package/dist/web/assets/client/taskSurface.js +442 -0
- package/dist/web/assets/client/view.js +49 -44
- package/dist/web/assets/shell.js +1 -1
- package/dist/web/assets/styles/cards.js +22 -4
- package/dist/web/controllerWeb.js +60 -0
- package/dist/web/webMutation.js +28 -0
- package/dist/web/webServer.js +133 -8
- package/dist/web/webSnapshot.js +81 -74
- package/dist/web/webTaskSurface.js +64 -0
- package/dist/workItem/dependencyGate.js +1 -1
- package/dist/workItem/workItem.js +84 -48
- package/dist/workspace/workItemChangeSetManager.js +16 -9
- package/docs/agent-result-consumption.md +96 -0
- package/docs/agent-result-consumption.zh-CN.md +81 -0
- package/docs/agent-runtime-drivers.md +93 -0
- package/docs/agent-runtime-drivers.zh-CN.md +77 -0
- package/docs/architecture/README.md +50 -0
- package/docs/architecture/README.zh-CN.md +43 -0
- package/docs/architecture/capabilities-and-resources.md +118 -0
- package/docs/architecture/capabilities-and-resources.zh-CN.md +83 -0
- package/docs/managed-turn-and-session-runtime.md +224 -0
- package/docs/managed-turn-and-session-runtime.zh-CN.md +180 -0
- package/docs/observability/README.md +83 -0
- package/docs/observability/README.zh-CN.md +71 -0
- package/docs/plugin-sdk.md +393 -0
- package/docs/plugin-sdk.zh-CN.md +293 -0
- package/docs/provider-runtime.md +165 -0
- package/docs/provider-runtime.zh-CN.md +132 -0
- package/docs/release-workflow.md +305 -0
- package/docs/release-workflow.zh-CN.md +237 -0
- package/docs/roles-and-configuration.md +115 -0
- package/docs/roles-and-configuration.zh-CN.md +96 -0
- package/docs/sqlite-control-plane-design.md +78 -0
- package/docs/sqlite-control-plane-design.zh-CN.md +62 -0
- package/docs/task-dag-semantics.md +80 -0
- package/docs/task-dag-semantics.zh-CN.md +59 -0
- package/docs/task-delivery.md +105 -0
- package/docs/task-delivery.zh-CN.md +82 -0
- package/docs/task-local-identity.md +8 -6
- package/docs/task-local-identity.zh-CN.md +58 -0
- package/docs/testing/verification-levels.md +88 -0
- package/docs/testing/verification-levels.zh-CN.md +69 -0
- package/i18n/README.zh-CN.md +270 -722
- package/package.json +3 -2
- package/skills/yui-leader/SKILL.md +88 -304
- package/skills/yui-leader/references/execution.md +303 -0
- package/skills/yui-leader/references/integration.md +39 -0
- package/skills/yui-leader/references/planning.md +109 -0
- package/skills/yui-leader/references/replicated-execution.md +42 -0
- package/skills/yui-leader/references/task-plugins.md +37 -0
- package/skills/yui-operator/SKILL.md +46 -62
- package/skills/yui-reviewer/SKILL.md +35 -36
- package/skills/yui-runtime/SKILL.md +88 -24
- package/skills/yui-runtime/references/publication.md +22 -0
- package/skills/yui-runtime/references/recovery.md +64 -0
- package/skills/yui-worker/SKILL.md +37 -39
- package/dist/cli/roleOptionCatalog.js +0 -68
- package/dist/context/sourceTurnContext.js +0 -30
- package/dist/execution/reviewMainTurn.js +0 -161
- package/dist/execution/workItemMainTurn.js +0 -164
- package/dist/lifecycle/exactTurnTerminalization.js +0 -407
- package/dist/runtime/preallocatedNativeSession.js +0 -13
- package/dist/runtime/runtimeStopReceipt.js +0 -42
- package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
|
@@ -1,472 +1,126 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
|
|
3
|
-
import { createRuntimeBinding, RuntimeGenerationMismatchError, RuntimeHostContentionError, RuntimeHostUnavailableError, RuntimeLaunchError } from "../runtime/index.js";
|
|
1
|
+
import { createRuntimeBinding } from "../runtime/index.js";
|
|
4
2
|
import { sameEffectiveLaunch, validateEffectiveLaunchSnapshot } from "../executor/effectiveLaunch.js";
|
|
5
|
-
|
|
6
|
-
constructor(message, options) {
|
|
7
|
-
super(message, options);
|
|
8
|
-
this.name = "RuntimeBindingContractError";
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
class RuntimeLaunchStateChangedError extends Error {
|
|
12
|
-
constructor(message, options) {
|
|
13
|
-
super(message, options);
|
|
14
|
-
this.name = "RuntimeLaunchStateChangedError";
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* One application service owns the reservation -> host -> persistence
|
|
19
|
-
* protocol for Controller/scheduler-driven Role launches. Foreground Task
|
|
20
|
-
* attach is deliberately outside this lifecycle boundary.
|
|
21
|
-
*/
|
|
3
|
+
/** Serialize local Role launches; failures preserve resources for explicit recovery. */
|
|
22
4
|
export class RuntimeLaunchCoordinator {
|
|
23
|
-
|
|
5
|
+
sessions;
|
|
24
6
|
host;
|
|
25
|
-
|
|
26
|
-
#
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
#runtimeIsolation;
|
|
30
|
-
constructor(reservations, host, options = {}) {
|
|
31
|
-
this.reservations = reservations;
|
|
7
|
+
options;
|
|
8
|
+
#launchTails = new Map();
|
|
9
|
+
constructor(sessions, host, options = {}) {
|
|
10
|
+
this.sessions = sessions;
|
|
32
11
|
this.host = host;
|
|
33
|
-
this
|
|
34
|
-
this.#now = options.now ?? (() => new Date());
|
|
35
|
-
this.#assertCurrent = options.assertCurrent;
|
|
36
|
-
this.#onCleanupRequired = options.onCleanupRequired;
|
|
37
|
-
this.#runtimeIsolation = options.runtimeIsolation;
|
|
12
|
+
this.options = options;
|
|
38
13
|
}
|
|
39
|
-
async prepare(request,
|
|
40
|
-
const
|
|
14
|
+
async prepare(request, assertCurrent, beforeHostStart) {
|
|
15
|
+
const key = request.owner.scope === "task"
|
|
41
16
|
? `task\0${request.owner.taskId}\0${request.owner.roleName}`
|
|
42
17
|
: `global\0${request.owner.roleName}`;
|
|
43
|
-
const previous = this.#launchTails.get(
|
|
18
|
+
const previous = this.#launchTails.get(key) ?? Promise.resolve();
|
|
44
19
|
let release;
|
|
45
20
|
const current = new Promise((resolve) => { release = resolve; });
|
|
46
21
|
const tail = previous.then(() => current);
|
|
47
|
-
this.#launchTails.set(
|
|
22
|
+
this.#launchTails.set(key, tail);
|
|
48
23
|
await previous;
|
|
49
24
|
try {
|
|
50
|
-
return await this.#
|
|
25
|
+
return await this.#launch(request, assertCurrent, beforeHostStart);
|
|
51
26
|
}
|
|
52
27
|
finally {
|
|
53
28
|
release();
|
|
54
|
-
if (this.#launchTails.get(
|
|
55
|
-
this.#launchTails.delete(
|
|
56
|
-
}
|
|
29
|
+
if (this.#launchTails.get(key) === tail)
|
|
30
|
+
this.#launchTails.delete(key);
|
|
57
31
|
}
|
|
58
32
|
}
|
|
59
|
-
#
|
|
60
|
-
async #prepareUnlocked(request, persistence, assertCurrent, beforeHostStart) {
|
|
33
|
+
async #launch(request, assertCurrent, beforeHostStart) {
|
|
61
34
|
const effective = validateEffectiveLaunchSnapshot(request.effective);
|
|
62
35
|
if (effective.agentId !== request.agentId
|
|
63
36
|
|| effective.adapterId !== request.adapterId
|
|
64
37
|
|| effective.workspace.root !== request.workspace) {
|
|
65
|
-
throw new TypeError("Runtime launch
|
|
66
|
-
}
|
|
67
|
-
if (this.#runtimeIsolation !== undefined && request.owner.scope === "task") {
|
|
68
|
-
if (request.managedWorkspace === undefined) {
|
|
69
|
-
throw new Error("An authoritative ManagedWorkspace owner is required for a Task runtime launch.");
|
|
70
|
-
}
|
|
71
|
-
if (request.managedWorkspace.owner.taskId !== request.owner.taskId
|
|
72
|
-
|| request.managedWorkspace.root !== request.workspace) {
|
|
73
|
-
throw new Error("Task runtime launch does not match its authoritative ManagedWorkspace.");
|
|
74
|
-
}
|
|
38
|
+
throw new TypeError("Runtime launch does not match its effective configuration.");
|
|
75
39
|
}
|
|
76
40
|
if (request.owner.scope === "global" && request.managedWorkspace !== undefined) {
|
|
77
41
|
throw new Error("A global runtime cannot use a Task ManagedWorkspace.");
|
|
78
42
|
}
|
|
79
|
-
let currentRequest = request;
|
|
80
43
|
const assertLaunchCurrent = () => {
|
|
81
|
-
this
|
|
44
|
+
this.options.assertCurrent?.(request);
|
|
82
45
|
assertCurrent?.();
|
|
83
46
|
};
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
throw new RuntimeLaunchError(true, request.hostActivationId, `Host activation is temporarily ${inspection.state}: ${request.owner.roleName}.`);
|
|
96
|
-
}
|
|
97
|
-
if (inspection.state === "running") {
|
|
98
|
-
proposedRuntimeGenerationId = request.hostActivationId;
|
|
99
|
-
reusedConfirmedRunningHost = true;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
let runtimeIsolation = reusedConfirmedRunningHost
|
|
103
|
-
? undefined
|
|
104
|
-
: this.#preflightRuntimeIsolation(request, proposedRuntimeGenerationId, proposedGenerationId, false);
|
|
105
|
-
let reservation = this.reservations.reserveRuntimeLaunch({
|
|
106
|
-
owner: request.owner,
|
|
107
|
-
runtimeGenerationId: proposedRuntimeGenerationId
|
|
108
|
-
}, assertLaunchCurrent, this.#now());
|
|
109
|
-
if (reservation.status === "existing") {
|
|
110
|
-
const inspection = await this.host.inspectOwner(request.owner);
|
|
111
|
-
if (inspection.state === "unavailable" || inspection.state === "starting") {
|
|
112
|
-
throw new RuntimeLaunchError(true, reservation.runtimeGenerationId, `Runtime is temporarily ${inspection.state}: ${request.owner.roleName}/${reservation.runtimeGenerationId}.`);
|
|
113
|
-
}
|
|
114
|
-
if (inspection.state === "stopped") {
|
|
115
|
-
const taskOwner = request.owner.scope === "task"
|
|
116
|
-
? request.owner
|
|
117
|
-
: undefined;
|
|
118
|
-
let exactCleanupAttempted = false;
|
|
119
|
-
let completed = false;
|
|
120
|
-
try {
|
|
121
|
-
completed = this.reservations.completeRuntimeLaunchReservation(request.owner, reservation.runtimeGenerationId, taskOwner !== undefined && this.#runtimeIsolation !== undefined
|
|
122
|
-
? () => {
|
|
123
|
-
exactCleanupAttempted = true;
|
|
124
|
-
this.#cleanupTaskLaunch(taskOwner, reservation.runtimeGenerationId);
|
|
125
|
-
}
|
|
126
|
-
: undefined);
|
|
127
|
-
}
|
|
128
|
-
catch (error) {
|
|
129
|
-
if (exactCleanupAttempted)
|
|
130
|
-
this.#requireCleanup(request.owner);
|
|
131
|
-
throw error;
|
|
132
|
-
}
|
|
133
|
-
if (!completed) {
|
|
134
|
-
if (exactCleanupAttempted)
|
|
135
|
-
this.#requireCleanup(request.owner);
|
|
136
|
-
throw new Error("Runtime launch reservation changed during recovery.");
|
|
137
|
-
}
|
|
138
|
-
reservation = this.reservations.reserveRuntimeLaunch({
|
|
139
|
-
owner: request.owner,
|
|
140
|
-
runtimeGenerationId: proposedRuntimeGenerationId
|
|
141
|
-
}, assertLaunchCurrent, this.#now());
|
|
142
|
-
if (reservation.status !== "reserved") {
|
|
143
|
-
throw new Error("Runtime launch reservation could not be renewed.");
|
|
47
|
+
assertLaunchCurrent();
|
|
48
|
+
let isolation;
|
|
49
|
+
if (request.owner.scope === "task" && this.options.runtimeIsolation !== undefined) {
|
|
50
|
+
const workspace = request.managedWorkspace;
|
|
51
|
+
// A Task that legitimately owns no workspace has nothing to isolate: an
|
|
52
|
+
// empty environment plan over no bound Project (S27). Skipping isolation
|
|
53
|
+
// here is what lets such a Leader launch at all; a *missing*
|
|
54
|
+
// authoritative workspace still fails closed below.
|
|
55
|
+
if (request.workspaceFree === true) {
|
|
56
|
+
if (workspace !== undefined) {
|
|
57
|
+
throw new Error("A workspace-free Task launch cannot carry a ManagedWorkspace.");
|
|
144
58
|
}
|
|
145
59
|
}
|
|
60
|
+
else if (workspace === undefined || workspace.owner.taskId !== request.owner.taskId
|
|
61
|
+
|| workspace.root !== request.workspace) {
|
|
62
|
+
throw new Error("Task launch requires its authoritative ManagedWorkspace.");
|
|
63
|
+
}
|
|
146
64
|
else {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
65
|
+
isolation = this.options.runtimeIsolation.preflight({
|
|
66
|
+
workspace,
|
|
67
|
+
...(request.runtimePolicy === undefined ? {} : { policy: request.runtimePolicy }),
|
|
68
|
+
allowExactActive: true
|
|
69
|
+
});
|
|
70
|
+
this.options.runtimeIsolation.activate(isolation);
|
|
150
71
|
}
|
|
151
72
|
}
|
|
152
|
-
const runtimeGenerationId = reservation.runtimeGenerationId;
|
|
153
73
|
let preflightObserved = beforeHostStart === undefined;
|
|
154
74
|
const observePreflight = (preflight) => {
|
|
155
|
-
if (preflightObserved)
|
|
156
|
-
|
|
75
|
+
if (preflightObserved || !sameOwner(preflight.owner, request.owner)
|
|
76
|
+
|| preflight.runId !== request.runId
|
|
77
|
+
|| preflight.agentId !== request.agentId
|
|
78
|
+
|| preflight.adapterId !== request.adapterId
|
|
79
|
+
|| !sameEffectiveLaunch(preflight.effective, request.effective)
|
|
80
|
+
|| (request.mode === "resume" && preflight.nativeSessionId !== request.nativeSessionId)) {
|
|
81
|
+
throw new Error("Session host pre-start facts do not match the requested launch.");
|
|
157
82
|
}
|
|
158
|
-
|
|
159
|
-
this.reservations.confirmRuntimeLaunchReservation({
|
|
160
|
-
owner: request.owner,
|
|
161
|
-
runtimeGenerationId
|
|
162
|
-
}, assertLaunchCurrent);
|
|
83
|
+
assertLaunchCurrent();
|
|
163
84
|
preflightObserved = true;
|
|
164
85
|
beforeHostStart?.(preflight);
|
|
165
|
-
// The pre-start persistence callback hands the fixed native Session to
|
|
166
|
-
// this reserved activation. From here on, fence against that exact new
|
|
167
|
-
// identity, not the historical Host we originally set out to restore.
|
|
168
|
-
// Do not accept both identities: a later change back is stale as well.
|
|
169
|
-
if (request.mode === "resume" && request.hostActivationId !== undefined) {
|
|
170
|
-
currentRequest = { ...request, hostActivationId: runtimeGenerationId };
|
|
171
|
-
}
|
|
172
|
-
assertLaunchCurrent();
|
|
173
86
|
};
|
|
174
|
-
|
|
175
|
-
try {
|
|
176
|
-
if (!reusedConfirmedRunningHost && runtimeIsolation !== undefined) {
|
|
177
|
-
// Activation is the first runtime-resource side effect and can occur
|
|
178
|
-
// only after the centralized read-only preflight and durable launch
|
|
179
|
-
// reservation have both succeeded.
|
|
180
|
-
this.#runtimeIsolation.activate(runtimeIsolation);
|
|
181
|
-
}
|
|
182
|
-
const rawBinding = request.mode === "new"
|
|
183
|
-
? await this.host.start({
|
|
184
|
-
mode: "new",
|
|
185
|
-
runtimeGenerationId,
|
|
186
|
-
owner: request.owner,
|
|
187
|
-
agentId: request.agentId,
|
|
188
|
-
adapterId: request.adapterId,
|
|
189
|
-
effective: request.effective,
|
|
190
|
-
workspace: request.workspace,
|
|
191
|
-
...(runtimeIsolation === undefined
|
|
192
|
-
? {}
|
|
193
|
-
: { runtimeIsolation: runtimeIsolation.descriptor }),
|
|
194
|
-
...(request.turnId === undefined ? {} : { turnId: request.turnId }),
|
|
195
|
-
...(request.environment === undefined
|
|
196
|
-
? {}
|
|
197
|
-
: { environment: request.environment })
|
|
198
|
-
}, beforeHostStart === undefined ? undefined : observePreflight)
|
|
199
|
-
: await this.host.restore({
|
|
200
|
-
mode: "resume",
|
|
201
|
-
runtimeGenerationId,
|
|
202
|
-
owner: request.owner,
|
|
203
|
-
agentId: request.agentId,
|
|
204
|
-
adapterId: request.adapterId,
|
|
205
|
-
effective: request.effective,
|
|
206
|
-
workspace: request.workspace,
|
|
207
|
-
...(runtimeIsolation === undefined
|
|
208
|
-
? {}
|
|
209
|
-
: { runtimeIsolation: runtimeIsolation.descriptor }),
|
|
210
|
-
...(request.turnId === undefined ? {} : { turnId: request.turnId }),
|
|
211
|
-
...(request.environment === undefined
|
|
212
|
-
? {}
|
|
213
|
-
: { environment: request.environment }),
|
|
214
|
-
nativeSessionId: requireText(request.nativeSessionId, "Native session id")
|
|
215
|
-
}, beforeHostStart === undefined ? undefined : observePreflight);
|
|
216
|
-
binding = requireMatchingRuntimeBinding(rawBinding, request, runtimeGenerationId);
|
|
217
|
-
if (!preflightObserved) {
|
|
218
|
-
throw new Error("Runtime session host did not expose a pre-host-start launch fence.");
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
catch (error) {
|
|
222
|
-
if (error instanceof RuntimeHostUnavailableError) {
|
|
223
|
-
// A failed reused attachment provides no authority to detach its
|
|
224
|
-
// native Conversation or schedule owner-wide physical cleanup.
|
|
225
|
-
throw error;
|
|
226
|
-
}
|
|
227
|
-
if (error instanceof RuntimeGenerationMismatchError) {
|
|
228
|
-
// The observed Host is not the requested activation. Neither killing
|
|
229
|
-
// it nor scheduling owner-wide cleanup is justified by that conflict.
|
|
230
|
-
throw new RuntimeLaunchError(false, runtimeGenerationId, error.message, "generation-mismatch", { cause: error });
|
|
231
|
-
}
|
|
232
|
-
if (error instanceof RuntimeHostContentionError && reusedConfirmedRunningHost) {
|
|
233
|
-
// The exact recovered generation remains authoritative. A late human
|
|
234
|
-
// writer is transient backpressure and must not settle, clean, or
|
|
235
|
-
// terminalize that reservation.
|
|
236
|
-
throw new RuntimeLaunchError(true, runtimeGenerationId, error.message, error.reason, { cause: error });
|
|
237
|
-
}
|
|
238
|
-
if (error instanceof RuntimeHostContentionError
|
|
239
|
-
&& !reusedConfirmedRunningHost) {
|
|
240
|
-
let exactCleanupAttempted = false;
|
|
241
|
-
let completed = false;
|
|
242
|
-
try {
|
|
243
|
-
completed = this.reservations.completeRuntimeLaunchReservation(request.owner, runtimeGenerationId, runtimeIsolation === undefined
|
|
244
|
-
? undefined
|
|
245
|
-
: () => {
|
|
246
|
-
exactCleanupAttempted = true;
|
|
247
|
-
this.#runtimeIsolation.cleanup(runtimeIsolation, "failure");
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
catch (cleanupError) {
|
|
251
|
-
if (exactCleanupAttempted)
|
|
252
|
-
this.#requireCleanup(request.owner);
|
|
253
|
-
throw cleanupError;
|
|
254
|
-
}
|
|
255
|
-
if (!completed) {
|
|
256
|
-
this.#requireCleanup(request.owner);
|
|
257
|
-
throw new Error("Busy managed runtime launch reservation changed during retry release.");
|
|
258
|
-
}
|
|
259
|
-
throw new RuntimeLaunchError(true, runtimeGenerationId, error.message, error instanceof RuntimeHostContentionError
|
|
260
|
-
? error.reason
|
|
261
|
-
: "previous-process", { cause: error });
|
|
262
|
-
}
|
|
263
|
-
if (error instanceof RuntimeBindingContractError) {
|
|
264
|
-
// Never pass an untrusted hostRef to stop(). Reconcile the requested
|
|
265
|
-
// owner through the durable, owner-addressed cleanup lane instead.
|
|
266
|
-
this.#requireCleanup(request.owner);
|
|
267
|
-
throw error;
|
|
268
|
-
}
|
|
269
|
-
await this.#settleFailedStart(request, runtimeGenerationId, reusedConfirmedRunningHost, runtimeIsolation);
|
|
270
|
-
throw error;
|
|
271
|
-
}
|
|
272
|
-
if (reusedConfirmedRunningHost && binding.hostCreated === true) {
|
|
273
|
-
await this.#compensateStartedHost(request.owner, binding, runtimeGenerationId, runtimeIsolation, reusedConfirmedRunningHost, new Error(`Runtime host was recreated while recovering an existing generation: ${request.owner.roleName}.`));
|
|
274
|
-
}
|
|
275
|
-
try {
|
|
276
|
-
assertLaunchCurrent();
|
|
277
|
-
const reservationState = this.reservations.confirmRuntimeLaunchReservation({
|
|
278
|
-
owner: request.owner,
|
|
279
|
-
runtimeGenerationId
|
|
280
|
-
}, assertLaunchCurrent);
|
|
281
|
-
if (reservationState === "reserved") {
|
|
282
|
-
if (binding.nativeSessionId !== undefined) {
|
|
283
|
-
this.reservations.recordReservedRuntimeNativeSession({
|
|
284
|
-
owner: request.owner,
|
|
285
|
-
runtimeGenerationId,
|
|
286
|
-
agentId: request.agentId,
|
|
287
|
-
adapterId: request.adapterId,
|
|
288
|
-
nativeSessionId: binding.nativeSessionId,
|
|
289
|
-
effective: request.effective
|
|
290
|
-
}, assertLaunchCurrent, this.#now());
|
|
291
|
-
}
|
|
292
|
-
else if (!this.reservations.completeRuntimeLaunchReservation(request.owner, runtimeGenerationId)) {
|
|
293
|
-
throw new Error("Runtime Host-start reservation changed before completion.");
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
catch (error) {
|
|
298
|
-
await this.#compensateStartedHost(request.owner, binding, runtimeGenerationId, runtimeIsolation, reusedConfirmedRunningHost, error);
|
|
299
|
-
}
|
|
300
|
-
return binding;
|
|
301
|
-
}
|
|
302
|
-
async #settleFailedStart(request, runtimeGenerationId, reusedConfirmedRunningHost, runtimeIsolation) {
|
|
303
|
-
let inspection;
|
|
304
|
-
try {
|
|
305
|
-
inspection = await this.host.inspectOwner(request.owner);
|
|
306
|
-
}
|
|
307
|
-
catch {
|
|
308
|
-
// A rebind/preflight failure did not create the already-confirmed host.
|
|
309
|
-
// Preserve its generation when the follow-up probe is merely unknown.
|
|
310
|
-
if (!reusedConfirmedRunningHost)
|
|
311
|
-
this.#requireCleanup(request.owner);
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
if (inspection.state === "stopped") {
|
|
315
|
-
if (runtimeIsolation !== undefined) {
|
|
316
|
-
try {
|
|
317
|
-
this.#runtimeIsolation.cleanup(runtimeIsolation, "failure");
|
|
318
|
-
}
|
|
319
|
-
catch (cleanupError) {
|
|
320
|
-
this.#requireCleanup(request.owner);
|
|
321
|
-
throw new Error(`Task runtime launch failed and exact resource cleanup also failed: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`, { cause: cleanupError });
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
if (!this.#settleConfirmedStopped(request, runtimeGenerationId)) {
|
|
325
|
-
this.#requireCleanup(request.owner);
|
|
326
|
-
}
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
if (reusedConfirmedRunningHost)
|
|
330
|
-
return;
|
|
331
|
-
this.#requireCleanup(request.owner);
|
|
332
|
-
}
|
|
333
|
-
async #compensateStartedHost(owner, binding, runtimeGenerationId, runtimeIsolation, reusedConfirmedRunningHost, cause) {
|
|
334
|
-
if (reusedConfirmedRunningHost && binding.hostCreated !== true) {
|
|
335
|
-
// Reattaching an existing activation gives this launch no ownership of
|
|
336
|
-
// it. A fresh activation inside a persistent Host is different: this
|
|
337
|
-
// launch still owns its startup and isolation cleanup even when the
|
|
338
|
-
// physical Host did not need to be created.
|
|
339
|
-
throw new RuntimeLaunchStateChangedError(`Runtime launch state changed while reusing a Host: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
|
|
340
|
-
}
|
|
341
|
-
try {
|
|
342
|
-
await this.host.stop(binding);
|
|
343
|
-
}
|
|
344
|
-
catch (stopError) {
|
|
345
|
-
this.#requireCleanup(owner);
|
|
346
|
-
throw new Error(`Runtime launch state changed. Runtime cleanup also failed: ${stopError instanceof Error ? stopError.message : String(stopError)}`, { cause: stopError });
|
|
347
|
-
}
|
|
348
|
-
let stopped = false;
|
|
349
|
-
try {
|
|
350
|
-
stopped = (await this.host.inspectOwner(owner)).state === "stopped";
|
|
351
|
-
}
|
|
352
|
-
catch {
|
|
353
|
-
// Durable owner cleanup below is the only safe fallback.
|
|
354
|
-
}
|
|
355
|
-
if (stopped && runtimeIsolation !== undefined) {
|
|
356
|
-
try {
|
|
357
|
-
this.#runtimeIsolation.cleanup(runtimeIsolation, "failure");
|
|
358
|
-
}
|
|
359
|
-
catch (cleanupError) {
|
|
360
|
-
this.#requireCleanup(owner);
|
|
361
|
-
throw new Error(`Runtime host stopped but exact Task resource cleanup failed: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`, { cause: cleanupError });
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
if (!stopped
|
|
365
|
-
|| !this.reservations.settleStoppedRuntimeLaunch({
|
|
366
|
-
owner,
|
|
367
|
-
runtimeGenerationId,
|
|
368
|
-
agentId: binding.agentId,
|
|
369
|
-
adapterId: binding.adapterId,
|
|
370
|
-
...(binding.nativeSessionId === undefined
|
|
371
|
-
? {}
|
|
372
|
-
: { nativeSessionId: binding.nativeSessionId })
|
|
373
|
-
}, this.#now())) {
|
|
374
|
-
this.#requireCleanup(owner);
|
|
375
|
-
}
|
|
376
|
-
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
377
|
-
throw new RuntimeLaunchStateChangedError(`Runtime launch was compensated after state changed: ${detail}`, { cause });
|
|
378
|
-
}
|
|
379
|
-
#preflightRuntimeIsolation(request, runtimeGenerationId, generationId, allowExactActive) {
|
|
380
|
-
if (this.#runtimeIsolation === undefined || request.owner.scope !== "task") {
|
|
381
|
-
return undefined;
|
|
382
|
-
}
|
|
383
|
-
return this.#runtimeIsolation.preflight({
|
|
384
|
-
workspace: request.managedWorkspace,
|
|
385
|
-
runtimeGenerationId,
|
|
386
|
-
generationId: requireText(generationId, "Launch generation id"),
|
|
387
|
-
...(request.runtimePolicy === undefined ? {} : { policy: request.runtimePolicy }),
|
|
388
|
-
...(allowExactActive ? { allowExactActive: true } : {})
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
#cleanupTaskLaunch(owner, runtimeGenerationId) {
|
|
392
|
-
const cleanupTaskLaunch = this.#runtimeIsolation?.cleanupTaskLaunch;
|
|
393
|
-
if (cleanupTaskLaunch === undefined) {
|
|
394
|
-
throw new Error("Exact Task runtime launch cleanup is unavailable.");
|
|
395
|
-
}
|
|
396
|
-
cleanupTaskLaunch.call(this.#runtimeIsolation, {
|
|
397
|
-
taskId: owner.taskId,
|
|
398
|
-
runtimeGenerationId,
|
|
399
|
-
reason: "interruption"
|
|
400
|
-
});
|
|
401
|
-
}
|
|
402
|
-
#settleConfirmedStopped(request, runtimeGenerationId) {
|
|
403
|
-
return this.reservations.settleStoppedRuntimeLaunch({
|
|
87
|
+
const shared = {
|
|
404
88
|
owner: request.owner,
|
|
405
|
-
runtimeGenerationId,
|
|
406
89
|
agentId: request.agentId,
|
|
407
90
|
adapterId: request.adapterId,
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
91
|
+
effective,
|
|
92
|
+
workspace: request.workspace,
|
|
93
|
+
...(isolation === undefined ? {} : { runtimeIsolation: isolation.descriptor }),
|
|
94
|
+
...(request.runId === undefined ? {} : { runId: request.runId }),
|
|
95
|
+
...(request.environment === undefined ? {} : { environment: request.environment })
|
|
96
|
+
};
|
|
97
|
+
const callback = beforeHostStart === undefined ? undefined : observePreflight;
|
|
98
|
+
if (request.mode === "resume" && !request.nativeSessionId) {
|
|
99
|
+
throw new Error("Restoring a Session requires its native session id.");
|
|
100
|
+
}
|
|
101
|
+
const binding = createRuntimeBinding(request.mode === "new"
|
|
102
|
+
? await this.host.start({ ...shared, mode: "new" }, callback)
|
|
103
|
+
: await this.host.restore({
|
|
104
|
+
...shared, mode: "resume", nativeSessionId: request.nativeSessionId
|
|
105
|
+
}, callback));
|
|
106
|
+
if (!preflightObserved || !sameOwner(binding.owner, request.owner)
|
|
107
|
+
|| binding.agentId !== request.agentId || binding.adapterId !== request.adapterId
|
|
108
|
+
|| (request.mode === "resume" && binding.nativeSessionId !== request.nativeSessionId)) {
|
|
109
|
+
throw new Error("Session host returned facts inconsistent with the requested launch.");
|
|
110
|
+
}
|
|
111
|
+
if (binding.nativeSessionId !== undefined) {
|
|
112
|
+
this.sessions.recordLaunchedRuntimeNativeSession({
|
|
113
|
+
owner: request.owner,
|
|
114
|
+
agentId: request.agentId,
|
|
115
|
+
adapterId: request.adapterId,
|
|
116
|
+
nativeSessionId: binding.nativeSessionId,
|
|
117
|
+
effective
|
|
118
|
+
}, assertLaunchCurrent, this.options.now?.() ?? new Date());
|
|
421
119
|
}
|
|
120
|
+
return binding;
|
|
422
121
|
}
|
|
423
122
|
}
|
|
424
|
-
function
|
|
425
|
-
|
|
426
|
-
&&
|
|
427
|
-
&& (preflight.owner.scope === "global"
|
|
428
|
-
|| (request.owner.scope === "task"
|
|
429
|
-
&& preflight.owner.taskId === request.owner.taskId));
|
|
430
|
-
if (preflight.runtimeGenerationId !== runtimeGenerationId
|
|
431
|
-
|| !ownerMatches
|
|
432
|
-
|| preflight.turnId !== request.turnId
|
|
433
|
-
|| preflight.agentId !== request.agentId
|
|
434
|
-
|| preflight.adapterId !== request.adapterId
|
|
435
|
-
|| !sameEffectiveLaunch(preflight.effective, request.effective)
|
|
436
|
-
|| (request.mode === "resume"
|
|
437
|
-
&& preflight.nativeSessionId !== request.nativeSessionId)) {
|
|
438
|
-
throw new Error(`Session host pre-start launch fence does not match the requested runtime: ${request.owner.roleName}.`);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
function requireMatchingRuntimeBinding(raw, request, runtimeGenerationId) {
|
|
442
|
-
let binding;
|
|
443
|
-
try {
|
|
444
|
-
binding = createRuntimeBinding(raw);
|
|
445
|
-
}
|
|
446
|
-
catch (error) {
|
|
447
|
-
throw new RuntimeBindingContractError("Session host returned an invalid runtime binding.", { cause: error });
|
|
448
|
-
}
|
|
449
|
-
const ownerMatches = binding.owner.scope === request.owner.scope
|
|
450
|
-
&& binding.owner.roleName === request.owner.roleName
|
|
451
|
-
&& (binding.owner.scope === "global"
|
|
452
|
-
|| (request.owner.scope === "task"
|
|
453
|
-
&& binding.owner.taskId === request.owner.taskId));
|
|
454
|
-
if (binding.runtimeGenerationId !== runtimeGenerationId
|
|
455
|
-
|| !ownerMatches
|
|
456
|
-
|| binding.agentId !== request.agentId
|
|
457
|
-
|| binding.adapterId !== request.adapterId
|
|
458
|
-
|| (request.mode === "resume"
|
|
459
|
-
&& binding.nativeSessionId !== request.nativeSessionId)) {
|
|
460
|
-
throw new RuntimeBindingContractError(`Session host returned a binding that does not match the requested runtime: ${request.owner.roleName}.`);
|
|
461
|
-
}
|
|
462
|
-
return binding;
|
|
463
|
-
}
|
|
464
|
-
function requireText(value, label) {
|
|
465
|
-
if (typeof value !== "string"
|
|
466
|
-
|| value.length === 0
|
|
467
|
-
|| value.trim() !== value
|
|
468
|
-
|| value.includes("\0")) {
|
|
469
|
-
throw new Error(`${label} is invalid.`);
|
|
470
|
-
}
|
|
471
|
-
return value;
|
|
123
|
+
function sameOwner(a, b) {
|
|
124
|
+
return a.scope === b.scope && a.roleName === b.roleName
|
|
125
|
+
&& (a.scope === "global" || (b.scope === "task" && a.taskId === b.taskId));
|
|
472
126
|
}
|
|
@@ -3,18 +3,18 @@ import { builtinAgentDriverRegistry } from "../runtime/builtinAgentDrivers.js";
|
|
|
3
3
|
import { normalizeAgentDriverHookClassification } from "../runtime/agentDriver.js";
|
|
4
4
|
import { mapAgentDriverHooks } from "../runtime/agentDriverObservation.js";
|
|
5
5
|
import { runtimeLifecycleSignalKey } from "../runtime/lifecycleReservation.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { formatRunReceiptId } from "../task/taskRecordReference.js";
|
|
7
|
+
import { boundedRunFailureDiagnostic, transportAgentResult } from "../domain/agentResultTransport.js";
|
|
8
8
|
import { FileRuntimeEventInbox, MAX_RUNTIME_EVENT_FILE_BYTES } from "./runtimeEventInbox.js";
|
|
9
|
-
import {
|
|
9
|
+
import { resolveRuntimeHookRunFence } from "./runtimeHookRunFence.js";
|
|
10
10
|
/**
|
|
11
11
|
* Single hidden ingress for every structured CLI Driver Hook. Native event
|
|
12
12
|
* names and payload shapes terminate here; the durable inbox contains only a
|
|
13
|
-
* provider-independent RuntimeObservation with an exact
|
|
13
|
+
* provider-independent RuntimeObservation with an exact Session/AgentRun fence.
|
|
14
14
|
*/
|
|
15
15
|
export async function runRuntimeObservationHookCommand(stdinJson, environment = process.env, call = callController, now = new Date(), dependencies = {}) {
|
|
16
16
|
if (environment.YUI_SESSION_SCOPE === "global") {
|
|
17
|
-
await
|
|
17
|
+
await runGlobalRuntimeRunHook(stdinJson, environment, call, now, dependencies);
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
20
|
const parsed = parseRuntimeObservationHook(stdinJson, environment, now, dependencies);
|
|
@@ -33,7 +33,7 @@ export async function runRuntimeObservationHookCommand(stdinJson, environment =
|
|
|
33
33
|
})
|
|
34
34
|
}, { timeoutMs: 100 }).catch(() => { });
|
|
35
35
|
}
|
|
36
|
-
async function
|
|
36
|
+
async function runGlobalRuntimeRunHook(stdinJson, environment, call, now, dependencies) {
|
|
37
37
|
const payload = parseObject(stdinJson);
|
|
38
38
|
const hookEventName = requireIdentity(payload.hook_event_name, "Agent Driver Hook event name");
|
|
39
39
|
if (hookEventName !== "Stop" && hookEventName !== "StopFailure")
|
|
@@ -51,12 +51,11 @@ async function runGlobalRuntimeTurnHook(stdinJson, environment, call, now, depen
|
|
|
51
51
|
}
|
|
52
52
|
const home = requireIdentity(environment.YUI_HOME, "YUI_HOME");
|
|
53
53
|
const roleName = requireIdentity(environment.YUI_ROLE, "Role name");
|
|
54
|
-
new FileRuntimeEventInbox(home, () => now).
|
|
54
|
+
new FileRuntimeEventInbox(home, () => now).enqueueRunTerminal({
|
|
55
55
|
scope: "global",
|
|
56
56
|
roleName,
|
|
57
57
|
agentId: requireIdentity(environment.YUI_AGENT_ID, "Agent id"),
|
|
58
58
|
adapterId: "claude",
|
|
59
|
-
runtimeGenerationId: requireIdentity(environment.YUI_RUNTIME_GENERATION_ID, "Runtime generation id"),
|
|
60
59
|
nativeSessionId,
|
|
61
60
|
nativeTurnId: optionalIdentity(driver.runtime.nativeTurnId(nativeHook)) ?? occurrenceId,
|
|
62
61
|
...(environment.YUI_SESSION_TITLE === undefined
|
|
@@ -77,7 +76,7 @@ function globalHookOutcome(payload, hookEventName) {
|
|
|
77
76
|
return {
|
|
78
77
|
status: "failed",
|
|
79
78
|
failureReason: "runtime-failed",
|
|
80
|
-
diagnostic:
|
|
79
|
+
diagnostic: boundedRunFailureDiagnostic(diagnostic)
|
|
81
80
|
};
|
|
82
81
|
}
|
|
83
82
|
export function parseRuntimeObservationHook(stdinJson, environment, now = new Date(), dependencies = {}) {
|
|
@@ -90,7 +89,7 @@ export function parseRuntimeObservationHook(stdinJson, environment, now = new Da
|
|
|
90
89
|
&& environment.YUI_ADAPTER_ID === "claude") {
|
|
91
90
|
// Existing native Conversations may retain an old Yui observer plugin.
|
|
92
91
|
// Only the managed stream owns execution facts: Hooks do not expose its
|
|
93
|
-
// input attempt, and associating them with the currently active
|
|
92
|
+
// input attempt, and associating them with the currently active AgentRun can
|
|
94
93
|
// steal a successor's result. This observer is not a permission handler;
|
|
95
94
|
// Claude's configured tool policy and other user plugins remain intact.
|
|
96
95
|
return {
|
|
@@ -107,19 +106,18 @@ export function parseRuntimeObservationHook(stdinJson, environment, now = new Da
|
|
|
107
106
|
const nativeSessionId = requireIdentity(driver.runtime.nativeSessionId(nativeHook), "Agent Driver native Session id");
|
|
108
107
|
const nativeTurnId = optionalIdentity(driver.runtime.nativeTurnId(nativeHook));
|
|
109
108
|
const classification = normalizeAgentDriverHookClassification(driver.runtime.classifyHook(nativeHook));
|
|
110
|
-
const fence = (dependencies.
|
|
109
|
+
const fence = (dependencies.resolveRunFence ?? resolveRuntimeHookRunFence)(environment, driver.adapterId, nativeSessionId, {
|
|
111
110
|
...(classification.startupSession === undefined
|
|
112
111
|
? {}
|
|
113
112
|
: { startupSession: classification.startupSession }),
|
|
114
113
|
terminal: classification.terminal,
|
|
115
114
|
...(classification.continuationId === undefined ? {} : {
|
|
116
115
|
continuationId: classification.continuationId,
|
|
117
|
-
continuationGeneration: classification.continuationGeneration ?? 1
|
|
118
116
|
}),
|
|
119
117
|
...(nativeTurnId === undefined ? {} : { nativeTurnId })
|
|
120
118
|
});
|
|
121
|
-
if (fence.
|
|
122
|
-
throw new Error("Agent Driver Hook requires a managed
|
|
119
|
+
if (fence.runId === undefined) {
|
|
120
|
+
throw new Error("Agent Driver Hook requires a managed AgentRun.");
|
|
123
121
|
}
|
|
124
122
|
const driverInput = {
|
|
125
123
|
driver,
|
|
@@ -133,15 +131,13 @@ export function parseRuntimeObservationHook(stdinJson, environment, now = new Da
|
|
|
133
131
|
fence: {
|
|
134
132
|
taskId: fence.taskId,
|
|
135
133
|
roleName: fence.roleName,
|
|
136
|
-
|
|
134
|
+
runId: fence.runId,
|
|
137
135
|
agentId: fence.agentId,
|
|
138
136
|
driverId,
|
|
139
|
-
runtimeGenerationId: fence.runtimeGenerationId,
|
|
140
137
|
conversationId: fence.nativeSessionId,
|
|
141
|
-
activationId: fence.runtimeGenerationId,
|
|
142
138
|
nativeSessionId: fence.nativeSessionId,
|
|
143
139
|
...(nativeTurnId === undefined ? {} : { nativeTurnId }),
|
|
144
|
-
receiptId: fence.receiptId ??
|
|
140
|
+
receiptId: fence.receiptId ?? formatRunReceiptId(fence.taskId, fence.runId)
|
|
145
141
|
},
|
|
146
142
|
payload
|
|
147
143
|
};
|