@zq-silk/yui 0.15.9 → 0.15.11
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/dist/agent/launchEnvironment.js +7 -0
- package/dist/cli/commandCatalog.js +26 -6
- package/dist/cli/interactionPolicy.js +3 -3
- package/dist/cli/updateOrchestrator.js +24 -1
- package/dist/cli/updatePorts.js +7 -3
- package/dist/cli/upgradeCommand.js +42 -2
- package/dist/cli.js +336 -93
- package/dist/commands/globalRoleCommands.js +314 -4
- package/dist/commands/projectCommands.js +6 -7
- package/dist/commands/releaseCommands.js +18 -0
- package/dist/commands/taskActor.js +25 -0
- package/dist/commands/taskCommands.js +511 -83
- package/dist/commands/taskIntegrationCommands.js +16 -38
- package/dist/commands/taskIntegrationQueueCommands.js +1 -1
- package/dist/commands/taskRemoteDeliveryCommand.js +6 -6
- package/dist/commands/taskRoleRuntimeStatus.js +35 -0
- package/dist/context/taskContext.js +38 -2
- package/dist/controller/agentHostObservation.js +155 -0
- package/dist/controller/clientRuntime.js +17 -2
- package/dist/controller/controller.js +3 -0
- package/dist/controller/fileSchedulerStoreAdapter.js +446 -13
- package/dist/controller/globalInputDelivery.js +119 -0
- package/dist/controller/jobControl.js +6 -2
- package/dist/controller/resourceInventory.js +14 -4
- package/dist/controller/resourceInventoryLinux.js +2 -6
- package/dist/controller/runtime.js +81 -6
- package/dist/controller/runtimeEventInbox.js +32 -3
- package/dist/controller/runtimeEventProcessor.js +26 -6
- package/dist/controller/runtimeHookRunFence.js +75 -19
- package/dist/controller/structuredProviderObservation.js +133 -70
- package/dist/coordination/workMailboxQueue.js +5 -0
- package/dist/execution/workItemExecutionProjection.js +1 -1
- package/dist/executor/agentExecutor.js +64 -4
- package/dist/executor/executorRegistry.js +3 -0
- package/dist/executor/fileRoleLaunchPlanner.js +78 -118
- package/dist/integration/deliveryObligation.js +2 -1
- package/dist/integration/gitIntegrationService.js +312 -382
- package/dist/integration/integrationAttempt.js +30 -4
- package/dist/integration/integrationQueueService.js +7 -7
- package/dist/integration/integrationSourceApplication.js +323 -0
- package/dist/message/globalInterrupt.js +33 -0
- package/dist/message/inputControlResolution.js +106 -0
- package/dist/message/message.js +367 -0
- package/dist/message/messageContinuation.js +126 -3
- package/dist/message/taskInterrupt.js +34 -0
- package/dist/observability/orchestrationMetrics.js +1 -1
- package/dist/release/releaseHandover.js +22 -0
- package/dist/release/releaseWorkflowPorts.js +15 -7
- package/dist/repository/gitWorkspace.js +72 -15
- package/dist/repository/taskWorkspaceCoordinator.js +134 -0
- package/dist/repository/taskWorkspacePreparer.js +120 -49
- package/dist/repository/workItemCandidateSnapshot.js +34 -0
- package/dist/resources/resourceDiscovery.js +3 -2
- package/dist/runtime/agentHost.js +152 -72
- package/dist/runtime/agentHostCompatibility.js +127 -0
- package/dist/runtime/agentHostProtocol.js +53 -0
- package/dist/runtime/executionEnvironment.js +0 -19
- package/dist/runtime/launchBroker.js +6 -0
- package/dist/runtime/sessionReconciliation.js +4 -4
- package/dist/runtime/taskRuntimeIsolation.js +30 -6
- package/dist/runtime/tmuxAdapters.js +5 -3
- package/dist/scheduler/operatorEvent.js +4 -0
- package/dist/scheduler/taskExecutionProjection.js +12 -1
- package/dist/scheduler/wakeReason.js +7 -1
- package/dist/scheduler/wakeupQueue.js +2 -0
- package/dist/setup/setupCommand.js +26 -8
- package/dist/storage/homeLayout.js +130 -0
- package/dist/storage/migrations/collapseWorktreeLayout.js +963 -0
- package/dist/storage/migrations/integrationContinuation.js +104 -0
- package/dist/storage/migrations/unifyHomeLayout.js +925 -0
- package/dist/storage/sqliteSchema.js +136 -4
- package/dist/storage/sqliteStore.js +40 -1
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/storeRpc.js +1 -0
- package/dist/storage/upgrade/upgradeOrchestrator.js +95 -2
- package/dist/task/archiveDiagnostics.js +128 -0
- package/dist/task/nextAction.js +44 -11
- package/dist/web/assets/client/app.js +55 -0
- package/dist/web/assets/client/components.js +1 -0
- package/dist/web/assets/client/i18n.js +6 -0
- package/dist/web/assets/client/taskSurface.js +106 -0
- package/dist/web/assets/client/view.js +7 -4
- package/dist/web/assets/shell.js +23 -0
- package/dist/web/assets/styles/layout.js +1 -1
- package/dist/web/assets/styles/widgets.js +12 -0
- package/dist/web/webServer.js +117 -1
- package/dist/web/webSnapshot.js +4 -3
- package/dist/web/webTaskSurface.js +222 -5
- package/dist/workspace/workItemChangeSetManager.js +18 -2
- package/docs/release-workflow.md +39 -0
- package/docs/release-workflow.zh-CN.md +29 -0
- package/docs/sqlite-control-plane-design.md +223 -1
- package/docs/testing/verification-levels.md +24 -0
- package/docs/testing/verification-levels.zh-CN.md +11 -0
- package/package.json +1 -1
- package/skills/yui-leader/references/execution.md +151 -49
- package/skills/yui-leader/references/integration.md +52 -2
- package/skills/yui-operator/SKILL.md +6 -1
- package/skills/yui-runtime/SKILL.md +27 -0
- package/skills/yui-runtime/references/publication.md +20 -0
|
@@ -342,6 +342,42 @@ export function updateTaskRoleProviderRuntime(set, binding, updatedAt) {
|
|
|
342
342
|
updatedAt: requireDate(updatedAt, "Provider Runtime Binding timestamp")
|
|
343
343
|
});
|
|
344
344
|
}
|
|
345
|
+
/**
|
|
346
|
+
* Bind a Global Role's Provider Runtime evidence, mirroring the Task Role
|
|
347
|
+
* writer (decision-3 §6/§9). Create-only: an existing distinct binding is a
|
|
348
|
+
* conflict, an identical one is idempotent. The Global set stays schemaVersion
|
|
349
|
+
* 5; only the optional providerBinding is added.
|
|
350
|
+
*/
|
|
351
|
+
export function bindGlobalRoleProviderRuntime(set, binding, updatedAt) {
|
|
352
|
+
validateRoleSessionSet(set);
|
|
353
|
+
const normalized = validateProviderRuntimeBinding(binding);
|
|
354
|
+
if (set.providerBinding != null) {
|
|
355
|
+
if (JSON.stringify(set.providerBinding) === JSON.stringify(normalized))
|
|
356
|
+
return set;
|
|
357
|
+
throw new Error("Global Role already has a Provider Runtime Binding.");
|
|
358
|
+
}
|
|
359
|
+
return validateRoleSessionSet({
|
|
360
|
+
...set,
|
|
361
|
+
providerBinding: normalized,
|
|
362
|
+
updatedAt: requireDate(updatedAt, "Provider Runtime Binding timestamp")
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
/** In-place update of a Global Role's Provider Runtime binding; namespace and
|
|
366
|
+
* account scope are immutable, exactly as for a Task Role. */
|
|
367
|
+
export function updateGlobalRoleProviderRuntime(set, binding, updatedAt) {
|
|
368
|
+
validateRoleSessionSet(set);
|
|
369
|
+
const normalized = validateProviderRuntimeBinding(binding);
|
|
370
|
+
if (set.providerBinding == null
|
|
371
|
+
|| normalized.providerNamespace !== set.providerBinding.providerNamespace
|
|
372
|
+
|| normalized.accountScope !== set.providerBinding.accountScope) {
|
|
373
|
+
throw new Error("Provider Runtime Binding identity cannot change in place.");
|
|
374
|
+
}
|
|
375
|
+
return validateRoleSessionSet({
|
|
376
|
+
...set,
|
|
377
|
+
providerBinding: normalized,
|
|
378
|
+
updatedAt: requireDate(updatedAt, "Provider Runtime Binding timestamp")
|
|
379
|
+
});
|
|
380
|
+
}
|
|
345
381
|
/**
|
|
346
382
|
* Detaches a confirmed-dead local Host without ending its resumable native
|
|
347
383
|
* Session. Host connections are disposable execution
|
|
@@ -409,7 +445,7 @@ export function recordTaskRoleNativeTurnBoundary(set, input, completedAt) {
|
|
|
409
445
|
export function validateRoleSessionSet(set) {
|
|
410
446
|
const ownerScope = set.owner?.scope;
|
|
411
447
|
rejectUnknownFields(set, ownerScope === "global"
|
|
412
|
-
? ["schemaVersion", "owner", "activeAgentId", "sessions", "updatedAt", "history"]
|
|
448
|
+
? ["schemaVersion", "owner", "activeAgentId", "sessions", "updatedAt", "history", "providerBinding", "interrupts"]
|
|
413
449
|
: [
|
|
414
450
|
"schemaVersion",
|
|
415
451
|
"owner",
|
|
@@ -428,10 +464,19 @@ export function validateRoleSessionSet(set) {
|
|
|
428
464
|
if (set.schemaVersion !== 5) {
|
|
429
465
|
throw new Error("Global Role session set schema version is invalid.");
|
|
430
466
|
}
|
|
431
|
-
|
|
432
|
-
|
|
467
|
+
const globalSet = set;
|
|
468
|
+
for (const [requestId, control] of Object.entries(globalSet.interrupts ?? {})) {
|
|
469
|
+
requireSafeIdentity(requestId, "Global interrupt request");
|
|
470
|
+
requireText(control.fingerprint, "Global interrupt fingerprint");
|
|
471
|
+
requireText(control.attemptId, "Global interrupt attempt");
|
|
472
|
+
requireText(control.nativeSessionId, "Global interrupt Session");
|
|
473
|
+
requireText(control.receiptId, "Global interrupt receipt");
|
|
474
|
+
if (control.receipt !== undefined
|
|
475
|
+
&& !["interrupt-requested", "interrupt-not-active", "interrupt-unknown", "interrupt-unavailable"]
|
|
476
|
+
.includes(control.receipt.state))
|
|
477
|
+
throw new Error("Global interrupt receipt is invalid.");
|
|
433
478
|
}
|
|
434
|
-
const history =
|
|
479
|
+
const history = globalSet.history;
|
|
435
480
|
if (history !== undefined) {
|
|
436
481
|
for (const [ref, session] of Object.entries(history)) {
|
|
437
482
|
requireSafeIdentity(ref, "Operator session ref");
|
|
@@ -441,6 +486,21 @@ export function validateRoleSessionSet(set) {
|
|
|
441
486
|
}
|
|
442
487
|
}
|
|
443
488
|
}
|
|
489
|
+
// A Global Role now carries the same optional Provider Runtime Binding shape
|
|
490
|
+
// as a Task Role (decision-3 §6/§9). It stays absent on every legacy set;
|
|
491
|
+
// when present, it is the exact native control evidence a Global steer or
|
|
492
|
+
// interrupt targets, validated identically to the Task branch. A fabricated
|
|
493
|
+
// Task binding is never accepted here, and its presence never upgrades the
|
|
494
|
+
// schemaVersion these raw-JSON sets are read at.
|
|
495
|
+
if (Object.hasOwn(globalSet, "providerBinding") && globalSet.providerBinding != null) {
|
|
496
|
+
const providerBinding = validateProviderRuntimeBinding(globalSet.providerBinding);
|
|
497
|
+
const conversationId = currentProviderConversation(providerBinding).conversationId;
|
|
498
|
+
const session = [...Object.values(globalSet.sessions), ...Object.values(globalSet.history ?? {})]
|
|
499
|
+
.find(entry => entry.agentId === providerBinding.accountScope && entry.nativeSessionId === conversationId);
|
|
500
|
+
if (session !== undefined && providerBinding.providerNamespace !== builtinDriverIdForAdapter(session.adapterId)) {
|
|
501
|
+
throw new Error("Provider Runtime Binding namespace does not match the Agent adapter.");
|
|
502
|
+
}
|
|
503
|
+
}
|
|
444
504
|
}
|
|
445
505
|
else {
|
|
446
506
|
if (set.schemaVersion !== 12) {
|
|
@@ -177,6 +177,9 @@ export class ExecutorRegistry {
|
|
|
177
177
|
return deliveryReport(outcome);
|
|
178
178
|
}
|
|
179
179
|
async notifyOperatorInputOnce(input) {
|
|
180
|
+
if (this.runtimePorts?.notifyOperatorInputOnce !== undefined) {
|
|
181
|
+
return this.runtimePorts.notifyOperatorInputOnce(input);
|
|
182
|
+
}
|
|
180
183
|
const probe = this.readiness(input.adapterId, "operator");
|
|
181
184
|
return this.tmux.sendRoleInputOnceIfReadyAsync === undefined
|
|
182
185
|
? this.tmux.sendRoleInputOnceIfReady("operator", input.roleName, input.receiptId, input.text, probe)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
3
|
import { mkdirSync, realpathSync } from "node:fs";
|
|
4
|
-
import {
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { isDeepStrictEqual } from "node:util";
|
|
7
7
|
import { assertExecutionEnvironmentCurrent } from "../runtime/executionEnvironment.js";
|
|
@@ -10,7 +10,7 @@ import { taskOwnsManagedWorkspace } from "../task/task.js";
|
|
|
10
10
|
import { configuredAgentToDefinition, resolveAgentEnvironment } from "../agent/agent.js";
|
|
11
11
|
import { NATIVE_AGENT_ENVIRONMENT_NAMES, nativeAgentEnvironmentNames, operationalAgentEnvironment, selectEnvironment } from "../agent/launchEnvironment.js";
|
|
12
12
|
import { activeRoleAgentBinding } from "../role/role.js";
|
|
13
|
-
import {
|
|
13
|
+
import { planningRuntimeCwd } from "../storage/homeLayout.js";
|
|
14
14
|
import { compileRoleSessionContext, roleSessionKind } from "../context/roleSessionContext.js";
|
|
15
15
|
import { materializeSessionBootstrap } from "../context/sessionBootstrapManifest.js";
|
|
16
16
|
import { resolveAgentAdapter } from "./agentAdapter.js";
|
|
@@ -117,7 +117,7 @@ export class FileRoleLaunchPlanner {
|
|
|
117
117
|
const planningDraft = purpose === "planning" && task.status === "draft";
|
|
118
118
|
// A planning cwd is a disposable per-Task runtime resource, not a delivery
|
|
119
119
|
// workspace. Materialize only the exact directory selected at creation.
|
|
120
|
-
if (planningDraft && resolve(role.workspace) === resolve(
|
|
120
|
+
if (planningDraft && resolve(role.workspace) === resolve(planningRuntimeCwd(this.home, task.id))) {
|
|
121
121
|
mkdirSync(role.workspace, { recursive: true, mode: 0o700 });
|
|
122
122
|
}
|
|
123
123
|
const workspaceFree = planningDraft || !taskOwnsManagedWorkspace(task);
|
|
@@ -236,6 +236,9 @@ export class FileRoleLaunchPlanner {
|
|
|
236
236
|
if (role === null)
|
|
237
237
|
throw new Error(`Global Role not found: ${input.roleName}.`);
|
|
238
238
|
const sessionSet = this.store.getGlobalRoleSessionSet(role.name);
|
|
239
|
+
if (activeLiveRoleAgentSession(sessionSet) !== null && sessionSet?.providerBinding == null) {
|
|
240
|
+
throw new Error("Global Role has an unmanaged live Session. Stop that exact Session before opening controlled input; it will not be silently replaced.");
|
|
241
|
+
}
|
|
239
242
|
const resolvedEffective = activeLiveRoleAgentSession(sessionSet)?.effective
|
|
240
243
|
?? resolveEffectiveLaunch({ role, purpose: "execution" });
|
|
241
244
|
if (input.effective !== undefined
|
|
@@ -249,6 +252,9 @@ export class FileRoleLaunchPlanner {
|
|
|
249
252
|
if (input.mode === "resume" && !compatibleExisting) {
|
|
250
253
|
throw new Error(`Global Role resume effective snapshot drifted: ${role.name}.`);
|
|
251
254
|
}
|
|
255
|
+
if (input.mode === "new" && sessionSet?.providerBinding != null) {
|
|
256
|
+
assertProviderConversationReplaceable(sessionSet.providerBinding);
|
|
257
|
+
}
|
|
252
258
|
return this.#compile(role, input, { scope: "global" }, undefined, input.mode === "resume" && compatibleExisting ? existing.nativeSessionId : undefined, undefined, effective, { purpose: "execution" });
|
|
253
259
|
}
|
|
254
260
|
#compile(role, input, owner, sessionTitle, knownNativeSessionId, workspaceOverride, effective, sessionPolicy) {
|
|
@@ -400,7 +406,6 @@ export class FileRoleLaunchPlanner {
|
|
|
400
406
|
const launchMode = resumeNativeSessionId === undefined
|
|
401
407
|
? "new"
|
|
402
408
|
: "resume";
|
|
403
|
-
const managedControl = owner.scope === "task";
|
|
404
409
|
// Only an Agent that accepts a caller-chosen Session id can have one
|
|
405
410
|
// preallocated. Keying this on the adapter name instead of the declared
|
|
406
411
|
// capability meant every non-Claude adapter was assumed to accept one.
|
|
@@ -408,17 +413,8 @@ export class FileRoleLaunchPlanner {
|
|
|
408
413
|
&& resumeNativeSessionId === undefined
|
|
409
414
|
? requireText(this.#createNativeSessionId(), "Native session id")
|
|
410
415
|
: resumeNativeSessionId;
|
|
411
|
-
const managedCompiled =
|
|
412
|
-
|
|
413
|
-
: undefined;
|
|
414
|
-
const compiled = managedCompiled !== undefined
|
|
415
|
-
? managedCompiled
|
|
416
|
-
: launchMode === "resume"
|
|
417
|
-
? adapter.compileResume({
|
|
418
|
-
...compileInput,
|
|
419
|
-
nativeSessionId: resumeNativeSessionId
|
|
420
|
-
})
|
|
421
|
-
: adapter.compileNew(compileInput);
|
|
416
|
+
const managedCompiled = adapter.compileManagedControl(compileInput, launchMode, preallocatedNativeSessionId);
|
|
417
|
+
const compiled = managedCompiled;
|
|
422
418
|
for (const path of [
|
|
423
419
|
bootstrap.manifestPath,
|
|
424
420
|
bootstrap.sessionCliPath,
|
|
@@ -437,9 +433,6 @@ export class FileRoleLaunchPlanner {
|
|
|
437
433
|
// Its native Hooks carry no such request fence and must not compete with
|
|
438
434
|
// the Host for acceptance, completion, or attachment lifecycle facts.
|
|
439
435
|
// Provider tool permissions remain in compiled config, not this observer.
|
|
440
|
-
if (binding.adapterId === "claude" && owner.scope === "global") {
|
|
441
|
-
args.push("--plugin-dir", ensureClaudeLifecyclePlugin(this.home, this.#cliPath));
|
|
442
|
-
}
|
|
443
436
|
if (binding.adapterId === "codex") {
|
|
444
437
|
// Interactive Task sessions may use notify for presentation.
|
|
445
438
|
// Managed AgentRuns receive lifecycle facts through their ordinary App Server
|
|
@@ -459,9 +452,7 @@ export class FileRoleLaunchPlanner {
|
|
|
459
452
|
else if (launchMode === "new") {
|
|
460
453
|
if (adapter.capabilities.nativeSessionDiscovery === "preallocated") {
|
|
461
454
|
const nativeSessionId = requireText(preallocatedNativeSessionId, "Native session id");
|
|
462
|
-
if (!
|
|
463
|
-
args.push("--session-id", nativeSessionId);
|
|
464
|
-
else if (!args.includes("--session-id"))
|
|
455
|
+
if (!args.includes("--session-id"))
|
|
465
456
|
args.push("--session-id", nativeSessionId);
|
|
466
457
|
session = readySession(input.agentId, binding.adapterId, nativeSessionId, effective);
|
|
467
458
|
}
|
|
@@ -484,76 +475,81 @@ export class FileRoleLaunchPlanner {
|
|
|
484
475
|
// Session lifecycle and AgentRun submission are separate atomic operations.
|
|
485
476
|
// Planning only starts or restores the exact native Session; delivery
|
|
486
477
|
// submits the AgentRun input after that Session fact is durable.
|
|
487
|
-
if (
|
|
478
|
+
if (owner.scope === "task" && input.runId !== undefined && (managedRun === null || managedRun.status !== "active")) {
|
|
488
479
|
throw new Error(`Managed AgentRun is no longer active: ${input.runId}.`);
|
|
489
480
|
}
|
|
490
|
-
const providerAuthority =
|
|
491
|
-
|
|
492
|
-
: undefined;
|
|
493
|
-
const providerOwnedRun = managedControl && input.mode === "resume" && input.runId !== undefined
|
|
481
|
+
const providerAuthority = this.#providerAuthorityForLaunch(owner.scope === "task" ? owner.taskId : undefined, role.name, input.mode);
|
|
482
|
+
let providerOwnedRun = owner.scope === "task" && input.mode === "resume" && input.runId !== undefined
|
|
494
483
|
? this.#providerOwnedRunForLaunch(owner.taskId, role.name, input.runId)
|
|
495
484
|
: undefined;
|
|
485
|
+
if (owner.scope === "global" && input.mode === "resume") {
|
|
486
|
+
const turn = this.store.getGlobalRoleSessionSet(role.name)?.providerBinding?.run;
|
|
487
|
+
if (turn?.status === "accepted") {
|
|
488
|
+
if (binding.adapterId !== "codex" || turn.nativeTurnId === undefined) {
|
|
489
|
+
throw new Error("This Global active Turn cannot be restored with exact native identity.");
|
|
490
|
+
}
|
|
491
|
+
providerOwnedRun = { attemptId: turn.attemptId, turnId: turn.nativeTurnId };
|
|
492
|
+
}
|
|
493
|
+
else if (turn != null && ["submitting", "delivery-unknown"].includes(turn.status)) {
|
|
494
|
+
throw new Error("Global input delivery is unconfirmed; resolve its exact current attempt before restoring.");
|
|
495
|
+
}
|
|
496
|
+
}
|
|
496
497
|
const providerNativeSessionId = binding.adapterId === "claude"
|
|
497
498
|
? preallocatedNativeSessionId
|
|
498
499
|
: resumeNativeSessionId;
|
|
499
|
-
const providerControl =
|
|
500
|
-
?
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
:
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
authority: providerAuthority
|
|
546
|
-
};
|
|
500
|
+
const providerControl = input.mode === "resume"
|
|
501
|
+
? {
|
|
502
|
+
schemaVersion: 1,
|
|
503
|
+
adapterId: binding.adapterId,
|
|
504
|
+
// The product identity is pinned by the snapshot this launch was
|
|
505
|
+
// resolved from, and the check above proves the Agent record still
|
|
506
|
+
// names it. Carrying only the adapter would leave the runtime with
|
|
507
|
+
// two products sharing one plan and no way to tell them apart.
|
|
508
|
+
component: binding.component,
|
|
509
|
+
transport: managedCompiled.transport,
|
|
510
|
+
endpointImplementation,
|
|
511
|
+
kind: "restore",
|
|
512
|
+
sessionOnly: input.runId === undefined,
|
|
513
|
+
mode: "resume",
|
|
514
|
+
nativeSessionId: requireText(providerNativeSessionId, "Managed Provider restore native session id"),
|
|
515
|
+
...(sessionTitle === undefined ? {} : { sessionTitle }),
|
|
516
|
+
...(managedCompiled.codexThread === undefined
|
|
517
|
+
? {}
|
|
518
|
+
: { codexThread: managedCompiled.codexThread }),
|
|
519
|
+
...(providerOwnedRun === undefined ? {} : { ownedTurn: providerOwnedRun }),
|
|
520
|
+
...(managedCompiled.acpSession === undefined
|
|
521
|
+
? {}
|
|
522
|
+
: { acpSession: managedCompiled.acpSession }),
|
|
523
|
+
authority: providerAuthority
|
|
524
|
+
}
|
|
525
|
+
: {
|
|
526
|
+
schemaVersion: 1,
|
|
527
|
+
adapterId: binding.adapterId,
|
|
528
|
+
component: binding.component,
|
|
529
|
+
transport: managedCompiled.transport,
|
|
530
|
+
endpointImplementation,
|
|
531
|
+
kind: "start",
|
|
532
|
+
sessionOnly: input.runId === undefined,
|
|
533
|
+
mode: "new",
|
|
534
|
+
...(providerNativeSessionId === undefined
|
|
535
|
+
? {}
|
|
536
|
+
: { nativeSessionId: providerNativeSessionId }),
|
|
537
|
+
...(sessionTitle === undefined ? {} : { sessionTitle }),
|
|
538
|
+
...(managedCompiled.codexThread === undefined
|
|
539
|
+
? {}
|
|
540
|
+
: { codexThread: managedCompiled.codexThread }),
|
|
541
|
+
...(managedCompiled.acpSession === undefined
|
|
542
|
+
? {}
|
|
543
|
+
: { acpSession: managedCompiled.acpSession }),
|
|
544
|
+
authority: providerAuthority
|
|
545
|
+
};
|
|
547
546
|
const launch = {
|
|
548
547
|
command,
|
|
549
548
|
args,
|
|
550
549
|
...(effective.executionEnvironment === undefined ? {} : {
|
|
551
550
|
executionEnvironment: structuredClone(effective.executionEnvironment)
|
|
552
551
|
}),
|
|
553
|
-
|
|
554
|
-
...(owner.scope === "global" && binding.adapterId === "codex"
|
|
555
|
-
? { interactiveCodexThread: compiled.codexThread }
|
|
556
|
-
: {}),
|
|
552
|
+
providerControl,
|
|
557
553
|
env: {
|
|
558
554
|
...launchEnvironment,
|
|
559
555
|
YUI_HOME: resolve(this.home),
|
|
@@ -593,13 +589,7 @@ export class FileRoleLaunchPlanner {
|
|
|
593
589
|
const scopedLaunch = owner.scope === "task"
|
|
594
590
|
? this.#applyWorkspaceScope(owner.taskId, role, launch, workspaceOverride)
|
|
595
591
|
: launch;
|
|
596
|
-
const
|
|
597
|
-
? {
|
|
598
|
-
...scopedLaunch,
|
|
599
|
-
args: addCodexSharedDaemonRemote(scopedLaunch.args, launchMode, scopedLaunch.env)
|
|
600
|
-
}
|
|
601
|
-
: scopedLaunch;
|
|
602
|
-
const ordinaryConversationLaunch = withCodexThreadEnvironment(sharedDaemonLaunch);
|
|
592
|
+
const ordinaryConversationLaunch = withCodexThreadEnvironment(scopedLaunch);
|
|
603
593
|
return {
|
|
604
594
|
role: {
|
|
605
595
|
name: role.name,
|
|
@@ -612,7 +602,9 @@ export class FileRoleLaunchPlanner {
|
|
|
612
602
|
};
|
|
613
603
|
}
|
|
614
604
|
#providerAuthorityForLaunch(taskId, roleName, mode) {
|
|
615
|
-
const binding =
|
|
605
|
+
const binding = (taskId === undefined
|
|
606
|
+
? this.store.getGlobalRoleSessionSet(roleName)
|
|
607
|
+
: this.store.getTaskRoleSessionSet(taskId, roleName))?.providerBinding;
|
|
616
608
|
if (binding === null || binding === undefined) {
|
|
617
609
|
return { epoch: 1, owner: "controller", holderId: "controller" };
|
|
618
610
|
}
|
|
@@ -743,38 +735,6 @@ function workspaceScopeEnvironment(environment, workspace) {
|
|
|
743
735
|
])))
|
|
744
736
|
};
|
|
745
737
|
}
|
|
746
|
-
function ensureClaudeLifecyclePlugin(home, cliPath) {
|
|
747
|
-
const root = join(resolve(home), "runtime", "claude-lifecycle-plugin");
|
|
748
|
-
writeTextFileAtomically(join(root, ".claude-plugin", "plugin.json"), `${JSON.stringify({
|
|
749
|
-
name: "yui-runtime-lifecycle",
|
|
750
|
-
description: "Yui-owned native lifecycle transport",
|
|
751
|
-
version: "1.0.0"
|
|
752
|
-
}, null, 2)}\n`);
|
|
753
|
-
const command = {
|
|
754
|
-
type: "command",
|
|
755
|
-
command: canonicalPath(process.execPath),
|
|
756
|
-
args: [canonicalPath(cliPath), "internal", "runtime-hook"]
|
|
757
|
-
};
|
|
758
|
-
writeTextFileAtomically(join(root, "hooks", "hooks.json"), `${JSON.stringify({
|
|
759
|
-
hooks: {
|
|
760
|
-
// All native names terminate at the Driver edge; core sees only
|
|
761
|
-
// canonical RuntimeObservation values.
|
|
762
|
-
SessionStart: [{ hooks: [command] }],
|
|
763
|
-
UserPromptSubmit: [{ hooks: [command] }],
|
|
764
|
-
PreToolUse: [{ hooks: [command] }],
|
|
765
|
-
PermissionRequest: [{ hooks: [command] }],
|
|
766
|
-
MessageDisplay: [{ hooks: [command] }],
|
|
767
|
-
PostToolUse: [{ hooks: [command] }],
|
|
768
|
-
PostToolUseFailure: [{ hooks: [command] }],
|
|
769
|
-
SubagentStart: [{ hooks: [command] }],
|
|
770
|
-
SubagentStop: [{ hooks: [command] }],
|
|
771
|
-
Stop: [{ hooks: [command] }],
|
|
772
|
-
StopFailure: [{ hooks: [command] }],
|
|
773
|
-
SessionEnd: [{ hooks: [command] }]
|
|
774
|
-
}
|
|
775
|
-
}, null, 2)}\n`);
|
|
776
|
-
return root;
|
|
777
|
-
}
|
|
778
738
|
function managedClaudeControlPlaneConfig(config, taskId, workItemId, runId) {
|
|
779
739
|
if (config.permission.strategy !== "configured")
|
|
780
740
|
return config;
|
|
@@ -93,7 +93,8 @@ export function latestGoverningQueueEntries(changeSets, queueEntries) {
|
|
|
93
93
|
export function integrationAttemptRequiresSettlement(attempt) {
|
|
94
94
|
return attempt.status === "running"
|
|
95
95
|
|| attempt.status === "validating"
|
|
96
|
-
|| attempt.status === "blocked"
|
|
96
|
+
|| attempt.status === "blocked"
|
|
97
|
+
|| attempt.status === "conflicted";
|
|
97
98
|
}
|
|
98
99
|
function candidateProjectHead(candidate, projectId) {
|
|
99
100
|
return candidate.gitSnapshot?.projects.find((project) => project.projectId === projectId)?.commit
|