@zq-silk/yui 1.1.2 → 2.1.0
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 +2 -1
- package/ARCHITECTURE.zh-CN.md +2 -1
- package/README.md +2 -0
- package/dist/cli/commandCatalog.js +344 -324
- package/dist/cli/commandDiscovery.js +69 -0
- package/dist/cli/completion.js +22 -227
- package/dist/cli/dynamicCompletion.js +12 -6
- package/dist/cli/invocationAuthority.js +2 -2
- package/dist/cli/invocationRouter.js +18 -7
- package/dist/cli/managedDiagnostics.js +2 -1
- package/dist/cli/updatePorts.js +0 -5
- package/dist/cli.js +184 -130
- package/dist/commands/capabilityCommands.js +5 -5
- package/dist/commands/controllerCommands.js +2 -1
- package/dist/commands/globalRoleCommands.js +86 -44
- package/dist/commands/grantCommands.js +48 -8
- package/dist/commands/taskCommands.js +157 -196
- package/dist/commands/taskContextCommand.js +29 -6
- package/dist/commands/taskFactCommands.js +10 -69
- package/dist/commands/taskInputCommands.js +26 -35
- package/dist/commands/taskPublicationCommands.js +2 -35
- package/dist/commands/taskPublicationVerifyCommand.js +1 -2
- package/dist/commands/taskUpstreamCommands.js +2 -1
- package/dist/context/runContextPack.js +8 -29
- package/dist/context/sessionBootstrapManifest.js +5 -101
- package/dist/context/taskContext.js +104 -41
- package/dist/controller/clientRuntime.js +16 -8
- package/dist/controller/fileSchedulerStoreAdapter.js +24 -0
- package/dist/controller/runtime.js +6 -0
- package/dist/core/controllerClient.js +46 -21
- package/dist/core/protocol.js +12 -7
- package/dist/doctor/doctor.js +4 -3
- package/dist/errors/cliError.js +4 -4
- package/dist/errors/cliFailure.js +213 -0
- package/dist/executor/fileRoleLaunchPlanner.js +1 -4
- package/dist/grant/capabilityGrant.js +13 -0
- package/dist/grant/taskAuthorization.js +127 -0
- package/dist/kernel/accessAssessment.js +1 -0
- package/dist/kernel/builtinCapabilities.js +88 -9
- package/dist/kernel/capabilityRegistry.js +64 -19
- package/dist/kernel/kernelPorts.js +2 -2
- package/dist/nativeAgent/agent.js +173 -0
- package/dist/nativeAgent/contracts.js +1 -0
- package/dist/nativeAgent/demo.js +29 -0
- package/dist/nativeAgent/index.js +3 -0
- package/dist/nativeAgent/mockProvider.js +43 -0
- package/dist/nativeAgent/textTools.js +156 -0
- package/dist/nativeAgent/validation.js +95 -0
- package/dist/output/boundedRead.js +118 -0
- package/dist/plugins/pluginService.js +98 -8
- package/dist/release/releaseWorkflowEngine.js +8 -1
- package/dist/resources/projectResourceService.js +23 -1
- package/dist/runtime/managedCaller.js +2 -2
- package/dist/runtime/managedIdentity.js +6 -0
- package/dist/runtime/runtimeCoherence.js +10 -8
- package/dist/storage/sqliteSchema.js +10 -0
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/taskStore.js +3 -0
- package/dist/surface/surfaceContributions.js +3 -0
- package/dist/task/leaderArchive.js +111 -0
- package/dist/task/leaderArchiveAuthority.js +24 -0
- package/dist/task/taskAuthority.js +5 -10
- package/dist/tmux/commandExecutor.js +7 -5
- package/dist/web/assets/assetManifest.js +38 -22
- package/dist/web/assets/client/api.js +115 -0
- package/dist/web/assets/client/app.js +555 -863
- package/dist/web/assets/client/components.js +323 -897
- package/dist/web/assets/client/detail.js +333 -0
- package/dist/web/assets/client/dock.js +225 -0
- package/dist/web/assets/client/dom.js +55 -3
- package/dist/web/assets/client/evidence.js +172 -0
- package/dist/web/assets/client/format.js +25 -14
- package/dist/web/assets/client/forms.js +230 -0
- package/dist/web/assets/client/i18n.js +1020 -791
- package/dist/web/assets/client/overview.js +115 -0
- package/dist/web/assets/client/records.js +63 -0
- package/dist/web/assets/client/sections.js +313 -0
- package/dist/web/assets/client/sidebar.js +117 -0
- package/dist/web/assets/client/theme.js +61 -22
- package/dist/web/assets/icons.js +39 -0
- package/dist/web/assets/shell.js +124 -118
- package/dist/web/assets/styles/base.js +41 -0
- package/dist/web/assets/styles/components.js +167 -0
- package/dist/web/assets/styles/layout.js +49 -77
- package/dist/web/assets/styles/markdown.js +16 -24
- package/dist/web/assets/styles/responsive.js +33 -44
- package/dist/web/assets/styles/tokens.js +65 -89
- package/dist/web/assets/styles/views.js +289 -0
- package/dist/web/webServer.js +2 -1
- package/docs/architecture/README.md +1 -0
- package/docs/architecture/README.zh-CN.md +1 -0
- package/docs/cli-information-contract.md +107 -0
- package/docs/cli-information-contract.zh-CN.md +81 -0
- package/docs/managed-turn-and-session-runtime.md +9 -0
- package/docs/managed-turn-and-session-runtime.zh-CN.md +6 -0
- package/docs/plugin-sdk.md +7 -3
- package/docs/plugin-sdk.zh-CN.md +5 -2
- package/docs/release-workflow.md +42 -9
- package/docs/release-workflow.zh-CN.md +30 -7
- package/docs/storage-baseline.md +5 -0
- package/docs/testing/verification-levels.md +2 -2
- package/i18n/README.zh-CN.md +2 -0
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +8 -1
- package/skills/yui-leader/references/authorization.md +64 -0
- package/skills/yui-leader/references/execution.md +18 -4
- package/skills/yui-leader/references/task-plugins.md +4 -2
- package/skills/yui-operator/SKILL.md +9 -2
- package/skills/yui-runtime/SKILL.md +77 -9
- package/skills/yui-runtime/references/publication.md +3 -1
- package/dist/web/assets/client/taskSummary.js +0 -350
- package/dist/web/assets/client/taskSurface.js +0 -616
- package/dist/web/assets/client/view.js +0 -608
- package/dist/web/assets/styles/cards.js +0 -247
- package/dist/web/assets/styles/widgets.js +0 -168
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { isDeepStrictEqual } from "node:util";
|
|
3
3
|
import { agentExecutionComponentLabel } from "../agent/executionComponents.js";
|
|
4
|
+
import { assertLeaderArchiveAdmission } from "../task/leaderArchiveAuthority.js";
|
|
4
5
|
import { createRun, runExecutionObservation, runPurposeAdmitsTaskState } from "../agentRun/agentRun.js";
|
|
5
6
|
import { isGitArtifactRefString, parseGitArtifactRef } from "../artifacts/gitArtifactRef.js";
|
|
6
7
|
import { contextSnapshotRef } from "../context/contextSnapshot.js";
|
|
7
8
|
import { buildRunContextDelta, buildRunContextPack, contextSnapshotDeltaRefIds, expandRunContextRef, freezeReviewStageContextSnapshot, freezeRunContextSnapshot, freezeWorkItemExecutionAssignmentContextSnapshot, readRunContextSnapshot, synthesisSourceRunIds } from "../context/runContextPack.js";
|
|
8
9
|
import { createRunInput } from "../context/runInputContract.js";
|
|
9
10
|
import { parseTaskCatalogOptions, readTaskCatalog, renderTaskCatalog } from "../context/taskCatalog.js";
|
|
10
|
-
import {
|
|
11
|
+
import { assertContextRecordReadable } from "../context/taskContext.js";
|
|
12
|
+
import { boundedDocument, readOptions, messageReceipt, recordPage } from "../output/boundedRead.js";
|
|
11
13
|
import { referencedWakeRunIds } from "../context/wakeRunReferences.js";
|
|
12
14
|
import { completeProcessing, releaseProcessing } from "../coordination/workMailbox.js";
|
|
13
15
|
import { enqueueRoleRunDispatch, enqueueWork, settleExactWorkExecution } from "../coordination/workMailboxQueue.js";
|
|
@@ -36,7 +38,7 @@ import { projectReviewerAvailability } from "../review/reviewerAvailability.js";
|
|
|
36
38
|
import { attachReviewExecutionGroup, createReviewRound, createTaskDeltaReviewRound, createTaskReviewRound, finishReviewRound, recordReviewWorkspaceDisposition, retryReviewRound, retryRunningReviewExecutionLane, retryTaskReviewRound, startReplicatedReviewRound, startReviewRound, updateReviewExecutionGroup, validateTaskReviewCandidate } from "../review/reviewRound.js";
|
|
37
39
|
import { sameTaskFinalReviewContract, taskFinalReviewConfig, validateTaskFinalReviewContract } from "../review/taskFinalReviewContract.js";
|
|
38
40
|
import { resolveRecordedTaskFinalReviewContract } from "../review/taskFinalReviewContractResolution.js";
|
|
39
|
-
import { copyGlobalRoleToTaskRole, createRole, createRoleAgentBinding, switchActiveRoleAgent, unbindRoleAgent, updateRole } from "../role/role.js";
|
|
41
|
+
import { copyGlobalRoleToTaskRole, activeRoleAgentBinding, createRole, createRoleAgentBinding, switchActiveRoleAgent, unbindRoleAgent, updateRole } from "../role/role.js";
|
|
40
42
|
import { roleLaunchEventPayload, saveTaskRoleUpdate } from "../role/taskRoleUpdate.js";
|
|
41
43
|
import { RUNTIME_SESSION_REPLACE_REQUIRED_REASON, runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
|
|
42
44
|
import { currentManagedRuntime, resolveManagedTaskReader } from "../runtime/managedCaller.js";
|
|
@@ -70,10 +72,12 @@ import { runGrantCommand } from "./grantCommands.js";
|
|
|
70
72
|
import { hasAgentConfigOptions, hasNoRoleMutation, parseRoleOptions, patchRoleAgentBinding, roleOptionSpecs, roleProfilePatch } from "./roleConfiguration.js";
|
|
71
73
|
import { assertRoleRuntimeMutationAllowed } from "./roleRuntimeGuard.js";
|
|
72
74
|
import { hasRoleLaunchContextOptions, validateConfiguredRoleSkills } from "./roleSkillValidation.js";
|
|
75
|
+
import { requireManagedGlobalCaller } from "../runtime/managedCaller.js";
|
|
76
|
+
import { hasManagedIdentity } from "../runtime/managedIdentity.js";
|
|
73
77
|
import { nonLeaderActivationIdentity, runTaskActivationCommand } from "./taskActivationCommands.js";
|
|
74
78
|
import { assertTaskOpen, clock, exactPositionals, leaderActionEventPayload, leaderMailbox, notifyMailbox, optionalNonEmptyOption, output, parseMultiValueTail, parseTail, presentTime, recordTaskEvent, recordTaskEventRecord, requiredOption, requiredText, requireTask, roleMailbox, taskActor, taskMailbox, taskRef, trimmed } from "./taskCommandSupport.js";
|
|
75
79
|
import { assertTaskCompletionPublishedTreeProof } from "./taskCompletionGate.js";
|
|
76
|
-
import { runTaskContextCommand } from "./taskContextCommand.js";
|
|
80
|
+
import { runTaskContextCommand, taskRecordList } from "./taskContextCommand.js";
|
|
77
81
|
import { taskBriefCommand, taskDecisionCommand, taskEventCommand, taskMilestoneCommand } from "./taskFactCommands.js";
|
|
78
82
|
import { openInputRequestCount, runTaskInputCommand } from "./taskInputCommands.js";
|
|
79
83
|
import { runTaskNextActionCommand } from "./taskNextActionCommand.js";
|
|
@@ -300,6 +304,29 @@ function formatCompletionBlockers(taskId, blockers) {
|
|
|
300
304
|
return `Task ${taskId} cannot complete: ${blockers.length} blocker(s) remain.\n${lines.join("\n")}`;
|
|
301
305
|
}
|
|
302
306
|
export function runTaskCommand(args, store, options = {}) {
|
|
307
|
+
// Read-only detail documents share one bounded transport. This is not a
|
|
308
|
+
// mutation replay mechanism: only the explicit read paths below accept a
|
|
309
|
+
// document cursor; authorization still runs inside each domain command.
|
|
310
|
+
const detail = ["show", "next-action", "remote-delivery"].includes(args[0] ?? "")
|
|
311
|
+
|| (["brief", "decision", "milestone", "event", "work", "wake", "review", "change-set"].includes(args[0] ?? "")
|
|
312
|
+
&& args[1] === "show")
|
|
313
|
+
|| (args[0] === "role" && (["show", "status"].includes(args[1] ?? "")
|
|
314
|
+
|| args[1] === "session" && args[2] === "inspect"));
|
|
315
|
+
if (!detail)
|
|
316
|
+
return executeTaskCommand(args, store, options);
|
|
317
|
+
const cursorIndex = args.indexOf("--cursor");
|
|
318
|
+
const cursor = cursorIndex < 0 ? undefined : args[cursorIndex + 1];
|
|
319
|
+
if (cursorIndex >= 0 && (cursor === undefined || cursor.startsWith("--")
|
|
320
|
+
|| args.lastIndexOf("--cursor") !== cursorIndex))
|
|
321
|
+
throw usageError("Detail read requires one --cursor value.");
|
|
322
|
+
const command = cursorIndex < 0 ? args : [...args.slice(0, cursorIndex), ...args.slice(cursorIndex + 2)];
|
|
323
|
+
const result = executeTaskCommand(command, store, options);
|
|
324
|
+
if (result.kind !== "output" || result.data === undefined)
|
|
325
|
+
return result;
|
|
326
|
+
const data = boundedDocument(result.data, `task-read:${JSON.stringify(command)}`, cursor);
|
|
327
|
+
return data === result.data ? result : output(`${JSON.stringify(data, null, 2)}\n`, data);
|
|
328
|
+
}
|
|
329
|
+
function executeTaskCommand(args, store, options = {}) {
|
|
303
330
|
const [command, ...rest] = args;
|
|
304
331
|
const delivery = command === "complete"
|
|
305
332
|
|| (command === "work" && ["dispatch", "synthesize", "review", "accept"].includes(rest[0] ?? ""))
|
|
@@ -766,6 +793,15 @@ function parseSubmissionIntentOption(raw, usage) {
|
|
|
766
793
|
throw usageError(`--intent must be one of ${TASK_SUBMISSION_INTENTS.join(", ")}: ${raw}.`, usage);
|
|
767
794
|
}
|
|
768
795
|
export function submitOperatorMessage(body, taskId, store, options = {}, intent, submissionKey) {
|
|
796
|
+
// Public terminals and ordinary unmanaged Agents retain the submission
|
|
797
|
+
// route. Managed callers cannot turn a Task Assignment into Operator input.
|
|
798
|
+
const callerEnvironment = options.environment ?? {};
|
|
799
|
+
if (hasManagedIdentity(callerEnvironment)) {
|
|
800
|
+
if (callerEnvironment.YUI_SESSION_SCOPE !== "global" || callerEnvironment.YUI_ROLE !== "operator") {
|
|
801
|
+
throw usageError("Operator submission requires a public caller or the current global Operator.");
|
|
802
|
+
}
|
|
803
|
+
requireManagedGlobalCaller(store, callerEnvironment);
|
|
804
|
+
}
|
|
769
805
|
const now = clock(options);
|
|
770
806
|
const effectiveIntent = normalizeSubmissionIntent(intent);
|
|
771
807
|
const result = store.transaction((tx) => {
|
|
@@ -1249,7 +1285,8 @@ function archiveTaskCommand(args, store, options) {
|
|
|
1249
1285
|
const now = clock(options);
|
|
1250
1286
|
const result = store.transaction((tx) => {
|
|
1251
1287
|
const task = requireTask(tx, request.taskId);
|
|
1252
|
-
const actor = taskActor(tx, options, task.id)
|
|
1288
|
+
const actor = options.archiveLeaderAdmission === undefined ? taskActor(tx, options, task.id)
|
|
1289
|
+
: (assertLeaderArchiveAdmission(tx, task.id, options.archiveLeaderAdmission), "leader");
|
|
1253
1290
|
if (task.status === "archived")
|
|
1254
1291
|
return { task, changed: false };
|
|
1255
1292
|
if (task.status !== "completed"
|
|
@@ -1309,6 +1346,9 @@ function archiveTaskCommand(args, store, options) {
|
|
|
1309
1346
|
})));
|
|
1310
1347
|
recordTaskEvent(tx, task.id, "task.archived", {
|
|
1311
1348
|
by: actor,
|
|
1349
|
+
...(options.archiveLeaderAdmission === undefined ? {} : {
|
|
1350
|
+
authorizationSource: JSON.stringify(options.archiveLeaderAdmission.source)
|
|
1351
|
+
}),
|
|
1312
1352
|
workspaceDisposition: request.disposition,
|
|
1313
1353
|
...(request.force ? {
|
|
1314
1354
|
force: "true", cleanup: "pending",
|
|
@@ -1496,7 +1536,22 @@ export function parseTaskArchiveArguments(args, command = "archive") {
|
|
|
1496
1536
|
const usage = "Task archive usage: "
|
|
1497
1537
|
+ `yui task ${command} <id> (--integrated|--abandon) [--force].`;
|
|
1498
1538
|
const taskId = args[0]?.trim();
|
|
1499
|
-
const flags =
|
|
1539
|
+
const flags = [];
|
|
1540
|
+
const values = new Map();
|
|
1541
|
+
for (let index = 1; index < args.length; index++) {
|
|
1542
|
+
const arg = args[index];
|
|
1543
|
+
if (["--source-message", "--purpose", "--request-id"].includes(arg)) {
|
|
1544
|
+
if (command !== "archive" || values.has(arg) || !args[index + 1]?.trim()
|
|
1545
|
+
|| args[index + 1].startsWith("--"))
|
|
1546
|
+
throw usageError(usage);
|
|
1547
|
+
values.set(arg, args[++index]);
|
|
1548
|
+
}
|
|
1549
|
+
else
|
|
1550
|
+
flags.push(arg);
|
|
1551
|
+
}
|
|
1552
|
+
if (values.size !== 0 && values.size !== 3) {
|
|
1553
|
+
throw usageError("Leader archive requires --source-message, --purpose and --request-id together.");
|
|
1554
|
+
}
|
|
1500
1555
|
if (taskId === undefined
|
|
1501
1556
|
|| taskId.length === 0
|
|
1502
1557
|
|| flags.some((flag, index) => (!["--integrated", "--abandon", "--force"].includes(flag)
|
|
@@ -1512,7 +1567,11 @@ export function parseTaskArchiveArguments(args, command = "archive") {
|
|
|
1512
1567
|
return {
|
|
1513
1568
|
taskId,
|
|
1514
1569
|
disposition: integrated ? "integrated" : "abandoned",
|
|
1515
|
-
force
|
|
1570
|
+
force,
|
|
1571
|
+
...(values.size === 0 ? {} : {
|
|
1572
|
+
sourceMessage: values.get("--source-message"), purpose: values.get("--purpose"),
|
|
1573
|
+
requestId: values.get("--request-id")
|
|
1574
|
+
})
|
|
1516
1575
|
};
|
|
1517
1576
|
}
|
|
1518
1577
|
function formatProjectCommits(projects) {
|
|
@@ -1522,9 +1581,18 @@ function formatProjectCommits(projects) {
|
|
|
1522
1581
|
export function validateTaskArchiveRequest(args, store, options = {}) {
|
|
1523
1582
|
const request = parseTaskArchiveArguments(args);
|
|
1524
1583
|
const task = requireTask(store, request.taskId);
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1584
|
+
if (options.archiveLeaderAdmission !== undefined) {
|
|
1585
|
+
assertLeaderArchiveAdmission(store, task.id, options.archiveLeaderAdmission);
|
|
1586
|
+
if (request.force || request.disposition !== "integrated") {
|
|
1587
|
+
throw usageError("Leader ordinary archive admission never authorizes force or abandonment.");
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
const archiveActor = options.archiveLeaderAdmission === undefined ? taskActor(store, options, task.id) : "leader";
|
|
1591
|
+
if (archiveActor === "leader" && options.archiveLeaderAdmission === undefined) {
|
|
1592
|
+
if (request.force || request.disposition === "abandoned") {
|
|
1593
|
+
throw usageError("Force or abandon archive requires independent user or Operator authorization.");
|
|
1594
|
+
}
|
|
1595
|
+
throw usageError("Leader archive requires a source-authorized Controller operation; use task archive with --source-message, --purpose and --request-id.");
|
|
1528
1596
|
}
|
|
1529
1597
|
if (task.status !== "archived"
|
|
1530
1598
|
&& task.status !== "completed"
|
|
@@ -1581,17 +1649,21 @@ function taskMessageCommand(args, store, options) {
|
|
|
1581
1649
|
}
|
|
1582
1650
|
if (command === "show") {
|
|
1583
1651
|
const usage = "Task message show usage: yui task message show <task/message>.";
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
const
|
|
1587
|
-
|
|
1652
|
+
const parsed = readOptions(rest, ["--cursor"]);
|
|
1653
|
+
exactPositionals(parsed.positionals, 1, usage);
|
|
1654
|
+
const ref = taskRecordReference(parsed.positionals[0], "message", "Message reference", options);
|
|
1655
|
+
assertContextRecordReadable(store, ref.taskId, "task-message", ref.localId, options.environment);
|
|
1656
|
+
const message = store.queryContextRecords(ref.taskId, {
|
|
1657
|
+
family: "task-message", ids: [ref.localId], limit: 1
|
|
1658
|
+
}).records[0]?.value;
|
|
1588
1659
|
if (message === undefined)
|
|
1589
1660
|
throw dataError("Message is unavailable in the caller's scope.");
|
|
1590
1661
|
const continuationRun = message.continuation?.runId === undefined
|
|
1591
1662
|
? null : store.getRun(ref.taskId, message.continuation.runId);
|
|
1592
1663
|
const expanded = { ...expandTaskMessageResult(message, (task, run) => store.getRun(task, run)),
|
|
1593
1664
|
...(continuationRun === null ? {} : { execution: runExecutionObservation(continuationRun, store.getTaskRoleSessionSet(ref.taskId, continuationRun.roleName)?.providerBinding, store.listEvents(ref.taskId)) }) };
|
|
1594
|
-
|
|
1665
|
+
const data = boundedDocument(expanded, `task:${ref.taskId}/message/${ref.localId}`, parsed.cursor);
|
|
1666
|
+
return { kind: "output", output: `${JSON.stringify(data, null, 2)}\n`, data };
|
|
1595
1667
|
}
|
|
1596
1668
|
if (command === "send") {
|
|
1597
1669
|
const usage = "Task message send usage: yui task message send <id> (<body>|--body-file <path|->) [--intent record|discuss|develop] [--request-id <key>] [--to <role> --work-item <id>|--review-round <id>].";
|
|
@@ -1613,60 +1685,20 @@ function taskMessageCommand(args, store, options) {
|
|
|
1613
1685
|
// A user/operator submission returns the unified §2.5 feedback; render each
|
|
1614
1686
|
// facet on its own line and expose the structure to non-text callers.
|
|
1615
1687
|
if (result.feedback !== undefined) {
|
|
1616
|
-
return output(renderSubmissionFeedback(result.feedback), { taskId: result.task.id, message: result.message, submission: result.feedback });
|
|
1688
|
+
return output(renderSubmissionFeedback(result.feedback), { taskId: result.task.id, message: messageReceipt(result.message), submission: result.feedback });
|
|
1617
1689
|
}
|
|
1618
1690
|
const reason = result.message.continuation?.notDeliveredReason;
|
|
1619
1691
|
const delivery = reason !== undefined ? { state: "not-delivered", reason }
|
|
1620
1692
|
: recipientRole !== undefined || result.queuedForLeader
|
|
1621
1693
|
? { state: "queued" } : { state: "saved" };
|
|
1622
|
-
return output(`Saved message ${result.message.id} to ${result.task.id} (${delivery.state}${reason === undefined ? "" : `: ${reason}`}).\n`, { taskId: result.task.id, message: result.message, delivery });
|
|
1694
|
+
return output(`Saved message ${result.message.id} to ${result.task.id} (${delivery.state}${reason === undefined ? "" : `: ${reason}`}).\n`, { taskId: result.task.id, message: messageReceipt(result.message), delivery });
|
|
1623
1695
|
}
|
|
1624
1696
|
if (command === "queue")
|
|
1625
1697
|
return queueTaskMessage(rest, store, options);
|
|
1626
1698
|
if (command === "steer")
|
|
1627
1699
|
return steerTaskMessage(rest, store, options);
|
|
1628
1700
|
if (command === "list") {
|
|
1629
|
-
|
|
1630
|
-
const parsed = parseTail(rest, new Set(["--after", "--limit"]), messageListUsage);
|
|
1631
|
-
exactPositionals(parsed.positionals, 1, messageListUsage);
|
|
1632
|
-
const task = requireTask(store, parsed.positionals[0]);
|
|
1633
|
-
let messages = listContextMessages(store, task.id, options.environment);
|
|
1634
|
-
const after = optionalNonEmptyOption(parsed.options, "--after");
|
|
1635
|
-
if (after !== undefined) {
|
|
1636
|
-
const afterMs = Date.parse(after);
|
|
1637
|
-
if (!Number.isFinite(afterMs))
|
|
1638
|
-
throw usageError("--after must be a valid timestamp.", messageListUsage);
|
|
1639
|
-
messages = messages.filter((m) => Date.parse(m.createdAt) > afterMs);
|
|
1640
|
-
}
|
|
1641
|
-
const limit = optionalNonEmptyOption(parsed.options, "--limit");
|
|
1642
|
-
if (limit !== undefined) {
|
|
1643
|
-
const n = Number(limit);
|
|
1644
|
-
if (!Number.isSafeInteger(n) || n <= 0)
|
|
1645
|
-
throw usageError("--limit must be a positive integer.", messageListUsage);
|
|
1646
|
-
messages = messages.slice(-n);
|
|
1647
|
-
}
|
|
1648
|
-
if (messages.length === 0)
|
|
1649
|
-
return "No messages found.\n";
|
|
1650
|
-
const retirements = new Map(store.listEvents(task.id).flatMap((event) => {
|
|
1651
|
-
const retirement = taskRecordRetirement(event);
|
|
1652
|
-
return retirement?.recordKind === "message"
|
|
1653
|
-
? [[retirement.recordId, retirement]]
|
|
1654
|
-
: [];
|
|
1655
|
-
}));
|
|
1656
|
-
const timeZone = store.getConfig().timeZone;
|
|
1657
|
-
return `${renderTable(`Task messages: ${task.id}`, [
|
|
1658
|
-
{ header: "Message", minWidth: 7, maxWidth: 18 },
|
|
1659
|
-
{ header: "Status", minWidth: 6, maxWidth: 9 },
|
|
1660
|
-
{ header: "Author", minWidth: 6, maxWidth: 18 },
|
|
1661
|
-
{ header: "Created", minWidth: 10, maxWidth: 28 },
|
|
1662
|
-
{ header: "Body", minWidth: 8, maxWidth: 72 }
|
|
1663
|
-
], messages.map((message) => [
|
|
1664
|
-
message.id,
|
|
1665
|
-
retirements.has(message.id) ? "retired" : "active",
|
|
1666
|
-
taskMessageAuthorLabel(message.author),
|
|
1667
|
-
presentTime(message.createdAt, timeZone),
|
|
1668
|
-
message.body
|
|
1669
|
-
]), defaultTableWidth())}\n`;
|
|
1701
|
+
return taskRecordList(rest, store, "task-message", options.environment);
|
|
1670
1702
|
}
|
|
1671
1703
|
if (command === "update") {
|
|
1672
1704
|
return updateMessage(rest, store, options);
|
|
@@ -1719,7 +1751,7 @@ function queueTaskInput(taskId, input, store, options) {
|
|
|
1719
1751
|
const delivery = result.idempotentReplay ? { state: "idempotent-replay" }
|
|
1720
1752
|
: reason !== undefined ? { state: "not-delivered", reason }
|
|
1721
1753
|
: recipientRole !== undefined || result.actor !== "leader" ? { state: "queued" } : { state: "saved" };
|
|
1722
|
-
return output(`Queued message ${result.message.id} to ${result.task.id} (${delivery.state}${reason === undefined ? "" : `: ${reason}`}).\n`, { taskId: result.task.id, message: result.message, delivery });
|
|
1754
|
+
return output(`Queued message ${result.message.id} to ${result.task.id} (${delivery.state}${reason === undefined ? "" : `: ${reason}`}).\n`, { taskId: result.task.id, message: messageReceipt(result.message), delivery });
|
|
1723
1755
|
}
|
|
1724
1756
|
/**
|
|
1725
1757
|
* `steer` targets only the exact current native Turn. It always persists the
|
|
@@ -1772,7 +1804,7 @@ function steerTaskInput(taskId, input, store, options) {
|
|
|
1772
1804
|
// unknown steer is visibly not-submitted/pending/accepted/rejected/
|
|
1773
1805
|
// delivery-unknown rather than silently re-attempted (message-5 gap D).
|
|
1774
1806
|
const controlState = taskMessageInputControlState(result.message);
|
|
1775
|
-
return output(`Steer message ${result.message.id} already recorded (idempotent-replay${controlState === undefined ? "" : `; control ${controlState}`}).\n`, { taskId: result.task.id, message: result.message,
|
|
1807
|
+
return output(`Steer message ${result.message.id} already recorded (idempotent-replay${controlState === undefined ? "" : `; control ${controlState}`}).\n`, { taskId: result.task.id, message: messageReceipt(result.message),
|
|
1776
1808
|
steer: { state: "idempotent-replay",
|
|
1777
1809
|
...(controlState === undefined ? {} : { control: controlState }) } });
|
|
1778
1810
|
}
|
|
@@ -1780,7 +1812,7 @@ function steerTaskInput(taskId, input, store, options) {
|
|
|
1780
1812
|
// match, and writer fence, all from durable state without a live Endpoint.
|
|
1781
1813
|
const resolution = resolveTaskInputControl(store, result.task.id, roleName, "steer", expectedTarget);
|
|
1782
1814
|
if (resolution.outcome !== "ready") {
|
|
1783
|
-
return output(`Steer message ${result.message.id} saved but not delivered (${resolution.code}: ${resolution.detail}).\n`, { taskId: result.task.id, message: result.message,
|
|
1815
|
+
return output(`Steer message ${result.message.id} saved but not delivered (${resolution.code}: ${resolution.detail}).\n`, { taskId: result.task.id, message: messageReceipt(result.message),
|
|
1784
1816
|
steer: { state: "not-steered", code: resolution.code, detail: resolution.detail } });
|
|
1785
1817
|
}
|
|
1786
1818
|
if (!leaderTarget) {
|
|
@@ -1792,7 +1824,7 @@ function steerTaskInput(taskId, input, store, options) {
|
|
|
1792
1824
|
|| recipient.workItemId !== current.workItemId
|
|
1793
1825
|
|| recipient.reviewRoundId !== current.reviewRoundId
|
|
1794
1826
|
|| messageContinuationBlocker(store, result.message) !== undefined) {
|
|
1795
|
-
return output(`Steer message ${result.message.id} saved but not delivered (TARGET_CHANGED: active Assignment differs).\n`, { taskId: result.task.id, message: result.message,
|
|
1827
|
+
return output(`Steer message ${result.message.id} saved but not delivered (TARGET_CHANGED: active Assignment differs).\n`, { taskId: result.task.id, message: messageReceipt(result.message),
|
|
1796
1828
|
steer: { state: "not-steered", code: "TARGET_CHANGED", detail: "The input does not belong to the active Turn's Assignment." } });
|
|
1797
1829
|
}
|
|
1798
1830
|
}
|
|
@@ -2057,7 +2089,7 @@ function updateMessage(args, store, options) {
|
|
|
2057
2089
|
? leaderMailbox(result.task.id) : taskMailbox(result.task.id));
|
|
2058
2090
|
}
|
|
2059
2091
|
return output(`${result.changed ? "Updated" : "Unchanged"} Task Message ${result.task.id}/${result.message.id}\n`, {
|
|
2060
|
-
message: result.message
|
|
2092
|
+
message: messageReceipt(result.message)
|
|
2061
2093
|
});
|
|
2062
2094
|
}
|
|
2063
2095
|
function retireMessage(args, store, options) {
|
|
@@ -2481,10 +2513,16 @@ function taskRoleSessionCommand(args, store, options) {
|
|
|
2481
2513
|
].join("\n") + "\n"
|
|
2482
2514
|
+ `\n${renderRoleLaunchComparison(role, active.effective)}\n`
|
|
2483
2515
|
+ (runConfigurationDetail === "" ? "" : `\n${runConfigurationDetail}\n`), {
|
|
2484
|
-
task,
|
|
2485
|
-
role,
|
|
2516
|
+
taskId: task.id,
|
|
2517
|
+
roleName: role.name,
|
|
2518
|
+
desired: { launchRevision: role.launchRevision, activeAgentId: role.activeAgentId,
|
|
2519
|
+
binding: activeRoleAgentBinding(role) },
|
|
2486
2520
|
session: active,
|
|
2487
|
-
providerBinding: binding
|
|
2521
|
+
providerBinding: binding === null ? null : {
|
|
2522
|
+
providerNamespace: binding.providerNamespace, accountScope: binding.accountScope,
|
|
2523
|
+
currentConversation: currentProviderConversation(binding),
|
|
2524
|
+
authority: binding.authority, run: binding.run, goal: binding.goal
|
|
2525
|
+
},
|
|
2488
2526
|
retry: providerRetryProjection(binding),
|
|
2489
2527
|
...(host === undefined ? {} : { host }),
|
|
2490
2528
|
...(runConfiguration === undefined ? {} : { runConfiguration })
|
|
@@ -2652,31 +2690,20 @@ function addTaskRole(args, store, options) {
|
|
|
2652
2690
|
].join("\n").concat("\n");
|
|
2653
2691
|
}
|
|
2654
2692
|
function listTaskRoles(args, store, options) {
|
|
2655
|
-
|
|
2656
|
-
|
|
2693
|
+
const parsed = readOptions(args);
|
|
2694
|
+
exactPositionals(parsed.positionals, 1, "Task role list usage: yui task role list <task> [--limit <n>] [--cursor <cursor>].");
|
|
2695
|
+
const task = requireTask(store, parsed.positionals[0]);
|
|
2657
2696
|
const roles = store.listRoles(task.id);
|
|
2658
|
-
const statuses = inspectTaskRoleRuntimeStatuses(task.id, roles, store, options.runtime?.inspectTaskRolePanes?.(task.id) ?? [], options.now?.() ?? new Date())
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
{ header: "Native session", minWidth: 10, maxWidth: 28 },
|
|
2669
|
-
{ header: "tmux", minWidth: 6, maxWidth: 22 }
|
|
2670
|
-
], statuses.map((status) => [
|
|
2671
|
-
status.roleName,
|
|
2672
|
-
status.agentId,
|
|
2673
|
-
status.health,
|
|
2674
|
-
taskRoleOpenInputLabel(status),
|
|
2675
|
-
taskRoleActiveWorkLabel(status),
|
|
2676
|
-
taskRoleLastRunLabel(status),
|
|
2677
|
-
taskRoleNativeSessionLabel(status),
|
|
2678
|
-
taskRoleTmuxLabel(status)
|
|
2679
|
-
]), defaultTableWidth())}\n`, { roles: statuses });
|
|
2697
|
+
const statuses = inspectTaskRoleRuntimeStatuses(task.id, roles, store, options.runtime?.inspectTaskRolePanes?.(task.id) ?? [], options.now?.() ?? new Date());
|
|
2698
|
+
const data = recordPage(statuses.map(status => ({
|
|
2699
|
+
roleName: status.roleName, agentId: status.agentId, recordedHealth: status.health,
|
|
2700
|
+
hostObservation: "not-requested",
|
|
2701
|
+
openInput: taskRoleOpenInputLabel(status), activeWork: taskRoleActiveWorkLabel(status),
|
|
2702
|
+
lastRun: taskRoleLastRunLabel(status), nativeSession: taskRoleNativeSessionLabel(status),
|
|
2703
|
+
tmux: taskRoleTmuxLabel(status),
|
|
2704
|
+
read: `task role status ${task.id} ${status.roleName}`
|
|
2705
|
+
})), `task:${task.id}/role-status`, parsed);
|
|
2706
|
+
return output(`${JSON.stringify(data)}\n`, data);
|
|
2680
2707
|
}
|
|
2681
2708
|
function taskRoleStatus(args, store, options) {
|
|
2682
2709
|
exactPositionals(args, 2, "Task role status usage: yui task role status <task> <role>.");
|
|
@@ -3011,7 +3038,7 @@ function taskWorkCommand(args, store, options) {
|
|
|
3011
3038
|
if (command === "create")
|
|
3012
3039
|
return createWork(rest, store, options);
|
|
3013
3040
|
if (command === "list")
|
|
3014
|
-
return
|
|
3041
|
+
return taskRecordList(rest, store, "work-item", options.environment);
|
|
3015
3042
|
if (command === "show")
|
|
3016
3043
|
return showWork(rest, store, options);
|
|
3017
3044
|
if (command === "edit")
|
|
@@ -3882,36 +3909,6 @@ function retireWork(args, store, options) {
|
|
|
3882
3909
|
options.runtime?.notifyMailboxChanged({ kind: "task", taskId: retired.taskId });
|
|
3883
3910
|
return output(`Retired Work Item ${retired.id}\n`, { workItem: retired });
|
|
3884
3911
|
}
|
|
3885
|
-
function listWork(args, store) {
|
|
3886
|
-
exactPositionals(args, 1, "Task work list usage: yui task work list <task>.");
|
|
3887
|
-
const task = requireTask(store, args[0]);
|
|
3888
|
-
const items = store.listWorkItems(task.id);
|
|
3889
|
-
const runs = store.listRuns(task.id);
|
|
3890
|
-
const sessionSets = store.listRoleSessionSets(task.id);
|
|
3891
|
-
const executions = items.map((item) => projectWorkItemExecution(item, runs, sessionSets, store));
|
|
3892
|
-
const rendered = items.length === 0
|
|
3893
|
-
? "No work items found.\n"
|
|
3894
|
-
: `${renderTable(`Task work: ${task.id}`, [
|
|
3895
|
-
{ header: "Work", minWidth: 6, maxWidth: 20 },
|
|
3896
|
-
{ header: "Status", minWidth: 6, maxWidth: 12 },
|
|
3897
|
-
{ header: "Role", minWidth: 4, maxWidth: 18 },
|
|
3898
|
-
{ header: "Shape", minWidth: 6, maxWidth: 10 },
|
|
3899
|
-
{ header: "Execution", minWidth: 12, maxWidth: 42 },
|
|
3900
|
-
{ header: "Next / Owner", minWidth: 12, maxWidth: 36 },
|
|
3901
|
-
{ header: "Title", minWidth: 8, maxWidth: 64 },
|
|
3902
|
-
{ header: "Outcome", minWidth: 8, maxWidth: 40 }
|
|
3903
|
-
], items.map((item, index) => [
|
|
3904
|
-
item.id,
|
|
3905
|
-
presentWorkStatus(item.status),
|
|
3906
|
-
item.assignee ?? "Leader",
|
|
3907
|
-
executions[index].shape,
|
|
3908
|
-
compactWorkItemExecution(executions[index]),
|
|
3909
|
-
`${executions[index].nextAction.kind} / ${executions[index].nextAction.owners.join(",") || "none"}`,
|
|
3910
|
-
item.title,
|
|
3911
|
-
item.outcome ?? "-"
|
|
3912
|
-
]), defaultTableWidth())}\n`;
|
|
3913
|
-
return output(rendered, { workItems: items, executions });
|
|
3914
|
-
}
|
|
3915
3912
|
function showWork(args, store, options) {
|
|
3916
3913
|
exactPositionals(args, 1, "Task work show usage: yui task work show <work>.");
|
|
3917
3914
|
const item = requireWorkItem(store, args[0], options);
|
|
@@ -3934,12 +3931,6 @@ function showWork(args, store, options) {
|
|
|
3934
3931
|
].join("\n");
|
|
3935
3932
|
return output(`${rendered}\n`, { workItem: item, execution });
|
|
3936
3933
|
}
|
|
3937
|
-
function compactWorkItemExecution(projection) {
|
|
3938
|
-
if (projection.shape === "direct")
|
|
3939
|
-
return `main=${projection.mainRun.status}`;
|
|
3940
|
-
const counts = projection.laneCounts;
|
|
3941
|
-
return `lanes ${counts.running}/${counts.succeeded}/${counts.needsAttention}/${counts.failed}/${counts.unknown}; ${projection.synthesis.status}`;
|
|
3942
|
-
}
|
|
3943
3934
|
function renderWorkItemExecutionProjection(projection) {
|
|
3944
3935
|
return [
|
|
3945
3936
|
`Execution Shape: ${projection.shape}`,
|
|
@@ -4402,7 +4393,7 @@ function retryFailedTaskReviewRound(args, store, options) {
|
|
|
4402
4393
|
function taskRunCommand(args, store, options) {
|
|
4403
4394
|
const [command, ...rest] = args;
|
|
4404
4395
|
if (command === "list")
|
|
4405
|
-
return
|
|
4396
|
+
return listRuns(rest, store, options);
|
|
4406
4397
|
if (command === "show")
|
|
4407
4398
|
return showRun(rest, store, options);
|
|
4408
4399
|
if (command === "context")
|
|
@@ -4673,7 +4664,7 @@ function runContextCommand(args, store, options) {
|
|
|
4673
4664
|
const [first, ...rest] = args;
|
|
4674
4665
|
if (first === "expand") {
|
|
4675
4666
|
const usage = "Task run context expand usage: yui task run context expand <task>/<run> <ref-id> --store <store> [--mode full].";
|
|
4676
|
-
const parsed = parseTail(rest, new Set(["--store", "--mode"]), usage);
|
|
4667
|
+
const parsed = parseTail(rest, new Set(["--store", "--mode", "--cursor"]), usage);
|
|
4677
4668
|
exactPositionals(parsed.positionals, 2, usage);
|
|
4678
4669
|
const refStore = requiredOption(parsed.options, "--store");
|
|
4679
4670
|
const mode = parsed.options.get("--mode");
|
|
@@ -4683,24 +4674,29 @@ function runContextCommand(args, store, options) {
|
|
|
4683
4674
|
const { taskId, runId } = parseRunContextReference(parsed.positionals[0]);
|
|
4684
4675
|
authorizeRunContext(store, taskId, runId, options.environment);
|
|
4685
4676
|
const expanded = store.transaction((tx) => expandRunContextRef(tx, taskId, runId, parsed.positionals[1], refStore));
|
|
4686
|
-
|
|
4677
|
+
const data = boundedDocument(expanded, `run:${taskId}/${runId}/${refStore}/${parsed.positionals[1]}`, parsed.options.get("--cursor"));
|
|
4678
|
+
return output(`${JSON.stringify(data, null, 2)}\n`, { context: data });
|
|
4687
4679
|
}
|
|
4688
4680
|
if (first === "delta") {
|
|
4689
|
-
|
|
4690
|
-
|
|
4681
|
+
const parsed = readOptions(rest, ["--after", "--cursor"]);
|
|
4682
|
+
if (parsed.positionals.length !== 1 || !parsed.values.has("--after")) {
|
|
4683
|
+
throw usageError("Task run context delta usage: yui task run context delta <task>/<run> --after <digest> [--cursor <cursor>].");
|
|
4691
4684
|
}
|
|
4692
|
-
const { taskId, runId } = parseRunContextReference(
|
|
4685
|
+
const { taskId, runId } = parseRunContextReference(parsed.positionals[0]);
|
|
4693
4686
|
authorizeRunContext(store, taskId, runId, options.environment);
|
|
4694
|
-
const delta = store.transaction((tx) => (buildRunContextDelta(tx, taskId, runId,
|
|
4695
|
-
|
|
4687
|
+
const delta = store.transaction((tx) => (buildRunContextDelta(tx, taskId, runId, parsed.values.get("--after"))));
|
|
4688
|
+
const data = boundedDocument(delta, `run:${taskId}/${runId}/delta/${parsed.values.get("--after")}`, parsed.cursor);
|
|
4689
|
+
return output(`${JSON.stringify(data)}\n`, { contextDelta: data });
|
|
4696
4690
|
}
|
|
4697
|
-
|
|
4691
|
+
const parsed = readOptions(rest, ["--cursor"]);
|
|
4692
|
+
if (first === undefined || parsed.positionals.length !== 0) {
|
|
4698
4693
|
throw usageError("Task run context usage: yui task run context <task>/<run>.");
|
|
4699
4694
|
}
|
|
4700
4695
|
const { taskId, runId } = parseRunContextReference(first);
|
|
4701
4696
|
authorizeRunContext(store, taskId, runId, options.environment);
|
|
4702
4697
|
const pack = store.transaction((tx) => buildRunContextPack(tx, taskId, runId));
|
|
4703
|
-
|
|
4698
|
+
const data = boundedDocument(pack, `run:${taskId}/${runId}/context`, parsed.cursor);
|
|
4699
|
+
return output(`${JSON.stringify(data)}\n`, { context: data });
|
|
4704
4700
|
}
|
|
4705
4701
|
function parseRunContextReference(value) {
|
|
4706
4702
|
const [taskId, runId, extra] = value.split("/");
|
|
@@ -4736,41 +4732,12 @@ function authorizeRunContext(store, taskId, runId, environment) {
|
|
|
4736
4732
|
}
|
|
4737
4733
|
}
|
|
4738
4734
|
function listRuns(args, store, options) {
|
|
4739
|
-
const usage = "Task run list usage: yui task run list <task|task/work>.";
|
|
4740
|
-
exactPositionals(args, 1, usage);
|
|
4741
4735
|
const reference = args[0];
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
return "No AgentRuns found.\n";
|
|
4748
|
-
const events = store.listEvents(taskId);
|
|
4749
|
-
return `${renderTable(`AgentRuns: ${item?.id ?? taskId}`, [
|
|
4750
|
-
{ header: "AgentRun", minWidth: 6, maxWidth: 20 },
|
|
4751
|
-
{ header: "Role", minWidth: 4, maxWidth: 22 },
|
|
4752
|
-
{ header: "Subject", minWidth: 7, maxWidth: 24 },
|
|
4753
|
-
{ header: "Purpose", minWidth: 6, maxWidth: 10 },
|
|
4754
|
-
{ header: "Mode", minWidth: 4, maxWidth: 8 },
|
|
4755
|
-
{ header: "Effective", minWidth: 10, maxWidth: 30 },
|
|
4756
|
-
{ header: "Profile", minWidth: 7, maxWidth: 8 },
|
|
4757
|
-
{ header: "Permission", minWidth: 8, maxWidth: 16 },
|
|
4758
|
-
{ header: "Status", minWidth: 6, maxWidth: 12 },
|
|
4759
|
-
{ header: "History", minWidth: 7, maxWidth: 9 },
|
|
4760
|
-
{ header: "Summary", minWidth: 8, maxWidth: 58 }
|
|
4761
|
-
], runs.map((run) => [
|
|
4762
|
-
run.id,
|
|
4763
|
-
run.roleName,
|
|
4764
|
-
run.workItemId ?? (run.reviewRoundId === undefined ? "task" : `review:${run.reviewRoundId}`),
|
|
4765
|
-
run.purpose,
|
|
4766
|
-
run.mode,
|
|
4767
|
-
`${run.effective.agentId}/${run.effective.adapterId} r${run.effective.sourceDesiredRevision}`,
|
|
4768
|
-
run.effective.profileAccess,
|
|
4769
|
-
run.effective.permission.strategy,
|
|
4770
|
-
run.status,
|
|
4771
|
-
isTaskRecordRetired(events, "run", run.id) ? "retired" : "active",
|
|
4772
|
-
run.result?.output ?? run.result?.diagnostic ?? "-"
|
|
4773
|
-
]), defaultTableWidth())}\n`;
|
|
4736
|
+
if (reference?.includes("/")) {
|
|
4737
|
+
const item = requireWorkItem(store, reference, options);
|
|
4738
|
+
return taskRecordList([item.taskId, "--work-item", item.id, ...args.slice(1)], store, "run", options.environment);
|
|
4739
|
+
}
|
|
4740
|
+
return taskRecordList(args, store, "run", options.environment);
|
|
4774
4741
|
}
|
|
4775
4742
|
/**
|
|
4776
4743
|
* Settles only the known bootstrap split where a failed Task-final AgentRun
|
|
@@ -5683,8 +5650,8 @@ function retryFailedReviewRun(previous, store, options, now) {
|
|
|
5683
5650
|
/** AgentRun details are retained audit evidence; continuation uses durable Task state. */
|
|
5684
5651
|
function showRun(args, store, options) {
|
|
5685
5652
|
const usage = "Task run show usage: yui task run show <task>/<run> [--json].";
|
|
5686
|
-
const
|
|
5687
|
-
const positionals =
|
|
5653
|
+
const parsed = readOptions(args.filter((arg) => arg !== "--json"), ["--cursor"]);
|
|
5654
|
+
const positionals = parsed.positionals;
|
|
5688
5655
|
exactPositionals(positionals, 1, usage);
|
|
5689
5656
|
const data = store.transaction((tx) => {
|
|
5690
5657
|
const run = requireRun(tx, positionals[0], options);
|
|
@@ -5693,9 +5660,9 @@ function showRun(args, store, options) {
|
|
|
5693
5660
|
.find((entry) => entry?.recordKind === "run" && entry.recordId === run.id) ?? null;
|
|
5694
5661
|
return { run: run, retirement, execution: runExecutionObservation(run, tx.getTaskRoleSessionSet(run.taskId, run.roleName)?.providerBinding, tx.listEvents(run.taskId)) };
|
|
5695
5662
|
});
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5663
|
+
const bounded = boundedDocument(data, `run:${data.run.taskId}/${data.run.id}`, parsed.cursor);
|
|
5664
|
+
if ("contentPage" in bounded)
|
|
5665
|
+
return output(`${JSON.stringify(bounded, null, 2)}\n`, bounded);
|
|
5699
5666
|
return {
|
|
5700
5667
|
kind: "output",
|
|
5701
5668
|
output: `Delivery observation: ${data.execution.delivery}\n` + renderRunShow(data.run, data.retirement),
|
|
@@ -6874,25 +6841,16 @@ function taskWakeDispatch(args, store, options) {
|
|
|
6874
6841
|
function taskWakeInspectionCommand(args, store) {
|
|
6875
6842
|
const [command, ...rest] = args;
|
|
6876
6843
|
if (command === "list") {
|
|
6877
|
-
const usage = "Task wake list usage: yui task wake list <task
|
|
6878
|
-
|
|
6879
|
-
|
|
6844
|
+
const usage = "Task wake list usage: yui task wake list <task> [--limit <n>] [--cursor <cursor>].";
|
|
6845
|
+
const parsed = readOptions(rest);
|
|
6846
|
+
exactPositionals(parsed.positionals, 1, usage);
|
|
6847
|
+
const task = requireTask(store, parsed.positionals[0]);
|
|
6880
6848
|
const wakes = store.listTaskWakes(task.id);
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
return output(`${
|
|
6886
|
-
{ header: "Wake", minWidth: 8, maxWidth: 18 },
|
|
6887
|
-
{ header: "Status", minWidth: 8, maxWidth: 12 },
|
|
6888
|
-
{ header: "Reasons", minWidth: 10, maxWidth: 40 },
|
|
6889
|
-
{ header: "Dispatched", minWidth: 10, maxWidth: 28 }
|
|
6890
|
-
], wakes.map((wake) => [
|
|
6891
|
-
wake.id,
|
|
6892
|
-
wake.status,
|
|
6893
|
-
wake.reasons.map(renderWakeReason).join(", "),
|
|
6894
|
-
presentTime(wake.createdAt, timeZone)
|
|
6895
|
-
]), defaultTableWidth())}\n`, { taskId: task.id, wakes });
|
|
6849
|
+
const data = recordPage(wakes.map(wake => ({
|
|
6850
|
+
id: wake.id, status: wake.status, fromCursor: wake.fromCursor, toCursor: wake.toCursor,
|
|
6851
|
+
createdAt: wake.createdAt, read: `task wake show ${task.id} ${wake.id}`
|
|
6852
|
+
})), `task:${task.id}/wake`, parsed);
|
|
6853
|
+
return output(`${JSON.stringify(data)}\n`, data);
|
|
6896
6854
|
}
|
|
6897
6855
|
if (command === "show") {
|
|
6898
6856
|
const usage = "Task wake show usage: yui task wake show <task> <wake>.";
|
|
@@ -6962,9 +6920,12 @@ function taskWakeInspectionCommand(args, store) {
|
|
|
6962
6920
|
taskId: task.id,
|
|
6963
6921
|
deliveryEvents,
|
|
6964
6922
|
wake,
|
|
6965
|
-
events,
|
|
6966
|
-
|
|
6967
|
-
|
|
6923
|
+
events: events.map(event => ({ id: event.id, type: event.type, createdAt: event.createdAt,
|
|
6924
|
+
read: `task event show ${task.id} ${event.id}` })),
|
|
6925
|
+
messages: messages.map(message => ({ id: message.id, kind: message.kind, author: message.author,
|
|
6926
|
+
resultRef: message.resultRef, read: `task message show ${task.id}/${message.id}` })),
|
|
6927
|
+
runs: runs.map(run => ({ id: run.id, status: run.status, purpose: run.purpose, roleName: run.roleName,
|
|
6928
|
+
read: `task run show ${task.id}/${run.id}` }))
|
|
6968
6929
|
});
|
|
6969
6930
|
}
|
|
6970
6931
|
throw usageError(command === undefined
|