@zq-silk/yui 0.8.1 → 0.8.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 +27 -28
- package/README.md +35 -46
- package/dist/cli/commandCatalog.js +49 -14
- package/dist/cli/interactionPolicy.js +4 -10
- package/dist/cli/invocationRouter.js +2 -1
- package/dist/cli.js +73 -21
- package/dist/commands/taskCommands.js +108 -53
- package/dist/controller/fileSchedulerStoreAdapter.js +389 -70
- package/dist/controller/resourceInventory.js +9 -5
- package/dist/controller/runtime.js +80 -7
- package/dist/controller/runtimeLaunchCoordinator.js +18 -78
- package/dist/controller/structuredProviderObservation.js +273 -0
- package/dist/executor/agentAdapter.js +40 -0
- package/dist/executor/agentExecutor.js +31 -7
- package/dist/executor/executorRegistry.js +11 -49
- package/dist/executor/fileRoleLaunchPlanner.js +115 -37
- package/dist/lifecycle/canonicalLifecycleEvent.js +5 -2
- package/dist/run/agentRun.js +2 -2
- package/dist/runtime/agentHost.js +767 -158
- package/dist/runtime/builtinAgentDrivers.js +1 -5
- package/dist/runtime/codexAppServerRuntime.js +67 -60
- package/dist/runtime/exactControlPlane.js +7 -2
- package/dist/runtime/index.js +6 -2
- package/dist/runtime/launchBroker.js +30 -8
- package/dist/runtime/providerAuthorityFence.js +24 -0
- package/dist/runtime/providerControl.js +63 -0
- package/dist/runtime/providerRecoveryDecision.js +55 -0
- package/dist/runtime/providerRuntimeIdentity.js +269 -19
- package/dist/runtime/runtimeBinding.js +20 -11
- package/dist/runtime/structuredProviderHost.js +476 -0
- package/dist/runtime/tmuxAdapters.js +143 -42
- package/dist/scheduler/activeRoleRunDelivery.js +206 -120
- package/dist/scheduler/leaderWakeupProcessor.js +141 -16
- package/dist/storage/migration/productionRegistry.js +111 -0
- package/dist/storage/taskStore.js +1 -1
- package/dist/tmux/tmuxManager.js +1 -1
- package/i18n/README.zh-CN.md +11 -8
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { isDeepStrictEqual } from "node:util";
|
|
3
3
|
import { createRunAssignment } from "../context/runContextContract.js";
|
|
4
4
|
import { buildRunContextPack, buildRunContextDelta, contextSnapshotDeltaRefIds, expandRunContextRef, freezeRunContextSnapshot } from "../context/runContextPack.js";
|
|
@@ -7,7 +7,8 @@ import { CliError, dataError, roleNotFound, runtimeError, taskNotFound, usageErr
|
|
|
7
7
|
import { createTaskEvent } from "../event/taskEvent.js";
|
|
8
8
|
import { clearMatchingLeaderStallAttention, isRoleRunStalled, RUN_PROGRESS_EVENT, RUN_RECOVERED_EVENT } from "../scheduler/roleRunStall.js";
|
|
9
9
|
import { readCommandText } from "./textInput.js";
|
|
10
|
-
import { createRoleSessionSet, roleAgentSessionResumeMode } from "../executor/agentExecutor.js";
|
|
10
|
+
import { createRoleSessionSet, roleAgentSessionResumeMode, updateTaskRoleProviderRuntime } from "../executor/agentExecutor.js";
|
|
11
|
+
import { currentProviderActivation, transferProviderAuthority } from "../runtime/providerRuntimeIdentity.js";
|
|
11
12
|
import { resolveEffectiveLaunch } from "../executor/effectiveLaunch.js";
|
|
12
13
|
import { defaultTableWidth, renderTable } from "../output/table.js";
|
|
13
14
|
import { formatTimestamp } from "../output/timePresentation.js";
|
|
@@ -16,7 +17,7 @@ import { createTaskMessage, taskMessageAuthorLabel } from "../message/message.js
|
|
|
16
17
|
import { cancelInputRequest } from "../input/inputRequest.js";
|
|
17
18
|
import { recoverExactAgentRun, terminalizeExactTaskRun, validateExactRunReviewRound } from "../lifecycle/exactRunTerminalization.js";
|
|
18
19
|
import { resetTaskRoleSessionGeneration } from "../lifecycle/taskRoleSessionReset.js";
|
|
19
|
-
import {
|
|
20
|
+
import { copyGlobalRoleToTaskRole, createRole, createRoleAgentBinding, switchActiveRoleAgent, unbindRoleAgent, updateRole, updateRoleStatus } from "../role/role.js";
|
|
20
21
|
import { agentRunDeliveryReceiptId, createAgentRun, withAgentRunContextSnapshot } from "../run/agentRun.js";
|
|
21
22
|
import { projectRunRecovery, readRunRecoveryFacts } from "../run/recoveryProjection.js";
|
|
22
23
|
import { matchYieldReceipt } from "../run/yieldReceipt.js";
|
|
@@ -240,7 +241,6 @@ export function runTaskCommand(args, store, options = {}) {
|
|
|
240
241
|
case "milestone": return taskMilestoneCommand(rest, store, options);
|
|
241
242
|
case "event": return taskEventCommand(rest, store);
|
|
242
243
|
case "continuation": return taskContinuationCommand(rest, store);
|
|
243
|
-
case "enter": return enterTaskRoleAlias(rest, store, options);
|
|
244
244
|
default:
|
|
245
245
|
throw usageError(command === undefined
|
|
246
246
|
? "Task command is required."
|
|
@@ -429,8 +429,8 @@ function updateTaskCommand(args, store, options) {
|
|
|
429
429
|
/** Compatibility helper for call sites that cannot yet handle foreground enter. */
|
|
430
430
|
export function runTaskOutputCommand(args, store, options = {}) {
|
|
431
431
|
const execution = runTaskCommand(args, store, options);
|
|
432
|
-
if (execution.kind
|
|
433
|
-
throw runtimeError("Task
|
|
432
|
+
if (execution.kind !== "output") {
|
|
433
|
+
throw runtimeError("Task Role foreground runtime control requires the CLI.");
|
|
434
434
|
}
|
|
435
435
|
return execution.output;
|
|
436
436
|
}
|
|
@@ -1192,8 +1192,12 @@ function taskRoleCommand(args, store, options) {
|
|
|
1192
1192
|
return output(unbindTaskRole(rest, store, options));
|
|
1193
1193
|
if (command === "reset")
|
|
1194
1194
|
return resetTaskRole(rest, store, options);
|
|
1195
|
-
if (command === "
|
|
1196
|
-
return
|
|
1195
|
+
if (command === "view")
|
|
1196
|
+
return viewTaskRole(rest, store);
|
|
1197
|
+
if (command === "takeover")
|
|
1198
|
+
return transferTaskRoleAuthority(rest, store, options, "takeover");
|
|
1199
|
+
if (command === "release")
|
|
1200
|
+
return transferTaskRoleAuthority(rest, store, options, "release");
|
|
1197
1201
|
throw usageError(command === undefined
|
|
1198
1202
|
? "Task role command is required."
|
|
1199
1203
|
: `Unknown command: task role ${command}`);
|
|
@@ -1506,60 +1510,111 @@ function unbindTaskRole(args, store, options) {
|
|
|
1506
1510
|
});
|
|
1507
1511
|
return `Unbound Agent ${args[2]} from ${result.taskId}/${result.name}\n`;
|
|
1508
1512
|
}
|
|
1509
|
-
function
|
|
1510
|
-
const usage = "Task role
|
|
1511
|
-
|
|
1512
|
-
const
|
|
1513
|
-
exactPositionals(parsed.positionals, 2, usage);
|
|
1514
|
-
if (parsed.options.has("--read-only") && parsed.options.has("--read-write")) {
|
|
1515
|
-
throw usageError("--read-only and --read-write are mutually exclusive.", usage);
|
|
1516
|
-
}
|
|
1517
|
-
const task = requireTask(store, parsed.positionals[0]);
|
|
1513
|
+
function viewTaskRole(args, store) {
|
|
1514
|
+
const usage = "Task role view usage: yui task role view <task> <role>.";
|
|
1515
|
+
exactPositionals(args, 2, usage);
|
|
1516
|
+
const task = requireTask(store, args[0]);
|
|
1518
1517
|
if (task.status !== "active") {
|
|
1519
|
-
throw usageError(inactiveTaskMessage(task, "
|
|
1518
|
+
throw usageError(inactiveTaskMessage(task, "viewing a role session"));
|
|
1520
1519
|
}
|
|
1521
|
-
const role = requireRole(store, task.id,
|
|
1522
|
-
const
|
|
1523
|
-
if (
|
|
1524
|
-
|
|
1520
|
+
const role = requireRole(store, task.id, args[1]);
|
|
1521
|
+
const session = store.getRoleSession(task.id, role.name);
|
|
1522
|
+
if (session === null || session.status === "stopped" || session.status === "broken") {
|
|
1523
|
+
throw usageError(`Task Role has no live Provider view: ${task.id}/${role.name}.`);
|
|
1525
1524
|
}
|
|
1526
1525
|
return {
|
|
1527
|
-
kind: "
|
|
1526
|
+
kind: "view",
|
|
1528
1527
|
taskId: task.id,
|
|
1529
1528
|
roleName: role.name,
|
|
1530
|
-
access,
|
|
1531
|
-
output: `
|
|
1529
|
+
access: "read-only",
|
|
1530
|
+
output: `Viewing ${role.name} for ${task.id} (read-only)\n`
|
|
1532
1531
|
};
|
|
1533
1532
|
}
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1533
|
+
function transferTaskRoleAuthority(args, store, options, action) {
|
|
1534
|
+
const usage = `Task role ${action} usage: yui task role ${action} <task> <role>.`;
|
|
1535
|
+
exactPositionals(args, 2, usage);
|
|
1536
|
+
const now = clock(options);
|
|
1537
|
+
try {
|
|
1538
|
+
return store.transaction((tx) => {
|
|
1539
|
+
const task = requireTask(tx, args[0]);
|
|
1540
|
+
if (task.status !== "active") {
|
|
1541
|
+
throw usageError(inactiveTaskMessage(task, `${action} Provider authority`));
|
|
1542
|
+
}
|
|
1543
|
+
const role = requireRole(tx, task.id, args[1]);
|
|
1544
|
+
const sessions = tx.getTaskRoleSessionSet(task.id, role.name);
|
|
1545
|
+
const session = sessions?.sessions[role.activeAgentId];
|
|
1546
|
+
const binding = sessions?.providerBinding;
|
|
1547
|
+
if (sessions === null || sessions === undefined || session === undefined
|
|
1548
|
+
|| binding === null || binding === undefined
|
|
1549
|
+
|| session.launchId === undefined
|
|
1550
|
+
|| session.status === "stopped" || session.status === "broken") {
|
|
1551
|
+
throw new Error(`Task Role has no live managed Provider: ${task.id}/${role.name}.`);
|
|
1552
|
+
}
|
|
1553
|
+
const activation = currentProviderActivation(binding);
|
|
1554
|
+
if (activation === null) {
|
|
1555
|
+
throw new Error(`Provider Activation is not live: ${task.id}/${role.name}.`);
|
|
1556
|
+
}
|
|
1557
|
+
if (action === "takeover") {
|
|
1558
|
+
const activeRun = tx.getActiveAgentRun(task.id, role.name);
|
|
1559
|
+
if (sessions.inFlight === null || activeRun?.id !== sessions.inFlight.runId) {
|
|
1560
|
+
throw new Error(`Task Role has no active managed Run for takeover: ${task.id}/${role.name}.`);
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
if (action === "takeover"
|
|
1564
|
+
&& binding.authority.owner !== "controller"
|
|
1565
|
+
&& binding.authority.owner !== "human") {
|
|
1566
|
+
throw new Error(`Provider authority is not Controller-owned: ${task.id}/${role.name}.`);
|
|
1567
|
+
}
|
|
1568
|
+
if (action === "release"
|
|
1569
|
+
&& binding.authority.owner !== "human"
|
|
1570
|
+
&& binding.authority.owner !== "controller") {
|
|
1571
|
+
throw new Error(`Provider authority is not human-owned: ${task.id}/${role.name}.`);
|
|
1572
|
+
}
|
|
1573
|
+
const desiredOwner = action === "takeover" ? "human" : "controller";
|
|
1574
|
+
const unchanged = binding.authority.owner === desiredOwner;
|
|
1575
|
+
const updatedBinding = unchanged
|
|
1576
|
+
? binding
|
|
1577
|
+
: transferProviderAuthority(binding, {
|
|
1578
|
+
expectedEpoch: binding.authority.epoch,
|
|
1579
|
+
expectedOwner: binding.authority.owner,
|
|
1580
|
+
owner: desiredOwner,
|
|
1581
|
+
holderId: action === "takeover" ? `human:${randomUUID()}` : activation.activationId,
|
|
1582
|
+
changedAt: now.toISOString()
|
|
1583
|
+
});
|
|
1584
|
+
const authority = updatedBinding.authority;
|
|
1585
|
+
if (authority.owner !== "controller" && authority.owner !== "human") {
|
|
1586
|
+
throw new Error("Provider authority transfer did not produce a writer.");
|
|
1587
|
+
}
|
|
1588
|
+
if (!unchanged) {
|
|
1589
|
+
tx.saveTaskRoleSessionSet(updateTaskRoleProviderRuntime(sessions, updatedBinding, now));
|
|
1590
|
+
recordTaskEvent(tx, task.id, "runtime.provider-authority-transferred", {
|
|
1591
|
+
role: role.name,
|
|
1592
|
+
owner: authority.owner,
|
|
1593
|
+
holderId: authority.holderId,
|
|
1594
|
+
epoch: String(authority.epoch)
|
|
1595
|
+
}, now);
|
|
1596
|
+
}
|
|
1597
|
+
return {
|
|
1598
|
+
kind: "authority",
|
|
1599
|
+
action,
|
|
1600
|
+
taskId: task.id,
|
|
1601
|
+
roleName: role.name,
|
|
1602
|
+
launchId: session.launchId,
|
|
1603
|
+
nativeSessionId: session.nativeSessionId,
|
|
1604
|
+
authority: {
|
|
1605
|
+
epoch: authority.epoch,
|
|
1606
|
+
owner: authority.owner,
|
|
1607
|
+
holderId: authority.holderId
|
|
1608
|
+
},
|
|
1609
|
+
output: action === "takeover"
|
|
1610
|
+
? `Human authority ${unchanged ? "replayed" : "acquired"} for ${task.id}/${role.name} at epoch ${authority.epoch}.\n`
|
|
1611
|
+
: `Controller authority ${unchanged ? "replayed" : "restored"} for ${task.id}/${role.name} at epoch ${authority.epoch}.\n`
|
|
1612
|
+
};
|
|
1613
|
+
});
|
|
1614
|
+
}
|
|
1615
|
+
catch (error) {
|
|
1616
|
+
throw usageError(messageOf(error), usage);
|
|
1556
1617
|
}
|
|
1557
|
-
return enterTaskRole([
|
|
1558
|
-
parsed.positionals[0],
|
|
1559
|
-
parsed.positionals[1] ?? LEADER_ROLE,
|
|
1560
|
-
...(parsed.options.has("--read-only") ? ["--read-only"] : []),
|
|
1561
|
-
...(parsed.options.has("--read-write") ? ["--read-write"] : [])
|
|
1562
|
-
], store, options);
|
|
1563
1618
|
}
|
|
1564
1619
|
function taskWorkCommand(args, store, options) {
|
|
1565
1620
|
const [command, ...rest] = args;
|