@zq-silk/yui 0.2.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +603 -133
- package/README.md +806 -31
- package/dist/agent/agent.js +2 -1
- package/dist/agent/argumentPolicy.js +3 -1
- package/dist/agent/launchEnvironment.js +106 -0
- package/dist/agent/managedRuntimeEnvironment.js +34 -0
- package/dist/brief/taskBrief.js +11 -1
- package/dist/cli/agentConfigurationPicker.js +287 -0
- package/dist/cli/commandCatalog.js +488 -60
- package/dist/cli/completion.js +146 -22
- package/dist/cli/helpRenderer.js +3 -1
- package/dist/cli/interactionCandidates.js +53 -15
- package/dist/cli/interactionPolicy.js +267 -30
- package/dist/cli/interactiveSelection.js +6 -2
- package/dist/cli/invocationRouter.js +5 -1
- package/dist/cli/operatorWizard.js +87 -0
- package/dist/cli/roleOptionCatalog.js +1 -0
- package/dist/cli/roleWizard.js +185 -21
- package/dist/cli/updateCommand.js +62 -19
- package/dist/cli/updateOrchestrator.js +539 -0
- package/dist/cli/updatePorts.js +1119 -0
- package/dist/cli/upgradeCommand.js +112 -0
- package/dist/cli.js +1420 -86
- package/dist/commands/agentCommands.js +146 -3
- package/dist/commands/configCommands.js +126 -0
- package/dist/commands/controllerCommands.js +365 -0
- package/dist/commands/globalRoleCommands.js +168 -126
- package/dist/commands/jobCommands.js +18 -8
- package/dist/commands/operatorCommands.js +159 -9
- package/dist/commands/profileCommands.js +203 -0
- package/dist/commands/projectCommands.js +650 -0
- package/dist/commands/roleConfiguration.js +85 -24
- package/dist/commands/roleRuntimeGuard.js +12 -0
- package/dist/commands/roleSkillValidation.js +47 -0
- package/dist/commands/taskActor.js +127 -0
- package/dist/commands/taskCommands.js +4201 -313
- package/dist/commands/taskCompletionGate.js +131 -0
- package/dist/commands/taskContextCommand.js +244 -30
- package/dist/commands/taskInputCommands.js +177 -59
- package/dist/commands/taskIntegrationCommands.js +303 -0
- package/dist/commands/taskOverviewCommand.js +363 -0
- package/dist/commands/taskRoleRuntimeStatus.js +125 -19
- package/dist/commands/textInput.js +15 -0
- package/dist/completion/completionInstaller.js +26 -22
- package/dist/config/yuiConfig.js +4 -3
- package/dist/context/dispatchContext.js +90 -38
- package/dist/context/roleSessionContext.js +119 -0
- package/dist/controller/claudeLifecycleHook.js +203 -0
- package/dist/controller/clientRuntime.js +408 -56
- package/dist/controller/codexLifecycleHook.js +108 -0
- package/dist/controller/controller.js +1089 -32
- package/dist/controller/domainIdentity.js +505 -0
- package/dist/controller/ephemeralResourceReaper.js +131 -0
- package/dist/controller/fileSchedulerStoreAdapter.js +2153 -103
- package/dist/controller/providerHookRunFence.js +127 -0
- package/dist/controller/resourceCleanupLinux.js +286 -0
- package/dist/controller/resourceInventory.js +531 -0
- package/dist/controller/resourceInventoryLinux.js +610 -0
- package/dist/controller/runtime.js +629 -10
- package/dist/controller/runtimeEventInbox.js +564 -0
- package/dist/controller/runtimeEventProcessor.js +248 -0
- package/dist/controller/runtimeLaunchCoordinator.js +477 -0
- package/dist/controller/sessionNotify.js +121 -78
- package/dist/coordination/deadlineScheduler.js +15 -0
- package/dist/coordination/mailboxScheduler.js +108 -0
- package/dist/coordination/workMailbox.js +329 -0
- package/dist/coordination/workMailboxQueue.js +86 -0
- package/dist/core/controllerClient.js +19 -5
- package/dist/core/controllerEndpoint.js +37 -0
- package/dist/core/controllerServer.js +218 -10
- package/dist/core/protocol.js +6 -2
- package/dist/decision/decision.js +2 -1
- package/dist/doctor/doctor.js +681 -32
- package/dist/domain/validation.js +53 -0
- package/dist/errors/cliError.js +5 -3
- package/dist/event/taskEvent.js +7 -3
- package/dist/execution/codexThreadNaming.js +160 -0
- package/dist/execution/executionGroup.js +579 -0
- package/dist/executor/agentAdapter.js +255 -40
- package/dist/executor/agentConfigurationCatalog.js +326 -0
- package/dist/executor/agentConfigurationProbe.js +506 -0
- package/dist/executor/agentExecutor.js +625 -10
- package/dist/executor/codexConfigConflict.js +290 -0
- package/dist/executor/effectiveLaunch.js +340 -0
- package/dist/executor/executorRegistry.js +238 -36
- package/dist/executor/fileRoleLaunchPlanner.js +550 -40
- package/dist/executor/turnCompletion.js +126 -0
- package/dist/input/inputRequest.js +30 -9
- package/dist/integration/changeSet.js +36 -0
- package/dist/integration/checkResult.js +24 -0
- package/dist/integration/gitIntegrationService.js +695 -0
- package/dist/integration/integrationAttempt.js +142 -0
- package/dist/interaction/operatorPresentation.js +96 -0
- package/dist/lifecycle/canonicalLifecycleEvent.js +342 -0
- package/dist/lifecycle/exactRunTerminalization.js +572 -0
- package/dist/lifecycle/providerLifecycleMapping.js +190 -0
- package/dist/lifecycle/taskRoleSessionReset.js +124 -0
- package/dist/message/message.js +23 -7
- package/dist/milestone/milestone.js +2 -1
- package/dist/operator/operatorSessionHistory.js +124 -0
- package/dist/output/agentConfigurationPresentation.js +43 -0
- package/dist/output/rolePresentation.js +34 -10
- package/dist/output/terminal.js +8 -0
- package/dist/output/timePresentation.js +55 -0
- package/dist/profile/agentProfile.js +128 -0
- package/dist/repository/gitWorkspace.js +578 -24
- package/dist/repository/project.js +213 -0
- package/dist/repository/taskWorkspaceCoordinator.js +392 -0
- package/dist/repository/taskWorkspacePreparer.js +1688 -191
- package/dist/review/reviewConfig.js +11 -0
- package/dist/review/reviewRound.js +399 -0
- package/dist/review/taskFinalReviewContract.js +90 -0
- package/dist/role/role.js +124 -23
- package/dist/run/agentRun.js +155 -12
- package/dist/run/runIdentity.js +82 -0
- package/dist/runtime/exactControlPlane.js +472 -0
- package/dist/runtime/index.js +8 -0
- package/dist/runtime/lifecycleReservation.js +38 -0
- package/dist/runtime/ports.js +11 -0
- package/dist/runtime/preallocatedNativeSession.js +13 -0
- package/dist/runtime/promptEnvelope.js +30 -0
- package/dist/runtime/runtimeBinding.js +31 -0
- package/dist/runtime/runtimeOwner.js +14 -0
- package/dist/runtime/sessionLaunchRequest.js +62 -0
- package/dist/runtime/sessionTitle.js +54 -0
- package/dist/runtime/taskRuntimeIsolation.js +643 -0
- package/dist/runtime/tmuxAdapters.js +315 -0
- package/dist/runtime/turnCompletion.js +3 -0
- package/dist/runtime/validation.js +23 -0
- package/dist/scheduler/activeRoleRunDelivery.js +342 -32
- package/dist/scheduler/activeTaskProgress.js +63 -0
- package/dist/scheduler/leaderFailure.js +2 -1
- package/dist/scheduler/leaderWakeupProcessor.js +307 -66
- package/dist/scheduler/operatorInputNotificationProcessor.js +109 -46
- package/dist/scheduler/operatorNotification.js +44 -2
- package/dist/scheduler/ports.js +28 -1
- package/dist/scheduler/roleRunLiveness.js +131 -25
- package/dist/scheduler/roleRunStall.js +951 -0
- package/dist/scheduler/taskExecutionProjection.js +544 -0
- package/dist/scheduler/wakeupQueue.js +3 -0
- package/dist/setup/setupCommand.js +302 -52
- package/dist/storage/compatibleTaskStore.js +102 -0
- package/dist/storage/migration/baseline.js +78 -0
- package/dist/storage/migration/classifier.js +51 -0
- package/dist/storage/migration/compatibleCodec.js +53 -0
- package/dist/storage/migration/engine.js +147 -0
- package/dist/storage/migration/index.js +33 -0
- package/dist/storage/migration/planner.js +154 -0
- package/dist/storage/migration/productionRegistry.js +486 -0
- package/dist/storage/migration/registry.js +169 -0
- package/dist/storage/migration/report.js +54 -0
- package/dist/storage/migration/types.js +31 -0
- package/dist/storage/storageSchema.js +147 -123
- package/dist/storage/storageVersions.js +11 -0
- package/dist/storage/taskStore.js +1793 -197
- package/dist/storage/upgrade/homeClassification.js +156 -0
- package/dist/storage/upgrade/homeMigrationTarget.js +595 -0
- package/dist/storage/upgrade/offlineUpgradeInventory.js +315 -0
- package/dist/storage/upgrade/productionMigrationRegistry.js +6 -0
- package/dist/storage/upgrade/recordVersionScan.js +176 -0
- package/dist/storage/upgrade/recordVersions.js +159 -0
- package/dist/storage/upgrade/switchProgress.js +80 -0
- package/dist/storage/upgrade/upgradeOrchestrator.js +948 -0
- package/dist/storage/upgrade/upgradeReceipt.js +161 -0
- package/dist/storage/upgradeCoordination.js +186 -0
- package/dist/storage/upgradeFence.js +366 -0
- package/dist/task/task.js +132 -26
- package/dist/task/taskRecordReference.js +66 -0
- package/dist/tmux/commandExecutor.js +75 -2
- package/dist/tmux/tmuxManager.js +747 -49
- package/dist/version.js +23 -0
- package/dist/web/assets/assetManifest.js +62 -0
- package/dist/web/assets/client/app.js +631 -0
- package/dist/web/assets/client/components.js +605 -0
- package/dist/web/assets/client/dom.js +14 -0
- package/dist/web/assets/client/format.js +28 -0
- package/dist/web/assets/client/i18n.js +494 -0
- package/dist/web/assets/client/markdown.js +114 -0
- package/dist/web/assets/client/theme.js +32 -0
- package/dist/web/assets/client/view.js +458 -0
- package/dist/web/assets/fontData.js +12 -0
- package/dist/web/assets/fonts.js +12 -0
- package/dist/web/assets/shell.js +114 -0
- package/dist/web/assets/styles/cards.js +135 -0
- package/dist/web/assets/styles/layout.js +47 -0
- package/dist/web/assets/styles/markdown.js +29 -0
- package/dist/web/assets/styles/responsive.js +39 -0
- package/dist/web/assets/styles/tokens.js +101 -0
- package/dist/web/assets/styles/widgets.js +147 -0
- package/dist/web/tmuxWebTerminal.js +158 -0
- package/dist/web/webServer.js +463 -0
- package/dist/web/webSnapshot.js +148 -0
- package/dist/workItem/workItem.js +642 -23
- package/dist/workspace/gitChangeSetCapture.js +86 -0
- package/dist/workspace/workItemChangeSetManager.js +445 -0
- package/dist/worktree/managedWorkspace.js +202 -0
- package/docs/task-local-identity.md +62 -0
- package/i18n/README.zh-CN.md +406 -31
- package/package.json +10 -2
- package/skills/yui-leader/SKILL.md +601 -39
- package/skills/yui-operator/SKILL.md +255 -34
- package/skills/yui-reviewer/SKILL.md +57 -0
- package/skills/yui-worker/SKILL.md +214 -17
- package/dist/commands/repositoryCommands.js +0 -86
- package/dist/operator/operatorContext.js +0 -66
- package/dist/repository/repository.js +0 -55
- package/dist/scheduler/archivedTaskRuntime.js +0 -12
- package/dist/worktree/roleWorkspace.js +0 -62
package/dist/cli/roleWizard.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { renderTable } from "../output/table.js";
|
|
2
|
+
import { selectAgentEffort, selectAgentModelAndEffort } from "./agentConfigurationPicker.js";
|
|
2
3
|
const TEXT_COLUMN = { header: "Selection", minWidth: 12, maxWidth: 34 };
|
|
3
4
|
export async function resolveRoleWizardArguments(commandArgs, ports, io) {
|
|
4
5
|
const args = [...commandArgs];
|
|
@@ -18,6 +19,17 @@ export async function resolveRoleWizardArguments(commandArgs, ports, io) {
|
|
|
18
19
|
}
|
|
19
20
|
return { kind: "unchanged", args };
|
|
20
21
|
}
|
|
22
|
+
export async function resolveGlobalRoleAgentConfigurationArguments(roleName, agentId, ports, io) {
|
|
23
|
+
const args = ["role", "update", roleName];
|
|
24
|
+
if (!io.interactive || io.json)
|
|
25
|
+
return { kind: "unchanged", args };
|
|
26
|
+
const role = asRole(await ports.call("role.show", { name: roleName }));
|
|
27
|
+
const binding = role?.agentBindings[agentId];
|
|
28
|
+
if (role === undefined || binding === undefined) {
|
|
29
|
+
return { kind: "cancelled", args };
|
|
30
|
+
}
|
|
31
|
+
return updateAgentBindingSettings(args, role, binding, ports, io);
|
|
32
|
+
}
|
|
21
33
|
function isGlobalRoleAdd(args) {
|
|
22
34
|
return args[0] === "role" && args[1] === "add";
|
|
23
35
|
}
|
|
@@ -146,7 +158,7 @@ async function configureRoleCreation(args, agent, ports, io, taskRole) {
|
|
|
146
158
|
return { kind: "cancelled", args };
|
|
147
159
|
return section === "role"
|
|
148
160
|
? configureNewRoleField(args, agent, ports, io, taskRole)
|
|
149
|
-
: configureNewAgentField(args, agent, io);
|
|
161
|
+
: configureNewAgentField(args, agent, ports, io);
|
|
150
162
|
}
|
|
151
163
|
async function configureNewRoleField(args, agent, ports, io, taskRole) {
|
|
152
164
|
const field = await choose("Role settings", [
|
|
@@ -175,16 +187,49 @@ async function configureNewRoleField(args, agent, ports, io, taskRole) {
|
|
|
175
187
|
void agent;
|
|
176
188
|
return setProfileField(args, field, io);
|
|
177
189
|
}
|
|
178
|
-
async function configureNewAgentField(args, agent, io) {
|
|
179
|
-
const
|
|
190
|
+
async function configureNewAgentField(args, agent, ports, io) {
|
|
191
|
+
const binding = {
|
|
180
192
|
agentId: agent.id,
|
|
181
193
|
adapterId: agent.adapterId,
|
|
182
|
-
config: {
|
|
183
|
-
|
|
194
|
+
config: {
|
|
195
|
+
adapterId: agent.adapterId,
|
|
196
|
+
permission: { strategy: "bypass" }
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
const resolved = await loadAgentCatalog(ports, binding);
|
|
200
|
+
const fields = agentFields(binding, resolved?.catalog);
|
|
184
201
|
const field = await choose(`Agent settings: ${agent.id}`, fields.map((candidate) => ({ value: candidate.value, cells: [candidate.label, "CLI default"] })), [TEXT_COLUMN, { header: "Current", minWidth: 12, maxWidth: 24 }], io, undefined, "field");
|
|
185
202
|
const selected = fields.find((candidate) => candidate.value === field);
|
|
186
203
|
if (selected === undefined)
|
|
187
204
|
return { kind: "cancelled", args };
|
|
205
|
+
if (selected.value === "model") {
|
|
206
|
+
if (resolved === undefined)
|
|
207
|
+
return { kind: "cancelled", args };
|
|
208
|
+
const selection = await selectAgentModelAndEffort(resolved, io, {});
|
|
209
|
+
return selection.kind === "cancelled"
|
|
210
|
+
? { kind: "cancelled", args }
|
|
211
|
+
: { kind: "resolved", args: appendModelEffortPatch(args, selection, false) };
|
|
212
|
+
}
|
|
213
|
+
if (selected.value === "effort") {
|
|
214
|
+
if (resolved === undefined)
|
|
215
|
+
return { kind: "cancelled", args };
|
|
216
|
+
const selection = await selectAgentEffort(resolved, io, {});
|
|
217
|
+
return selection.kind === "cancelled"
|
|
218
|
+
? { kind: "cancelled", args }
|
|
219
|
+
: {
|
|
220
|
+
kind: "resolved",
|
|
221
|
+
args: selection.effort === undefined ? args : [...args, "--effort", selection.effort]
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
if (selected.value === "permission-strategy") {
|
|
225
|
+
const strategy = await promptAgentFieldValue(selected, io);
|
|
226
|
+
if (strategy === undefined || strategy.length === 0)
|
|
227
|
+
return { kind: "cancelled", args };
|
|
228
|
+
const permissionArgs = await configuredPermissionArgs(binding, resolved?.catalog, strategy, io);
|
|
229
|
+
return permissionArgs === undefined
|
|
230
|
+
? { kind: "cancelled", args }
|
|
231
|
+
: { kind: "resolved", args: [...args, ...permissionArgs] };
|
|
232
|
+
}
|
|
188
233
|
const value = await promptAgentFieldValue(selected, io);
|
|
189
234
|
return value === undefined
|
|
190
235
|
? { kind: "cancelled", args }
|
|
@@ -211,7 +256,7 @@ async function updateRole(args, role, ports, io, taskRole) {
|
|
|
211
256
|
return { kind: "cancelled", args };
|
|
212
257
|
return section === "role"
|
|
213
258
|
? updateRoleSettings(args, role, ports, io, taskRole)
|
|
214
|
-
: updateAgentSettings(args, role, io);
|
|
259
|
+
: updateAgentSettings(args, role, ports, io);
|
|
215
260
|
}
|
|
216
261
|
async function settingsSection(title, io, taskRole) {
|
|
217
262
|
return choose(title, [
|
|
@@ -281,7 +326,7 @@ async function setProfileField(args, field, io) {
|
|
|
281
326
|
args: [...args, ...values.flatMap((entry) => [options.set, entry])]
|
|
282
327
|
};
|
|
283
328
|
}
|
|
284
|
-
async function updateAgentSettings(args, role, io) {
|
|
329
|
+
async function updateAgentSettings(args, role, ports, io) {
|
|
285
330
|
const bindings = Object.values(role.agentBindings);
|
|
286
331
|
const selectedId = await choose("Select Role Agent binding", bindings.map((binding) => ({
|
|
287
332
|
value: binding.agentId,
|
|
@@ -296,7 +341,11 @@ async function updateAgentSettings(args, role, io) {
|
|
|
296
341
|
const binding = role.agentBindings[selectedId];
|
|
297
342
|
if (binding === undefined)
|
|
298
343
|
return { kind: "cancelled", args };
|
|
299
|
-
|
|
344
|
+
return updateAgentBindingSettings(args, role, binding, ports, io);
|
|
345
|
+
}
|
|
346
|
+
async function updateAgentBindingSettings(args, role, binding, ports, io) {
|
|
347
|
+
const resolved = await loadAgentCatalog(ports, binding, role.workspace);
|
|
348
|
+
const fields = agentFields(binding, resolved?.catalog);
|
|
300
349
|
const field = await choose(`Agent settings: ${binding.agentId}`, [
|
|
301
350
|
...fields.map((candidate) => ({
|
|
302
351
|
value: candidate.value,
|
|
@@ -315,6 +364,51 @@ async function updateAgentSettings(args, role, io) {
|
|
|
315
364
|
const selectedField = fields.find((candidate) => candidate.value === field);
|
|
316
365
|
if (selectedField === undefined)
|
|
317
366
|
return { kind: "cancelled", args };
|
|
367
|
+
if (selectedField.value === "model") {
|
|
368
|
+
if (resolved === undefined)
|
|
369
|
+
return { kind: "cancelled", args };
|
|
370
|
+
const selection = await selectAgentModelAndEffort(resolved, io, {
|
|
371
|
+
currentModel: stringField(binding.config, "model"),
|
|
372
|
+
currentEffort: stringField(binding.config, "effort")
|
|
373
|
+
});
|
|
374
|
+
return selection.kind === "cancelled"
|
|
375
|
+
? { kind: "cancelled", args }
|
|
376
|
+
: {
|
|
377
|
+
kind: "resolved",
|
|
378
|
+
args: appendModelEffortPatch([...args, "--agent", binding.agentId], selection, true)
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
if (selectedField.value === "effort") {
|
|
382
|
+
if (resolved === undefined)
|
|
383
|
+
return { kind: "cancelled", args };
|
|
384
|
+
const selection = await selectAgentEffort(resolved, io, {
|
|
385
|
+
model: stringField(binding.config, "model"),
|
|
386
|
+
currentEffort: stringField(binding.config, "effort")
|
|
387
|
+
});
|
|
388
|
+
if (selection.kind === "cancelled")
|
|
389
|
+
return { kind: "cancelled", args };
|
|
390
|
+
return {
|
|
391
|
+
kind: "resolved",
|
|
392
|
+
args: [
|
|
393
|
+
...args,
|
|
394
|
+
"--agent", binding.agentId,
|
|
395
|
+
...(selection.effort === undefined
|
|
396
|
+
? ["--clear-effort"] : ["--effort", selection.effort])
|
|
397
|
+
]
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
if (selectedField.value === "permission-strategy") {
|
|
401
|
+
const strategy = await promptAgentFieldValue(selectedField, io);
|
|
402
|
+
if (strategy === undefined || strategy.length === 0)
|
|
403
|
+
return { kind: "cancelled", args };
|
|
404
|
+
const permissionArgs = await configuredPermissionArgs(binding, resolved?.catalog, strategy, io);
|
|
405
|
+
if (permissionArgs === undefined)
|
|
406
|
+
return { kind: "cancelled", args };
|
|
407
|
+
return {
|
|
408
|
+
kind: "resolved",
|
|
409
|
+
args: [...args, "--agent", binding.agentId, ...permissionArgs]
|
|
410
|
+
};
|
|
411
|
+
}
|
|
318
412
|
const action = await choose(`Update ${selectedField.label}`, [
|
|
319
413
|
{ value: "keep", cells: ["Keep current", selectedField.current] },
|
|
320
414
|
{ value: "clear", cells: ["Use CLI default", "Remove override"] },
|
|
@@ -325,7 +419,7 @@ async function updateAgentSettings(args, role, io) {
|
|
|
325
419
|
if (action === "clear") {
|
|
326
420
|
return {
|
|
327
421
|
kind: "resolved",
|
|
328
|
-
args: [...args, "--agent", binding.agentId, selectedField.clear]
|
|
422
|
+
args: [...args, "--agent", binding.agentId, ...selectedField.clear]
|
|
329
423
|
};
|
|
330
424
|
}
|
|
331
425
|
const value = await promptAgentFieldValue(selectedField, io);
|
|
@@ -336,31 +430,101 @@ async function updateAgentSettings(args, role, io) {
|
|
|
336
430
|
args: [...args, "--agent", binding.agentId, selectedField.set, value]
|
|
337
431
|
};
|
|
338
432
|
}
|
|
339
|
-
function agentFields(binding) {
|
|
433
|
+
function agentFields(binding, catalog) {
|
|
340
434
|
const config = binding.config;
|
|
341
435
|
const permission = entity(config.permission) ?? {};
|
|
342
436
|
return [
|
|
343
|
-
agentField("model", "Model", config.model, "--model", "--clear-model"),
|
|
344
|
-
agentField("effort", "Effort", config.effort, "--effort", "--clear-effort"),
|
|
345
|
-
|
|
346
|
-
|
|
437
|
+
agentField("model", "Model", config.model, "--model", ["--clear-model"]),
|
|
438
|
+
agentField("effort", "Effort", config.effort, "--effort", ["--clear-effort"]),
|
|
439
|
+
agentField("permission-strategy", "Permission strategy", permission.strategy, "--permission-strategy", ["--permission-strategy", "default"], catalogChoices(catalog, "permission.strategy", ["default", "bypass", "configured"])),
|
|
440
|
+
...(binding.adapterId === "codex" && permission.strategy === "configured" ? [
|
|
441
|
+
agentField("sandbox", "Sandbox", permission.sandbox, "--sandbox", ["--permission-strategy", "default"], catalogChoices(catalog, "permission.sandbox", [
|
|
347
442
|
"read-only", "workspace-write", "danger-full-access"
|
|
348
|
-
]),
|
|
349
|
-
agentField("approval", "Approval", permission.approval, "--approval", "--
|
|
443
|
+
])),
|
|
444
|
+
agentField("approval", "Approval", permission.approval, "--approval", ["--permission-strategy", "default"], catalogChoices(catalog, "permission.approval", [
|
|
350
445
|
"untrusted", "on-request", "never"
|
|
351
|
-
])
|
|
352
|
-
|
|
353
|
-
|
|
446
|
+
]))
|
|
447
|
+
] : []),
|
|
448
|
+
...(binding.adapterId === "codex" ? [
|
|
449
|
+
agentField("search", "Web search", config.search, "--search", ["--clear-search"], [
|
|
450
|
+
...catalogChoices(catalog, "search", ["true"])
|
|
354
451
|
])
|
|
355
452
|
] : []),
|
|
356
|
-
...(binding.adapterId === "claude" ? [
|
|
357
|
-
agentField("permission-mode", "Permission mode", permission.mode, "--permission-mode", "--
|
|
453
|
+
...(binding.adapterId === "claude" && permission.strategy === "configured" ? [
|
|
454
|
+
agentField("permission-mode", "Permission mode", permission.mode, "--permission-mode", ["--permission-strategy", "default"], catalogChoices(catalog, "permission.mode"))
|
|
358
455
|
] : [])
|
|
359
456
|
];
|
|
360
457
|
}
|
|
458
|
+
async function loadAgentCatalog(ports, binding, cwd) {
|
|
459
|
+
const value = await ports.call("agent.capabilities", {
|
|
460
|
+
agentId: binding.agentId,
|
|
461
|
+
config: binding.config,
|
|
462
|
+
...(cwd === undefined ? {} : { cwd })
|
|
463
|
+
});
|
|
464
|
+
const input = entity(value);
|
|
465
|
+
return input !== undefined
|
|
466
|
+
&& (input.source === "live" || input.source === "cache" || input.source === "fallback")
|
|
467
|
+
&& entity(input.catalog) !== undefined
|
|
468
|
+
? value
|
|
469
|
+
: undefined;
|
|
470
|
+
}
|
|
471
|
+
function catalogChoices(catalog, key, fallback = []) {
|
|
472
|
+
const field = catalog?.fields.find((candidate) => candidate.key === key);
|
|
473
|
+
return field === undefined ? [...fallback] : field.choices.map(({ value }) => value);
|
|
474
|
+
}
|
|
475
|
+
function appendModelEffortPatch(args, selection, update) {
|
|
476
|
+
return [
|
|
477
|
+
...args,
|
|
478
|
+
...(selection.model === undefined
|
|
479
|
+
? update ? ["--clear-model"] : []
|
|
480
|
+
: ["--model", selection.model]),
|
|
481
|
+
...(selection.effort === undefined
|
|
482
|
+
? update ? ["--clear-effort"] : []
|
|
483
|
+
: ["--effort", selection.effort])
|
|
484
|
+
];
|
|
485
|
+
}
|
|
361
486
|
function agentField(value, label, current, set, clear, choices) {
|
|
362
487
|
return { value, label, current: display(current), set, clear, ...(choices === undefined ? {} : { choices }) };
|
|
363
488
|
}
|
|
489
|
+
async function configuredPermissionArgs(binding, catalog, strategy, io) {
|
|
490
|
+
if (strategy !== "configured")
|
|
491
|
+
return ["--permission-strategy", strategy];
|
|
492
|
+
if (binding.adapterId === "codex") {
|
|
493
|
+
const field = await choose("Native permission option", [
|
|
494
|
+
{ value: "sandbox", cells: ["Sandbox"] },
|
|
495
|
+
{ value: "approval", cells: ["Approval"] }
|
|
496
|
+
], [TEXT_COLUMN], io, "sandbox", "option");
|
|
497
|
+
if (field === undefined)
|
|
498
|
+
return undefined;
|
|
499
|
+
const option = field === "sandbox" ? "--sandbox" : "--approval";
|
|
500
|
+
const value = await promptAgentFieldValue(agentField(field, field === "sandbox" ? "Sandbox" : "Approval", undefined, option, ["--permission-strategy", "default"], field === "sandbox"
|
|
501
|
+
? catalogChoices(catalog, "permission.sandbox", [
|
|
502
|
+
"read-only", "workspace-write", "danger-full-access"
|
|
503
|
+
])
|
|
504
|
+
: catalogChoices(catalog, "permission.approval", [
|
|
505
|
+
"untrusted", "on-request", "never"
|
|
506
|
+
])), io);
|
|
507
|
+
return value === undefined
|
|
508
|
+
? undefined
|
|
509
|
+
: ["--permission-strategy", "configured", option, value];
|
|
510
|
+
}
|
|
511
|
+
const field = await choose("Native permission option", [
|
|
512
|
+
{ value: "mode", cells: ["Permission mode"] },
|
|
513
|
+
{ value: "allowed", cells: ["Allowed tool"] },
|
|
514
|
+
{ value: "disallowed", cells: ["Disallowed tool"] }
|
|
515
|
+
], [TEXT_COLUMN], io, "mode", "option");
|
|
516
|
+
if (field === undefined)
|
|
517
|
+
return undefined;
|
|
518
|
+
const option = field === "mode"
|
|
519
|
+
? "--permission-mode"
|
|
520
|
+
: field === "allowed" ? "--allowed-tool" : "--disallowed-tool";
|
|
521
|
+
const value = field === "mode"
|
|
522
|
+
? await promptAgentFieldValue(agentField("permission-mode", "Permission mode", undefined, option, ["--permission-strategy", "default"], catalogChoices(catalog, "permission.mode")), io)
|
|
523
|
+
: (await io.question(`${field === "allowed" ? "Allowed" : "Disallowed"} tool: `))?.trim();
|
|
524
|
+
return value === undefined || value.length === 0
|
|
525
|
+
? undefined
|
|
526
|
+
: ["--permission-strategy", "configured", option, value];
|
|
527
|
+
}
|
|
364
528
|
async function promptAgentFieldValue(field, io) {
|
|
365
529
|
return field.choices === undefined
|
|
366
530
|
? (await io.question(`${field.label}: `))?.trim()
|
|
@@ -1,22 +1,65 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { resolveYuiHome } from "../storage/taskStore.js";
|
|
2
|
+
import { createUpdatePorts } from "./updatePorts.js";
|
|
3
|
+
import { runUpdate } from "./updateOrchestrator.js";
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Run `yui update` as a side-by-side, recoverable orchestration.
|
|
6
|
+
*
|
|
7
|
+
* The new package is staged beside the live install and used to run a read-only
|
|
8
|
+
* preflight against the target Home. Current/compatible-old storage promotes the
|
|
9
|
+
* binary through the exact Controller handoff without a Home switch; only a
|
|
10
|
+
* migration-required verdict enters the offline backup/switch path. On failure
|
|
11
|
+
* it reports the precise phase and recovery boundary. See
|
|
12
|
+
* {@link runUpdate} for the exact, narrowed rollback boundary (this release does
|
|
13
|
+
* not introduce a versioned binary pointer, so it does not claim binary+Home
|
|
14
|
+
* dual-resource atomicity).
|
|
15
|
+
*
|
|
16
|
+
* Returns a process exit code: 0 on success or already-current, 5 on abort.
|
|
7
17
|
*/
|
|
8
|
-
export function runUpdateCommand(spawn =
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (result.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
export function runUpdateCommand(environment = process.env, spawn, write = (text) => process.stdout.write(text), ports) {
|
|
19
|
+
const home = resolveYuiHome(environment);
|
|
20
|
+
const resolvedPorts = ports ?? createUpdatePorts(environment, spawn);
|
|
21
|
+
const result = runUpdate(resolvedPorts, { home });
|
|
22
|
+
write(`${renderUpdateResult(result)}\n`);
|
|
23
|
+
// Both an abort and an ambiguous result are non-success exits; ambiguous is
|
|
24
|
+
// distinct (manual verification required), so it gets its own exit code.
|
|
25
|
+
if (result.outcome === "aborted")
|
|
26
|
+
return 5;
|
|
27
|
+
if (result.outcome === "ambiguous")
|
|
28
|
+
return 6;
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
/** Render an {@link UpdateResult} as concise, CLI-style text. */
|
|
32
|
+
export function renderUpdateResult(result) {
|
|
33
|
+
const rendered = (() => {
|
|
34
|
+
switch (result.outcome) {
|
|
35
|
+
case "already-current":
|
|
36
|
+
return "Yui is already up to date; nothing to install.";
|
|
37
|
+
case "updated":
|
|
38
|
+
return result.storageBackupPath === undefined
|
|
39
|
+
? result.path === "compatible-fast"
|
|
40
|
+
? `Updated Yui to ${result.version} via the compatible fast path; the Home was not migrated.`
|
|
41
|
+
: `Updated Yui to ${result.version}; storage was already current.`
|
|
42
|
+
: `Updated Yui to ${result.version}. Storage was migrated; original Home backed up at `
|
|
43
|
+
+ `${result.storageBackupPath}.`;
|
|
44
|
+
case "aborted":
|
|
45
|
+
return [
|
|
46
|
+
`Update aborted during ${result.phase}: ${result.message}`,
|
|
47
|
+
result.recoverable
|
|
48
|
+
? "The current install and Home remain usable."
|
|
49
|
+
: result.phase === "activate-binary" && result.storageBackupPath === undefined
|
|
50
|
+
? "The Home was not migrated, but binary health is unknown; do not assume the current install is usable."
|
|
51
|
+
: "Manual recovery is required (see below).",
|
|
52
|
+
`Action: ${result.action}`
|
|
53
|
+
].join("\n");
|
|
54
|
+
case "ambiguous":
|
|
55
|
+
return [
|
|
56
|
+
`Update result is UNKNOWN after ${result.phase}: ${result.message}`,
|
|
57
|
+
"Manual verification is required — do NOT assume the update succeeded or was a no-op.",
|
|
58
|
+
`Action: ${result.action}`
|
|
59
|
+
].join("\n");
|
|
60
|
+
}
|
|
61
|
+
})();
|
|
62
|
+
return result.cleanupWarning === undefined
|
|
63
|
+
? rendered
|
|
64
|
+
: `${rendered}\nWarning: ${result.cleanupWarning}`;
|
|
22
65
|
}
|