@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,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { callController } from "../core/controllerClient.js";
|
|
2
|
+
import { callController, ControllerClientError } from "../core/controllerClient.js";
|
|
3
3
|
import { builtinAgentDriverRegistry } from "../runtime/builtinAgentDrivers.js";
|
|
4
4
|
import { standardAgentError } from "../runtime/agentError.js";
|
|
5
5
|
import { transportAgentResult } from "../domain/agentResultTransport.js";
|
|
@@ -7,15 +7,75 @@ import { createRuntimeObservation, runtimeObservationSemanticKey } from "../runt
|
|
|
7
7
|
import { runtimeLifecycleSignalKey } from "../runtime/lifecycleReservation.js";
|
|
8
8
|
import { isForeignHandoverLockHeld } from "../release/runtimeRelease.js";
|
|
9
9
|
import { FileRuntimeEventInbox } from "./runtimeEventInbox.js";
|
|
10
|
-
import {
|
|
11
|
-
import { openCurrentTaskStore } from "../storage/currentTaskStore.js";
|
|
10
|
+
import { resolveRuntimeHookRunFence } from "./runtimeHookRunFence.js";
|
|
12
11
|
let structuredSequence = 0;
|
|
12
|
+
export async function publishStructuredProviderAttachmentExit(input) {
|
|
13
|
+
const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
|
|
14
|
+
const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
|
|
15
|
+
const owner = resolveRuntimeHookRunFence(input.environment, adapterId, input.nativeSessionId, {
|
|
16
|
+
terminal: true, attemptId: input.attemptId, nativeTurnId: input.nativeTurnId
|
|
17
|
+
});
|
|
18
|
+
await persistAndApply(input.home, [observation({
|
|
19
|
+
kind: input.failed ? "session.failed" : "session.ended", observedAt: input.observedAt,
|
|
20
|
+
sequence: nextStructuredSequence(), ordinal: 0,
|
|
21
|
+
fence: {
|
|
22
|
+
taskId: owner.taskId, roleName: owner.roleName, agentId: owner.agentId, driverId: driver.id,
|
|
23
|
+
nativeSessionId: input.nativeSessionId, conversationId: input.nativeSessionId,
|
|
24
|
+
...(owner.runId === undefined ? {} : { runId: owner.runId }),
|
|
25
|
+
...(input.attemptId === undefined ? {} : { receiptId: input.attemptId }),
|
|
26
|
+
...(input.nativeTurnId === undefined ? {} : { nativeTurnId: input.nativeTurnId })
|
|
27
|
+
}
|
|
28
|
+
})], owner.taskId, owner.roleName);
|
|
29
|
+
}
|
|
30
|
+
export async function publishStructuredProviderActivity(input) {
|
|
31
|
+
const activity = input.activity;
|
|
32
|
+
const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
|
|
33
|
+
const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
|
|
34
|
+
const owner = resolveRuntimeHookRunFence(input.environment, adapterId, activity.nativeSessionId, {
|
|
35
|
+
nativeTurnId: activity.nativeTurnId, attemptId: activity.attemptId
|
|
36
|
+
});
|
|
37
|
+
const event = observation({
|
|
38
|
+
kind: activity.phase === "model" ? "activity.observed" : `operation.${activity.phase}`,
|
|
39
|
+
observedAt: activity.observedAt, sequence: nextStructuredSequence(), ordinal: 0,
|
|
40
|
+
fence: {
|
|
41
|
+
taskId: owner.taskId, roleName: owner.roleName,
|
|
42
|
+
...(owner.runId === undefined ? {} : { runId: owner.runId }),
|
|
43
|
+
agentId: owner.agentId, driverId: driver.id,
|
|
44
|
+
nativeSessionId: activity.nativeSessionId, conversationId: activity.conversationId,
|
|
45
|
+
receiptId: activity.attemptId,
|
|
46
|
+
...(activity.nativeTurnId === undefined ? {} : { nativeTurnId: activity.nativeTurnId })
|
|
47
|
+
},
|
|
48
|
+
payload: activity.phase === "model"
|
|
49
|
+
? { activity: "model", activityId: activity.id }
|
|
50
|
+
: { operation: "tool", operationId: activity.id }
|
|
51
|
+
});
|
|
52
|
+
await persistAndApply(input.home, [event], owner.taskId, owner.roleName);
|
|
53
|
+
}
|
|
54
|
+
/** An exact provider item id is evidence of visible input, not an inferred
|
|
55
|
+
* human author. The original managed request is never replaced.
|
|
56
|
+
*/
|
|
57
|
+
export async function publishStructuredProviderInputObserved(input) {
|
|
58
|
+
const observed = input.observed;
|
|
59
|
+
const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
|
|
60
|
+
const fence = resolveRuntimeHookRunFence(input.environment, adapterId, observed.nativeSessionId, {
|
|
61
|
+
nativeTurnId: observed.nativeTurnId, terminal: true, sessionOnly: true
|
|
62
|
+
});
|
|
63
|
+
if (fence.runId === undefined)
|
|
64
|
+
return; // Ordinary chat need not be mirrored.
|
|
65
|
+
await persistAndApply(input.home, [observation({
|
|
66
|
+
kind: "input.accepted", observedAt: observed.observedAt, sequence: nextStructuredSequence(), ordinal: 0,
|
|
67
|
+
fence: { ...fence, driverId: builtinAgentDriverRegistry().requireByAdapterId(adapterId).id,
|
|
68
|
+
conversationId: observed.conversationId, nativeTurnId: observed.nativeTurnId,
|
|
69
|
+
receiptId: `native-input:${observed.nativeTurnId}/${observed.inputId}` },
|
|
70
|
+
payload: { input: observed.input }
|
|
71
|
+
})], fence.taskId, fence.roleName);
|
|
72
|
+
}
|
|
13
73
|
export async function publishStructuredProviderStarted(input) {
|
|
14
74
|
if (input.started.clientOwned)
|
|
15
75
|
return;
|
|
16
76
|
const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
|
|
17
77
|
const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
|
|
18
|
-
const fence =
|
|
78
|
+
const fence = resolveRuntimeHookRunFence(input.environment, adapterId, input.started.nativeSessionId, {
|
|
19
79
|
nativeTurnId: input.started.nativeTurnId,
|
|
20
80
|
sessionOnly: true
|
|
21
81
|
});
|
|
@@ -30,9 +90,7 @@ export async function publishStructuredProviderStarted(input) {
|
|
|
30
90
|
roleName: fence.roleName,
|
|
31
91
|
agentId: fence.agentId,
|
|
32
92
|
driverId: driver.id,
|
|
33
|
-
runtimeGenerationId: fence.runtimeGenerationId,
|
|
34
93
|
conversationId: input.started.conversationId,
|
|
35
|
-
activationId: requireIdentity(input.activationId, "Provider Activation id"),
|
|
36
94
|
nativeSessionId: input.started.nativeSessionId,
|
|
37
95
|
nativeTurnId: input.started.nativeTurnId,
|
|
38
96
|
receiptId
|
|
@@ -45,7 +103,7 @@ export async function publishStructuredProviderAccepted(input) {
|
|
|
45
103
|
const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
|
|
46
104
|
const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
|
|
47
105
|
const startupSession = driver.capabilities.observation.sessionBootstrap;
|
|
48
|
-
const fence =
|
|
106
|
+
const fence = resolveRuntimeHookRunFence(input.environment, adapterId, input.receipt.nativeSessionId, {
|
|
49
107
|
startupSession,
|
|
50
108
|
nativeTurnId: input.receipt.nativeTurnId,
|
|
51
109
|
attemptId: input.receipt.attemptId
|
|
@@ -54,23 +112,21 @@ export async function publishStructuredProviderAccepted(input) {
|
|
|
54
112
|
const commonFence = {
|
|
55
113
|
taskId: fence.taskId,
|
|
56
114
|
roleName: fence.roleName,
|
|
57
|
-
...(fence.
|
|
115
|
+
...(fence.runId === undefined ? {} : { runId: fence.runId }),
|
|
58
116
|
agentId: fence.agentId,
|
|
59
117
|
driverId: driver.id,
|
|
60
|
-
runtimeGenerationId: fence.runtimeGenerationId,
|
|
61
118
|
conversationId: input.receipt.conversationId,
|
|
62
|
-
activationId: executionActivationId(input.home, fence, input.activationId, input.receipt.nativeSessionId),
|
|
63
119
|
nativeSessionId: input.receipt.nativeSessionId,
|
|
64
120
|
...(input.receipt.nativeTurnId === undefined ? {} : {
|
|
65
121
|
nativeTurnId: input.receipt.nativeTurnId
|
|
66
122
|
}),
|
|
67
123
|
// The structured Host owns the exact input attempt identity. Runtime
|
|
68
|
-
// descriptor receipts name the
|
|
69
|
-
// continuation or human-takeover
|
|
124
|
+
// descriptor receipts name the AgentRun bootstrap and must not overwrite a
|
|
125
|
+
// continuation or human-takeover AgentRun.
|
|
70
126
|
receiptId: input.receipt.attemptId
|
|
71
127
|
};
|
|
72
128
|
const baseSequence = nextStructuredSequence();
|
|
73
|
-
// Opening owns the Session
|
|
129
|
+
// Opening owns the Session lifecycle. A receipt arriving after
|
|
74
130
|
// its terminal must not reopen either lifecycle as an acceptance side effect.
|
|
75
131
|
const observations = [observation({
|
|
76
132
|
kind: "turn.accepted",
|
|
@@ -82,20 +138,62 @@ export async function publishStructuredProviderAccepted(input) {
|
|
|
82
138
|
})];
|
|
83
139
|
await persistAndApply(input.home, observations, fence.taskId, fence.roleName);
|
|
84
140
|
}
|
|
141
|
+
/** Steer settles an additional input, never the parent AgentRun's initial delivery. */
|
|
142
|
+
export async function publishStructuredProviderInputSettlement(input) {
|
|
143
|
+
const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
|
|
144
|
+
const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
|
|
145
|
+
const fence = resolveRuntimeHookRunFence(input.environment, adapterId, input.nativeSessionId, {
|
|
146
|
+
nativeTurnId: input.nativeTurnId,
|
|
147
|
+
terminal: true
|
|
148
|
+
});
|
|
149
|
+
if (fence.runId === undefined)
|
|
150
|
+
throw new Error("Steer settlement has no exact original AgentRun.");
|
|
151
|
+
const entry = observation({
|
|
152
|
+
kind: input.status === "accepted" ? "input.accepted"
|
|
153
|
+
: input.status === "rejected" ? "input.rejected" : "input.delivery-unknown",
|
|
154
|
+
observedAt: new Date().toISOString(),
|
|
155
|
+
sequence: nextStructuredSequence(),
|
|
156
|
+
ordinal: 0,
|
|
157
|
+
fence: {
|
|
158
|
+
taskId: fence.taskId,
|
|
159
|
+
roleName: fence.roleName,
|
|
160
|
+
runId: fence.runId,
|
|
161
|
+
agentId: fence.agentId,
|
|
162
|
+
driverId: driver.id,
|
|
163
|
+
conversationId: input.nativeSessionId,
|
|
164
|
+
nativeSessionId: input.nativeSessionId,
|
|
165
|
+
nativeTurnId: input.nativeTurnId,
|
|
166
|
+
receiptId: input.attemptId
|
|
167
|
+
},
|
|
168
|
+
payload: {
|
|
169
|
+
input: input.boundedText,
|
|
170
|
+
...(input.failure === undefined ? {} : {
|
|
171
|
+
failure: {
|
|
172
|
+
error: standardAgentError({
|
|
173
|
+
source: "host",
|
|
174
|
+
phase: "turn-submit",
|
|
175
|
+
message: input.failure.detail,
|
|
176
|
+
raw: input.failure.raw ?? input.failure.detail,
|
|
177
|
+
inputDisposition: input.status === "unknown" ? "unknown" : "not-accepted"
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
await persistAndApply(input.home, [entry], fence.taskId, fence.roleName);
|
|
184
|
+
}
|
|
85
185
|
export async function publishStructuredProviderOpened(input) {
|
|
86
186
|
const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
|
|
87
187
|
const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
|
|
88
188
|
const startupSession = driver.capabilities.observation.sessionBootstrap;
|
|
89
|
-
const fence =
|
|
189
|
+
const fence = resolveRuntimeHookRunFence(input.environment, adapterId, input.nativeSessionId, { startupSession });
|
|
90
190
|
const commonFence = {
|
|
91
191
|
taskId: fence.taskId,
|
|
92
192
|
roleName: fence.roleName,
|
|
93
|
-
...(fence.
|
|
193
|
+
...(fence.runId === undefined ? {} : { runId: fence.runId }),
|
|
94
194
|
agentId: fence.agentId,
|
|
95
195
|
driverId: driver.id,
|
|
96
|
-
runtimeGenerationId: fence.runtimeGenerationId,
|
|
97
196
|
conversationId: input.conversationId,
|
|
98
|
-
activationId: requireIdentity(input.activationId, "Provider Activation id"),
|
|
99
197
|
nativeSessionId: input.nativeSessionId,
|
|
100
198
|
...(fence.receiptId === undefined ? {} : { receiptId: fence.receiptId })
|
|
101
199
|
};
|
|
@@ -113,19 +211,13 @@ export async function publishStructuredProviderOpened(input) {
|
|
|
113
211
|
ordinal: 1,
|
|
114
212
|
fence: commonFence,
|
|
115
213
|
payload: { recoverability: input.recoverability }
|
|
116
|
-
}), observation({
|
|
117
|
-
kind: "activation.started",
|
|
118
|
-
observedAt: input.observedAt,
|
|
119
|
-
sequence,
|
|
120
|
-
ordinal: 2,
|
|
121
|
-
fence: commonFence
|
|
122
214
|
})];
|
|
123
215
|
await persistAndApply(input.home, observations, fence.taskId, fence.roleName);
|
|
124
216
|
}
|
|
125
217
|
export async function publishStructuredProviderGoal(input) {
|
|
126
218
|
const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
|
|
127
219
|
const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
|
|
128
|
-
const fence =
|
|
220
|
+
const fence = resolveRuntimeHookRunFence(input.environment, adapterId, input.conversationId, { sessionOnly: true });
|
|
129
221
|
const goal = input.goal;
|
|
130
222
|
const observedAt = input.observedAt ?? goal?.updatedAt ?? new Date().toISOString();
|
|
131
223
|
const goalObservation = observation({
|
|
@@ -138,9 +230,7 @@ export async function publishStructuredProviderGoal(input) {
|
|
|
138
230
|
roleName: fence.roleName,
|
|
139
231
|
agentId: fence.agentId,
|
|
140
232
|
driverId: driver.id,
|
|
141
|
-
runtimeGenerationId: fence.runtimeGenerationId,
|
|
142
233
|
conversationId: input.conversationId,
|
|
143
|
-
activationId: requireIdentity(input.activationId, "Provider Activation id"),
|
|
144
234
|
nativeSessionId: input.conversationId
|
|
145
235
|
},
|
|
146
236
|
payload: goal === null ? {} : {
|
|
@@ -156,27 +246,19 @@ export async function publishStructuredProviderGoal(input) {
|
|
|
156
246
|
export async function publishStructuredConversationRecoverability(input) {
|
|
157
247
|
const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
|
|
158
248
|
const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
|
|
159
|
-
const fence =
|
|
249
|
+
const fence = resolveRuntimeHookRunFence(input.environment, adapterId, input.conversationId, { sessionOnly: true });
|
|
160
250
|
const sequence = nextStructuredSequence();
|
|
161
251
|
const observationFence = {
|
|
162
252
|
taskId: fence.taskId,
|
|
163
253
|
roleName: fence.roleName,
|
|
164
|
-
...(fence.
|
|
254
|
+
...(fence.runId === undefined ? {} : { runId: fence.runId }),
|
|
165
255
|
agentId: fence.agentId,
|
|
166
256
|
driverId: driver.id,
|
|
167
|
-
runtimeGenerationId: fence.runtimeGenerationId,
|
|
168
257
|
conversationId: input.conversationId,
|
|
169
|
-
activationId: requireIdentity(input.activationId, "Provider Activation id"),
|
|
170
258
|
nativeSessionId: input.conversationId,
|
|
171
259
|
...(fence.receiptId === undefined ? {} : { receiptId: fence.receiptId })
|
|
172
260
|
};
|
|
173
261
|
const observations = [observation({
|
|
174
|
-
kind: "activation.started",
|
|
175
|
-
observedAt: input.observedAt,
|
|
176
|
-
sequence,
|
|
177
|
-
ordinal: 0,
|
|
178
|
-
fence: observationFence
|
|
179
|
-
}), observation({
|
|
180
262
|
kind: "conversation.observed",
|
|
181
263
|
observedAt: input.observedAt,
|
|
182
264
|
sequence,
|
|
@@ -184,22 +266,12 @@ export async function publishStructuredConversationRecoverability(input) {
|
|
|
184
266
|
fence: observationFence,
|
|
185
267
|
payload: { recoverability: input.recoverability }
|
|
186
268
|
})];
|
|
187
|
-
if (input.recoverability === "unrecoverable") {
|
|
188
|
-
observations.push(observation({
|
|
189
|
-
kind: "activation.failed",
|
|
190
|
-
observedAt: input.observedAt,
|
|
191
|
-
sequence,
|
|
192
|
-
ordinal: 2,
|
|
193
|
-
fence: observationFence,
|
|
194
|
-
payload: {}
|
|
195
|
-
}));
|
|
196
|
-
}
|
|
197
269
|
await persistAndApply(input.home, observations, fence.taskId, fence.roleName);
|
|
198
270
|
}
|
|
199
271
|
export async function publishStructuredProviderTerminal(input) {
|
|
200
272
|
const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
|
|
201
273
|
const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
|
|
202
|
-
const fence =
|
|
274
|
+
const fence = resolveRuntimeHookRunFence(input.environment, adapterId, input.terminal.nativeSessionId, {
|
|
203
275
|
terminal: true,
|
|
204
276
|
nativeTurnId: input.terminal.nativeTurnId,
|
|
205
277
|
attemptId: input.terminal.attemptId,
|
|
@@ -249,12 +321,10 @@ export async function publishStructuredProviderTerminal(input) {
|
|
|
249
321
|
fence: {
|
|
250
322
|
taskId: fence.taskId,
|
|
251
323
|
roleName: fence.roleName,
|
|
252
|
-
...(fence.
|
|
324
|
+
...(fence.runId === undefined ? {} : { runId: fence.runId }),
|
|
253
325
|
agentId: fence.agentId,
|
|
254
326
|
driverId: driver.id,
|
|
255
|
-
runtimeGenerationId: fence.runtimeGenerationId,
|
|
256
327
|
conversationId: input.terminal.conversationId,
|
|
257
|
-
activationId: executionActivationId(input.home, fence, input.activationId, input.terminal.nativeSessionId),
|
|
258
328
|
nativeSessionId: input.terminal.nativeSessionId,
|
|
259
329
|
...(input.terminal.nativeTurnId === undefined ? {} : {
|
|
260
330
|
nativeTurnId: input.terminal.nativeTurnId
|
|
@@ -263,35 +333,15 @@ export async function publishStructuredProviderTerminal(input) {
|
|
|
263
333
|
? fence.receiptId === undefined ? {} : { receiptId: fence.receiptId }
|
|
264
334
|
: { receiptId: input.terminal.attemptId })
|
|
265
335
|
},
|
|
266
|
-
payload
|
|
336
|
+
payload: {
|
|
337
|
+
...payload,
|
|
338
|
+
...(kind !== "turn.completed" && transported.status === "completed"
|
|
339
|
+
? { output: transported.output } : {}),
|
|
340
|
+
...(input.terminal.input === undefined ? {} : { input: input.terminal.input })
|
|
341
|
+
}
|
|
267
342
|
});
|
|
268
343
|
await persistAndApply(input.home, [terminalObservation], fence.taskId, fence.roleName);
|
|
269
344
|
}
|
|
270
|
-
export async function publishStructuredProviderActivationTerminal(input) {
|
|
271
|
-
const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
|
|
272
|
-
const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
|
|
273
|
-
const fence = resolveRuntimeHookTurnFence(input.environment, adapterId, input.nativeSessionId, { sessionOnly: true });
|
|
274
|
-
const terminal = observation({
|
|
275
|
-
kind: input.status === "failed" ? "activation.failed" : "activation.ended",
|
|
276
|
-
observedAt: input.observedAt,
|
|
277
|
-
sequence: nextStructuredSequence(),
|
|
278
|
-
ordinal: 0,
|
|
279
|
-
fence: {
|
|
280
|
-
taskId: fence.taskId,
|
|
281
|
-
roleName: fence.roleName,
|
|
282
|
-
...(fence.turnId === undefined ? {} : { turnId: fence.turnId }),
|
|
283
|
-
agentId: fence.agentId,
|
|
284
|
-
driverId: driver.id,
|
|
285
|
-
runtimeGenerationId: fence.runtimeGenerationId,
|
|
286
|
-
conversationId: requireIdentity(input.conversationId, "Provider Conversation id"),
|
|
287
|
-
activationId: requireIdentity(input.activationId, "Provider Activation id"),
|
|
288
|
-
nativeSessionId: requireIdentity(input.nativeSessionId, "native Session id"),
|
|
289
|
-
...(fence.receiptId === undefined ? {} : { receiptId: fence.receiptId })
|
|
290
|
-
},
|
|
291
|
-
payload: {}
|
|
292
|
-
});
|
|
293
|
-
await persistAndApply(input.home, [terminal], fence.taskId, fence.roleName);
|
|
294
|
-
}
|
|
295
345
|
function observation(input) {
|
|
296
346
|
const eventId = `agent-host-${randomUUID()}`;
|
|
297
347
|
const partial = {
|
|
@@ -330,24 +380,6 @@ function requireIdentity(value, label) {
|
|
|
330
380
|
}
|
|
331
381
|
return value.trim();
|
|
332
382
|
}
|
|
333
|
-
function executionActivationId(home, fence, sourceActivationId, nativeSessionId) {
|
|
334
|
-
const sourceId = requireIdentity(sourceActivationId, "Provider Activation id");
|
|
335
|
-
const store = openCurrentTaskStore(home);
|
|
336
|
-
try {
|
|
337
|
-
const binding = store.getTaskRoleSessionSet(fence.taskId, fence.roleName)?.providerBinding;
|
|
338
|
-
const source = binding?.activations.find(entry => entry.activationId === sourceId);
|
|
339
|
-
const original = binding?.activations.find(entry => entry.activationId === fence.runtimeGenerationId);
|
|
340
|
-
if (source?.conversationId !== nativeSessionId || original?.conversationId !== nativeSessionId) {
|
|
341
|
-
throw new Error("Structured execution observation source does not belong to its native Conversation.");
|
|
342
|
-
}
|
|
343
|
-
// A reattached collector can observe the old execution, but its current
|
|
344
|
-
// attachment must not replace that execution's durable Activation identity.
|
|
345
|
-
return original.activationId;
|
|
346
|
-
}
|
|
347
|
-
finally {
|
|
348
|
-
store.close();
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
383
|
async function persistAndApply(home, observations, taskId, roleName) {
|
|
352
384
|
const inbox = new FileRuntimeEventInbox(home);
|
|
353
385
|
for (const entry of observations)
|
|
@@ -362,17 +394,24 @@ async function persistAndApply(home, observations, taskId, roleName) {
|
|
|
362
394
|
let result;
|
|
363
395
|
try {
|
|
364
396
|
result = await callController(home, "runtime.observation-apply", entry, {
|
|
365
|
-
|
|
397
|
+
// This is only an eager application hint after durable enqueue, not
|
|
398
|
+
// native admission. Bound it like the wake signal so a frozen
|
|
399
|
+
// Controller cannot serialize ten seconds of delay per tool event.
|
|
400
|
+
timeoutMs: 100
|
|
366
401
|
});
|
|
367
402
|
}
|
|
368
403
|
catch (error) {
|
|
369
|
-
//
|
|
370
|
-
//
|
|
371
|
-
|
|
404
|
+
// Persistence already succeeded. A stopped, frozen or reconnecting
|
|
405
|
+
// Controller only delays applying this exact observation; it does not
|
|
406
|
+
// fail the native execution or poison its reusable Host.
|
|
407
|
+
if (isForeignHandoverLockHeld(home)
|
|
408
|
+
|| (error instanceof ControllerClientError
|
|
409
|
+
&& ["CONTROLLER_NOT_RUNNING", "CONTROLLER_UNAVAILABLE", "CONTROLLER_TIMEOUT",
|
|
410
|
+
"CONTROLLER_DELIVERY_UNKNOWN"].includes(error.code)))
|
|
372
411
|
return;
|
|
373
412
|
throw error;
|
|
374
413
|
}
|
|
375
|
-
// A fast Provider can accept the initial
|
|
414
|
+
// A fast Provider can accept the initial AgentRun before the scheduler call
|
|
376
415
|
// that launched this Host has returned and committed `turn.pushed`. The
|
|
377
416
|
// immutable inbox entry already makes that exact fenced fact durable;
|
|
378
417
|
// `deferred` therefore means "retained for replay", not delivery failure.
|
|
@@ -315,7 +315,7 @@ function parseTarget(value) {
|
|
|
315
315
|
function parseRef(value, label) {
|
|
316
316
|
const ref = record(value, label);
|
|
317
317
|
const types = [
|
|
318
|
-
"task", "
|
|
318
|
+
"task", "run", "work-item", "input", "session", "message", "event"
|
|
319
319
|
];
|
|
320
320
|
if (!types.includes(ref.type))
|
|
321
321
|
throw new Error(`${label} type is invalid`);
|
|
@@ -358,7 +358,7 @@ function copyTarget(target) {
|
|
|
358
358
|
};
|
|
359
359
|
}
|
|
360
360
|
}
|
|
361
|
-
function copyRef(ref) {
|
|
361
|
+
export function copyRef(ref) {
|
|
362
362
|
if (!("taskId" in ref)) {
|
|
363
363
|
if (ref.type !== "task" && ref.type !== "session") {
|
|
364
364
|
throw new Error(`entity reference taskId is required for ${ref.type}`);
|
|
@@ -373,7 +373,7 @@ function copyRef(ref) {
|
|
|
373
373
|
}
|
|
374
374
|
function mailboxTaskRecordKind(type) {
|
|
375
375
|
switch (type) {
|
|
376
|
-
case "
|
|
376
|
+
case "run": return "run";
|
|
377
377
|
case "work-item": return "workItem";
|
|
378
378
|
case "input": return "inputRequest";
|
|
379
379
|
case "message": return "message";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { completeProcessing, consumePendingBatch, createWorkMailbox, enqueueSignal, mailboxBatches, mailboxEntityRefKey } from "./workMailbox.js";
|
|
2
|
-
const
|
|
2
|
+
const LEGACY_ROLE_RUN_DISPATCH_REASONS = new Set([
|
|
3
3
|
"turn-dispatched",
|
|
4
4
|
"turn-retried",
|
|
5
5
|
"review-requested",
|
|
@@ -19,34 +19,33 @@ export function enqueueWork(store, target, reason, occurredAt, refs = [], metada
|
|
|
19
19
|
return queued;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
|
-
* The sole ordinary Role
|
|
23
|
-
* authority; this signal only asks the Controller to deliver that exact
|
|
22
|
+
* The sole ordinary Role AgentRun wake shape. The AgentRun is durable execution
|
|
23
|
+
* authority; this signal only asks the Controller to deliver that exact AgentRun.
|
|
24
24
|
* Leader is deliberately excluded because its Role mailbox is reserved for
|
|
25
|
-
* semantic event wakes and force-steer batches. A Leader active
|
|
25
|
+
* semantic event wakes and force-steer batches. A Leader active AgentRun is
|
|
26
26
|
* selected directly from durable state by its targeted Controller pass.
|
|
27
27
|
*/
|
|
28
|
-
export function
|
|
28
|
+
export function enqueueRoleRunDispatch(store, input) {
|
|
29
29
|
if (input.roleName === "leader")
|
|
30
30
|
return null;
|
|
31
|
-
return enqueueWork(store,
|
|
31
|
+
return enqueueWork(store, roleRunTarget(input), input.reason, input.occurredAt, [roleRunRef(input)], {
|
|
32
32
|
source: "turn-dispatch",
|
|
33
|
-
dedupeKey:
|
|
33
|
+
dedupeKey: roleRunDispatchDedupeKey(input)
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
|
-
* Captures only the mailbox prefix that contains one exact Role
|
|
37
|
+
* Captures only the mailbox prefix that contains one exact Role AgentRun dispatch.
|
|
38
38
|
* A later signal may append while Provider delivery is in flight; its suffix
|
|
39
39
|
* remains pending when this token is settled.
|
|
40
40
|
*/
|
|
41
|
-
export function
|
|
42
|
-
if (
|
|
43
|
-
|| mailbox === null
|
|
41
|
+
export function captureRoleRunDispatch(mailbox, input) {
|
|
42
|
+
if (mailbox === null
|
|
44
43
|
|| mailbox.target.kind !== "role"
|
|
45
44
|
|| mailbox.target.taskId !== input.taskId
|
|
46
45
|
|| mailbox.target.roleName !== input.roleName) {
|
|
47
46
|
return null;
|
|
48
47
|
}
|
|
49
|
-
const exactRef =
|
|
48
|
+
const exactRef = roleRunRef(input);
|
|
50
49
|
if (mailbox.processing?.executionRef !== undefined
|
|
51
50
|
&& mailboxEntityRefKey(mailbox.processing.executionRef) === mailboxEntityRefKey(exactRef)) {
|
|
52
51
|
return {
|
|
@@ -54,30 +53,34 @@ export function captureRoleTurnDispatch(mailbox, input) {
|
|
|
54
53
|
batchId: mailbox.processing.batchId
|
|
55
54
|
};
|
|
56
55
|
}
|
|
56
|
+
// A Leader's initial planning batch may be explicitly bound to its Run.
|
|
57
|
+
// Never infer a Leader dispatch from pending semantic notifications.
|
|
58
|
+
if (input.roleName === "leader")
|
|
59
|
+
return null;
|
|
57
60
|
const pending = mailbox.pending;
|
|
58
61
|
if (pending === null)
|
|
59
62
|
return null;
|
|
60
|
-
const dedupeKey =
|
|
63
|
+
const dedupeKey = roleRunDispatchDedupeKey(input);
|
|
61
64
|
if (mailbox.recentDedupeKeys.includes(dedupeKey))
|
|
62
65
|
return null;
|
|
63
66
|
const keyIndex = pending.dedupeKeys.indexOf(dedupeKey);
|
|
64
67
|
if (keyIndex >= 0 && pending.dedupeKeys.length === pending.requestCount) {
|
|
65
|
-
const
|
|
66
|
-
if (
|
|
68
|
+
const runSequence = pending.fromSequence + keyIndex;
|
|
69
|
+
if (runSequence <= pending.toSequence) {
|
|
67
70
|
return {
|
|
68
71
|
kind: "pending",
|
|
69
72
|
fromSequence: pending.fromSequence,
|
|
70
|
-
toSequence:
|
|
73
|
+
toSequence: runSequence
|
|
71
74
|
};
|
|
72
75
|
}
|
|
73
76
|
}
|
|
74
77
|
// Valid earlier dispatches used sequence-generated dedupe keys and could
|
|
75
78
|
// include a companion WorkItem ref. Consume that complete legacy batch once
|
|
76
|
-
// the exact
|
|
79
|
+
// the exact AgentRun reaches an accepted or terminal boundary.
|
|
77
80
|
if (pending.requestCount === 1
|
|
78
81
|
&& pending.sources.length === 1
|
|
79
82
|
&& pending.sources[0] === "yui"
|
|
80
|
-
&& pending.reasons.some((reason) =>
|
|
83
|
+
&& pending.reasons.some((reason) => LEGACY_ROLE_RUN_DISPATCH_REASONS.has(reason))
|
|
81
84
|
&& pending.refs.some((ref) => (mailboxEntityRefKey(ref) === mailboxEntityRefKey(exactRef)))) {
|
|
82
85
|
return {
|
|
83
86
|
kind: "pending",
|
|
@@ -88,19 +91,19 @@ export function captureRoleTurnDispatch(mailbox, input) {
|
|
|
88
91
|
return null;
|
|
89
92
|
}
|
|
90
93
|
/**
|
|
91
|
-
* Settles one exact ordinary Role
|
|
94
|
+
* Settles one exact ordinary Role AgentRun dispatch. Provider acceptance is the
|
|
92
95
|
* normal boundary; terminalization calls the same operation for conclusively
|
|
93
96
|
* unaccepted and valid earlier dispatches.
|
|
94
97
|
*/
|
|
95
|
-
export function
|
|
98
|
+
export function settleRoleRunDispatch(store, input, expected) {
|
|
96
99
|
if (expected === null)
|
|
97
100
|
return "absent";
|
|
98
|
-
const target =
|
|
101
|
+
const target = roleRunTarget(input);
|
|
99
102
|
const mailbox = store.getWorkMailbox(target);
|
|
100
|
-
const current =
|
|
103
|
+
const current = captureRoleRunDispatch(mailbox, input);
|
|
101
104
|
if (current === null || mailbox === null)
|
|
102
105
|
return "absent";
|
|
103
|
-
if (expected !== undefined && !
|
|
106
|
+
if (expected !== undefined && !sameRoleRunDispatchToken(current, expected)) {
|
|
104
107
|
return "state-changed";
|
|
105
108
|
}
|
|
106
109
|
const token = expected ?? current;
|
|
@@ -135,9 +138,9 @@ export function completeWorkExecution(store, target, executionRef) {
|
|
|
135
138
|
/**
|
|
136
139
|
* Completes a mailbox execution or fails the surrounding transaction.
|
|
137
140
|
*
|
|
138
|
-
* A terminal
|
|
141
|
+
* A terminal AgentRun and its processing mailbox batch are one consistency
|
|
139
142
|
* boundary. Silently accepting a missing or mismatched batch would leave
|
|
140
|
-
* durable work stuck in `processing` after the
|
|
143
|
+
* durable work stuck in `processing` after the AgentRun has already ended.
|
|
141
144
|
*/
|
|
142
145
|
export function requireCompleteWorkExecution(store, target, executionRef) {
|
|
143
146
|
const mailbox = store.getWorkMailbox(target);
|
|
@@ -156,7 +159,7 @@ export function requireCompleteWorkExecution(store, target, executionRef) {
|
|
|
156
159
|
+ `${executionRef.type}/${executionRef.id}.`);
|
|
157
160
|
}
|
|
158
161
|
/**
|
|
159
|
-
* Settles the exact
|
|
162
|
+
* Settles the exact AgentRun delivery boundary, including the short window before
|
|
160
163
|
* the scheduler has claimed its single pending dispatch. A merged pending
|
|
161
164
|
* batch is never discarded because its signal-to-ref mapping is no longer
|
|
162
165
|
* recoverable.
|
|
@@ -183,24 +186,24 @@ export function settleExactWorkExecution(store, target, executionRef) {
|
|
|
183
186
|
function timestamp(value) {
|
|
184
187
|
return value instanceof Date ? value.toISOString() : value;
|
|
185
188
|
}
|
|
186
|
-
function
|
|
189
|
+
function roleRunTarget(input) {
|
|
187
190
|
return {
|
|
188
191
|
kind: "role",
|
|
189
192
|
taskId: input.taskId,
|
|
190
193
|
roleName: input.roleName
|
|
191
194
|
};
|
|
192
195
|
}
|
|
193
|
-
function
|
|
196
|
+
function roleRunRef(input) {
|
|
194
197
|
return {
|
|
195
|
-
type: "
|
|
198
|
+
type: "run",
|
|
196
199
|
taskId: input.taskId,
|
|
197
|
-
id: input.
|
|
200
|
+
id: input.runId
|
|
198
201
|
};
|
|
199
202
|
}
|
|
200
|
-
function
|
|
201
|
-
return `role-turn:${input.taskId}:${input.roleName}:${input.
|
|
203
|
+
function roleRunDispatchDedupeKey(input) {
|
|
204
|
+
return `role-turn:${input.taskId}:${input.roleName}:${input.runId}`;
|
|
202
205
|
}
|
|
203
|
-
function
|
|
206
|
+
function sameRoleRunDispatchToken(left, right) {
|
|
204
207
|
return left.kind === right.kind
|
|
205
208
|
&& (left.kind === "pending"
|
|
206
209
|
? right.kind === "pending"
|
package/dist/core/boundedRpc.js
CHANGED
|
@@ -145,10 +145,15 @@ export class BoundedRpcClient {
|
|
|
145
145
|
}
|
|
146
146
|
#newReadyPromise() {
|
|
147
147
|
this.#readyFired = false;
|
|
148
|
-
|
|
148
|
+
const ready = new Promise((resolve, reject) => {
|
|
149
149
|
this.#readyResolve = resolve;
|
|
150
150
|
this.#readyReject = reject;
|
|
151
151
|
});
|
|
152
|
+
// Closing during startup is legal even if no request has awaited ready.
|
|
153
|
+
// Observe that rejection without replacing the original promise: send()
|
|
154
|
+
// still receives the failure instead of an invented ready worker.
|
|
155
|
+
void ready.catch(() => undefined);
|
|
156
|
+
return ready;
|
|
152
157
|
}
|
|
153
158
|
#workerUrl() {
|
|
154
159
|
return this.#workerScript instanceof URL
|
|
@@ -219,6 +224,8 @@ export class BoundedRpcClient {
|
|
|
219
224
|
}
|
|
220
225
|
// Brief backoff to avoid a hot crash loop.
|
|
221
226
|
await new Promise((resolve) => setTimeout(resolve, this.#restartBackoffMs));
|
|
227
|
+
if (this.#closed)
|
|
228
|
+
return;
|
|
222
229
|
this.#generation += 1;
|
|
223
230
|
this.#port?.close();
|
|
224
231
|
this.#ready = this.#newReadyPromise();
|
|
@@ -102,7 +102,7 @@ export async function callController(home, method, params = {}, options = {}) {
|
|
|
102
102
|
* Home identity, PID, and process-start identity; an unprovable process is
|
|
103
103
|
* never touched.
|
|
104
104
|
*/
|
|
105
|
-
export async function stopOrphanedFileTaskController(home, timeoutMs) {
|
|
105
|
+
export async function stopOrphanedFileTaskController(home, timeoutMs, options = {}) {
|
|
106
106
|
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1) {
|
|
107
107
|
throw new TypeError("Controller timeout must be a positive integer.");
|
|
108
108
|
}
|
|
@@ -110,6 +110,11 @@ export async function stopOrphanedFileTaskController(home, timeoutMs) {
|
|
|
110
110
|
const candidate = findLiveControllerProcessForHome(homeFilesystemId);
|
|
111
111
|
if (candidate === undefined)
|
|
112
112
|
return undefined;
|
|
113
|
+
if ((options.expectedPid !== undefined && candidate.pid !== options.expectedPid)
|
|
114
|
+
|| (options.expectedProcessStartIdentity !== undefined
|
|
115
|
+
&& candidate.processStartIdentity !== options.expectedProcessStartIdentity)) {
|
|
116
|
+
throw new Error("Controller ownership changed before physical recovery.");
|
|
117
|
+
}
|
|
113
118
|
if (inspectLiveControllerProcess(candidate.pid, homeFilesystemId, candidate.processStartIdentity) === undefined)
|
|
114
119
|
return undefined;
|
|
115
120
|
try {
|
|
@@ -121,7 +126,21 @@ export async function stopOrphanedFileTaskController(home, timeoutMs) {
|
|
|
121
126
|
throw error;
|
|
122
127
|
}
|
|
123
128
|
const deadline = Date.now() + timeoutMs;
|
|
129
|
+
const forceAt = Date.now() + Math.min(1000, timeoutMs / 2);
|
|
130
|
+
let forced = false;
|
|
124
131
|
while (inspectLiveControllerProcess(candidate.pid, homeFilesystemId, candidate.processStartIdentity) !== undefined) {
|
|
132
|
+
if (options.force && !forced && Date.now() >= forceAt) {
|
|
133
|
+
// The loop revalidates UID, entrypoint, Home and process start identity
|
|
134
|
+
// immediately before escalation. Never signal a successor Controller.
|
|
135
|
+
try {
|
|
136
|
+
process.kill(candidate.pid, "SIGKILL");
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
if (!isNodeError(error) || error.code !== "ESRCH")
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
forced = true;
|
|
143
|
+
}
|
|
125
144
|
if (Date.now() >= deadline) {
|
|
126
145
|
throw new ControllerClientError("CONTROLLER_TIMEOUT", `Orphaned Controller did not stop within ${timeoutMs} ms.`);
|
|
127
146
|
}
|