@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
package/dist/cli.js
CHANGED
|
@@ -12,6 +12,8 @@ import { nativeAgentEnvironmentNames } from "./agent/launchEnvironment.js";
|
|
|
12
12
|
import { listArtifactsCapability, readArtifactCapability, saveArtifactCapability } from "./artifacts/artifactCapability.js";
|
|
13
13
|
import { renderAgentConfigurationResolutionNotice } from "./cli/agentConfigurationPicker.js";
|
|
14
14
|
import { describeCommandTree, findCommandNode } from "./cli/commandCatalog.js";
|
|
15
|
+
import { discoveryCommandTree } from "./cli/commandDiscovery.js";
|
|
16
|
+
import { contextRecordReader } from "./context/taskContext.js";
|
|
15
17
|
import { renderCompletion } from "./cli/completion.js";
|
|
16
18
|
import { runCompletionWizard } from "./cli/completionWizard.js";
|
|
17
19
|
import { resolveCompletionCandidates } from "./cli/dynamicCompletion.js";
|
|
@@ -20,7 +22,8 @@ import { allowsInteractiveSelection, resolveInteractiveArguments } from "./cli/i
|
|
|
20
22
|
import { routeInvocation } from "./cli/invocationRouter.js";
|
|
21
23
|
import { operatorOfflineCommand, taskDiagnosticTarget } from "./cli/managedDiagnostics.js";
|
|
22
24
|
import { assertConfigurationAuthority, assertTaskInvocationScope } from "./cli/invocationAuthority.js";
|
|
23
|
-
import { requireManagedGlobalCaller } from "./runtime/managedCaller.js";
|
|
25
|
+
import { requireManagedGlobalCaller, ManagedRuntimeDriftError } from "./runtime/managedCaller.js";
|
|
26
|
+
import { hasManagedIdentity } from "./runtime/managedIdentity.js";
|
|
24
27
|
import { resolveOperatorWizardArguments } from "./cli/operatorWizard.js";
|
|
25
28
|
import { resolveGlobalRoleAgentConfigurationArguments, resolveRoleWizardArguments } from "./cli/roleWizard.js";
|
|
26
29
|
import { runUpdateCommand } from "./cli/updateCommand.js";
|
|
@@ -41,7 +44,7 @@ import { runProjectCommand } from "./commands/projectCommands.js";
|
|
|
41
44
|
import { renderReleaseActivateResult, renderReleaseInstallResult, renderReleaseList, resolveReleaseActivationDriver, runReleaseActivate, runReleaseInstall, runReleaseList } from "./commands/releaseCommands.js";
|
|
42
45
|
import { runResourcesCommand } from "./commands/resourcesCommands.js";
|
|
43
46
|
import { parseSessionReconcileOptions, parseSessionStopOptions, runSessionReconcileCommand, runSessionStopCommand } from "./commands/sessionCommands.js";
|
|
44
|
-
import { assertTaskDeliveryAuthority, taskLocalActor } from "./task/taskAuthority.js";
|
|
47
|
+
import { assertTaskDeliveryAuthority, taskLocalActor, resolveJobCaller } from "./task/taskAuthority.js";
|
|
45
48
|
import { runTaskBaseStatusCommand } from "./commands/taskBaseCommands.js";
|
|
46
49
|
import { runTaskChangeSetCommand } from "./commands/taskChangeSetCommands.js";
|
|
47
50
|
import { assertWorkItemDependenciesCompletedForCommand, dispatchPreparedReviewRound, failPendingReviewRound, parseTaskArchiveArguments, parseTaskCompletionRequest, planReplicatedWorkItemLanes, preflightTaskCompletion, preserveReviewRoundWorkspace, previewTaskRoleAgentConfigurationMutation, requireWorkItemAssignee, runTaskCommand, validateTaskArchiveRequest } from "./commands/taskCommands.js";
|
|
@@ -58,7 +61,7 @@ import { runWorkflowCommandAsync } from "./commands/workflowCommands.js";
|
|
|
58
61
|
import { FileCompletionManager } from "./completion/fileCompletionManager.js";
|
|
59
62
|
import { CONFIG_DOMAINS } from "./config/configCatalog.js";
|
|
60
63
|
import { resolveTmuxBin, resolveTmuxHistoryLimit } from "./config/yuiConfig.js";
|
|
61
|
-
import { readSessionBootstrapManifest
|
|
64
|
+
import { readSessionBootstrapManifest } from "./context/sessionBootstrapManifest.js";
|
|
62
65
|
import { assertFileTaskControllerStorageCompatible, ensureFileTaskController, FileTaskWorkflowRuntime, refreshRunningFileTaskControllerConfiguration, refreshRunningFileTaskControllerEnvironment, restartFileTaskController, stopFileTaskController } from "./controller/clientRuntime.js";
|
|
63
66
|
import { FileSchedulerStoreAdapter } from "./controller/fileSchedulerStoreAdapter.js";
|
|
64
67
|
import { createControllerIntegrationJobPort } from "./controller/jobClient.js";
|
|
@@ -70,6 +73,7 @@ import { SessionOwnerReconciliation } from "./controller/sessionOwnerReconciliat
|
|
|
70
73
|
import { callController, ControllerClientError } from "./core/controllerClient.js";
|
|
71
74
|
import { buildDoctorReport, renderDoctor, runDoctorCommand } from "./doctor/doctor.js";
|
|
72
75
|
import { agentNotFound, CliError, runtimeError, usageError } from "./errors/cliError.js";
|
|
76
|
+
import { describeCliFailure, renderCliFailure, sanitizeFailureText, sanitizeFailureDetails } from "./errors/cliFailure.js";
|
|
73
77
|
import { AgentConfigurationCatalogService, validateAgentLaunchConfiguration } from "./executor/agentConfigurationCatalog.js";
|
|
74
78
|
import { FileRoleLaunchPlanner } from "./executor/fileRoleLaunchPlanner.js";
|
|
75
79
|
import { createGitHubCliPublicationVerifier } from "./external/githubPublicationVerifier.js";
|
|
@@ -82,7 +86,7 @@ import { parseTaskAgentCapabilityQuery } from "./commands/taskAgentCapabilities.
|
|
|
82
86
|
import { capabilityReaderIdentity } from "./controller/agentCapabilities.js";
|
|
83
87
|
import { formatTimestamp } from "./output/timePresentation.js";
|
|
84
88
|
import { resolveAgentProfileView } from "./profile/agentProfileRuntime.js";
|
|
85
|
-
import { assertCliHomeReleaseFence
|
|
89
|
+
import { assertCliHomeReleaseFence } from "./release/cliHomeReleaseFence.js";
|
|
86
90
|
import { createReleaseWorkflowPorts } from "./release/releaseWorkflowPorts.js";
|
|
87
91
|
import { acquireHandoverLock, readRuntimeIdentity } from "./release/runtimeRelease.js";
|
|
88
92
|
import { NodeGitWorkspace } from "./repository/gitWorkspace.js";
|
|
@@ -102,7 +106,6 @@ import { requireManagedTaskCaller, resolveManagedTaskReader } from "./runtime/ma
|
|
|
102
106
|
import { assertRuntimeCoherence } from "./runtime/runtimeCoherence.js";
|
|
103
107
|
import { runSetupCommand, validateSetupInvocation } from "./setup/setupCommand.js";
|
|
104
108
|
import { openCurrentTaskStore, validateCurrentTaskStore } from "./storage/currentTaskStore.js";
|
|
105
|
-
import { SqliteSchemaError } from "./storage/sqliteSchema.js";
|
|
106
109
|
import { inspectStorageSchema } from "./storage/storageSchema.js";
|
|
107
110
|
import { resolveYuiHome } from "./storage/taskStore.js";
|
|
108
111
|
import { renderArchiveDiagnostics, taskArchiveDiagnostics } from "./task/archiveDiagnostics.js";
|
|
@@ -123,51 +126,44 @@ const taskFinalReviewInvocation = extractTaskFinalReviewRequest(process.argv.sli
|
|
|
123
126
|
const rawArgs = [...taskFinalReviewInvocation.args];
|
|
124
127
|
const jsonOutput = rawArgs.includes("--json");
|
|
125
128
|
const args = normalizeAliases(jsonOutput ? rawArgs.filter((argument) => argument !== "--json") : rawArgs);
|
|
129
|
+
let invocationHome;
|
|
126
130
|
void main().catch((error) => {
|
|
127
131
|
if (error instanceof CleanupInspectionError) {
|
|
128
132
|
error = cleanupCliError(error, error.checks[0]?.resource ?? "workspace");
|
|
129
133
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
: `${error.code}: ${error.message}${error.helpText === undefined ? "" : `\n\n${error.helpText.trimEnd()}`}`;
|
|
134
|
-
process.stderr.write(`${rendered}\n`);
|
|
135
|
-
process.exitCode = error.exitCode;
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
const message = runtimeFailureMessage(error);
|
|
139
|
-
process.stderr.write(`${jsonOutput
|
|
140
|
-
? JSON.stringify({ ok: false, code: "RUNTIME_ERROR", message, details: {} })
|
|
141
|
-
: `RUNTIME_ERROR: ${message}`}\n`);
|
|
142
|
-
process.exitCode = 5;
|
|
134
|
+
const failure = describeCliFailure(error, failureContext());
|
|
135
|
+
process.stderr.write(`${renderCliFailure(failure, jsonOutput)}\n`);
|
|
136
|
+
process.exitCode = failure.exitCode;
|
|
143
137
|
});
|
|
144
|
-
function
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
return message;
|
|
163
|
-
}
|
|
138
|
+
function failureContext() {
|
|
139
|
+
const route = routeInvocation(args);
|
|
140
|
+
const node = "node" in route ? route.node : route.helpNode;
|
|
141
|
+
const operands = args.slice(node.path.length - 1);
|
|
142
|
+
const publicValues = new Set([
|
|
143
|
+
...Object.values(node.argumentValues).flat(),
|
|
144
|
+
...Object.values(node.optionValues).flat()
|
|
145
|
+
]);
|
|
146
|
+
const recordId = /^(?:task|project|message|run|work|wake|operation|review|input|job|integration|publication)-\d+(?:\/(?:message|run|work|wake|review|input|job|integration|publication)-\d+)?$/;
|
|
147
|
+
return {
|
|
148
|
+
operation: node.path.join(" "),
|
|
149
|
+
targets: operands.filter(value => recordId.test(value)),
|
|
150
|
+
// Do not replay argv: operands include Message bodies, config values and credentials.
|
|
151
|
+
privateValues: operands.filter(value => !/^--[a-z][a-z-]*$/.test(value) && !recordId.test(value) && !publicValues.has(value)),
|
|
152
|
+
home: invocationHome ?? process.env.YUI_HOME ?? "(default Home unresolved)",
|
|
153
|
+
cli: fileURLToPath(import.meta.url),
|
|
154
|
+
environment: process.env
|
|
155
|
+
};
|
|
164
156
|
}
|
|
165
157
|
export async function main() {
|
|
166
158
|
const home = resolveYuiHome(process.env);
|
|
159
|
+
const discovery = discoveryCommandTree(process.env);
|
|
160
|
+
invocationHome = home;
|
|
167
161
|
const routedForFence = args.length === 0 ? undefined : routeInvocation(args);
|
|
168
162
|
const managedInvocation = process.env.YUI_SESSION_SCOPE === "task"
|
|
169
163
|
|| process.env.YUI_SESSION_SCOPE === "global";
|
|
170
164
|
const homeFreeInvocation = args.length === 0
|
|
165
|
+
|| (args[0] === "config" && (args[1] === "describe"
|
|
166
|
+
|| (args[1] === "completion" && args[2] === "candidates")))
|
|
171
167
|
|| (args[0] === "version" && args.length === 1)
|
|
172
168
|
|| routedForFence?.kind === "help"
|
|
173
169
|
|| routedForFence?.kind === "path-error"
|
|
@@ -188,7 +184,7 @@ export async function main() {
|
|
|
188
184
|
stdio: "inherit"
|
|
189
185
|
});
|
|
190
186
|
if (delegated.error !== undefined) {
|
|
191
|
-
throw runtimeError(
|
|
187
|
+
throw runtimeError("Target release activation driver could not start.", { cause: delegated.error });
|
|
192
188
|
}
|
|
193
189
|
if (delegated.signal !== null) {
|
|
194
190
|
throw runtimeError(`Target release activation driver stopped by signal ${delegated.signal}.`);
|
|
@@ -197,16 +193,16 @@ export async function main() {
|
|
|
197
193
|
return;
|
|
198
194
|
}
|
|
199
195
|
if (args.length === 0) {
|
|
200
|
-
emit(renderCommandHelp(
|
|
196
|
+
emit(renderCommandHelp(discovery, VERSION), false, jsonOutput ? describeCommandTree(discovery) : undefined);
|
|
201
197
|
return;
|
|
202
198
|
}
|
|
203
199
|
if (args[0] === "version" && args.length === 1) {
|
|
204
200
|
emit(VERSION, true, yuiVersionIdentity());
|
|
205
201
|
return;
|
|
206
202
|
}
|
|
207
|
-
const invocation = routeInvocation(args);
|
|
203
|
+
const invocation = routeInvocation(args, discovery);
|
|
208
204
|
if (invocation.kind === "help") {
|
|
209
|
-
emit(renderCommandHelp(invocation.node, VERSION), true);
|
|
205
|
+
emit(renderCommandHelp(invocation.node, VERSION), true, jsonOutput ? describeCommandTree(invocation.node) : undefined);
|
|
210
206
|
return;
|
|
211
207
|
}
|
|
212
208
|
if (invocation.kind === "path-error") {
|
|
@@ -217,11 +213,22 @@ export async function main() {
|
|
|
217
213
|
}
|
|
218
214
|
if (args[0] === "version")
|
|
219
215
|
throw usageError("Version usage: yui version");
|
|
216
|
+
// Offline discovery is not an execution credential. Target selectors enter
|
|
217
|
+
// the original authenticated path lazily, only when stored data is needed.
|
|
218
|
+
if (args[0] === "config" && args[1] === "completion" && args[2] === "candidates") {
|
|
219
|
+
await completionCommand(home, invocation.node);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (args[0] === "config" && args[1] === "describe") {
|
|
223
|
+
const target = findCommandNode(args[2] === undefined ? ["config"] : ["config", args[2]], discovery);
|
|
224
|
+
if (args.length > 3 || !target)
|
|
225
|
+
throw usageError("Config describe usage: yui config describe [visible-domain].");
|
|
226
|
+
emit(renderCommandHelp(target, VERSION), false, describeCommandTree(target));
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
220
229
|
const { contract: taskFinalReviewContract, verifiedStore } = await preflightManagedTaskControlPlane();
|
|
221
230
|
assertTaskInvocationScope(args, process.env);
|
|
222
|
-
if (["config", "resources"].includes(args[0] ?? "") && (
|
|
223
|
-
|| process.env.YUI_ROLE !== undefined || process.env.YUI_AGENT_ID !== undefined
|
|
224
|
-
|| process.env.YUI_NATIVE_SESSION_ID !== undefined)) {
|
|
231
|
+
if (["config", "resources"].includes(args[0] ?? "") && hasManagedIdentity(process.env)) {
|
|
225
232
|
const ownedStore = verifiedStore === undefined ? openCurrentTaskStore(home) : undefined;
|
|
226
233
|
try {
|
|
227
234
|
assertConfigurationAuthority(args, verifiedStore ?? ownedStore, process.env);
|
|
@@ -240,7 +247,10 @@ export async function main() {
|
|
|
240
247
|
const subcommand = args[1];
|
|
241
248
|
if (subcommand === "install" && args.length === 3) {
|
|
242
249
|
const result = runReleaseInstall(home, args[2]);
|
|
243
|
-
|
|
250
|
+
if (result.outcome === "aborted")
|
|
251
|
+
emitFailureResult(renderReleaseInstallResult(result), result);
|
|
252
|
+
else
|
|
253
|
+
emit(renderReleaseInstallResult(result), false, result);
|
|
244
254
|
if (result.outcome === "aborted")
|
|
245
255
|
process.exitCode = 5;
|
|
246
256
|
return;
|
|
@@ -259,7 +269,11 @@ export async function main() {
|
|
|
259
269
|
+ "(or activate the active release when exactly one is installed).");
|
|
260
270
|
}
|
|
261
271
|
const result = await runReleaseActivate(home, releaseId);
|
|
262
|
-
|
|
272
|
+
if (result.outcome === "aborted" || result.outcome === "dual-owner") {
|
|
273
|
+
emitFailureResult(renderReleaseActivateResult(result), result);
|
|
274
|
+
}
|
|
275
|
+
else
|
|
276
|
+
emit(renderReleaseActivateResult(result), false, result);
|
|
263
277
|
if (result.outcome === "aborted" || result.outcome === "dual-owner") {
|
|
264
278
|
process.exitCode = 5;
|
|
265
279
|
}
|
|
@@ -271,21 +285,6 @@ export async function main() {
|
|
|
271
285
|
await completionCommand(home, invocation.node);
|
|
272
286
|
return;
|
|
273
287
|
}
|
|
274
|
-
if (args[0] === "config" && args[1] === "describe") {
|
|
275
|
-
const describeNode = findCommandNode(["config", "describe"]);
|
|
276
|
-
if (describeNode === undefined)
|
|
277
|
-
throw new Error("Config describe command is missing from the catalog.");
|
|
278
|
-
const domain = args[2];
|
|
279
|
-
const domains = describeNode.argumentValues[0] ?? [];
|
|
280
|
-
if (args.length > 3 || (domain !== undefined && !domains.includes(domain))) {
|
|
281
|
-
throw usageError(`Config describe usage: ${describeNode.usage.join(" | ")}.`);
|
|
282
|
-
}
|
|
283
|
-
const target = findCommandNode(domain === undefined ? ["config"] : ["config", domain]);
|
|
284
|
-
if (target === undefined)
|
|
285
|
-
throw new Error(`Config domain is missing from the catalog: ${domain}.`);
|
|
286
|
-
emit(renderCommandHelp(target, VERSION), false, describeCommandTree(target));
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
288
|
if (args[0] === "capability") {
|
|
290
289
|
const result = await runCapabilityCommand(args.slice(1), home, process.env);
|
|
291
290
|
emit(JSON.stringify(result, null, 2), false, result);
|
|
@@ -356,7 +355,7 @@ export async function main() {
|
|
|
356
355
|
codex = await prepareLocalCodexStartup(startupStore, home, process.env);
|
|
357
356
|
}
|
|
358
357
|
catch (error) {
|
|
359
|
-
throw runtimeError(
|
|
358
|
+
throw runtimeError("Controller is ready, but Codex shared startup failed.", { cause: error });
|
|
360
359
|
}
|
|
361
360
|
const lines = ["Yui Controller is ready."];
|
|
362
361
|
if (codex.daemons.length === 0)
|
|
@@ -398,20 +397,13 @@ export async function main() {
|
|
|
398
397
|
if (args[0] === "upgrade") {
|
|
399
398
|
const result = await runUpgradeCommand(args.slice(1), home);
|
|
400
399
|
process.exitCode = result.exitCode;
|
|
401
|
-
|
|
400
|
+
if (result.exitCode !== 0)
|
|
401
|
+
emitFailureResult(result.output, result.data);
|
|
402
|
+
else
|
|
403
|
+
emit(result.output, false, result.data);
|
|
402
404
|
return;
|
|
403
405
|
}
|
|
404
406
|
if (args[0] === "internal") {
|
|
405
|
-
if (args[1] === "session-cli-refresh" && args.length === 2) {
|
|
406
|
-
if (process.env.YUI_SESSION_SCOPE === "task"
|
|
407
|
-
|| (process.env.YUI_SESSION_SCOPE === "global" && process.env.YUI_ROLE !== "operator")) {
|
|
408
|
-
throw usageError("Managed Session CLI refresh may be run only by the user or global Operator.");
|
|
409
|
-
}
|
|
410
|
-
const result = refreshManagedSessionCliWrappers(home, currentInvocationEntryPoint());
|
|
411
|
-
emit(`Refreshed ${result.refreshed} managed Session CLI wrapper(s); `
|
|
412
|
-
+ `${result.current} already current, ${result.skipped} skipped.`, false, result);
|
|
413
|
-
return;
|
|
414
|
-
}
|
|
415
407
|
if (args[1] === "agent-host" && args.length === 3) {
|
|
416
408
|
process.exitCode = await runAgentHost({
|
|
417
409
|
home,
|
|
@@ -483,17 +475,7 @@ export async function main() {
|
|
|
483
475
|
catch (error) {
|
|
484
476
|
if (!(error instanceof ControllerClientError))
|
|
485
477
|
throw error;
|
|
486
|
-
|
|
487
|
-
process.stderr.write(`${JSON.stringify({
|
|
488
|
-
ok: false,
|
|
489
|
-
code: error.code,
|
|
490
|
-
message: error.message,
|
|
491
|
-
details: {}
|
|
492
|
-
})}\n`);
|
|
493
|
-
}
|
|
494
|
-
else {
|
|
495
|
-
process.stderr.write(`RUNTIME_ERROR: ${error.message}\n`);
|
|
496
|
-
}
|
|
478
|
+
process.stderr.write(`${renderCliFailure(describeCliFailure(error, failureContext()), jsonOutput, error.code)}\n`);
|
|
497
479
|
process.exitCode = 5;
|
|
498
480
|
}
|
|
499
481
|
return;
|
|
@@ -517,17 +499,7 @@ export async function main() {
|
|
|
517
499
|
// unknown-active block.
|
|
518
500
|
if (!(error instanceof ControllerClientError))
|
|
519
501
|
throw error;
|
|
520
|
-
|
|
521
|
-
process.stderr.write(`${JSON.stringify({
|
|
522
|
-
ok: false,
|
|
523
|
-
code: error.code,
|
|
524
|
-
message: error.message,
|
|
525
|
-
details: {}
|
|
526
|
-
})}\n`);
|
|
527
|
-
}
|
|
528
|
-
else {
|
|
529
|
-
process.stderr.write(`RUNTIME_ERROR: ${error.message}\n`);
|
|
530
|
-
}
|
|
502
|
+
process.stderr.write(`${renderCliFailure(describeCliFailure(error, failureContext()), jsonOutput, error.code)}\n`);
|
|
531
503
|
process.exitCode = 5;
|
|
532
504
|
}
|
|
533
505
|
return;
|
|
@@ -674,7 +646,7 @@ export async function main() {
|
|
|
674
646
|
yuiHome: home,
|
|
675
647
|
historyLimit: resolveTmuxHistoryLimit(store.getConfig().tmuxHistoryLimit),
|
|
676
648
|
terminalInput: process.stdin,
|
|
677
|
-
onWarning: (message) =>
|
|
649
|
+
onWarning: (message) => writeCliWarning(message)
|
|
678
650
|
});
|
|
679
651
|
const telemetry = openSchedulerTelemetry(home, store.getConfig());
|
|
680
652
|
try {
|
|
@@ -684,8 +656,11 @@ export async function main() {
|
|
|
684
656
|
const runtime = new FileTaskWorkflowRuntime(home, store, schedulerStore, planner, tmux, workspacePreparer, {
|
|
685
657
|
environment: process.env,
|
|
686
658
|
onError: (error) => {
|
|
687
|
-
|
|
688
|
-
|
|
659
|
+
// Advisory async failure: preserve the foreground command's exit status.
|
|
660
|
+
const failure = describeCliFailure(error, failureContext());
|
|
661
|
+
process.stderr.write(`${renderCliFailure({
|
|
662
|
+
...failure, details: { ...failure.details, advisory: true }
|
|
663
|
+
}, jsonOutput)}\n`);
|
|
689
664
|
}
|
|
690
665
|
});
|
|
691
666
|
const workspaceCoordinator = new TaskWorkspaceCoordinator(store, workspacePreparer, runtime);
|
|
@@ -845,6 +820,10 @@ export async function main() {
|
|
|
845
820
|
? [resolved[1], ...resolved.slice(2)]
|
|
846
821
|
: ["session", resolved[1] ?? "", ...resolved.slice(2)];
|
|
847
822
|
const result = runGlobalRoleCommand(sessionArgs, store, roleOptions);
|
|
823
|
+
if (typeof result !== "string" && result.kind === "output") {
|
|
824
|
+
emit(result.output, false, result.data);
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
848
827
|
if (typeof result === "string") {
|
|
849
828
|
emit(result);
|
|
850
829
|
return;
|
|
@@ -893,6 +872,14 @@ export async function main() {
|
|
|
893
872
|
emit(result);
|
|
894
873
|
return;
|
|
895
874
|
}
|
|
875
|
+
if (result.kind === "output") {
|
|
876
|
+
if (globalInputFailure !== undefined) {
|
|
877
|
+
emitControlFailure(globalInputFailure.detail, globalInputFailure.code, globalInputFailure.data);
|
|
878
|
+
}
|
|
879
|
+
else
|
|
880
|
+
emit(result.output, false, result.data);
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
896
883
|
if (result.kind === "input-steer") {
|
|
897
884
|
// Core already persisted the durable Global Message and proved target +
|
|
898
885
|
// capability + writer fence from the Global Role's own Session set. This
|
|
@@ -1101,8 +1088,7 @@ export async function main() {
|
|
|
1101
1088
|
finalizeStoppedTaskExecution(result.taskId, store);
|
|
1102
1089
|
}
|
|
1103
1090
|
catch (error) {
|
|
1104
|
-
|
|
1105
|
-
throw runtimeError(`Task execution is stopped and durable progress is preserved, but physical runtime cleanup failed: ${message}`);
|
|
1091
|
+
throw runtimeError("Task execution is stopped and durable progress is preserved, but physical runtime cleanup failed.", { cause: error });
|
|
1106
1092
|
}
|
|
1107
1093
|
emit(result.output, false, result);
|
|
1108
1094
|
return;
|
|
@@ -1317,6 +1303,19 @@ export async function main() {
|
|
|
1317
1303
|
let archiveRemoteDeliveryProof;
|
|
1318
1304
|
let archiveTaskReviewCandidate;
|
|
1319
1305
|
if (resolved[1] === "archive") {
|
|
1306
|
+
const request = parseTaskArchiveArguments(resolved.slice(2));
|
|
1307
|
+
if (request.sourceMessage !== undefined) {
|
|
1308
|
+
if (request.force || request.disposition !== "integrated") {
|
|
1309
|
+
throw usageError("Leader ordinary archive does not authorize --force or --abandon.");
|
|
1310
|
+
}
|
|
1311
|
+
const result = await callController(home, "capability.call", {
|
|
1312
|
+
taskId: request.taskId, caller: resolveJobCaller(process.env, request.taskId),
|
|
1313
|
+
request: { name: "task.archive", requestId: request.requestId,
|
|
1314
|
+
input: { taskId: request.taskId, sourceMessage: request.sourceMessage, purpose: request.purpose } }
|
|
1315
|
+
});
|
|
1316
|
+
emit("Controller archive result; inspect task events if this Session ends before the receipt.\n", false, result);
|
|
1317
|
+
return;
|
|
1318
|
+
}
|
|
1320
1319
|
const { taskId, disposition, force } = validateTaskArchiveRequest(resolved.slice(2), store, {
|
|
1321
1320
|
runtime,
|
|
1322
1321
|
environment: process.env,
|
|
@@ -1497,7 +1496,7 @@ export async function main() {
|
|
|
1497
1496
|
})
|
|
1498
1497
|
});
|
|
1499
1498
|
for (const warning of completionWarnings) {
|
|
1500
|
-
|
|
1499
|
+
writeCliWarning(warning);
|
|
1501
1500
|
}
|
|
1502
1501
|
// Refresh observes remote objects only. Choosing and executing an
|
|
1503
1502
|
// upstream Integration belongs to its explicit command, never completion.
|
|
@@ -1962,6 +1961,9 @@ async function preflightManagedTaskControlPlane() {
|
|
|
1962
1961
|
if (process.env.YUI_SESSION_SCOPE === "global") {
|
|
1963
1962
|
return await preflightManagedGlobalControlPlane();
|
|
1964
1963
|
}
|
|
1964
|
+
if (hasManagedIdentity(process.env)) {
|
|
1965
|
+
throw usageError("Managed Agent identity is incomplete; refusing to infer user authority.");
|
|
1966
|
+
}
|
|
1965
1967
|
if (taskFinalReviewInvocation.request !== undefined) {
|
|
1966
1968
|
throw new Error("Task final-review contract may only be established from the Task Leader's managed Session.");
|
|
1967
1969
|
}
|
|
@@ -2035,7 +2037,7 @@ async function preflightManagedGlobalControlPlane() {
|
|
|
2035
2037
|
const expectedRoleKind = process.env.YUI_ROLE === "operator" ? "operator" : "global";
|
|
2036
2038
|
if (manifest.owner.scope !== "global"
|
|
2037
2039
|
|| manifest.roleKind !== expectedRoleKind) {
|
|
2038
|
-
throw new
|
|
2040
|
+
throw new ManagedRuntimeDriftError("Managed global invocation does not match its Session Manifest.");
|
|
2039
2041
|
}
|
|
2040
2042
|
if (expectedRoleKind === "operator" && ["doctor", "upgrade", "update"].includes(args[0] ?? "")) {
|
|
2041
2043
|
// These commands inspect/adopt the storage contract themselves. Requiring
|
|
@@ -2059,28 +2061,24 @@ async function preflightManagedGlobalControlPlane() {
|
|
|
2059
2061
|
}
|
|
2060
2062
|
return { contract: undefined, verifiedStore };
|
|
2061
2063
|
}
|
|
2062
|
-
/**
|
|
2063
|
-
* The entry point the current invocation resolves to. Only its executable and
|
|
2064
|
-
* CLI path are used, to retarget managed Session wrappers at this installation.
|
|
2065
|
-
*/
|
|
2066
|
-
function currentInvocationEntryPoint() {
|
|
2067
|
-
return {
|
|
2068
|
-
executable: process.execPath,
|
|
2069
|
-
cliEntry: fileURLToPath(import.meta.url)
|
|
2070
|
-
};
|
|
2071
|
-
}
|
|
2072
2064
|
function assertManagedSessionManifest(home, scope) {
|
|
2073
2065
|
const manifestPath = process.env.YUI_SESSION_MANIFEST;
|
|
2074
2066
|
if (manifestPath === undefined) {
|
|
2075
|
-
throw new
|
|
2067
|
+
throw new ManagedRuntimeDriftError("Managed control-plane invocation requires its Session Manifest.");
|
|
2068
|
+
}
|
|
2069
|
+
let manifest;
|
|
2070
|
+
try {
|
|
2071
|
+
manifest = readSessionBootstrapManifest(manifestPath);
|
|
2072
|
+
}
|
|
2073
|
+
catch (error) {
|
|
2074
|
+
throw new ManagedRuntimeDriftError("Managed Session Manifest could not be verified.", { cause: error });
|
|
2076
2075
|
}
|
|
2077
|
-
const manifest = readSessionBootstrapManifest(manifestPath);
|
|
2078
2076
|
if (manifest.owner.scope !== scope) {
|
|
2079
|
-
throw new
|
|
2077
|
+
throw new ManagedRuntimeDriftError("Managed invocation scope does not match its Session Manifest.");
|
|
2080
2078
|
}
|
|
2081
2079
|
if (scope === "task" && (manifest.owner.scope !== "task"
|
|
2082
2080
|
|| manifest.owner.taskId !== process.env.YUI_TASK_ID)) {
|
|
2083
|
-
throw new
|
|
2081
|
+
throw new ManagedRuntimeDriftError("Managed Task invocation does not match its Session Manifest owner.");
|
|
2084
2082
|
}
|
|
2085
2083
|
const expectedPath = resolve(home, "runtime", "session-manifests", `${manifest.digest}.json`);
|
|
2086
2084
|
// YUI_HOME is canonicalized (its macOS /var -> /private/var prefix is a
|
|
@@ -2093,7 +2091,7 @@ function assertManagedSessionManifest(home, scope) {
|
|
|
2093
2091
|
canonicalManifestPath = resolve(manifestPath);
|
|
2094
2092
|
}
|
|
2095
2093
|
if (canonicalManifestPath !== expectedPath) {
|
|
2096
|
-
throw new
|
|
2094
|
+
throw new ManagedRuntimeDriftError("Managed Session Manifest path is outside this YUI_HOME.");
|
|
2097
2095
|
}
|
|
2098
2096
|
return manifest;
|
|
2099
2097
|
}
|
|
@@ -2104,7 +2102,7 @@ function cleanupCliError(error, fallbackResource) {
|
|
|
2104
2102
|
if (error instanceof WorkspaceCleanupBlockedError) {
|
|
2105
2103
|
return usageError(error.message, undefined, cleanupBlockedDetails(error.reason, error.resource, error.retryable));
|
|
2106
2104
|
}
|
|
2107
|
-
return new CliError("RUNTIME_ERROR", error instanceof Error ? error.message : String(error), undefined, cleanupBlockedDetails("cleanup-failed", fallbackResource, true));
|
|
2105
|
+
return new CliError("RUNTIME_ERROR", error instanceof Error ? error.message : String(error), undefined, cleanupBlockedDetails("cleanup-failed", fallbackResource, true), { cause: error });
|
|
2108
2106
|
}
|
|
2109
2107
|
function cleanupBlockedDetails(reason, resource, retryable, checks) {
|
|
2110
2108
|
return {
|
|
@@ -2540,7 +2538,7 @@ async function prepareCodexForCurrentRoles(store, home, targetAgentId) {
|
|
|
2540
2538
|
}
|
|
2541
2539
|
}
|
|
2542
2540
|
catch (error) {
|
|
2543
|
-
const detail = error
|
|
2541
|
+
const detail = describeCliFailure(error, failureContext()).message;
|
|
2544
2542
|
const permissionDenied = isCodexInspectionPermissionError(error);
|
|
2545
2543
|
codexAppNotice(`${permissionDenied
|
|
2546
2544
|
? "Codex sharing could not be prepared or verified from this process"
|
|
@@ -2559,7 +2557,7 @@ function assertHomeStartupAuthority(store) {
|
|
|
2559
2557
|
requireManagedGlobalCaller(store, process.env);
|
|
2560
2558
|
}
|
|
2561
2559
|
function codexAppNotice(message, notification) {
|
|
2562
|
-
|
|
2560
|
+
writeCliWarning(message);
|
|
2563
2561
|
if (process.platform !== "darwin")
|
|
2564
2562
|
return;
|
|
2565
2563
|
// The native TUI clears terminal output on attach, so keep the actionable
|
|
@@ -2569,6 +2567,12 @@ function codexAppNotice(message, notification) {
|
|
|
2569
2567
|
`display notification "${notification}" with title "Yui"`
|
|
2570
2568
|
], { stdio: "ignore", timeout: 3_000 });
|
|
2571
2569
|
}
|
|
2570
|
+
function writeCliWarning(message) {
|
|
2571
|
+
const safe = sanitizeFailureText(message, failureContext());
|
|
2572
|
+
process.stderr.write(`${jsonOutput
|
|
2573
|
+
? JSON.stringify({ ok: false, code: "RUNTIME_ERROR", message: safe, details: { advisory: true } })
|
|
2574
|
+
: `Warning: ${safe}`}\n`);
|
|
2575
|
+
}
|
|
2572
2576
|
function renderControllerResult(method, value) {
|
|
2573
2577
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
2574
2578
|
return JSON.stringify(value);
|
|
@@ -2595,10 +2599,23 @@ async function completionCommand(home, node) {
|
|
|
2595
2599
|
if (prefix === undefined || separator !== 4) {
|
|
2596
2600
|
throw usageError("Completion candidates usage: yui config completion candidates <prefix> -- <words...>");
|
|
2597
2601
|
}
|
|
2602
|
+
let selection;
|
|
2598
2603
|
const candidates = await resolveCompletionCandidates({
|
|
2599
2604
|
current: prefix,
|
|
2600
2605
|
words: args.slice(separator + 1),
|
|
2601
|
-
|
|
2606
|
+
root: discoveryCommandTree(process.env),
|
|
2607
|
+
ports: { call: async (method, params) => {
|
|
2608
|
+
if (!selection) {
|
|
2609
|
+
assertCliHomeReleaseFence({
|
|
2610
|
+
home, packageRoot: fileURLToPath(new URL("../", import.meta.url)),
|
|
2611
|
+
entryPath: fileURLToPath(import.meta.url), args
|
|
2612
|
+
});
|
|
2613
|
+
await preflightManagedTaskControlPlane();
|
|
2614
|
+
assertTaskInvocationScope(args.slice(separator + 1), process.env);
|
|
2615
|
+
selection = completionSelectionPorts(home);
|
|
2616
|
+
}
|
|
2617
|
+
return selection.call(method, params);
|
|
2618
|
+
} }
|
|
2602
2619
|
});
|
|
2603
2620
|
process.stdout.write(candidates.length === 0 ? "" : `${candidates.join("\n")}\n`);
|
|
2604
2621
|
return;
|
|
@@ -2771,13 +2788,12 @@ async function warmConfigurationMutationCatalog(commandArgs, store, catalogs) {
|
|
|
2771
2788
|
async function liveHostObservationsForTaskCommand(args, store, home) {
|
|
2772
2789
|
if (args[0] !== "task" || args[1] !== "role")
|
|
2773
2790
|
return undefined;
|
|
2774
|
-
const inspect = args[2] === "session" && args[3] === "inspect" && args.length
|
|
2775
|
-
const status = args[2] === "status" && args.length
|
|
2776
|
-
|
|
2777
|
-
if (!inspect && !status && !list)
|
|
2791
|
+
const inspect = args[2] === "session" && args[3] === "inspect" && args.length >= 6;
|
|
2792
|
+
const status = args[2] === "status" && args.length >= 5;
|
|
2793
|
+
if (!inspect && !status)
|
|
2778
2794
|
return undefined;
|
|
2779
2795
|
const taskId = args[inspect ? 4 : 3];
|
|
2780
|
-
const roles =
|
|
2796
|
+
const roles = [args[inspect ? 5 : 4]];
|
|
2781
2797
|
const entries = await Promise.all(roles.map(async (roleName) => [
|
|
2782
2798
|
roleName, await readLiveHostObservation(store, home, taskId, roleName)
|
|
2783
2799
|
]));
|
|
@@ -2942,7 +2958,37 @@ function completionSelectionPorts(home) {
|
|
|
2942
2958
|
return { call: () => [] };
|
|
2943
2959
|
}
|
|
2944
2960
|
const store = readableStore(home);
|
|
2945
|
-
|
|
2961
|
+
const ports = selectionPorts(store, new AgentConfigurationCatalogService(home, { environment: process.env }));
|
|
2962
|
+
if (process.env.YUI_SESSION_SCOPE !== "task")
|
|
2963
|
+
return ports;
|
|
2964
|
+
const taskId = process.env.YUI_TASK_ID;
|
|
2965
|
+
const readable = contextRecordReader(store, taskId, process.env);
|
|
2966
|
+
const families = {
|
|
2967
|
+
"task.list": "task", "project.list": "project-policy", "task.role.list": "role",
|
|
2968
|
+
"task.work.list": "work-item", "task.message.list": "task-message", "task.input.list": "input-request",
|
|
2969
|
+
"task.turn.list": "run", "task.decision.list": "task-decision", "task.milestone.list": "task-milestone",
|
|
2970
|
+
"task.event.list": "task-event", "task.change-set.list": "change-set",
|
|
2971
|
+
"task.integration.list": "integration-attempt"
|
|
2972
|
+
};
|
|
2973
|
+
return { call: async (method, params) => {
|
|
2974
|
+
if (params.taskId !== undefined && params.taskId !== taskId)
|
|
2975
|
+
return [];
|
|
2976
|
+
const family = families[method];
|
|
2977
|
+
if (!family)
|
|
2978
|
+
return []; // Completion never needs broader authority than Context.
|
|
2979
|
+
const scopedParams = method === "task.input.list" ? { ...params, taskId } : params;
|
|
2980
|
+
const values = await ports.call(method, scopedParams);
|
|
2981
|
+
if (!Array.isArray(values))
|
|
2982
|
+
return [];
|
|
2983
|
+
return values.filter(value => {
|
|
2984
|
+
const id = String(value.id ?? value.name ?? "");
|
|
2985
|
+
if (method === "task.list" && id !== taskId)
|
|
2986
|
+
return false;
|
|
2987
|
+
if (method === "project.list" && !store.getTask(taskId)?.projectBindings.some(binding => binding.projectId === id))
|
|
2988
|
+
return false;
|
|
2989
|
+
return readable(family, id);
|
|
2990
|
+
});
|
|
2991
|
+
} };
|
|
2946
2992
|
}
|
|
2947
2993
|
function emit(output, literal = false, data) {
|
|
2948
2994
|
const normalized = literal ? output.trimEnd() : output.trimEnd();
|
|
@@ -2954,9 +3000,17 @@ function emit(output, literal = false, data) {
|
|
|
2954
3000
|
}
|
|
2955
3001
|
function emitControlFailure(message, code, details) {
|
|
2956
3002
|
process.exitCode = 2;
|
|
3003
|
+
const context = failureContext();
|
|
3004
|
+
const safeMessage = sanitizeFailureText(message.trim(), context);
|
|
3005
|
+
const safeDetails = sanitizeFailureDetails({ value: details }, context).value;
|
|
2957
3006
|
process.stdout.write(`${jsonOutput
|
|
2958
|
-
? JSON.stringify({ ok: false, code, message:
|
|
2959
|
-
:
|
|
3007
|
+
? JSON.stringify({ ok: false, code, message: safeMessage, details: safeDetails })
|
|
3008
|
+
: safeMessage}\n`);
|
|
3009
|
+
}
|
|
3010
|
+
/** Domain-owned failure reports retain their output envelope and effect receipts. */
|
|
3011
|
+
function emitFailureResult(output, data) {
|
|
3012
|
+
const context = failureContext();
|
|
3013
|
+
emit(sanitizeFailureText(output, context), false, sanitizeFailureDetails({ value: data }, context).value);
|
|
2960
3014
|
}
|
|
2961
3015
|
/**
|
|
2962
3016
|
* The human line for a live steer, corrected to the *actual* live acceptance
|
|
@@ -3,7 +3,7 @@ import { resolveJobCaller } from "../task/taskAuthority.js";
|
|
|
3
3
|
import { callFileTaskController } from "../controller/clientRuntime.js";
|
|
4
4
|
export async function runCapabilityCommand(args, home, environment) {
|
|
5
5
|
const [action, ...rest] = args;
|
|
6
|
-
const usage = "yui capability search [query] --task <id> | commands --task <id> | panels --task <id> | describe <name> --task <id> [--provider <id>] [--version <version>] | call <name> --task <id> --input <json> [--provider <id>] [--version <version>] [--request-id <id>]";
|
|
6
|
+
const usage = "yui capability search [query] --task <id> | commands --task <id> | panels --task <id> | describe <name> --task <id> [--input <json>] [--provider <id>] [--version <version>] | call <name> --task <id> --input <json> [--provider <id>] [--version <version>] [--request-id <id>]";
|
|
7
7
|
if (!["search", "commands", "panels", "describe", "call"].includes(action))
|
|
8
8
|
throw usageError(usage);
|
|
9
9
|
const surfaceList = action === "commands" || action === "panels";
|
|
@@ -29,12 +29,12 @@ export async function runCapabilityCommand(args, home, environment) {
|
|
|
29
29
|
throw usageError(usage);
|
|
30
30
|
if ((action === "search" || surfaceList) && [...flags.keys()].some((key) => key !== "--task"))
|
|
31
31
|
throw usageError(usage);
|
|
32
|
-
if (action === "describe" &&
|
|
32
|
+
if (action === "describe" && flags.has("--request-id"))
|
|
33
33
|
throw usageError(usage);
|
|
34
34
|
let input;
|
|
35
|
-
if (action === "call")
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
if (action === "call" && !flags.has("--input"))
|
|
36
|
+
throw usageError("Capability call requires --input <json>.", usage);
|
|
37
|
+
if (flags.has("--input")) {
|
|
38
38
|
try {
|
|
39
39
|
input = JSON.parse(flags.get("--input"));
|
|
40
40
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { usageError } from "../errors/cliError.js";
|
|
2
|
+
import { describeCliFailure } from "../errors/cliFailure.js";
|
|
2
3
|
import { defaultTableWidth, renderTable } from "../output/table.js";
|
|
3
4
|
import { DEFAULT_RECONCILIATION_INTERVAL_SECONDS } from "../config/yuiConfig.js";
|
|
4
5
|
import { evaluateStorageHealth, UNSUPPORTED } from "../observability/runtimeIdentity.js";
|
|
@@ -280,7 +281,7 @@ export async function runInteractiveControllerCleanup(input) {
|
|
|
280
281
|
catch (error) {
|
|
281
282
|
failed.push({
|
|
282
283
|
id: resource.id,
|
|
283
|
-
message: error
|
|
284
|
+
message: describeCliFailure(error).message
|
|
284
285
|
});
|
|
285
286
|
}
|
|
286
287
|
}
|