@zq-silk/yui 0.14.0 → 0.14.2
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 +64 -35
- package/README.md +258 -125
- package/dist/agent/argumentPolicy.js +2 -1
- package/dist/agent/managedRuntimeEnvironment.js +5 -8
- package/dist/cli/commandCatalog.js +74 -109
- package/dist/cli/helpRenderer.js +1 -2
- package/dist/cli/interactionCandidates.js +10 -0
- package/dist/cli/interactionPolicy.js +76 -37
- package/dist/cli/roleWizard.js +5 -6
- package/dist/cli/updateOrchestrator.js +10 -8
- package/dist/cli/updatePorts.js +17 -13
- package/dist/cli/upgradeCommand.js +2 -5
- package/dist/cli.js +268 -231
- package/dist/commands/agentCommands.js +13 -0
- package/dist/commands/configCommands.js +7 -19
- package/dist/commands/configOverview.js +3 -2
- package/dist/commands/durableJobCommands.js +1 -1
- package/dist/commands/executionAuditCommands.js +4 -9
- package/dist/commands/globalRoleCommands.js +17 -0
- package/dist/commands/profileCommands.js +200 -30
- package/dist/commands/sessionCommands.js +1 -1
- package/dist/commands/taskActor.js +29 -127
- package/dist/commands/taskChangeSetCommands.js +1 -3
- package/dist/commands/taskCommands.js +1771 -2107
- package/dist/commands/taskCompletionGate.js +27 -103
- package/dist/commands/taskContextCommand.js +47 -80
- package/dist/commands/taskExecutionCommands.js +9 -27
- package/dist/commands/taskInputCommands.js +10 -10
- package/dist/commands/taskIntegrationCommands.js +69 -61
- package/dist/commands/taskIntegrationQueueCommands.js +1 -1
- package/dist/commands/taskNextActionCommand.js +8 -29
- package/dist/commands/taskOverviewCommand.js +25 -3
- package/dist/commands/taskPublicationCommands.js +151 -85
- package/dist/commands/taskPublicationVerifyCommand.js +181 -0
- package/dist/commands/taskRemoteDeliveryCommand.js +134 -0
- package/dist/commands/taskRoleRuntimeStatus.js +5 -6
- package/dist/commands/taskUpstreamCommands.js +79 -95
- package/dist/config/configCatalog.js +1 -1
- package/dist/context/contextSnapshot.js +17 -2
- package/dist/context/sessionBootstrapManifest.js +18 -1
- package/dist/context/sourceTurnContext.js +30 -0
- package/dist/context/turnContextPack.js +107 -48
- package/dist/context/turnInputContract.js +11 -4
- package/dist/context/wakeNotification.js +84 -22
- package/dist/controller/agentRuntimeObserver.js +9 -12
- package/dist/controller/clientRuntime.js +13 -13
- package/dist/controller/controller.js +11 -11
- package/dist/controller/fileSchedulerStoreAdapter.js +262 -219
- package/dist/controller/jobControl.js +11 -10
- package/dist/controller/resourceInventory.js +6 -6
- package/dist/controller/resourceInventoryLinux.js +2 -2
- package/dist/controller/runtime.js +18 -61
- package/dist/controller/runtimeEventInbox.js +57 -34
- package/dist/controller/runtimeEventProcessor.js +36 -96
- package/dist/controller/runtimeHookTurnFence.js +33 -57
- package/dist/controller/runtimeLaunchCoordinator.js +44 -40
- package/dist/controller/runtimeObservationHook.js +18 -12
- package/dist/controller/sessionNotify.js +43 -28
- package/dist/controller/sessionOwnerReconciliation.js +21 -21
- package/dist/controller/structuredProviderObservation.js +13 -16
- package/dist/coordination/workMailboxQueue.js +132 -0
- package/dist/core/controllerServer.js +1 -0
- package/dist/domain/agentResultTransport.js +60 -0
- package/dist/execution/executionHealth.js +111 -118
- package/dist/execution/reviewMainTurn.js +161 -0
- package/dist/execution/workItemExecution.js +454 -0
- package/dist/execution/workItemExecutionProjection.js +309 -0
- package/dist/execution/workItemMainTurn.js +164 -0
- package/dist/executor/agentExecutor.js +19 -19
- package/dist/executor/executorRegistry.js +7 -28
- package/dist/executor/fileRoleLaunchPlanner.js +51 -83
- package/dist/external/githubPublicationVerifier.js +114 -0
- package/dist/external/gitlabPublicationVerifier.js +158 -0
- package/dist/external/pinnedCommandRunner.js +73 -0
- package/dist/integration/changeSetManifest.js +0 -3
- package/dist/integration/deliveryObligation.js +43 -6
- package/dist/integration/gitIntegrationService.js +284 -101
- package/dist/integration/integrationAttempt.js +64 -14
- package/dist/integration/integrationQueueEntry.js +5 -35
- package/dist/integration/integrationQueueService.js +65 -194
- package/dist/lifecycle/canonicalLifecycleEvent.js +16 -15
- package/dist/lifecycle/exactTurnTerminalization.js +100 -97
- package/dist/message/message.js +16 -0
- package/dist/observability/executionAudit.js +4 -25
- package/dist/observability/faultClassification.js +58 -70
- package/dist/observability/orchestrationMetrics.js +8 -50
- package/dist/profile/agentProfile.js +60 -15
- package/dist/profile/agentProfileRuntime.js +100 -0
- package/dist/release/releaseWorkflowPorts.js +5 -68
- package/dist/repository/executionLaneGitSnapshot.js +80 -0
- package/dist/repository/gitWorkspace.js +9 -67
- package/dist/repository/taskBaseFreshness.js +3 -1
- package/dist/repository/taskWorkspaceCoordinator.js +32 -4
- package/dist/repository/taskWorkspacePreparer.js +252 -411
- package/dist/resources/liveReferences.js +6 -55
- package/dist/resources/resourceDiscovery.js +1 -30
- package/dist/resources/resourceRegistrar.js +0 -23
- package/dist/review/deltaRecheck.js +8 -65
- package/dist/review/reviewAcceptance.js +22 -19
- package/dist/review/reviewConfig.js +0 -10
- package/dist/review/reviewDecision.js +2 -2
- package/dist/review/reviewRound.js +147 -273
- package/dist/review/reviewerAvailability.js +13 -23
- package/dist/role/role.js +3 -0
- package/dist/runtime/agentDriverObservation.js +1 -1
- package/dist/runtime/agentHost.js +51 -51
- package/dist/runtime/builtinAgentDrivers.js +9 -2
- package/dist/runtime/codexAppServerRuntime.js +23 -5
- package/dist/runtime/exactControlPlane.js +2 -267
- package/dist/runtime/firstProgressAdvisory.js +1 -1
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/launchBroker.js +11 -11
- package/dist/runtime/lifecycleReservation.js +2 -2
- package/dist/runtime/managedCaller.js +111 -0
- package/dist/runtime/ports.js +16 -3
- package/dist/runtime/preallocatedNativeSession.js +2 -2
- package/dist/runtime/processExitObservation.js +3 -2
- package/dist/runtime/providerContinuationReconciliationService.js +1 -1
- package/dist/runtime/runtimeBinding.js +1 -1
- package/dist/runtime/runtimeObservation.js +33 -16
- package/dist/runtime/runtimeSessionCandidate.js +2 -2
- package/dist/runtime/runtimeStopReceipt.js +11 -11
- package/dist/runtime/sessionLaunchRequest.js +2 -2
- package/dist/runtime/sessionOwnerIdentity.js +9 -9
- package/dist/runtime/sessionOwnerRegistry.js +13 -13
- package/dist/runtime/sessionReconciliation.js +4 -4
- package/dist/runtime/sessionTerminationGuard.js +9 -9
- package/dist/runtime/sessionTokenMetrics.js +5 -7
- package/dist/runtime/structuredProviderHost.js +5 -5
- package/dist/runtime/taskRuntimeIsolation.js +24 -24
- package/dist/runtime/tmuxAdapters.js +32 -30
- package/dist/scheduler/activeRoleTurnDelivery.js +37 -15
- package/dist/scheduler/leaderWakeupProcessor.js +78 -55
- package/dist/scheduler/roleTurnLiveness.js +6 -6
- package/dist/scheduler/roleTurnStall.js +8 -9
- package/dist/scheduler/taskExecutionProjection.js +19 -41
- package/dist/scheduler/taskObservabilityProjection.js +75 -122
- package/dist/storage/sqliteSchema.js +1 -21
- package/dist/storage/sqliteStore.js +62 -47
- package/dist/storage/storageSchema.js +1 -8
- package/dist/storage/storageVersions.js +7 -4
- package/dist/storage/taskStore.js +8 -8
- package/dist/storage/upgrade/upgradeOrchestrator.js +112 -83
- package/dist/task/completionReadiness.js +17 -98
- package/dist/task/deliveryGuard.js +9 -11
- package/dist/task/draftPlan.js +142 -0
- package/dist/task/nextAction.js +179 -477
- package/dist/task/publicationVerification.js +1 -0
- package/dist/task/remoteDelivery.js +233 -0
- package/dist/task/task.js +108 -4
- package/dist/task/taskRecordReference.js +0 -1
- package/dist/turn/turn.js +109 -16
- package/dist/verification/verificationGateService.js +0 -26
- package/dist/web/assets/client/components.js +99 -121
- package/dist/web/assets/client/i18n.js +136 -58
- package/dist/web/assets/client/view.js +44 -0
- package/dist/web/assets/styles/cards.js +3 -15
- package/dist/web/assets/styles/widgets.js +4 -0
- package/dist/web/webSnapshot.js +29 -14
- package/dist/workItem/dependencyGate.js +34 -0
- package/dist/workItem/workItem.js +99 -266
- package/dist/workspace/workItemChangeSetManager.js +15 -59
- package/docs/task-local-identity.md +1 -1
- package/i18n/README.zh-CN.md +165 -59
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +272 -782
- package/skills/yui-operator/SKILL.md +190 -365
- package/skills/yui-reviewer/SKILL.md +40 -33
- package/skills/yui-runtime/SKILL.md +27 -6
- package/skills/yui-worker/SKILL.md +19 -6
- package/dist/execution/candidateConvergence.js +0 -623
- package/dist/execution/executionGroup.js +0 -854
- package/dist/execution/resourceBroker.js +0 -426
- package/dist/executor/launchPlan.js +0 -16
- package/dist/review/reviewFinding.js +0 -240
- package/dist/review/reviewFindingLedger.js +0 -550
- package/dist/review/reviewOutcomeClassifier.js +0 -255
- package/dist/scheduler/resourceQueueProjection.js +0 -71
- package/dist/task/repairWave.js +0 -150
|
@@ -239,7 +239,7 @@ function assertCallerAuthorized(store, caller, taskId) {
|
|
|
239
239
|
|| binding === undefined
|
|
240
240
|
|| agentId === undefined
|
|
241
241
|
|| caller.adapterId === undefined
|
|
242
|
-
|| caller.
|
|
242
|
+
|| caller.runtimeGenerationId === undefined
|
|
243
243
|
|| sessions === null
|
|
244
244
|
|| sessions.activeAgentId !== role.activeAgentId
|
|
245
245
|
|| session === null
|
|
@@ -247,7 +247,7 @@ function assertCallerAuthorized(store, caller, taskId) {
|
|
|
247
247
|
|| binding.adapterId !== caller.adapterId
|
|
248
248
|
|| session.agentId !== agentId
|
|
249
249
|
|| session.adapterId !== caller.adapterId
|
|
250
|
-
|| session.
|
|
250
|
+
|| session.runtimeGenerationId !== caller.runtimeGenerationId
|
|
251
251
|
|| (caller.nativeSessionId !== undefined
|
|
252
252
|
&& session.nativeSessionId !== caller.nativeSessionId)) {
|
|
253
253
|
throw jobControlError("UNAUTHORIZED", "DurableJob control requires the current managed global Agent Session.");
|
|
@@ -257,11 +257,12 @@ function assertCallerAuthorized(store, caller, taskId) {
|
|
|
257
257
|
if (caller.taskId !== taskId) {
|
|
258
258
|
throw jobControlError("UNAUTHORIZED", "A managed Task Session may not start or cancel Jobs for a different Task.");
|
|
259
259
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
260
|
+
// The Turn is resolved from durable state rather than presented by the
|
|
261
|
+
// caller: a long-lived Session process cannot hold a current Turn in its
|
|
262
|
+
// frozen environment, and its own claim would add nothing the store does
|
|
263
|
+
// not already own.
|
|
264
|
+
const run = caller.role === undefined ? null : store.getActiveTurn(taskId, caller.role);
|
|
265
|
+
if (run === null || run.status !== "active") {
|
|
265
266
|
throw jobControlError("UNAUTHORIZED", "A managed Task Session's Role is not bound to an active Turn.");
|
|
266
267
|
}
|
|
267
268
|
// rr13: Verify the non-replayable per-Session caller key. The key is injected
|
|
@@ -489,7 +490,7 @@ function parseCaller(value) {
|
|
|
489
490
|
}
|
|
490
491
|
const record = value;
|
|
491
492
|
const allowed = new Set([
|
|
492
|
-
"scope", "taskId", "role", "agentId", "adapterId", "
|
|
493
|
+
"scope", "taskId", "role", "agentId", "adapterId", "runtimeGenerationId", "nativeSessionId",
|
|
493
494
|
"turnId", "callerKey"
|
|
494
495
|
]);
|
|
495
496
|
for (const key of Object.keys(record)) {
|
|
@@ -510,7 +511,7 @@ function parseCaller(value) {
|
|
|
510
511
|
const role = optionalId("role");
|
|
511
512
|
const agentId = optionalId("agentId");
|
|
512
513
|
const adapterId = optionalId("adapterId");
|
|
513
|
-
const
|
|
514
|
+
const runtimeGenerationId = optionalId("runtimeGenerationId");
|
|
514
515
|
const nativeSessionId = optionalId("nativeSessionId");
|
|
515
516
|
const turnId = optionalId("turnId");
|
|
516
517
|
const callerKey = record.callerKey === undefined
|
|
@@ -522,7 +523,7 @@ function parseCaller(value) {
|
|
|
522
523
|
...(role === undefined ? {} : { role }),
|
|
523
524
|
...(agentId === undefined ? {} : { agentId }),
|
|
524
525
|
...(adapterId === undefined ? {} : { adapterId }),
|
|
525
|
-
...(
|
|
526
|
+
...(runtimeGenerationId === undefined ? {} : { runtimeGenerationId }),
|
|
526
527
|
...(nativeSessionId === undefined ? {} : { nativeSessionId }),
|
|
527
528
|
...(turnId === undefined ? {} : { turnId }),
|
|
528
529
|
...(callerKey === undefined ? {} : { callerKey })
|
|
@@ -36,7 +36,7 @@ export function createRuntimeResourceActivityTracker() {
|
|
|
36
36
|
identity.agentId,
|
|
37
37
|
identity.adapterId,
|
|
38
38
|
identity.nativeSessionId ?? null,
|
|
39
|
-
identity.
|
|
39
|
+
identity.runtimeGenerationId ?? null
|
|
40
40
|
]);
|
|
41
41
|
const current = {
|
|
42
42
|
identity: identityKey,
|
|
@@ -261,7 +261,7 @@ function roleOwner(role) {
|
|
|
261
261
|
agentId: role.agentId,
|
|
262
262
|
...(role.adapterId === undefined ? {} : { adapterId: role.adapterId }),
|
|
263
263
|
...(role.nativeSessionId === undefined ? {} : { nativeSessionId: role.nativeSessionId }),
|
|
264
|
-
...(role.
|
|
264
|
+
...(role.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: role.runtimeGenerationId }),
|
|
265
265
|
...(role.turnId === undefined ? {} : { turnId: role.turnId })
|
|
266
266
|
};
|
|
267
267
|
}
|
|
@@ -274,7 +274,7 @@ function roleOwner(role) {
|
|
|
274
274
|
agentId: role.agentId,
|
|
275
275
|
...(role.adapterId === undefined ? {} : { adapterId: role.adapterId }),
|
|
276
276
|
...(role.nativeSessionId === undefined ? {} : { nativeSessionId: role.nativeSessionId }),
|
|
277
|
-
...(role.
|
|
277
|
+
...(role.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: role.runtimeGenerationId }),
|
|
278
278
|
...(role.turnId === undefined ? {} : { turnId: role.turnId })
|
|
279
279
|
};
|
|
280
280
|
}
|
|
@@ -444,7 +444,7 @@ function matchesResourceIdentity(identity, owner) {
|
|
|
444
444
|
|| typeof identity.adapterId !== "string"
|
|
445
445
|
|| identity.adapterId.length === 0
|
|
446
446
|
|| (identity.nativeSessionId !== undefined && !hasIdentityText(identity.nativeSessionId))
|
|
447
|
-
|| (identity.
|
|
447
|
+
|| (identity.runtimeGenerationId !== undefined && !hasIdentityText(identity.runtimeGenerationId)))
|
|
448
448
|
return false;
|
|
449
449
|
if (owner.kind !== "task-role"
|
|
450
450
|
|| owner.taskId !== identity.taskId
|
|
@@ -453,12 +453,12 @@ function matchesResourceIdentity(identity, owner) {
|
|
|
453
453
|
|| owner.agentId !== identity.agentId
|
|
454
454
|
|| owner.adapterId !== identity.adapterId)
|
|
455
455
|
return false;
|
|
456
|
-
if (!hasIdentityText(identity.nativeSessionId) && !hasIdentityText(identity.
|
|
456
|
+
if (!hasIdentityText(identity.nativeSessionId) && !hasIdentityText(identity.runtimeGenerationId))
|
|
457
457
|
return false;
|
|
458
458
|
if (identity.nativeSessionId !== undefined
|
|
459
459
|
&& owner.nativeSessionId !== identity.nativeSessionId)
|
|
460
460
|
return false;
|
|
461
|
-
if (identity.
|
|
461
|
+
if (identity.runtimeGenerationId !== undefined && owner.runtimeGenerationId !== identity.runtimeGenerationId)
|
|
462
462
|
return false;
|
|
463
463
|
return true;
|
|
464
464
|
}
|
|
@@ -634,7 +634,7 @@ function loadHomeState(home, warnings, options) {
|
|
|
634
634
|
agentId,
|
|
635
635
|
...(adapterId === undefined ? {} : { adapterId }),
|
|
636
636
|
...(session === null ? {} : { nativeSessionId: session.nativeSessionId }),
|
|
637
|
-
...(session?.
|
|
637
|
+
...(session?.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: session.runtimeGenerationId })
|
|
638
638
|
};
|
|
639
639
|
});
|
|
640
640
|
const appendTaskRole = (task, role) => {
|
|
@@ -652,7 +652,7 @@ function loadHomeState(home, warnings, options) {
|
|
|
652
652
|
agentId,
|
|
653
653
|
...(adapterId === undefined ? {} : { adapterId }),
|
|
654
654
|
...(session === null ? {} : { nativeSessionId: session.nativeSessionId }),
|
|
655
|
-
...(session?.
|
|
655
|
+
...(session?.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: session.runtimeGenerationId }),
|
|
656
656
|
...(run === null ? {} : { turnId: run.id })
|
|
657
657
|
});
|
|
658
658
|
};
|
|
@@ -25,7 +25,7 @@ import { createFileArtifactPort, createLinuxProcessPort, DurableJobSupervisor }
|
|
|
25
25
|
import { createDurableJobControl } from "./jobControl.js";
|
|
26
26
|
import { FileRuntimeEventInbox } from "./runtimeEventInbox.js";
|
|
27
27
|
import { AgentRuntimeObserver } from "./agentRuntimeObserver.js";
|
|
28
|
-
import { AsyncRuntimeEventProcessor, FileRuntimeEventProcessor, createAsyncRuntimeObserver } from "./runtimeEventProcessor.js";
|
|
28
|
+
import { AsyncRuntimeEventProcessor, FileRuntimeEventProcessor, createAsyncRuntimeObserver, } from "./runtimeEventProcessor.js";
|
|
29
29
|
import { RuntimeLaunchCoordinator } from "./runtimeLaunchCoordinator.js";
|
|
30
30
|
import { ephemeralDomainFromEnvironment, recordEphemeralTmuxTarget } from "./domainIdentity.js";
|
|
31
31
|
import { createEphemeralResourceReaper } from "./ephemeralResourceReaper.js";
|
|
@@ -41,41 +41,6 @@ import { appendGlobalProcessExitObservation } from "../runtime/globalProcessExit
|
|
|
41
41
|
import { builtinAgentDriverRegistry } from "../runtime/builtinAgentDrivers.js";
|
|
42
42
|
import { createRuntimeObservation, runtimeObservationFromTaskEvent } from "../runtime/runtimeObservation.js";
|
|
43
43
|
import { createTaskEvent } from "../event/taskEvent.js";
|
|
44
|
-
/** Refreshes only the exact Task runtime generation folded by the event transaction. */
|
|
45
|
-
export function refreshAppliedTaskRuntimeDescriptor(store, planner, input) {
|
|
46
|
-
if (input.launchId === undefined)
|
|
47
|
-
return;
|
|
48
|
-
const run = input.turnId === undefined
|
|
49
|
-
? null
|
|
50
|
-
: store.getTurn(input.taskId, input.turnId);
|
|
51
|
-
if (input.turnId !== undefined && run === null) {
|
|
52
|
-
throw new Error("Prepared Task runtime generation is not current.");
|
|
53
|
-
}
|
|
54
|
-
// A terminal completion has already settled this exact Turn and no later
|
|
55
|
-
// prompt can use its descriptor. Acknowledge the applied provider fact
|
|
56
|
-
// without republishing a dead generation.
|
|
57
|
-
if (run !== null && run.status !== "active")
|
|
58
|
-
return;
|
|
59
|
-
const session = store.getTaskRoleSessionSet(input.taskId, input.roleName)
|
|
60
|
-
?.sessions[input.agentId];
|
|
61
|
-
const effective = run?.effective ?? session?.effective;
|
|
62
|
-
if (effective === undefined
|
|
63
|
-
|| session === undefined
|
|
64
|
-
|| session.agentId !== input.agentId
|
|
65
|
-
|| session.adapterId !== input.adapterId
|
|
66
|
-
|| session.launchId !== input.launchId
|
|
67
|
-
|| session.nativeSessionId !== input.nativeSessionId
|
|
68
|
-
|| (run !== null && (run.roleName !== input.roleName
|
|
69
|
-
|| run.effective.agentId !== input.agentId
|
|
70
|
-
|| run.effective.adapterId !== input.adapterId))) {
|
|
71
|
-
throw new Error("Prepared Task runtime generation is not current.");
|
|
72
|
-
}
|
|
73
|
-
planner.refreshTaskRuntimeDescriptor({
|
|
74
|
-
...input,
|
|
75
|
-
launchId: input.launchId,
|
|
76
|
-
workspace: effective.workspace.root
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
44
|
/** Production composition root for the current SQLite TaskStore + tmux Controller. */
|
|
80
45
|
export async function startFileTaskControllerRuntime(home, options = {}) {
|
|
81
46
|
// The current Home always uses SQLite. The persistence worker is enabled by
|
|
@@ -159,7 +124,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
|
|
|
159
124
|
while (!signal.aborted) {
|
|
160
125
|
const session = schedulerStore.getRoleSession(owner.taskId, owner.roleName, request.agentId);
|
|
161
126
|
if (session !== null
|
|
162
|
-
&& session.
|
|
127
|
+
&& session.runtimeGenerationId === request.runtimeGenerationId
|
|
163
128
|
&& typeof session.nativeSessionId === "string"
|
|
164
129
|
&& session.nativeSessionId.trim().length > 0) {
|
|
165
130
|
return session.nativeSessionId;
|
|
@@ -170,7 +135,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
|
|
|
170
135
|
&& event.observation.fence.taskId === owner.taskId
|
|
171
136
|
&& event.observation.fence.roleName === owner.roleName
|
|
172
137
|
&& event.observation.fence.agentId === request.agentId
|
|
173
|
-
&& event.observation.fence.
|
|
138
|
+
&& event.observation.fence.runtimeGenerationId === request.runtimeGenerationId
|
|
174
139
|
&& typeof event.observation.fence.nativeSessionId === "string"
|
|
175
140
|
&& event.observation.fence.nativeSessionId.trim().length > 0) {
|
|
176
141
|
return event.observation.fence.nativeSessionId;
|
|
@@ -186,7 +151,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
|
|
|
186
151
|
owner: binding.owner,
|
|
187
152
|
agentId: binding.agentId,
|
|
188
153
|
adapterId: binding.adapterId,
|
|
189
|
-
|
|
154
|
+
runtimeGenerationId: binding.runtimeGenerationId,
|
|
190
155
|
...(binding.nativeSessionId === undefined
|
|
191
156
|
? {}
|
|
192
157
|
: { nativeSessionId: binding.nativeSessionId }),
|
|
@@ -222,7 +187,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
|
|
|
222
187
|
return sessionOwners.terminateOwner(owner).then((result) => {
|
|
223
188
|
if (result.outcome === "stop-blocked") {
|
|
224
189
|
(options.onError ?? (() => undefined))(new Error(`Role runtime cleanup could not prove physical exit: ${result.remaining
|
|
225
|
-
.map(({ record, detail }) => `${record.
|
|
190
|
+
.map(({ record, detail }) => `${record.runtimeGenerationId}: ${detail}`)
|
|
226
191
|
.join("; ")}`));
|
|
227
192
|
}
|
|
228
193
|
return result.outcome === "stop-confirmed";
|
|
@@ -294,9 +259,9 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
|
|
|
294
259
|
return [];
|
|
295
260
|
const identity = owner.turnId === undefined
|
|
296
261
|
|| owner.adapterId === undefined
|
|
297
|
-
|| (owner.nativeSessionId === undefined && owner.
|
|
262
|
+
|| (owner.nativeSessionId === undefined && owner.runtimeGenerationId === undefined)
|
|
298
263
|
|| (owner.nativeSessionId !== undefined && owner.nativeSessionId.trim().length === 0)
|
|
299
|
-
|| (owner.
|
|
264
|
+
|| (owner.runtimeGenerationId !== undefined && owner.runtimeGenerationId.trim().length === 0)
|
|
300
265
|
? undefined
|
|
301
266
|
: {
|
|
302
267
|
taskId: owner.taskId,
|
|
@@ -307,7 +272,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
|
|
|
307
272
|
...(owner.nativeSessionId === undefined
|
|
308
273
|
? {}
|
|
309
274
|
: { nativeSessionId: owner.nativeSessionId }),
|
|
310
|
-
...(owner.
|
|
275
|
+
...(owner.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: owner.runtimeGenerationId })
|
|
311
276
|
};
|
|
312
277
|
const changed = !active || input.turnId === undefined
|
|
313
278
|
? false
|
|
@@ -320,7 +285,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
|
|
|
320
285
|
...(input.nativeSessionId === undefined
|
|
321
286
|
? {}
|
|
322
287
|
: { nativeSessionId: input.nativeSessionId }),
|
|
323
|
-
...(input.
|
|
288
|
+
...(input.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: input.runtimeGenerationId })
|
|
324
289
|
}, resource);
|
|
325
290
|
return [{
|
|
326
291
|
taskId: owner.taskId,
|
|
@@ -464,16 +429,8 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
|
|
|
464
429
|
workspacePreparer,
|
|
465
430
|
runtimeEventProcessor: options.runtimeEventProcessor
|
|
466
431
|
?? (useWorker && asyncStoreClient !== undefined
|
|
467
|
-
? new AsyncRuntimeEventProcessor(runtimeEventInbox, createAsyncRuntimeObserver((method, args) => asyncStoreClient.invokeObserver(method, args))
|
|
468
|
-
|
|
469
|
-
refreshAppliedTaskRuntimeDescriptor(store, planner, input);
|
|
470
|
-
}
|
|
471
|
-
})
|
|
472
|
-
: new FileRuntimeEventProcessor(runtimeEventInbox, schedulerStore, {
|
|
473
|
-
onTaskRuntimeApplied: (input) => {
|
|
474
|
-
refreshAppliedTaskRuntimeDescriptor(store, planner, input);
|
|
475
|
-
}
|
|
476
|
-
})),
|
|
432
|
+
? new AsyncRuntimeEventProcessor(runtimeEventInbox, createAsyncRuntimeObserver((method, args) => asyncStoreClient.invokeObserver(method, args)))
|
|
433
|
+
: new FileRuntimeEventProcessor(runtimeEventInbox, schedulerStore)),
|
|
477
434
|
runtimeObserver: options.runtimeObserver
|
|
478
435
|
?? new AgentRuntimeObserver(store, runtimeEventInbox),
|
|
479
436
|
domainIdentity,
|
|
@@ -567,7 +524,7 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
|
|
|
567
524
|
roleName: value.roleName,
|
|
568
525
|
...(value.turnId === undefined ? {} : { turnId: value.turnId }),
|
|
569
526
|
agentId: value.agentId,
|
|
570
|
-
|
|
527
|
+
runtimeGenerationId: value.runtimeGenerationId,
|
|
571
528
|
nativeSessionId: value.nativeSessionId,
|
|
572
529
|
attemptId: value.attemptId,
|
|
573
530
|
authorityEpoch: value.authorityEpoch,
|
|
@@ -634,7 +591,7 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
|
|
|
634
591
|
const runtime = runtimeObservationFromTaskEvent(event);
|
|
635
592
|
return runtime !== null
|
|
636
593
|
&& runtime.fence.turnId === observation.turnId
|
|
637
|
-
&& runtime.fence.
|
|
594
|
+
&& runtime.fence.runtimeGenerationId === observation.runtimeGenerationId
|
|
638
595
|
&& runtime.kind === "turn.failed"
|
|
639
596
|
&& Date.parse(runtime.receivedAt) <= Date.parse(observation.observedAt);
|
|
640
597
|
});
|
|
@@ -661,7 +618,7 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
|
|
|
661
618
|
observationId: observation.observationId,
|
|
662
619
|
processKind: observation.processKind,
|
|
663
620
|
roleName: observation.roleName,
|
|
664
|
-
|
|
621
|
+
runtimeGenerationId: observation.runtimeGenerationId,
|
|
665
622
|
observedAt: observation.observedAt,
|
|
666
623
|
classification,
|
|
667
624
|
observation: JSON.stringify(observation)
|
|
@@ -674,16 +631,16 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
|
|
|
674
631
|
if (params === null || typeof params !== "object" || Array.isArray(params)) {
|
|
675
632
|
throw applicationError("INVALID_PARAMS", "Launch redemption params are invalid.");
|
|
676
633
|
}
|
|
677
|
-
const
|
|
634
|
+
const runtimeGenerationId = params.runtimeGenerationId;
|
|
678
635
|
const ticket = params.ticket;
|
|
679
636
|
const hostPid = params.hostPid;
|
|
680
|
-
if (typeof
|
|
637
|
+
if (typeof runtimeGenerationId !== "string" || typeof ticket !== "string"
|
|
681
638
|
|| !Number.isSafeInteger(hostPid) || hostPid <= 0) {
|
|
682
639
|
throw applicationError("INVALID_PARAMS", "Launch redemption identity is invalid.");
|
|
683
640
|
}
|
|
684
641
|
// The launch payload is validated at reservation time and every member
|
|
685
642
|
// of its discriminated Provider-control union is JSON serializable.
|
|
686
|
-
return launchBrokerForHome(store.rootDirectory()).redeem(
|
|
643
|
+
return launchBrokerForHome(store.rootDirectory()).redeem(runtimeGenerationId, ticket);
|
|
687
644
|
}
|
|
688
645
|
if (method === "runtime.replace-agent-environment") {
|
|
689
646
|
if (environmentRefresher === undefined) {
|
|
@@ -1124,7 +1081,7 @@ function providerTurnControlParams(params) {
|
|
|
1124
1081
|
roleName: requiredParam(value.roleName),
|
|
1125
1082
|
...(value.turnId === undefined ? {} : { turnId: requiredParam(value.turnId) }),
|
|
1126
1083
|
agentId: requiredParam(value.agentId),
|
|
1127
|
-
|
|
1084
|
+
runtimeGenerationId: requiredParam(value.runtimeGenerationId),
|
|
1128
1085
|
nativeSessionId: requiredParam(value.nativeSessionId),
|
|
1129
1086
|
attemptId: requiredParam(value.attemptId),
|
|
1130
1087
|
authorityEpoch: authorityEpoch,
|
|
@@ -2,7 +2,7 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
2
2
|
import { closeSync, constants, existsSync, fchmodSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { createRuntimeObservation, isRuntimeTokenEvidence } from "../runtime/runtimeObservation.js";
|
|
5
|
-
|
|
5
|
+
import { boundedTurnFailureDiagnostic, transportAgentResult } from "../domain/agentResultTransport.js";
|
|
6
6
|
export const MAX_RUNTIME_EVENT_FILE_BYTES = 16 * 1024 * 1024;
|
|
7
7
|
const RUNTIME_EVENT_DIRECTORY = join("runtime", "inbox");
|
|
8
8
|
const INVALID_RUNTIME_EVENT_DIRECTORY = join("runtime", "inbox-invalid");
|
|
@@ -39,12 +39,12 @@ export class FileRuntimeEventInbox {
|
|
|
39
39
|
});
|
|
40
40
|
return this.publish(event);
|
|
41
41
|
}
|
|
42
|
-
|
|
43
|
-
const normalized =
|
|
42
|
+
enqueueTurnTerminal(input) {
|
|
43
|
+
const normalized = normalizeNativeTurnTerminalInput(input);
|
|
44
44
|
return this.publish(Object.freeze({
|
|
45
45
|
schemaVersion: 1,
|
|
46
|
-
id: runtimeEventId("native-turn-
|
|
47
|
-
type: "native-turn-
|
|
46
|
+
id: runtimeEventId("native-turn-terminal", normalized),
|
|
47
|
+
type: "native-turn-terminal",
|
|
48
48
|
receivedAt: this.now().toISOString(),
|
|
49
49
|
...normalized
|
|
50
50
|
}));
|
|
@@ -275,27 +275,31 @@ function runtimeEventId(type, input) {
|
|
|
275
275
|
provider.roleName,
|
|
276
276
|
provider.agentId,
|
|
277
277
|
provider.adapterId,
|
|
278
|
-
provider.
|
|
278
|
+
provider.runtimeGenerationId ?? null,
|
|
279
279
|
provider.nativeSessionId,
|
|
280
280
|
provider.nativeTurnId,
|
|
281
281
|
provider.turnId ?? null
|
|
282
282
|
];
|
|
283
283
|
return `turn-${createHash("sha256").update(JSON.stringify(common)).digest("hex")}`;
|
|
284
284
|
}
|
|
285
|
-
function
|
|
285
|
+
function normalizeNativeTurnTerminalInput(input) {
|
|
286
286
|
const scope = input.scope;
|
|
287
287
|
if (scope !== "task" && scope !== "global")
|
|
288
288
|
throw invalidEvent();
|
|
289
|
-
if (
|
|
289
|
+
if (!["completed", "failed", "cancelled"].includes(input.providerStatus))
|
|
290
290
|
throw invalidEvent();
|
|
291
|
+
const outcome = normalizeRuntimeTurnTerminalOutcome(input.outcome);
|
|
292
|
+
if (outcome.status === "completed" && input.providerStatus !== "completed") {
|
|
293
|
+
throw invalidEvent("Only a completed Provider Turn may carry a completed Agent result.");
|
|
294
|
+
}
|
|
291
295
|
const common = {
|
|
292
296
|
scope,
|
|
293
297
|
roleName: requireIdentityText(input.roleName, "Role name"),
|
|
294
298
|
agentId: requireIdentityText(input.agentId, "Agent id"),
|
|
295
299
|
adapterId: input.adapterId,
|
|
296
|
-
...(input.
|
|
300
|
+
...(input.runtimeGenerationId === undefined
|
|
297
301
|
? {}
|
|
298
|
-
: {
|
|
302
|
+
: { runtimeGenerationId: requireIdentityText(input.runtimeGenerationId, "Runtime generation id") }),
|
|
299
303
|
nativeSessionId: requireIdentityText(input.nativeSessionId, "Native session id"),
|
|
300
304
|
nativeTurnId: requireIdentityText(input.nativeTurnId, "Provider native Turn id"),
|
|
301
305
|
...(input.turnId === undefined
|
|
@@ -304,15 +308,41 @@ function normalizeNativeTurnCompletedInput(input) {
|
|
|
304
308
|
...(input.title === undefined
|
|
305
309
|
? {}
|
|
306
310
|
: { title: requireIdentityText(input.title, "Session title") }),
|
|
307
|
-
|
|
311
|
+
providerStatus: input.providerStatus,
|
|
312
|
+
outcome
|
|
308
313
|
};
|
|
309
|
-
if (
|
|
310
|
-
|| common.summary.length === 0)
|
|
314
|
+
if (common.adapterId !== "codex" && common.adapterId !== "claude")
|
|
311
315
|
throw invalidEvent();
|
|
312
316
|
return scope === "task"
|
|
313
317
|
? { ...common, taskId: requireIdentityText(input.taskId, "Task id") }
|
|
314
318
|
: common;
|
|
315
319
|
}
|
|
320
|
+
function normalizeRuntimeTurnTerminalOutcome(input) {
|
|
321
|
+
if (!isObject(input)) {
|
|
322
|
+
throw invalidEvent("Runtime Turn terminal outcome is invalid.");
|
|
323
|
+
}
|
|
324
|
+
if (input.status === "completed")
|
|
325
|
+
return transportAgentResult(input.output);
|
|
326
|
+
if (input.status !== "failed"
|
|
327
|
+
|| ![
|
|
328
|
+
"startup-failed",
|
|
329
|
+
"runtime-failed",
|
|
330
|
+
"delivery-unknown",
|
|
331
|
+
"missing-result",
|
|
332
|
+
"workspace-unavailable",
|
|
333
|
+
"workspace-dirty",
|
|
334
|
+
"workspace-branch-mismatch",
|
|
335
|
+
"cancelled"
|
|
336
|
+
]
|
|
337
|
+
.includes(input.failureReason)) {
|
|
338
|
+
throw invalidEvent("Runtime Turn failure outcome is invalid.");
|
|
339
|
+
}
|
|
340
|
+
return {
|
|
341
|
+
status: "failed",
|
|
342
|
+
diagnostic: boundedTurnFailureDiagnostic(input.diagnostic),
|
|
343
|
+
failureReason: input.failureReason
|
|
344
|
+
};
|
|
345
|
+
}
|
|
316
346
|
function normalizeDurableJobTerminalInput(input) {
|
|
317
347
|
if (input.scope !== "task")
|
|
318
348
|
throw invalidEvent();
|
|
@@ -335,7 +365,7 @@ function parseRuntimeEvent(value) {
|
|
|
335
365
|
throw invalidEvent();
|
|
336
366
|
switch (value.type) {
|
|
337
367
|
case "runtime-observation": return parseRuntimeObservationEvent(value);
|
|
338
|
-
case "native-turn-
|
|
368
|
+
case "native-turn-terminal": return parseNativeTurnTerminalEvent(value);
|
|
339
369
|
case "durable-job-terminal": return parseDurableJobTerminalEvent(value);
|
|
340
370
|
default: throw invalidEvent();
|
|
341
371
|
}
|
|
@@ -380,20 +410,22 @@ function parseDurableJobTerminalEvent(value) {
|
|
|
380
410
|
...normalized
|
|
381
411
|
});
|
|
382
412
|
}
|
|
383
|
-
function
|
|
413
|
+
function parseNativeTurnTerminalEvent(value) {
|
|
384
414
|
const scope = value.scope;
|
|
385
415
|
const expected = scope === "task"
|
|
386
416
|
? [
|
|
387
417
|
"schemaVersion", "id", "type", "receivedAt", "scope", "taskId",
|
|
388
|
-
"roleName", "agentId", "adapterId", "nativeSessionId", "nativeTurnId",
|
|
389
|
-
|
|
418
|
+
"roleName", "agentId", "adapterId", "nativeSessionId", "nativeTurnId",
|
|
419
|
+
"providerStatus", "outcome",
|
|
420
|
+
...(value.runtimeGenerationId === undefined ? [] : ["runtimeGenerationId"]),
|
|
390
421
|
...(value.turnId === undefined ? [] : ["turnId"]),
|
|
391
422
|
...(value.title === undefined ? [] : ["title"])
|
|
392
423
|
]
|
|
393
424
|
: [
|
|
394
425
|
"schemaVersion", "id", "type", "receivedAt", "scope",
|
|
395
|
-
"roleName", "agentId", "adapterId", "nativeSessionId", "nativeTurnId",
|
|
396
|
-
|
|
426
|
+
"roleName", "agentId", "adapterId", "nativeSessionId", "nativeTurnId",
|
|
427
|
+
"providerStatus", "outcome",
|
|
428
|
+
...(value.runtimeGenerationId === undefined ? [] : ["runtimeGenerationId"]),
|
|
397
429
|
...(value.turnId === undefined ? [] : ["turnId"]),
|
|
398
430
|
...(value.title === undefined ? [] : ["title"])
|
|
399
431
|
];
|
|
@@ -402,23 +434,24 @@ function parseNativeTurnCompletedEvent(value) {
|
|
|
402
434
|
|| !hasExactKeys(value, expected))
|
|
403
435
|
throw invalidEvent();
|
|
404
436
|
const receivedAt = requireTimestamp(value.receivedAt);
|
|
405
|
-
const normalized =
|
|
437
|
+
const normalized = normalizeNativeTurnTerminalInput({
|
|
406
438
|
scope,
|
|
407
439
|
...(scope === "task" ? { taskId: value.taskId } : {}),
|
|
408
440
|
roleName: value.roleName,
|
|
409
441
|
agentId: value.agentId,
|
|
410
442
|
adapterId: value.adapterId,
|
|
411
|
-
...(value.
|
|
443
|
+
...(value.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: value.runtimeGenerationId }),
|
|
412
444
|
nativeSessionId: value.nativeSessionId,
|
|
413
445
|
nativeTurnId: value.nativeTurnId,
|
|
414
446
|
...(value.turnId === undefined ? {} : { turnId: value.turnId }),
|
|
415
447
|
...(value.title === undefined ? {} : { title: value.title }),
|
|
416
|
-
|
|
448
|
+
providerStatus: value.providerStatus,
|
|
449
|
+
outcome: value.outcome
|
|
417
450
|
});
|
|
418
451
|
return Object.freeze({
|
|
419
452
|
schemaVersion: 1,
|
|
420
453
|
id: requireIdentityText(value.id, "Event id"),
|
|
421
|
-
type: "native-turn-
|
|
454
|
+
type: "native-turn-terminal",
|
|
422
455
|
receivedAt,
|
|
423
456
|
...normalized
|
|
424
457
|
});
|
|
@@ -438,15 +471,6 @@ function requireTimestamp(value) {
|
|
|
438
471
|
throw invalidEvent();
|
|
439
472
|
return timestamp;
|
|
440
473
|
}
|
|
441
|
-
function truncateUtf8(value, maximumBytes) {
|
|
442
|
-
const encoded = Buffer.from(value, "utf8");
|
|
443
|
-
if (encoded.length <= maximumBytes)
|
|
444
|
-
return value;
|
|
445
|
-
let end = maximumBytes;
|
|
446
|
-
while (end > 0 && (encoded[end] & 0b1100_0000) === 0b1000_0000)
|
|
447
|
-
end -= 1;
|
|
448
|
-
return encoded.subarray(0, end).toString("utf8");
|
|
449
|
-
}
|
|
450
474
|
function ensureInboxDirectory(directory) {
|
|
451
475
|
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
452
476
|
}
|
|
@@ -471,12 +495,11 @@ function hasSameIdentity(left, right) {
|
|
|
471
495
|
&& (!("roleName" in left) || !("roleName" in right) || left.roleName === right.roleName)
|
|
472
496
|
&& (!("agentId" in left) || !("agentId" in right) || left.agentId === right.agentId)
|
|
473
497
|
&& (!("adapterId" in left) || !("adapterId" in right) || left.adapterId === right.adapterId)
|
|
474
|
-
&& (!("
|
|
498
|
+
&& (!("runtimeGenerationId" in left) || !("runtimeGenerationId" in right) || left.runtimeGenerationId === right.runtimeGenerationId)
|
|
475
499
|
&& (!("nativeSessionId" in left)
|
|
476
500
|
|| !("nativeSessionId" in right)
|
|
477
501
|
|| left.nativeSessionId === right.nativeSessionId)
|
|
478
502
|
&& (!("turnId" in left) || !("turnId" in right) || left.turnId === right.turnId)
|
|
479
|
-
&& (!("turnId" in left) || !("turnId" in right) || left.turnId === right.turnId)
|
|
480
503
|
&& (!("jobId" in left) || !("jobId" in right) || left.jobId === right.jobId);
|
|
481
504
|
}
|
|
482
505
|
function compareRuntimeEvents(left, right) {
|