@zq-silk/yui 0.6.8 → 0.6.10
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/README.md +10 -3
- package/dist/cli/commandCatalog.js +1 -1
- package/dist/commands/taskCommands.js +63 -28
- package/dist/commands/taskContextCommand.js +27 -1
- package/dist/commands/taskRoleRuntimeStatus.js +17 -6
- package/dist/controller/agentRuntimeObserver.js +6 -3
- package/dist/controller/controller.js +29 -47
- package/dist/controller/fileSchedulerStoreAdapter.js +572 -258
- package/dist/controller/runtime.js +8 -1
- package/dist/controller/runtimeEventInbox.js +16 -5
- package/dist/controller/runtimeHookRunFence.js +51 -5
- package/dist/controller/runtimeObservationHook.js +8 -2
- package/dist/coordination/workMailbox.js +408 -28
- package/dist/coordination/workMailboxQueue.js +12 -10
- package/dist/executor/agentExecutor.js +101 -94
- package/dist/executor/executorRegistry.js +47 -2
- package/dist/executor/fileRoleLaunchPlanner.js +4 -2
- package/dist/lifecycle/exactRunTerminalization.js +1 -7
- package/dist/repository/taskWorkspaceCoordinator.js +9 -4
- package/dist/runtime/agentDriver.js +83 -4
- package/dist/runtime/agentDriverObservation.js +25 -10
- package/dist/runtime/builtinAgentDrivers.js +168 -18
- package/dist/runtime/codexAppServerRuntime.js +355 -0
- package/dist/runtime/continuationManager.js +117 -0
- package/dist/runtime/index.js +2 -0
- package/dist/runtime/lifecycleReservation.js +4 -3
- package/dist/runtime/promptEnvelope.js +14 -3
- package/dist/runtime/providerContinuation.js +225 -0
- package/dist/runtime/providerContinuationReconciliationService.js +172 -0
- package/dist/runtime/providerRuntimeIdentity.js +232 -0
- package/dist/runtime/providerRuntimeReconciler.js +166 -0
- package/dist/runtime/runtimeContinuationProjection.js +34 -0
- package/dist/runtime/runtimeObservation.js +217 -6
- package/dist/runtime/runtimeProjection.js +172 -11
- package/dist/scheduler/activeRoleRunDelivery.js +314 -1
- package/dist/scheduler/leaderWakeupProcessor.js +2 -1
- package/dist/scheduler/operatorInputNotificationProcessor.js +3 -2
- package/dist/scheduler/roleRunLiveness.js +8 -7
- package/dist/scheduler/roleRunStall.js +4 -2
- package/dist/scheduler/taskExecutionProjection.js +2 -2
- package/dist/storage/migration/productionRegistry.js +474 -1
- package/dist/storage/sqliteSchema.js +102 -21
- package/dist/storage/sqliteStore.js +52 -110
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/storeRpc.js +0 -1
- package/dist/storage/taskStore.js +40 -53
- package/dist/storage/upgrade/sqliteStateMigration.js +0 -21
- package/dist/task/nextAction.js +1 -1
- package/dist/web/assets/client/app.js +1 -1
- package/dist/web/assets/client/components.js +233 -4
- package/dist/web/assets/client/i18n.js +166 -2
- package/dist/web/assets/client/view.js +30 -13
- package/dist/web/assets/styles/cards.js +62 -0
- package/dist/web/assets/styles/widgets.js +1 -0
- package/dist/web/webSnapshot.js +11 -2
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +33 -24
- package/skills/yui-operator/SKILL.md +7 -5
|
@@ -16,7 +16,7 @@ import { AsyncTaskStoreClient, resolveStoreWorkerEnabledForHome } from "../stora
|
|
|
16
16
|
import { FileTaskWorkspacePreparer } from "../repository/taskWorkspacePreparer.js";
|
|
17
17
|
import { NodeCommandExecutor } from "../tmux/commandExecutor.js";
|
|
18
18
|
import { TmuxManager, yuiTmuxServerName } from "../tmux/tmuxManager.js";
|
|
19
|
-
import { FileTaskRuntimeIsolation, TmuxPromptPushAdapter, TmuxSessionHost } from "../runtime/index.js";
|
|
19
|
+
import { FileTaskRuntimeIsolation, TmuxPromptPushAdapter, TmuxSessionHost, ProviderContinuationReconciliationService } from "../runtime/index.js";
|
|
20
20
|
import { startFileTaskController } from "./controller.js";
|
|
21
21
|
import { FileSchedulerStoreAdapter } from "./fileSchedulerStoreAdapter.js";
|
|
22
22
|
import { openSchedulerTelemetry } from "../telemetry/telemetryWiring.js";
|
|
@@ -224,6 +224,9 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
|
|
|
224
224
|
sessionHost,
|
|
225
225
|
promptPush,
|
|
226
226
|
launchCoordinator,
|
|
227
|
+
...(options.providerInputRouting === undefined
|
|
228
|
+
? {}
|
|
229
|
+
: { providerInputRouting: options.providerInputRouting }),
|
|
227
230
|
roleResourceInventory: async (panes, inputs) => {
|
|
228
231
|
const inventory = await scanInventory(panes);
|
|
229
232
|
return inventory.resources.flatMap((resource) => {
|
|
@@ -370,6 +373,9 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
|
|
|
370
373
|
onError: options.onError
|
|
371
374
|
});
|
|
372
375
|
const jobControl = createDurableJobControl(store);
|
|
376
|
+
const continuationReconciler = options.continuationMetadata === undefined
|
|
377
|
+
? undefined
|
|
378
|
+
: new ProviderContinuationReconciliationService(store, schedulerStore, options.continuationMetadata);
|
|
373
379
|
const running = await startFileTaskController(home, schedulerStore, delivery, lifecycleDispatcher, {
|
|
374
380
|
intervalMs: options.intervalMs
|
|
375
381
|
?? reconciliationIntervalMilliseconds(store.getConfig().reconciliationIntervalSeconds),
|
|
@@ -382,6 +388,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
|
|
|
382
388
|
lifecycleHost,
|
|
383
389
|
jobSupervisor,
|
|
384
390
|
jobControl,
|
|
391
|
+
...(continuationReconciler === undefined ? {} : { continuationReconciler }),
|
|
385
392
|
...(resourceReaper === undefined ? {} : { resourceReaper }),
|
|
386
393
|
resourceAutoGc,
|
|
387
394
|
onExpiredEphemeralDomain: (domain) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
-
import { closeSync, constants, existsSync, fchmodSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync,
|
|
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 { withUpgradeCoordinationLock } from "../storage/upgradeCoordination.js";
|
|
5
5
|
import { createRuntimeObservation } from "../runtime/runtimeObservation.js";
|
|
@@ -213,9 +213,18 @@ export class FileRuntimeEventInbox {
|
|
|
213
213
|
const invalidDirectory = join(this.home, INVALID_RUNTIME_EVENT_DIRECTORY);
|
|
214
214
|
ensureInboxDirectory(invalidDirectory);
|
|
215
215
|
const source = join(this.directory, name);
|
|
216
|
-
|
|
216
|
+
// One semantic ingress identity owns one quarantine slot. Repeated poison
|
|
217
|
+
// entries replace neither the first diagnostic nor create an event storm.
|
|
218
|
+
const target = join(invalidDirectory, name);
|
|
217
219
|
try {
|
|
218
|
-
|
|
220
|
+
try {
|
|
221
|
+
linkSync(source, target);
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
if (!isNodeError(error, "EEXIST"))
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
227
|
+
unlinkSync(source);
|
|
219
228
|
fsyncDirectory(this.directory);
|
|
220
229
|
fsyncDirectory(invalidDirectory);
|
|
221
230
|
}
|
|
@@ -237,9 +246,11 @@ function runtimeEventId(type, input) {
|
|
|
237
246
|
if (type === "runtime-observation") {
|
|
238
247
|
const observation = input.observation;
|
|
239
248
|
return `turn-${createHash("sha256").update(JSON.stringify([
|
|
240
|
-
|
|
249
|
+
2,
|
|
241
250
|
type,
|
|
242
|
-
observation
|
|
251
|
+
observation.fence.taskId ?? null,
|
|
252
|
+
observation.fence.roleName,
|
|
253
|
+
observation.semanticKey
|
|
243
254
|
])).digest("hex")}`;
|
|
244
255
|
}
|
|
245
256
|
if (type === "durable-job-terminal") {
|
|
@@ -49,7 +49,19 @@ export function resolveRuntimeHookRunFence(environment, adapterId, payloadNative
|
|
|
49
49
|
}
|
|
50
50
|
const inFlight = sessions?.inFlight;
|
|
51
51
|
const session = sessions?.sessions[agentId];
|
|
52
|
-
const
|
|
52
|
+
const roleMailbox = store.getWorkMailbox({ kind: "role", taskId, roleName });
|
|
53
|
+
const roleInputDelivery = roleMailbox?.inputDelivery;
|
|
54
|
+
const roleExecution = roleMailbox?.processing?.executionRef;
|
|
55
|
+
const activationReceiptId = roleInputDelivery?.executionRef?.type === "run"
|
|
56
|
+
&& roleInputDelivery.executionRef.taskId === taskId
|
|
57
|
+
&& roleInputDelivery.executionRef.id === inFlight?.runId
|
|
58
|
+
? roleInputDelivery.attemptId
|
|
59
|
+
: roleExecution?.type === "run"
|
|
60
|
+
&& roleExecution.taskId === taskId
|
|
61
|
+
&& roleExecution.id === inFlight?.runId
|
|
62
|
+
? roleMailbox.processing.batchId
|
|
63
|
+
: inFlight?.receiptId;
|
|
64
|
+
const acceptedTurn = options.nativeTurnId === undefined
|
|
53
65
|
? null
|
|
54
66
|
: acceptedTurnBinding(store.listEvents(taskId), {
|
|
55
67
|
taskId,
|
|
@@ -58,6 +70,14 @@ export function resolveRuntimeHookRunFence(environment, adapterId, payloadNative
|
|
|
58
70
|
nativeSessionId,
|
|
59
71
|
nativeTurnId: options.nativeTurnId
|
|
60
72
|
});
|
|
73
|
+
const acceptedBinding = acceptedTurn ?? (options.continuationId === undefined ? null : knownContinuationBinding(store.listEvents(taskId), {
|
|
74
|
+
taskId,
|
|
75
|
+
roleName,
|
|
76
|
+
agentId,
|
|
77
|
+
nativeSessionId,
|
|
78
|
+
continuationId: options.continuationId,
|
|
79
|
+
continuationGeneration: options.continuationGeneration ?? 1
|
|
80
|
+
}));
|
|
61
81
|
const mailbox = store.getWorkMailbox(runtimeLifecycleTarget({
|
|
62
82
|
scope: "task",
|
|
63
83
|
taskId,
|
|
@@ -163,15 +183,15 @@ export function resolveRuntimeHookRunFence(environment, adapterId, payloadNative
|
|
|
163
183
|
if (run.effective.workspace.root !== workspace) {
|
|
164
184
|
throw new Error("Runtime observation Hook workspace does not match the durable Run snapshot.");
|
|
165
185
|
}
|
|
166
|
-
if (session !== undefined) {
|
|
186
|
+
if (session !== undefined && acceptedBinding === null) {
|
|
167
187
|
if (session.adapterId !== adapterId
|
|
168
|
-
||
|
|
188
|
+
|| session.launchId !== effectiveLaunchId
|
|
169
189
|
|| session.nativeSessionId !== nativeSessionId
|
|
170
190
|
|| session.effective.workspace.root !== workspace) {
|
|
171
191
|
throw new Error("Runtime observation Hook Session does not match its durable generation.");
|
|
172
192
|
}
|
|
173
193
|
}
|
|
174
|
-
else {
|
|
194
|
+
else if (session === undefined && acceptedBinding === null) {
|
|
175
195
|
if (!discoveredStartup && !preallocatedStartup) {
|
|
176
196
|
throw new Error("Runtime observation Hook launch is not durably reserved.");
|
|
177
197
|
}
|
|
@@ -183,12 +203,38 @@ export function resolveRuntimeHookRunFence(environment, adapterId, payloadNative
|
|
|
183
203
|
launchId: effectiveLaunchId,
|
|
184
204
|
runId,
|
|
185
205
|
...(acceptedBinding?.fence.receiptId === undefined
|
|
186
|
-
?
|
|
206
|
+
? activationReceiptId === undefined ? {} : { receiptId: activationReceiptId }
|
|
187
207
|
: { receiptId: acceptedBinding.fence.receiptId }),
|
|
188
208
|
nativeSessionId,
|
|
189
209
|
workspace
|
|
190
210
|
};
|
|
191
211
|
}
|
|
212
|
+
function knownContinuationBinding(events, expected) {
|
|
213
|
+
const matches = events
|
|
214
|
+
.map(runtimeObservationFromTaskEvent)
|
|
215
|
+
.filter((observation) => observation !== null
|
|
216
|
+
&& observation.kind.startsWith("continuation.")
|
|
217
|
+
&& observation.fence.taskId === expected.taskId
|
|
218
|
+
&& observation.fence.roleName === expected.roleName
|
|
219
|
+
&& observation.fence.agentId === expected.agentId
|
|
220
|
+
&& observation.fence.nativeSessionId === expected.nativeSessionId
|
|
221
|
+
&& observation.fence.continuationId === expected.continuationId
|
|
222
|
+
&& observation.fence.continuationGeneration === expected.continuationGeneration
|
|
223
|
+
&& observation.fence.runId !== undefined)
|
|
224
|
+
.sort((left, right) => (left.receivedAt.localeCompare(right.receivedAt)
|
|
225
|
+
|| (left.sequence ?? -1) - (right.sequence ?? -1)
|
|
226
|
+
|| (left.ordinal ?? -1) - (right.ordinal ?? -1)
|
|
227
|
+
|| left.eventId.localeCompare(right.eventId)));
|
|
228
|
+
const binding = matches.at(-1) ?? null;
|
|
229
|
+
if (binding === null)
|
|
230
|
+
return null;
|
|
231
|
+
if (matches.some((candidate) => candidate.fence.runId !== binding.fence.runId
|
|
232
|
+
|| candidate.fence.launchId !== binding.fence.launchId
|
|
233
|
+
|| candidate.fence.receiptId !== binding.fence.receiptId)) {
|
|
234
|
+
throw new Error("Runtime observation Hook continuation has conflicting durable Run bindings.");
|
|
235
|
+
}
|
|
236
|
+
return binding;
|
|
237
|
+
}
|
|
192
238
|
function acceptedTurnBinding(events, expected) {
|
|
193
239
|
const matches = events
|
|
194
240
|
.map(runtimeObservationFromTaskEvent)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { callController } from "../core/controllerClient.js";
|
|
2
2
|
import { builtinAgentDriverRegistry } from "../runtime/builtinAgentDrivers.js";
|
|
3
3
|
import { normalizeAgentDriverHookClassification } from "../runtime/agentDriver.js";
|
|
4
|
-
import {
|
|
4
|
+
import { mapAgentDriverHooks } from "../runtime/agentDriverObservation.js";
|
|
5
5
|
import { runtimeLifecycleSignalKey } from "../runtime/lifecycleReservation.js";
|
|
6
6
|
import { formatAgentRunReceiptId } from "../task/taskRecordReference.js";
|
|
7
7
|
import { FileRuntimeEventInbox, MAX_RUNTIME_EVENT_FILE_BYTES } from "./runtimeEventInbox.js";
|
|
@@ -44,6 +44,10 @@ export function parseRuntimeObservationHook(stdinJson, environment, now = new Da
|
|
|
44
44
|
? {}
|
|
45
45
|
: { startupSession: classification.startupSession }),
|
|
46
46
|
terminal: classification.terminal,
|
|
47
|
+
...(classification.continuationId === undefined ? {} : {
|
|
48
|
+
continuationId: classification.continuationId,
|
|
49
|
+
continuationGeneration: classification.continuationGeneration ?? 1
|
|
50
|
+
}),
|
|
47
51
|
...(nativeTurnId === undefined ? {} : { nativeTurnId })
|
|
48
52
|
});
|
|
49
53
|
const driverInput = {
|
|
@@ -63,13 +67,15 @@ export function parseRuntimeObservationHook(stdinJson, environment, now = new Da
|
|
|
63
67
|
driverId,
|
|
64
68
|
launchId: fence.launchId,
|
|
65
69
|
sessionGenerationId: fence.launchId,
|
|
70
|
+
conversationId: fence.nativeSessionId,
|
|
71
|
+
activationId: fence.launchId,
|
|
66
72
|
nativeSessionId: fence.nativeSessionId,
|
|
67
73
|
nativeTurnId: nativeTurnId ?? fence.runId,
|
|
68
74
|
receiptId: fence.receiptId ?? formatAgentRunReceiptId(fence.taskId, fence.runId)
|
|
69
75
|
},
|
|
70
76
|
payload
|
|
71
77
|
};
|
|
72
|
-
const observations =
|
|
78
|
+
const observations = mapAgentDriverHooks({ ...driverInput, ordinal: 0 });
|
|
73
79
|
return {
|
|
74
80
|
home: requireIdentity(environment.YUI_HOME, "YUI_HOME"),
|
|
75
81
|
taskId: fence.taskId,
|