@zq-silk/yui 0.15.7 → 0.15.8
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 +192 -399
- package/README.md +127 -1149
- package/dist/agent/adapterCatalog.js +15 -2
- package/dist/agent/agent.js +23 -3
- package/dist/agent/argumentPolicy.js +7 -1
- package/dist/agent/connectionPlan.js +62 -0
- package/dist/agent/executionComponents.js +158 -0
- package/dist/agent/launchEnvironment.js +31 -3
- package/dist/agent/managedRuntimeEnvironment.js +3 -5
- package/dist/{turn/turn.js → agentRun/agentRun.js} +166 -109
- package/dist/{turn/turnIdentity.js → agentRun/runIdentity.js} +4 -4
- package/dist/brief/taskBrief.js +12 -0
- package/dist/cli/agentConfigurationPicker.js +13 -0
- package/dist/cli/commandCatalog.js +157 -70
- package/dist/cli/interactionCandidates.js +5 -5
- package/dist/cli/interactionPolicy.js +38 -8
- package/dist/cli/invocationRouter.js +1 -1
- package/dist/cli/managedDiagnostics.js +28 -0
- package/dist/cli/operatorWizard.js +1 -7
- package/dist/cli/roleOptionOrder.js +27 -0
- package/dist/cli/roleWizard.js +50 -14
- package/dist/cli/updateOrchestrator.js +1 -1
- package/dist/cli/updatePorts.js +3 -4
- package/dist/cli.js +178 -95
- package/dist/commands/agentCommands.js +72 -14
- package/dist/commands/capabilityCommands.js +9 -6
- package/dist/commands/configCommands.js +20 -20
- package/dist/commands/deliveryGuardPreflight.js +2 -2
- package/dist/commands/executionAuditCommands.js +24 -24
- package/dist/commands/globalRoleCommands.js +1 -1
- package/dist/commands/grantCommands.js +4 -4
- package/dist/commands/operatorCommands.js +1 -7
- package/dist/commands/projectCommands.js +4 -4
- package/dist/commands/resourcesCommands.js +2 -2
- package/dist/commands/roleConfiguration.js +25 -5
- package/dist/commands/roleRuntimeGuard.js +4 -5
- package/dist/commands/sessionCommands.js +3 -7
- package/dist/commands/taskActivationCommands.js +259 -0
- package/dist/commands/taskActor.js +28 -49
- package/dist/commands/taskCommands.js +1188 -710
- package/dist/commands/taskContextCommand.js +39 -583
- package/dist/commands/taskExecutionCommands.js +32 -32
- package/dist/commands/taskInputCommands.js +40 -104
- package/dist/commands/taskIntegrationCommands.js +3 -2
- package/dist/commands/taskIntegrationQueueCommands.js +1 -1
- package/dist/commands/taskNextActionCommand.js +8 -8
- package/dist/commands/taskOverviewCommand.js +33 -45
- package/dist/commands/taskRemoteDeliveryCommand.js +2 -2
- package/dist/commands/taskRoleRuntimeStatus.js +133 -102
- package/dist/commands/telemetryCommands.js +36 -38
- package/dist/config/configCatalog.js +4 -4
- package/dist/config/yuiConfig.js +8 -8
- package/dist/context/contextSnapshot.js +10 -10
- package/dist/context/dispatchContext.js +11 -11
- package/dist/context/roleSessionContext.js +6 -3
- package/dist/context/{turnContextPack.js → runContextPack.js} +146 -81
- package/dist/context/{turnInputContract.js → runInputContract.js} +73 -60
- package/dist/context/sessionBootstrapManifest.js +21 -2
- package/dist/context/sourceRunContext.js +30 -0
- package/dist/context/taskContext.js +458 -0
- package/dist/context/wakeNotification.js +27 -27
- package/dist/controller/agentRuntimeObserver.js +21 -24
- package/dist/controller/capabilityBridge.js +17 -6
- package/dist/controller/clientRuntime.js +65 -92
- package/dist/controller/controller.js +114 -188
- package/dist/controller/fileSchedulerStoreAdapter.js +787 -887
- package/dist/controller/jobControl.js +54 -85
- package/dist/controller/resourceInventory.js +8 -27
- package/dist/controller/resourceInventoryLinux.js +12 -13
- package/dist/controller/runtime.js +529 -479
- package/dist/controller/runtimeEventInbox.js +55 -25
- package/dist/controller/runtimeEventProcessor.js +22 -31
- package/dist/controller/{runtimeHookTurnFence.js → runtimeHookRunFence.js} +91 -115
- package/dist/controller/runtimeLaunchCoordinator.js +80 -426
- package/dist/controller/runtimeObservationHook.js +14 -18
- package/dist/controller/sessionNotify.js +16 -24
- package/dist/controller/sessionOwnerReconciliation.js +168 -50
- package/dist/controller/structuredProviderObservation.js +138 -99
- package/dist/coordination/workMailbox.js +3 -3
- package/dist/coordination/workMailboxQueue.js +36 -33
- package/dist/core/boundedRpc.js +8 -1
- package/dist/core/controllerClient.js +20 -1
- package/dist/core/controllerServer.js +4 -4
- package/dist/doctor/doctor.js +13 -2
- package/dist/domain/agentResultTransport.js +9 -9
- package/dist/execution/codexThreadNaming.js +2 -8
- package/dist/execution/executionHealth.js +51 -63
- package/dist/execution/reviewMainRun.js +137 -0
- package/dist/execution/workItemExecution.js +28 -29
- package/dist/execution/workItemExecutionProjection.js +99 -107
- package/dist/execution/workItemMainRun.js +141 -0
- package/dist/executor/agentAdapter.js +227 -20
- package/dist/executor/agentConfigurationCatalog.js +126 -4
- package/dist/executor/agentConfigurationProbe.js +162 -4
- package/dist/executor/agentExecutor.js +79 -78
- package/dist/executor/effectiveLaunch.js +105 -18
- package/dist/executor/executorRegistry.js +29 -44
- package/dist/executor/fileRoleLaunchPlanner.js +229 -154
- package/dist/executor/workspacePreflightClassification.js +16 -16
- package/dist/grant/capabilityGrant.js +6 -3
- package/dist/input/inputRequest.js +12 -10
- package/dist/integration/gitIntegrationService.js +4 -11
- package/dist/integration/integrationQueueService.js +4 -4
- package/dist/interaction/operatorPresentation.js +1 -1
- package/dist/kernel/builtinCapabilities.js +247 -12
- package/dist/kernel/capabilityRegistry.js +64 -18
- package/dist/kernel/instanceHost.js +12 -1
- package/dist/kernel/kernelPorts.js +2 -2
- package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
- package/dist/lifecycle/exactRunTerminalization.js +449 -0
- package/dist/message/message.js +62 -6
- package/dist/message/messageContinuation.js +204 -0
- package/dist/observability/executionAudit.js +70 -72
- package/dist/observability/faultClassification.js +2 -2
- package/dist/observability/orchestrationMetrics.js +8 -8
- package/dist/operator/operatorSessionHistory.js +1 -7
- package/dist/output/agentConfigurationPresentation.js +8 -3
- package/dist/output/agentRunConfigurationPresentation.js +128 -0
- package/dist/output/rolePresentation.js +54 -3
- package/dist/plugins/pluginChild.js +104 -0
- package/dist/plugins/pluginIntent.js +26 -0
- package/dist/plugins/pluginInterpreter.js +43 -0
- package/dist/plugins/pluginPackage.js +101 -0
- package/dist/plugins/pluginProcess.js +112 -0
- package/dist/plugins/pluginService.js +380 -0
- package/dist/profile/agentProfile.js +1 -1
- package/dist/repository/gitWorkspace.js +26 -4
- package/dist/repository/project.js +19 -4
- package/dist/repository/taskBaseFreshness.js +13 -13
- package/dist/repository/taskWorkspaceCoordinator.js +20 -27
- package/dist/repository/taskWorkspacePreparer.js +344 -83
- package/dist/resources/autoResourceGc.js +3 -3
- package/dist/resources/liveReferences.js +3 -3
- package/dist/resources/projectResource.js +123 -0
- package/dist/resources/projectResourceService.js +421 -0
- package/dist/resources/resourceDiscovery.js +6 -6
- package/dist/resources/resourceGc.js +1 -1
- package/dist/resources/resourceRegistrar.js +1 -1
- package/dist/resources/resourceTypes.js +1 -1
- package/dist/review/deltaRecheck.js +3 -3
- package/dist/review/reviewAcceptance.js +16 -16
- package/dist/review/reviewDecision.js +7 -7
- package/dist/review/reviewRound.js +21 -20
- package/dist/review/reviewerAvailability.js +2 -2
- package/dist/role/role.js +51 -7
- package/dist/role/taskRoleUpdate.js +30 -0
- package/dist/runtime/acpProtocol.js +425 -0
- package/dist/runtime/acpSession.js +731 -0
- package/dist/runtime/acpSessionConfiguration.js +260 -0
- package/dist/runtime/agentDriver.js +30 -11
- package/dist/runtime/agentEndpoint.js +278 -0
- package/dist/runtime/agentEndpointIdentity.js +86 -0
- package/dist/runtime/agentEndpointOwnership.js +239 -0
- package/dist/runtime/agentError.js +2 -10
- package/dist/runtime/agentHost.js +565 -314
- package/dist/runtime/agentRunConfiguration.js +258 -0
- package/dist/runtime/builtinAgentDrivers.js +134 -18
- package/dist/runtime/builtinAgentErrorMappers.js +55 -3
- package/dist/runtime/builtinTranscriptUsage.js +1 -1
- package/dist/runtime/claude-process-owner +0 -0
- package/dist/runtime/codexAppServerRuntime.js +38 -30
- package/dist/runtime/codexInteractiveHost.js +41 -6
- package/dist/runtime/continuationManager.js +2 -6
- package/dist/runtime/executionEnvironment.js +30 -0
- package/dist/runtime/firstProgressAdvisory.js +11 -11
- package/dist/runtime/index.js +4 -3
- package/dist/runtime/jsonLineChannel.js +109 -0
- package/dist/runtime/launchBroker.js +91 -16
- package/dist/runtime/launchDiagnostics.js +2 -2
- package/dist/runtime/lifecycleReservation.js +10 -18
- package/dist/runtime/managedCaller.js +61 -17
- package/dist/runtime/nativeSessionControl.js +102 -0
- package/dist/runtime/ports.js +6 -21
- package/dist/runtime/processExitObservation.js +8 -7
- package/dist/runtime/promptEnvelope.js +17 -6
- package/dist/runtime/providerContinuation.js +3 -9
- package/dist/runtime/providerContinuationReconciliationService.js +4 -13
- package/dist/runtime/providerControl.js +2 -7
- package/dist/runtime/providerRuntimeIdentity.js +110 -222
- package/dist/runtime/providerRuntimeReconciler.js +5 -9
- package/dist/runtime/runtimeBinding.js +0 -1
- package/dist/runtime/runtimeContinuationProjection.js +4 -7
- package/dist/runtime/runtimeDeadlines.js +9 -0
- package/dist/runtime/runtimeHealthPolicy.js +1 -1
- package/dist/runtime/runtimeObservation.js +29 -65
- package/dist/runtime/runtimeProjection.js +43 -51
- package/dist/runtime/runtimeSessionCandidate.js +1 -3
- package/dist/runtime/sessionLaunchRequest.js +3 -7
- package/dist/runtime/sessionOwnerIdentity.js +7 -54
- package/dist/runtime/sessionOwnerRegistry.js +22 -17
- package/dist/runtime/sessionReconciliation.js +4 -8
- package/dist/runtime/sessionTerminationGuard.js +70 -259
- package/dist/runtime/sessionTokenMetrics.js +5 -16
- package/dist/runtime/structuredProviderHost.js +237 -117
- package/dist/runtime/taskRuntimeIsolation.js +39 -122
- package/dist/runtime/tmuxAdapters.js +39 -86
- package/dist/scheduler/activeRoleRunDelivery.js +354 -0
- package/dist/scheduler/leaderWakeupProcessor.js +75 -266
- package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
- package/dist/scheduler/ports.js +80 -9
- package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
- package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
- package/dist/scheduler/taskExecutionProjection.js +120 -124
- package/dist/scheduler/taskObservabilityProjection.js +29 -29
- package/dist/scheduler/taskWake.js +11 -4
- package/dist/scheduler/wakeReason.js +9 -1
- package/dist/setup/setupCommand.js +1 -0
- package/dist/storage/migrations/agentRunContract.js +159 -0
- package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
- package/dist/storage/sqliteSchema.js +431 -5
- package/dist/storage/sqliteStore.js +375 -220
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/storeRpc.js +10 -5
- package/dist/storage/taskStore.js +13 -11
- package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
- package/dist/surface/surfaceContributions.js +102 -0
- package/dist/task/completionReadiness.js +32 -6
- package/dist/task/deliveryGuard.js +16 -16
- package/dist/task/draftPlan.js +72 -12
- package/dist/task/nextAction.js +144 -128
- package/dist/task/remoteDelivery.js +6 -6
- package/dist/task/task.js +184 -18
- package/dist/task/taskActivation.js +301 -0
- package/dist/task/taskActivationService.js +392 -0
- package/dist/task/taskRecordReference.js +5 -4
- package/dist/task/taskRecordRetirement.js +1 -1
- package/dist/telemetry/sqliteTelemetryStore.js +55 -68
- package/dist/telemetry/telemetryConfig.js +14 -14
- package/dist/telemetry/telemetryWiring.js +2 -2
- package/dist/web/assets/assetManifest.js +2 -0
- package/dist/web/assets/client/app.js +120 -20
- package/dist/web/assets/client/components.js +87 -54
- package/dist/web/assets/client/i18n.js +83 -41
- package/dist/web/assets/client/markdown.js +1 -1
- package/dist/web/assets/client/taskSurface.js +353 -0
- package/dist/web/assets/client/view.js +49 -44
- package/dist/web/assets/shell.js +1 -1
- package/dist/web/assets/styles/cards.js +22 -4
- package/dist/web/controllerWeb.js +60 -0
- package/dist/web/webMutation.js +28 -0
- package/dist/web/webServer.js +118 -8
- package/dist/web/webSnapshot.js +81 -74
- package/dist/web/webTaskSurface.js +64 -0
- package/dist/workItem/dependencyGate.js +1 -1
- package/dist/workItem/workItem.js +80 -48
- package/dist/workspace/workItemChangeSetManager.js +16 -9
- package/docs/agent-result-consumption.md +94 -0
- package/docs/agent-runtime-drivers.md +91 -0
- package/docs/architecture/README.md +38 -0
- package/docs/architecture/capabilities-and-resources.md +79 -0
- package/docs/managed-turn-and-session-runtime.md +222 -0
- package/docs/observability/README.md +81 -0
- package/docs/plugin-sdk.md +290 -0
- package/docs/provider-runtime.md +163 -0
- package/docs/release-workflow.md +303 -0
- package/docs/roles-and-configuration.md +113 -0
- package/docs/sqlite-control-plane-design.md +76 -0
- package/docs/task-dag-semantics.md +57 -0
- package/docs/task-delivery.md +103 -0
- package/docs/task-local-identity.md +6 -6
- package/docs/testing/verification-levels.md +86 -0
- package/i18n/README.zh-CN.md +98 -739
- package/package.json +2 -2
- package/skills/yui-leader/SKILL.md +130 -103
- package/skills/yui-leader/references/integration.md +39 -0
- package/skills/yui-leader/references/replicated-execution.md +42 -0
- package/skills/yui-leader/references/task-plugins.md +33 -0
- package/skills/yui-operator/SKILL.md +30 -59
- package/skills/yui-reviewer/SKILL.md +35 -36
- package/skills/yui-runtime/SKILL.md +88 -24
- package/skills/yui-runtime/references/publication.md +22 -0
- package/skills/yui-runtime/references/recovery.md +64 -0
- package/skills/yui-worker/SKILL.md +37 -39
- package/dist/cli/roleOptionCatalog.js +0 -68
- package/dist/context/sourceTurnContext.js +0 -30
- package/dist/execution/reviewMainTurn.js +0 -161
- package/dist/execution/workItemMainTurn.js +0 -164
- package/dist/lifecycle/exactTurnTerminalization.js +0 -407
- package/dist/runtime/preallocatedNativeSession.js +0 -13
- package/dist/runtime/runtimeStopReceipt.js +0 -42
- package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { isDeepStrictEqual } from "node:util";
|
|
2
2
|
import { agentNotFound, usageError } from "../errors/cliError.js";
|
|
3
3
|
import { defaultTableWidth, renderTable } from "../output/table.js";
|
|
4
|
+
import { isAgentAdapterId, supportedAgentAdapterIds } from "../agent/adapterCatalog.js";
|
|
5
|
+
import { adapterIdForExecutionComponent, agentExecutionComponentLabel, defaultExecutionComponentForAdapter, isAgentExecutionComponentId, supportedAgentExecutionComponentIds } from "../agent/executionComponents.js";
|
|
4
6
|
import { createConfiguredAgent, validateConfiguredAgent } from "../agent/agent.js";
|
|
5
7
|
import { LIVE_SESSION_ACKNOWLEDGEMENT_OPTION } from "./roleRuntimeGuard.js";
|
|
6
8
|
import { hasRuntimeLifecycleWork, runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
|
|
7
|
-
const SUPPORTED_ADAPTERS = Object.freeze(["codex", "claude"]);
|
|
8
9
|
export function runAgentCommand(args, store) {
|
|
9
10
|
const [command, ...rest] = args;
|
|
10
11
|
switch (command) {
|
|
@@ -23,16 +24,24 @@ function addAgent(args, store) {
|
|
|
23
24
|
const [rawId, ...tail] = args;
|
|
24
25
|
const id = agentId(rawId);
|
|
25
26
|
const parsed = parseAgentOptions(tail, "add");
|
|
26
|
-
const
|
|
27
|
-
if (
|
|
28
|
-
|
|
27
|
+
const component = parsed.one("--component")?.trim();
|
|
28
|
+
if (component !== undefined)
|
|
29
|
+
assertComponent(component);
|
|
30
|
+
// Naming the component is enough: it determines its own connection plan, so
|
|
31
|
+
// there is one fact to state rather than a pair that could contradict.
|
|
32
|
+
const adapterId = parsed.one("--adapter")
|
|
33
|
+
?? (component === undefined ? undefined : adapterIdForExecutionComponent(component))
|
|
34
|
+
?? (isAgentAdapterId(id) ? id : undefined);
|
|
35
|
+
if (adapterId === undefined) {
|
|
36
|
+
throw usageError("--component or --adapter is required.");
|
|
37
|
+
}
|
|
29
38
|
assertAdapter(adapterId);
|
|
30
39
|
const command = parsed.one("--command")?.trim();
|
|
31
40
|
if (command === undefined || command.length === 0)
|
|
32
41
|
throw usageError("--command is required.");
|
|
33
42
|
let agent;
|
|
34
43
|
try {
|
|
35
|
-
agent = createConfiguredAgent(id, adapterId, command, parsed.many("--arg"), parsed.many("--env").map(parseEnvironmentBinding), new Date());
|
|
44
|
+
agent = createConfiguredAgent(id, adapterId, command, parsed.many("--arg"), parsed.many("--env").map(parseEnvironmentBinding), new Date(), component);
|
|
36
45
|
}
|
|
37
46
|
catch (error) {
|
|
38
47
|
throw usageError(error instanceof Error ? error.message : String(error));
|
|
@@ -50,11 +59,13 @@ function listAgents(args, store) {
|
|
|
50
59
|
return "No agents configured.\n";
|
|
51
60
|
return `${renderTable("Agents", [
|
|
52
61
|
{ header: "Agent", minWidth: 5, maxWidth: 24 },
|
|
62
|
+
{ header: "Component", minWidth: 9, maxWidth: 20 },
|
|
53
63
|
{ header: "Adapter", minWidth: 7, maxWidth: 12 },
|
|
54
64
|
{ header: "Command", minWidth: 7, maxWidth: 48 },
|
|
55
65
|
{ header: "Environment", minWidth: 11, maxWidth: 32 }
|
|
56
66
|
], agents.map((agent) => [
|
|
57
67
|
agent.id,
|
|
68
|
+
agent.component,
|
|
58
69
|
agent.adapterId,
|
|
59
70
|
[agent.command, ...agent.baseArgs].join(" "),
|
|
60
71
|
agent.environment.map((binding) => `${binding.target}<-${binding.sourceName}`).join(", ")
|
|
@@ -86,11 +97,25 @@ function updateAgent(args, store) {
|
|
|
86
97
|
const adapterId = parsed.one("--adapter")?.trim();
|
|
87
98
|
if (adapterId !== undefined)
|
|
88
99
|
assertAdapter(adapterId);
|
|
100
|
+
const component = parsed.one("--component")?.trim();
|
|
101
|
+
if (component !== undefined)
|
|
102
|
+
assertComponent(component);
|
|
103
|
+
if (component !== undefined && adapterId !== undefined
|
|
104
|
+
&& adapterIdForExecutionComponent(component) !== adapterId) {
|
|
105
|
+
throw usageError(`Agent execution component ${component} is reached over the `
|
|
106
|
+
+ `${adapterIdForExecutionComponent(component)} connection plan, not ${adapterId}. `
|
|
107
|
+
+ "Pass --component alone to move the Agent onto its own plan.");
|
|
108
|
+
}
|
|
89
109
|
const command = parsed.one("--command")?.trim();
|
|
90
110
|
if (command !== undefined && command.length === 0)
|
|
91
111
|
throw usageError("--command is required.");
|
|
92
|
-
const
|
|
112
|
+
const requestedPatch = {
|
|
93
113
|
...(adapterId === undefined ? {} : { adapterId }),
|
|
114
|
+
// Changing the component can move the Agent onto its plan, which is the one
|
|
115
|
+
// way the two stay consistent without asking the operator to restate both.
|
|
116
|
+
...(component === undefined
|
|
117
|
+
? {}
|
|
118
|
+
: { component, adapterId: adapterIdForExecutionComponent(component) }),
|
|
94
119
|
...(command === undefined ? {} : { command }),
|
|
95
120
|
...(parsed.has("--arg")
|
|
96
121
|
? { baseArgs: parsed.many("--arg") }
|
|
@@ -104,6 +129,14 @@ function updateAgent(args, store) {
|
|
|
104
129
|
const existing = tx.getConfiguredAgent(id);
|
|
105
130
|
if (existing === null)
|
|
106
131
|
return null;
|
|
132
|
+
// Derive a default only when actually leaving the stored plan. Restating
|
|
133
|
+
// the same plan must preserve an explicitly identified ACP component.
|
|
134
|
+
const patch = {
|
|
135
|
+
...requestedPatch,
|
|
136
|
+
...(component === undefined && adapterId !== undefined && adapterId !== existing.adapterId
|
|
137
|
+
? { component: defaultExecutionComponentForAdapter(adapterId) }
|
|
138
|
+
: {})
|
|
139
|
+
};
|
|
107
140
|
const changes = actualAgentChanges(existing, patch);
|
|
108
141
|
if (!changes.operational) {
|
|
109
142
|
return { status: "unchanged", agent: existing };
|
|
@@ -117,22 +150,37 @@ function updateAgent(args, store) {
|
|
|
117
150
|
const liveSession = findNonStoppedSessionReference(tx, id);
|
|
118
151
|
if (liveSession !== null && !parsed.has(LIVE_SESSION_ACKNOWLEDGEMENT_OPTION)) {
|
|
119
152
|
throw usageError(`${describeReference(liveSession)} runs a live native session (${liveSession.status}) on `
|
|
120
|
-
+ `Agent ${id}, so this change applies to its next Host
|
|
153
|
+
+ `Agent ${id}, so this change applies to its next Host process instead of the `
|
|
121
154
|
+ "running one.\n"
|
|
122
155
|
+ `Re-run with ${LIVE_SESSION_ACKNOWLEDGEMENT_OPTION} to record the change and keep that `
|
|
123
156
|
+ "session.\n"
|
|
124
157
|
+ "Stop the affected Role session first to apply it to a fresh session instead.");
|
|
125
158
|
}
|
|
126
|
-
|
|
159
|
+
// A component change is refused on a referenced Agent for the same reason
|
|
160
|
+
// an adapter change is, and the reason is not symmetry: the product identity
|
|
161
|
+
// is copied into Role bindings and frozen into every Session snapshot at
|
|
162
|
+
// launch. Rewriting only the Agent leaves those copies asserting the old
|
|
163
|
+
// product while the new command runs, so a Session resumes against one
|
|
164
|
+
// product under another's name. Rewriting the copies instead would relabel
|
|
165
|
+
// history that really did run the old product. Neither is correctable here,
|
|
166
|
+
// so the change is refused and the operator binds a new Agent explicitly —
|
|
167
|
+
// which leaves existing Sessions pinned to what they actually ran.
|
|
168
|
+
const identityChange = changes.adapter
|
|
169
|
+
? { axis: "adapter", target: "adapter" }
|
|
170
|
+
: changes.component ? { axis: "execution component", target: "component" } : null;
|
|
171
|
+
if (identityChange !== null) {
|
|
127
172
|
const profile = findAgentProfileReference(tx, id);
|
|
128
173
|
if (profile !== null) {
|
|
129
|
-
throw usageError(`Agent ${id}
|
|
174
|
+
throw usageError(`Agent ${id} ${identityChange.axis} cannot change because Agent Profile `
|
|
175
|
+
+ `${profile.id} references it. `
|
|
130
176
|
+ "Update that explicit Profile or create a new Agent ID instead.");
|
|
131
177
|
}
|
|
132
178
|
const binding = findRoleBindingReference(tx, id);
|
|
133
179
|
if (binding !== null) {
|
|
134
|
-
throw usageError(`Agent ${id}
|
|
135
|
-
+
|
|
180
|
+
throw usageError(`Agent ${id} ${identityChange.axis} cannot change because `
|
|
181
|
+
+ `${describeReference(binding)} references it. `
|
|
182
|
+
+ `Create a new Agent ID with the target ${identityChange.target} and bind the Role `
|
|
183
|
+
+ "to it instead.");
|
|
136
184
|
}
|
|
137
185
|
}
|
|
138
186
|
assertValidAgentCandidate(existing, patch, now);
|
|
@@ -184,12 +232,14 @@ function removeAgent(args, store) {
|
|
|
184
232
|
}
|
|
185
233
|
function actualAgentChanges(existing, patch) {
|
|
186
234
|
const adapter = patch.adapterId !== undefined && patch.adapterId !== existing.adapterId;
|
|
235
|
+
const component = patch.component !== undefined && patch.component !== existing.component;
|
|
187
236
|
const operational = adapter
|
|
237
|
+
|| component
|
|
188
238
|
|| (patch.command !== undefined && patch.command !== existing.command)
|
|
189
239
|
|| (patch.baseArgs !== undefined && !isDeepStrictEqual(patch.baseArgs, existing.baseArgs))
|
|
190
240
|
|| (patch.environment !== undefined
|
|
191
241
|
&& !isDeepStrictEqual(patch.environment, existing.environment));
|
|
192
|
-
return { adapter, operational };
|
|
242
|
+
return { adapter, component, operational };
|
|
193
243
|
}
|
|
194
244
|
function assertValidAgentCandidate(existing, patch, now) {
|
|
195
245
|
try {
|
|
@@ -274,6 +324,7 @@ function describeReference(reference) {
|
|
|
274
324
|
function parseAgentOptions(args, mode) {
|
|
275
325
|
const valueOptions = new Map([
|
|
276
326
|
["--adapter", { repeatable: false, allowOptionLikeValue: false }],
|
|
327
|
+
["--component", { repeatable: false, allowOptionLikeValue: false }],
|
|
277
328
|
["--command", { repeatable: false, allowOptionLikeValue: false }],
|
|
278
329
|
["--arg", { repeatable: true, allowOptionLikeValue: true }],
|
|
279
330
|
["--env", { repeatable: true, allowOptionLikeValue: false }]
|
|
@@ -339,8 +390,14 @@ function agentId(value) {
|
|
|
339
390
|
return value.trim();
|
|
340
391
|
}
|
|
341
392
|
function assertAdapter(value) {
|
|
342
|
-
if (!
|
|
343
|
-
throw usageError(`Agent adapter is not supported: ${value}. Supported adapters: ${
|
|
393
|
+
if (!isAgentAdapterId(value)) {
|
|
394
|
+
throw usageError(`Agent adapter is not supported: ${value}. Supported adapters: ${supportedAgentAdapterIds().join(", ")}.`);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
function assertComponent(value) {
|
|
398
|
+
if (!isAgentExecutionComponentId(value)) {
|
|
399
|
+
throw usageError(`Agent execution component is not supported: ${value}. Supported components: `
|
|
400
|
+
+ `${supportedAgentExecutionComponentIds().join(", ")}.`);
|
|
344
401
|
}
|
|
345
402
|
}
|
|
346
403
|
function assertNoArguments(args, message) {
|
|
@@ -350,6 +407,7 @@ function assertNoArguments(args, message) {
|
|
|
350
407
|
function renderAgent(title, agent) {
|
|
351
408
|
return [
|
|
352
409
|
title,
|
|
410
|
+
`Component: ${agent.component} (${agentExecutionComponentLabel(agent.component)})`,
|
|
353
411
|
`Adapter: ${agent.adapterId}`,
|
|
354
412
|
`Executable: ${agent.command}`,
|
|
355
413
|
`Arguments: ${agent.baseArgs.join(" ")}`,
|
|
@@ -3,9 +3,10 @@ import { resolveJobCaller } from "./taskActor.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> | describe <name> --task <id> [--provider <id>] [--version <version>] | call <name> --task <id> --input <json> [--provider <id>] [--version <version>] [--request-id <id>]";
|
|
7
|
-
if (!["search", "describe", "call"].includes(action))
|
|
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>]";
|
|
7
|
+
if (!["search", "commands", "panels", "describe", "call"].includes(action))
|
|
8
8
|
throw usageError(usage);
|
|
9
|
+
const surfaceList = action === "commands" || action === "panels";
|
|
9
10
|
const flags = new Map();
|
|
10
11
|
const positionals = [];
|
|
11
12
|
const allowed = new Set(["--task", "--provider", "--version", "--input", "--request-id"]);
|
|
@@ -22,9 +23,11 @@ export async function runCapabilityCommand(args, home, environment) {
|
|
|
22
23
|
flags.set(arg, next);
|
|
23
24
|
}
|
|
24
25
|
const taskId = flags.get("--task") ?? environment.YUI_TASK_ID;
|
|
25
|
-
if (!taskId || positionals.length > 1
|
|
26
|
+
if (!taskId || positionals.length > 1
|
|
27
|
+
|| (!surfaceList && action !== "search" && !positionals.length)
|
|
28
|
+
|| (surfaceList && positionals.length))
|
|
26
29
|
throw usageError(usage);
|
|
27
|
-
if (action === "search" && [...flags.keys()].some((key) => key !== "--task"))
|
|
30
|
+
if ((action === "search" || surfaceList) && [...flags.keys()].some((key) => key !== "--task"))
|
|
28
31
|
throw usageError(usage);
|
|
29
32
|
if (action === "describe" && (flags.has("--input") || flags.has("--request-id")))
|
|
30
33
|
throw usageError(usage);
|
|
@@ -39,9 +42,9 @@ export async function runCapabilityCommand(args, home, environment) {
|
|
|
39
42
|
throw usageError("Invalid capability JSON input.");
|
|
40
43
|
}
|
|
41
44
|
}
|
|
42
|
-
return callFileTaskController(home, `capability.${action}`, {
|
|
45
|
+
return callFileTaskController(home, `capability.${surfaceList ? "search" : action}`, {
|
|
43
46
|
taskId, caller: resolveJobCaller(environment, taskId),
|
|
44
|
-
...(action === "search" ? { query: positionals[0] ?? "" } : {
|
|
47
|
+
...(surfaceList ? { surface: action } : action === "search" ? { query: positionals[0] ?? "" } : {
|
|
45
48
|
request: {
|
|
46
49
|
name: positionals[0],
|
|
47
50
|
...(input === undefined ? {} : { input }),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { mkdirSync, realpathSync } from "node:fs";
|
|
2
2
|
import { isAbsolute, relative, resolve } from "node:path";
|
|
3
3
|
import { usageError } from "../errors/cliError.js";
|
|
4
|
-
import { DEFAULT_AGENT_LAUNCH_INACTIVITY_TIMEOUT_SECONDS, DEFAULT_CONTROLLER_TASK_CONCURRENCY, DEFAULT_DELIVERY_TIMEOUT_SECONDS, DEFAULT_LEADER_NEXT_ACTION_MODE,
|
|
4
|
+
import { DEFAULT_AGENT_LAUNCH_INACTIVITY_TIMEOUT_SECONDS, DEFAULT_CONTROLLER_TASK_CONCURRENCY, DEFAULT_DELIVERY_TIMEOUT_SECONDS, DEFAULT_LEADER_NEXT_ACTION_MODE, DEFAULT_LEADER_SEMANTIC_BUDGET_RUNS, DEFAULT_RECONCILIATION_INTERVAL_SECONDS, DEFAULT_RESOURCES_GC_MODE, DEFAULT_RESOURCES_QUARANTINE_TTL_HOURS, DEFAULT_TMUX_HISTORY_LIMIT, LEADER_NEXT_ACTION_MODES, reconciliationIntervalMilliseconds, resolveAgentLaunchInactivityTimeoutSeconds, resolveControllerTaskConcurrency, resolveDeliveryTimeoutSeconds, resolveLeaderNextActionMode, resolveLeaderSemanticBudgetRuns, resolveResourcesGcAutoQuarantine, resolveResourcesGcMode, resolveResourcesQuarantineTtlHours, resolveRuntimeHealth, resolveTelemetryEnabled, resolveTelemetryRunCap, resolveTelemetryTerminalKeep, resolveTmuxBin, resolveTmuxHistoryLimit } from "../config/yuiConfig.js";
|
|
5
5
|
import { CONFIG_DEFINITIONS, CONFIG_KEYS, configDefinition, configDefinitionsForDomain } from "../config/configCatalog.js";
|
|
6
6
|
import { resolveTimeZone } from "../output/timePresentation.js";
|
|
7
7
|
import { defaultTableWidth, renderTable } from "../output/table.js";
|
|
@@ -77,12 +77,12 @@ export function effectiveConfigData(config, domain) {
|
|
|
77
77
|
controllerTaskConcurrency: resolveControllerTaskConcurrency(config.controllerTaskConcurrency),
|
|
78
78
|
agentLaunchInactivityTimeoutSeconds: resolveAgentLaunchInactivityTimeoutSeconds(config.agentLaunchInactivityTimeoutSeconds),
|
|
79
79
|
deliveryTimeoutSeconds: resolveDeliveryTimeoutSeconds(config.deliveryTimeoutSeconds),
|
|
80
|
-
|
|
80
|
+
leaderSemanticBudgetRuns: resolveLeaderSemanticBudgetRuns(config.leaderSemanticBudgetRuns),
|
|
81
81
|
tmuxBin: resolveTmuxBin(config.tmuxBin),
|
|
82
82
|
tmuxHistoryLimit: resolveTmuxHistoryLimit(config.tmuxHistoryLimit),
|
|
83
83
|
telemetryEnabled: resolveTelemetryEnabled(config.telemetryEnabled),
|
|
84
84
|
telemetryTerminalKeep: resolveTelemetryTerminalKeep(config.telemetryTerminalKeep),
|
|
85
|
-
|
|
85
|
+
telemetryRunCap: resolveTelemetryRunCap(config.telemetryRunCap),
|
|
86
86
|
review: config.review === undefined
|
|
87
87
|
? null
|
|
88
88
|
: {
|
|
@@ -263,23 +263,23 @@ const CONFIG_KEY_HANDLERS = [
|
|
|
263
263
|
}
|
|
264
264
|
},
|
|
265
265
|
{
|
|
266
|
-
key: "leader-semantic-budget-
|
|
266
|
+
key: "leader-semantic-budget-runs",
|
|
267
267
|
showLabel: "Leader semantic budget",
|
|
268
|
-
showValue: (config) => `${
|
|
268
|
+
showValue: (config) => `${resolveLeaderSemanticBudgetRuns(config.leaderSemanticBudgetRuns)} runs`,
|
|
269
269
|
set(args, store) {
|
|
270
|
-
const usage = "Workflow config set usage: yui config workflow set leader-semantic-budget-
|
|
270
|
+
const usage = "Workflow config set usage: yui config workflow set leader-semantic-budget-runs <1-20>.";
|
|
271
271
|
if (args.length !== 1)
|
|
272
272
|
throw usageError(usage);
|
|
273
|
-
const
|
|
274
|
-
saveConfigKey(store, (config) => ({ ...config,
|
|
275
|
-
return `Leader semantic budget set to ${
|
|
273
|
+
const leaderSemanticBudgetRuns = validatedConfigValue(() => resolveLeaderSemanticBudgetRuns(Number(args[0])), usage);
|
|
274
|
+
saveConfigKey(store, (config) => ({ ...config, leaderSemanticBudgetRuns }));
|
|
275
|
+
return `Leader semantic budget set to ${leaderSemanticBudgetRuns} runs\n`;
|
|
276
276
|
},
|
|
277
277
|
clear(store) {
|
|
278
278
|
saveConfigKey(store, (config) => {
|
|
279
|
-
const {
|
|
279
|
+
const { leaderSemanticBudgetRuns: _removed, ...rest } = config;
|
|
280
280
|
return rest;
|
|
281
281
|
});
|
|
282
|
-
return `Leader semantic budget reset to ${
|
|
282
|
+
return `Leader semantic budget reset to ${DEFAULT_LEADER_SEMANTIC_BUDGET_RUNS} runs\n`;
|
|
283
283
|
}
|
|
284
284
|
},
|
|
285
285
|
{
|
|
@@ -520,22 +520,22 @@ const CONFIG_KEY_HANDLERS = [
|
|
|
520
520
|
}
|
|
521
521
|
},
|
|
522
522
|
{
|
|
523
|
-
key: "telemetry-
|
|
524
|
-
showLabel: "Telemetry
|
|
525
|
-
showValue: (config) => String(
|
|
523
|
+
key: "telemetry-run-cap",
|
|
524
|
+
showLabel: "Telemetry AgentRun cap",
|
|
525
|
+
showValue: (config) => String(resolveTelemetryRunCap(config.telemetryRunCap)),
|
|
526
526
|
set(args, store) {
|
|
527
527
|
if (args.length !== 1)
|
|
528
|
-
throw usageError("Tools config set usage: yui config tools set telemetry-
|
|
529
|
-
const
|
|
530
|
-
saveConfigKey(store, (config) => ({ ...config,
|
|
531
|
-
return `Telemetry
|
|
528
|
+
throw usageError("Tools config set usage: yui config tools set telemetry-run-cap <n>.");
|
|
529
|
+
const telemetryRunCap = validatedConfigValue(() => resolveTelemetryRunCap(Number(args[0])), "Tools config set usage: yui config tools set telemetry-run-cap <n>.");
|
|
530
|
+
saveConfigKey(store, (config) => ({ ...config, telemetryRunCap }));
|
|
531
|
+
return `Telemetry AgentRun cap set to ${telemetryRunCap}\n`;
|
|
532
532
|
},
|
|
533
533
|
clear(store) {
|
|
534
534
|
saveConfigKey(store, (config) => {
|
|
535
|
-
const {
|
|
535
|
+
const { telemetryRunCap: _removed, ...rest } = config;
|
|
536
536
|
return rest;
|
|
537
537
|
});
|
|
538
|
-
return "Telemetry
|
|
538
|
+
return "Telemetry AgentRun cap reset to default\n";
|
|
539
539
|
}
|
|
540
540
|
},
|
|
541
541
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolveLeaderNextActionMode,
|
|
1
|
+
import { resolveLeaderNextActionMode, resolveLeaderSemanticBudgetRuns } from "../config/yuiConfig.js";
|
|
2
2
|
import { usageError } from "../errors/cliError.js";
|
|
3
3
|
import { detectDeliveryDuplicates, evaluateDeliveryGuard, evaluateSemanticBudget, formatDeliveryDuplicate } from "../task/deliveryGuard.js";
|
|
4
4
|
export function runDeliveryGuardPreflight(store, taskId, intent, options = {}) {
|
|
@@ -15,7 +15,7 @@ export function runDeliveryGuardPreflight(store, taskId, intent, options = {}) {
|
|
|
15
15
|
+ "Reuse the existing proof, or set leader.nextActionMode=warn to proceed with a warning.");
|
|
16
16
|
}
|
|
17
17
|
if (options.budget === true) {
|
|
18
|
-
const budget = evaluateSemanticBudget(facts,
|
|
18
|
+
const budget = evaluateSemanticBudget(facts, resolveLeaderSemanticBudgetRuns(store.getConfig().leaderSemanticBudgetRuns));
|
|
19
19
|
if (budget.exhausted) {
|
|
20
20
|
warnings.push(`Semantic progress budget: ${budget.reason}`);
|
|
21
21
|
}
|
|
@@ -92,26 +92,26 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
|
|
|
92
92
|
else {
|
|
93
93
|
lines.push("", ...sectionError("tasks", report));
|
|
94
94
|
}
|
|
95
|
-
if (report.
|
|
96
|
-
const
|
|
97
|
-
lines.push("", `
|
|
98
|
-
const faultRows = Object.entries(
|
|
95
|
+
if (report.runs.status === "ok" && report.runs.data !== undefined) {
|
|
96
|
+
const runs = report.runs.data;
|
|
97
|
+
lines.push("", `AgentRuns: ${runs.total} total · ${runs.failed} failed (${(runs.failureRate * 100).toFixed(1)}%) · ${runs.completed} completed · ${runs.active} active`, `Duration: ${formatDuration(runs.cumulativeDurationMs)} total · ${formatDuration(runs.failedDurationMs)} in failed AgentRuns`, `By role: ${runs.byRole.leader} leader · ${runs.byRole.reviewer} reviewer · ${runs.byRole.implementer} implementer/worker · ${runs.byRole.other} other`, `By purpose: ${runs.byPurpose.execution} execution · ${runs.byPurpose.review} review`);
|
|
98
|
+
const faultRows = Object.entries(runs.faultClasses)
|
|
99
99
|
.filter(([, count]) => count > 0)
|
|
100
100
|
.sort((left, right) => right[1] - left[1]);
|
|
101
101
|
if (faultRows.length > 0) {
|
|
102
|
-
lines.push(renderTable("
|
|
102
|
+
lines.push(renderTable("AgentRun failure classes", [
|
|
103
103
|
{ header: "Class", minWidth: 24, maxWidth: 40 },
|
|
104
104
|
{ header: "Count", minWidth: 5, maxWidth: 8 }
|
|
105
105
|
], faultRows.map(([name, count]) => [name, String(count)]), width));
|
|
106
106
|
}
|
|
107
|
-
if (
|
|
108
|
-
const phaseRows = Object.entries(
|
|
107
|
+
if (runs.launchFailures.total > 0) {
|
|
108
|
+
const phaseRows = Object.entries(runs.launchFailures.byPhase)
|
|
109
109
|
.filter(([, count]) => count > 0)
|
|
110
110
|
.sort((left, right) => right[1] - left[1]);
|
|
111
|
-
const kindRows = Object.entries(
|
|
111
|
+
const kindRows = Object.entries(runs.launchFailures.byKind)
|
|
112
112
|
.filter(([, count]) => count > 0)
|
|
113
113
|
.sort((left, right) => right[1] - left[1]);
|
|
114
|
-
lines.push("", `Launch failures: ${
|
|
114
|
+
lines.push("", `Launch failures: ${runs.launchFailures.total}`, `By phase: ${phaseRows.map(([name, count]) => `${name}=${count}`).join(" · ")}`, `By kind: ${kindRows.map(([name, count]) => `${name}=${count}`).join(" · ")}`);
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
else {
|
|
@@ -119,9 +119,9 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
|
|
|
119
119
|
}
|
|
120
120
|
if (report.wakes.status === "ok" && report.wakes.data !== undefined) {
|
|
121
121
|
const wakes = report.wakes.data;
|
|
122
|
-
lines.push("", `Leader wakes: ${wakes.
|
|
122
|
+
lines.push("", `Leader wakes: ${wakes.leaderRuns} AgentRuns · ${wakes.withWakeReasons} with reasons`);
|
|
123
123
|
if (wakes.suppressedWakes.status === "ok") {
|
|
124
|
-
lines.push(`Suppressed wakes: ${wakes.suppressedWakes.data ?? 0} (scheduler single-flight, not failed
|
|
124
|
+
lines.push(`Suppressed wakes: ${wakes.suppressedWakes.data ?? 0} (scheduler single-flight, not failed AgentRuns)`);
|
|
125
125
|
}
|
|
126
126
|
else if (wakes.suppressedWakes.status === "unsupported") {
|
|
127
127
|
lines.push("Suppressed wakes: unsupported (no quiescence producer in this build)");
|
|
@@ -139,11 +139,11 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
|
|
|
139
139
|
}
|
|
140
140
|
if (report.sessions.status === "ok" && report.sessions.data !== undefined) {
|
|
141
141
|
const sessions = report.sessions.data;
|
|
142
|
-
lines.push("", `Sessions: ${sessions.
|
|
143
|
-
+ ` · lifecycle events ${sessions.lifecycleEvents} · stop failures ${sessions.stopFailures}`, `Terminal by
|
|
144
|
-
+ ` · ${sessions.
|
|
145
|
-
+ ` · ${sessions.
|
|
146
|
-
+ ` · ${sessions.
|
|
142
|
+
lines.push("", `Sessions: ${sessions.count} count · ${sessions.broken} broken · ${sessions.stopped} stopped · ${sessions.other} other`, `Resets: ${sessions.resets} · Historical conversation switches ${sessions.conversationSwitches}`
|
|
143
|
+
+ ` · lifecycle events ${sessions.lifecycleEvents} · stop failures ${sessions.stopFailures}`, `Terminal by AgentRun relation: ${sessions.terminalByRunRelation.postRunCompleted} post-turn-completed`
|
|
144
|
+
+ ` · ${sessions.terminalByRunRelation.runFailed} turn-failed`
|
|
145
|
+
+ ` · ${sessions.terminalByRunRelation.activeRun} active-turn`
|
|
146
|
+
+ ` · ${sessions.terminalByRunRelation.noRun} no-turn`);
|
|
147
147
|
}
|
|
148
148
|
else {
|
|
149
149
|
lines.push("", ...sectionError("sessions", report));
|
|
@@ -185,7 +185,7 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
|
|
|
185
185
|
.map(([category, count]) => `${category}:${count}`).join(", ")}`);
|
|
186
186
|
lines.push(renderTable("Agent errors", [
|
|
187
187
|
{ header: "Task", minWidth: 8, maxWidth: 14 },
|
|
188
|
-
{ header: "
|
|
188
|
+
{ header: "AgentRun", minWidth: 14, maxWidth: 24 },
|
|
189
189
|
{ header: "Role", minWidth: 8, maxWidth: 12 },
|
|
190
190
|
{ header: "Category", minWidth: 12, maxWidth: 20 },
|
|
191
191
|
{ header: "Code", minWidth: 16, maxWidth: 32 },
|
|
@@ -194,7 +194,7 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
|
|
|
194
194
|
{ header: "Session", minWidth: 12, maxWidth: 16 }
|
|
195
195
|
], errors.entries.map((entry) => [
|
|
196
196
|
entry.taskId,
|
|
197
|
-
entry.
|
|
197
|
+
entry.runId,
|
|
198
198
|
entry.roleName,
|
|
199
199
|
entry.category,
|
|
200
200
|
entry.code,
|
|
@@ -223,7 +223,7 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
|
|
|
223
223
|
lines.push(renderTable("Task orchestration metrics", [
|
|
224
224
|
{ header: "Task", minWidth: 7, maxWidth: 14 },
|
|
225
225
|
{ header: "Type", minWidth: 8, maxWidth: 12 },
|
|
226
|
-
{ header: "
|
|
226
|
+
{ header: "AgentRuns", minWidth: 4, maxWidth: 6 },
|
|
227
227
|
{ header: "WIs", minWidth: 3, maxWidth: 5 },
|
|
228
228
|
{ header: "Review F/D/X", minWidth: 12, maxWidth: 16 },
|
|
229
229
|
{ header: "Integration A/F/R", minWidth: 17, maxWidth: 20 },
|
|
@@ -233,11 +233,11 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
|
|
|
233
233
|
], orchestration.tasks.map((task) => [
|
|
234
234
|
task.taskId,
|
|
235
235
|
task.taskType ?? "unspecified",
|
|
236
|
-
String(task.
|
|
236
|
+
String(task.runs.total),
|
|
237
237
|
String(task.workItems),
|
|
238
238
|
`${task.reviews.full}/${task.reviews.delta}/${task.reviews.failed}`,
|
|
239
239
|
`${task.integrations.attempts}/${task.integrations.failed}/${task.integrations.repeatedIdentities}`,
|
|
240
|
-
String(task.
|
|
240
|
+
String(task.providerSessionsBeforeFirstProgress),
|
|
241
241
|
String(task.terminalWorkspaceCount),
|
|
242
242
|
String(task.advisories.length)
|
|
243
243
|
]), width));
|
|
@@ -276,15 +276,15 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
|
|
|
276
276
|
if (report.topLongRunning.status === "ok" && report.topLongRunning.data !== undefined) {
|
|
277
277
|
const entries = report.topLongRunning.data;
|
|
278
278
|
if (entries.length > 0) {
|
|
279
|
-
lines.push("", renderTable("Top long-running
|
|
279
|
+
lines.push("", renderTable("Top long-running AgentRuns", [
|
|
280
280
|
{ header: "Task", minWidth: 8, maxWidth: 14 },
|
|
281
|
-
{ header: "
|
|
281
|
+
{ header: "AgentRun", minWidth: 14, maxWidth: 24 },
|
|
282
282
|
{ header: "Role", minWidth: 10, maxWidth: 20 },
|
|
283
283
|
{ header: "Status", minWidth: 8, maxWidth: 10 },
|
|
284
284
|
{ header: "Duration", minWidth: 8, maxWidth: 10 }
|
|
285
285
|
], entries.map((entry) => [
|
|
286
286
|
entry.taskId,
|
|
287
|
-
entry.
|
|
287
|
+
entry.runId,
|
|
288
288
|
entry.roleName,
|
|
289
289
|
entry.status,
|
|
290
290
|
formatDuration(entry.durationMs)
|
|
@@ -248,7 +248,7 @@ function bindRole(args, store) {
|
|
|
248
248
|
const activeSession = existingSet?.sessions[existingSet.activeAgentId];
|
|
249
249
|
try {
|
|
250
250
|
const switched = switchActiveRoleAgent(withBinding, existingSet ?? createRoleSessionSet({ scope: "global", roleName: name }, role.activeAgentId, now), agentId, {
|
|
251
|
-
|
|
251
|
+
activeRun: false,
|
|
252
252
|
nativeProcessRunning: activeSession !== undefined
|
|
253
253
|
&& activeSession.status === "active"
|
|
254
254
|
}, now);
|
|
@@ -67,13 +67,13 @@ function issueGrant(args, store, options) {
|
|
|
67
67
|
* Grant issue and revoke carry irreversible authority: they mint or revoke
|
|
68
68
|
* the capability that lets a managed Agent perform irreversible site changes.
|
|
69
69
|
* The only accepted origin is the authenticated global Operator Session,
|
|
70
|
-
* whose
|
|
70
|
+
* whose native conversation ID is matched against the durable live binding by
|
|
71
71
|
* isCurrentGlobalOperator.
|
|
72
72
|
*
|
|
73
73
|
* Absence of YUI identity vars is deliberately NOT treated as user authority:
|
|
74
74
|
* a managed Agent can clear its child-process environment, so a "clean"
|
|
75
75
|
* environment is indistinguishable from a scrubbed managed one. A Task-scoped
|
|
76
|
-
* Session,
|
|
76
|
+
* Session, an absent conversation identity, and a replaced global conversation are
|
|
77
77
|
* all refused. Caller-supplied --granter/--by labels are not identity; the
|
|
78
78
|
* recorded granter/revoker is bound to the Operator Session instead.
|
|
79
79
|
*/
|
|
@@ -83,8 +83,8 @@ function authorizeGrantOrigin(store, env, usage) {
|
|
|
83
83
|
"session. A managed Agent cannot self-issue or self-revoke a " +
|
|
84
84
|
"capability grant, and a clean environment is not user authority.", usage);
|
|
85
85
|
}
|
|
86
|
-
//
|
|
87
|
-
return `operator:${
|
|
86
|
+
// Identity comes from the matched durable conversation, not an env label.
|
|
87
|
+
return `operator:${store.getGlobalRole("operator").activeAgentId}`;
|
|
88
88
|
}
|
|
89
89
|
function showGrant(args, store) {
|
|
90
90
|
const usage = "Task grant show usage: yui task grant show <task> <grant-id>.";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { usageError } from "../errors/cliError.js";
|
|
2
|
+
import { agentAdapterLabel as adapterLabel } from "../agent/adapterCatalog.js";
|
|
2
3
|
import { createRoleSessionSet } from "../executor/agentExecutor.js";
|
|
3
4
|
import { listOperatorSessions, projectOperatorStatus, prepareOperatorNewSession, prepareOperatorResumeSession } from "../operator/operatorSessionHistory.js";
|
|
4
5
|
import { defaultTableWidth, renderTable } from "../output/table.js";
|
|
@@ -214,13 +215,6 @@ function requireOperator(store) {
|
|
|
214
215
|
throw usageError("Operator is not configured. Run yui setup first.");
|
|
215
216
|
return role;
|
|
216
217
|
}
|
|
217
|
-
function adapterLabel(adapterId) {
|
|
218
|
-
return adapterId === "codex"
|
|
219
|
-
? "Codex"
|
|
220
|
-
: adapterId === "claude"
|
|
221
|
-
? "Claude"
|
|
222
|
-
: adapterId;
|
|
223
|
-
}
|
|
224
218
|
function requiredValue(value, option) {
|
|
225
219
|
if (value === undefined || value.startsWith("--") || value.trim().length === 0) {
|
|
226
220
|
throw usageError(`${option} is required.`);
|
|
@@ -555,7 +555,7 @@ function assertNoActiveTaskBinding(store, project, action) {
|
|
|
555
555
|
if (references.activeTaskIds.length > 0) {
|
|
556
556
|
const delivery = [
|
|
557
557
|
...references.unresolvedWorkItemRefs,
|
|
558
|
-
...references.
|
|
558
|
+
...references.activeRunRefs,
|
|
559
559
|
...references.unresolvedIntegrationRefs
|
|
560
560
|
];
|
|
561
561
|
throw usageError(`Project cannot be ${action} while an active Task binds it: ${project.id}. `
|
|
@@ -846,7 +846,7 @@ async function replaceProject(args, store, options) {
|
|
|
846
846
|
}
|
|
847
847
|
/**
|
|
848
848
|
* Auditable soft deprecation. The catalog record, checkout, and every
|
|
849
|
-
* historical Task/
|
|
849
|
+
* historical Task/AgentRun/Review/Integration/Publication reference are retained;
|
|
850
850
|
* the Project can no longer be bound to new work or maintained. Hard removal
|
|
851
851
|
* is a separate `project delete` decision.
|
|
852
852
|
*/
|
|
@@ -871,7 +871,7 @@ function retireProjectCommand(args, store, options) {
|
|
|
871
871
|
`Retired project ${retired.project.id} (${retired.project.name})`,
|
|
872
872
|
`Reason: ${parsed.reason}`,
|
|
873
873
|
`Retired by: ${retiredBy} at ${retired.project.retirement?.retiredAt ?? "?"}`,
|
|
874
|
-
"The catalog record, checkout, and historical Task/
|
|
874
|
+
"The catalog record, checkout, and historical Task/AgentRun/Review/Integration/Publication evidence are retained.",
|
|
875
875
|
...(retired.references.boundTaskIds.length === 0
|
|
876
876
|
? []
|
|
877
877
|
: [`Historical Task bindings retained: ${retired.references.boundTaskIds.join(", ")}.`]),
|
|
@@ -998,7 +998,7 @@ function removeRetiredProjectRecord(store, projectId) {
|
|
|
998
998
|
if (references.boundTaskIds.length > 0) {
|
|
999
999
|
throw usageError(`Project cannot be deleted while Task records reference it: ${latest.id}. `
|
|
1000
1000
|
+ `Bound Tasks: ${references.boundTaskIds.join(", ")}. `
|
|
1001
|
-
+ "Historical Task/
|
|
1001
|
+
+ "Historical Task/AgentRun/Review/Integration/Publication evidence must stay resolvable; keep the Project retired instead.");
|
|
1002
1002
|
}
|
|
1003
1003
|
if (!tx.removeProject(latest.id)) {
|
|
1004
1004
|
throw new Error(`Project was already removed: ${latest.id}.`);
|
|
@@ -123,11 +123,11 @@ function collectTaskStatuses(store) {
|
|
|
123
123
|
}
|
|
124
124
|
return statuses;
|
|
125
125
|
}
|
|
126
|
-
/** Workspace paths claimed by active durable Jobs (
|
|
126
|
+
/** Workspace paths claimed by active durable Jobs (AgentRuns). */
|
|
127
127
|
function collectActiveWorkspaceOwnerPaths(store) {
|
|
128
128
|
const paths = [];
|
|
129
129
|
for (const task of store.listTasks()) {
|
|
130
|
-
for (const run of store.
|
|
130
|
+
for (const run of store.listRuns(task.id)) {
|
|
131
131
|
if (run.status !== "active")
|
|
132
132
|
continue;
|
|
133
133
|
const workspace = run.workspace;
|
|
@@ -187,7 +187,12 @@ function permissionPatch(binding, parsed) {
|
|
|
187
187
|
}
|
|
188
188
|
const current = binding.config.permission;
|
|
189
189
|
if (selected !== "configured" && !nativeOptions) {
|
|
190
|
-
|
|
190
|
+
// Nothing about permission was named, so the binding keeps what it already
|
|
191
|
+
// had. The fallback applies only to a binding that somehow carries no
|
|
192
|
+
// permission at all, and it must be the adapter's own default rather than a
|
|
193
|
+
// fixed `bypass`: ACP defaults to `default`, and defaulting it to bypass
|
|
194
|
+
// here would widen authority the user never granted.
|
|
195
|
+
return structuredClone(current ?? defaultRoleAgentConfig(binding.adapterId).permission);
|
|
191
196
|
}
|
|
192
197
|
const permission = current?.strategy === "configured"
|
|
193
198
|
? structuredClone(current)
|
|
@@ -199,6 +204,15 @@ function permissionPatch(binding, parsed) {
|
|
|
199
204
|
if (parsed.has("--approval"))
|
|
200
205
|
permission.approval = requiredText(parsed.one("--approval"));
|
|
201
206
|
}
|
|
207
|
+
else if (binding.adapterId === "acp") {
|
|
208
|
+
// An ACP Session's configured permission is exactly one mode id, matched
|
|
209
|
+
// against what the Agent enumerates at launch. Tool rules are a Claude
|
|
210
|
+
// launch-flag concept with no ACP equivalent, so they are excluded above
|
|
211
|
+
// rather than silently written into a config the adapter would reject.
|
|
212
|
+
if (parsed.has("--permission-mode")) {
|
|
213
|
+
permission.mode = requiredText(parsed.one("--permission-mode"));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
202
216
|
else {
|
|
203
217
|
if (parsed.has("--permission-mode")) {
|
|
204
218
|
permission.mode = requiredText(parsed.one("--permission-mode"));
|
|
@@ -242,16 +256,22 @@ function assertAgentOptionConflicts(parsed) {
|
|
|
242
256
|
}
|
|
243
257
|
function assertAdapterOptions(adapterId, parsed) {
|
|
244
258
|
const codex = ["--sandbox", "--approval", "--search", "--clear-search"];
|
|
245
|
-
const
|
|
246
|
-
"--permission-mode",
|
|
259
|
+
const tools = [
|
|
247
260
|
"--allowed-tool", "--clear-allowed-tools",
|
|
248
261
|
"--disallowed-tool", "--clear-disallowed-tools"
|
|
249
262
|
];
|
|
250
263
|
if (adapterId !== "codex" && codex.some((option) => parsed.has(option))) {
|
|
251
264
|
throw usageError("Sandbox, approval, and search settings are only supported by Codex.");
|
|
252
265
|
}
|
|
253
|
-
if (adapterId !== "claude" &&
|
|
254
|
-
throw usageError("
|
|
266
|
+
if (adapterId !== "claude" && tools.some((option) => parsed.has(option))) {
|
|
267
|
+
throw usageError("Tool rules are only supported by Claude.");
|
|
268
|
+
}
|
|
269
|
+
// `--permission-mode` is shared: Claude takes its own permission mode as a
|
|
270
|
+
// launch flag, and ACP selects a session mode the Agent enumerated. Codex has
|
|
271
|
+
// neither, so it stays excluded. Which mode ids are valid is not decided here
|
|
272
|
+
// — for ACP only the live Session can say, and that check happens there.
|
|
273
|
+
if (adapterId !== "claude" && adapterId !== "acp" && parsed.has("--permission-mode")) {
|
|
274
|
+
throw usageError("Permission mode is only supported by Claude and ACP Agents.");
|
|
255
275
|
}
|
|
256
276
|
}
|
|
257
277
|
function assertPairs(parsed, pairs) {
|