@zq-silk/yui 0.7.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/ARCHITECTURE.md +27 -28
  2. package/README.md +79 -71
  3. package/dist/cli/commandCatalog.js +283 -136
  4. package/dist/cli/completion.js +3 -3
  5. package/dist/cli/helpRenderer.js +3 -0
  6. package/dist/cli/interactionPolicy.js +48 -33
  7. package/dist/cli/interactiveSelection.js +1 -1
  8. package/dist/cli/invocationRouter.js +3 -2
  9. package/dist/cli/roleWizard.js +8 -8
  10. package/dist/cli.js +189 -93
  11. package/dist/commands/agentCommands.js +5 -5
  12. package/dist/commands/configCommands.js +351 -104
  13. package/dist/commands/configOverview.js +60 -0
  14. package/dist/commands/deliveryGuardPreflight.js +2 -2
  15. package/dist/commands/globalRoleCommands.js +9 -9
  16. package/dist/commands/profileCommands.js +8 -8
  17. package/dist/commands/resourcesCommands.js +6 -5
  18. package/dist/commands/taskCommands.js +111 -59
  19. package/dist/commands/taskRoleRuntimeStatus.js +3 -1
  20. package/dist/commands/telemetryCommands.js +11 -6
  21. package/dist/config/configCatalog.js +42 -0
  22. package/dist/config/yuiConfig.js +80 -35
  23. package/dist/context/sessionBootstrapManifest.js +1 -1
  24. package/dist/controller/clientRuntime.js +0 -2
  25. package/dist/controller/controller.js +21 -9
  26. package/dist/controller/fileSchedulerStoreAdapter.js +409 -79
  27. package/dist/controller/resourceInventory.js +9 -5
  28. package/dist/controller/runtime.js +112 -25
  29. package/dist/controller/runtimeLaunchCoordinator.js +18 -78
  30. package/dist/controller/structuredProviderObservation.js +273 -0
  31. package/dist/doctor/doctor.js +2 -2
  32. package/dist/executor/agentAdapter.js +40 -0
  33. package/dist/executor/agentExecutor.js +31 -7
  34. package/dist/executor/executorRegistry.js +11 -49
  35. package/dist/executor/fileRoleLaunchPlanner.js +115 -37
  36. package/dist/lifecycle/canonicalLifecycleEvent.js +5 -2
  37. package/dist/resources/autoResourceGc.js +3 -1
  38. package/dist/review/reviewConfig.js +0 -2
  39. package/dist/run/agentRun.js +2 -2
  40. package/dist/run/providerRetry.js +29 -16
  41. package/dist/run/providerRetryConfig.js +5 -3
  42. package/dist/runtime/agentHost.js +767 -158
  43. package/dist/runtime/builtinAgentDrivers.js +1 -5
  44. package/dist/runtime/codexAppServerRuntime.js +67 -60
  45. package/dist/runtime/exactControlPlane.js +7 -2
  46. package/dist/runtime/index.js +6 -2
  47. package/dist/runtime/launchBroker.js +30 -8
  48. package/dist/runtime/launchDiagnostics.js +1 -1
  49. package/dist/runtime/providerAuthorityFence.js +24 -0
  50. package/dist/runtime/providerControl.js +63 -0
  51. package/dist/runtime/providerRecoveryDecision.js +55 -0
  52. package/dist/runtime/providerRuntimeIdentity.js +269 -19
  53. package/dist/runtime/runtimeBinding.js +20 -11
  54. package/dist/runtime/structuredProviderHost.js +476 -0
  55. package/dist/runtime/tmuxAdapters.js +143 -42
  56. package/dist/scheduler/activeRoleRunDelivery.js +206 -120
  57. package/dist/scheduler/leaderWakeupProcessor.js +141 -16
  58. package/dist/scheduler/roleRunStall.js +12 -9
  59. package/dist/setup/setupCommand.js +153 -492
  60. package/dist/storage/compatibleTaskStore.js +9 -5
  61. package/dist/storage/migration/productionRegistry.js +169 -0
  62. package/dist/storage/taskStore.js +22 -3
  63. package/dist/telemetry/sqliteTelemetryStore.js +9 -1
  64. package/dist/telemetry/telemetryConfig.js +1 -18
  65. package/dist/telemetry/telemetryStore.js +2 -2
  66. package/dist/telemetry/telemetryWiring.js +6 -5
  67. package/dist/tmux/tmuxManager.js +1 -1
  68. package/dist/web/webSnapshot.js +5 -3
  69. package/i18n/README.zh-CN.md +48 -40
  70. package/package.json +1 -1
  71. package/skills/yui-leader/SKILL.md +12 -5
  72. package/skills/yui-operator/SKILL.md +44 -6
  73. package/skills/yui-runtime/SKILL.md +1 -1
@@ -55,7 +55,7 @@ ${bashDynamicOptionCases(entries)}
55
55
  if [[ "$dynamic" == true ]]; then
56
56
  while IFS= read -r dynamic_candidate; do
57
57
  [[ -n "$dynamic_candidate" ]] && dynamic_candidates+=("$dynamic_candidate")
58
- done < <(command ${identity} completion candidates "$current" -- "\${COMP_WORDS[@]:1:COMP_CWORD-1}" 2>/dev/null)
58
+ done < <(command ${identity} config completion candidates "$current" -- "\${COMP_WORDS[@]:1:COMP_CWORD-1}" 2>/dev/null)
59
59
  candidates=("\${dynamic_candidates[@]}")
60
60
  elif [[ "$current" == -* ]]; then
61
61
  case "$path" in
@@ -95,7 +95,7 @@ ${zshDynamicOptionCases(entries)}
95
95
  esac
96
96
  fi
97
97
  if [[ "$dynamic" == true ]]; then
98
- dynamic_output="$(command ${identity} completion candidates "$current" -- "\${(@)words[2,CURRENT-1]}" 2>/dev/null)"
98
+ dynamic_output="$(command ${identity} config completion candidates "$current" -- "\${(@)words[2,CURRENT-1]}" 2>/dev/null)"
99
99
  candidates=("\${(@f)dynamic_output}")
100
100
  elif [[ "$current" == -* ]]; then
101
101
  case "$command_path" in
@@ -151,7 +151,7 @@ function renderFish(entries, identity) {
151
151
  "end",
152
152
  `function ${prefix}_dynamic`,
153
153
  " set -l words (commandline -opc)",
154
- ` ${identity} completion candidates (commandline -ct) -- $words[2..-1] 2>/dev/null`,
154
+ ` ${identity} config completion candidates (commandline -ct) -- $words[2..-1] 2>/dev/null`,
155
155
  "end"
156
156
  ];
157
157
  for (const entry of entries) {
@@ -15,6 +15,9 @@ export function renderCommandHelp(node, version) {
15
15
  const width = Math.max(...node.options.map((option) => option.length));
16
16
  lines.push("", "Options:", ...node.options.map((option) => ` ${option.padEnd(width)} ${describeOption(option)}`));
17
17
  }
18
+ if (node.examples.length > 0) {
19
+ lines.push("", "Examples:", ...node.examples.map((example) => ` ${example}`));
20
+ }
18
21
  return `${lines.join("\n")}\n`;
19
22
  }
20
23
  function describeOption(option) {
@@ -1,3 +1,4 @@
1
+ import { findCommandNode } from "./commandCatalog.js";
1
2
  const taskTarget = (command, argumentIndex = 2, statuses) => ({
2
3
  commandPath: ["task", command],
3
4
  selectors: [{
@@ -47,7 +48,7 @@ export const INTERACTION_POLICIES = Object.freeze([
47
48
  "--development": "value"
48
49
  }
49
50
  },
50
- ...["add", "update", "retire", "list", "show"].map((command) => ({
51
+ ...["add", "retire", "list", "show"].map((command) => ({
51
52
  commandPath: ["project", "knowledge", command],
52
53
  selectors: [{
53
54
  argumentIndex: 3,
@@ -57,26 +58,24 @@ export const INTERACTION_POLICIES = Object.freeze([
57
58
  }],
58
59
  ...(command === "add"
59
60
  ? { trailingOptions: { "--body": "value" } }
60
- : command === "update"
61
- ? { trailingOptions: { "--title": "value", "--body": "value" } }
62
- : command === "list"
63
- ? { trailingOptions: { "--all": "flag" } }
64
- : {})
61
+ : command === "list"
62
+ ? { trailingOptions: { "--all": "flag" } }
63
+ : {})
65
64
  })),
66
65
  ...["show", "capabilities", "update", "remove"].map((command) => ({
67
- commandPath: ["agent", command],
66
+ commandPath: ["config", "agent", command],
68
67
  selectors: [{
69
- argumentIndex: 2,
68
+ argumentIndex: 3,
70
69
  entity: "agent",
71
70
  provider: "configured-agents",
72
71
  actionTarget: true
73
72
  }],
74
73
  ...(command === "remove"
75
- ? { confirmation: { action: "Remove Agent", targetArgumentIndex: 2 } }
74
+ ? { confirmation: { action: "Remove Agent", targetArgumentIndex: 3 } }
76
75
  : {})
77
76
  })),
78
77
  {
79
- commandPath: ["role", "add"],
78
+ commandPath: ["config", "role", "add"],
80
79
  selectors: [{
81
80
  option: "--agent",
82
81
  requiredOption: true,
@@ -93,29 +92,31 @@ export const INTERACTION_POLICIES = Object.freeze([
93
92
  "--search": "value"
94
93
  }
95
94
  },
96
- ...["show", "update", "remove", "enter"].map((command) => ({
97
- commandPath: ["role", command],
95
+ ...["show", "update", "remove", "enter", "context"].map((command) => ({
96
+ commandPath: command === "enter" || command === "context"
97
+ ? ["session", command]
98
+ : ["config", "role", command],
98
99
  selectors: [{
99
- argumentIndex: 2,
100
+ argumentIndex: command === "enter" || command === "context" ? 2 : 3,
100
101
  entity: "global-role",
101
102
  provider: "global-roles",
102
103
  actionTarget: true
103
104
  }],
104
105
  ...(command === "remove"
105
- ? { confirmation: { action: "Remove Role", targetArgumentIndex: 2 } }
106
+ ? { confirmation: { action: "Remove Role", targetArgumentIndex: 3 } }
106
107
  : {})
107
108
  })),
108
109
  ...["bind", "unbind"].map((command) => ({
109
- commandPath: ["role", command],
110
+ commandPath: ["config", "role", command],
110
111
  selectors: [
111
- { argumentIndex: 2, entity: "global-role", provider: "global-roles", actionTarget: true },
112
- { argumentIndex: 3, entity: "agent", provider: "configured-agents", actionTarget: false }
112
+ { argumentIndex: 3, entity: "global-role", provider: "global-roles", actionTarget: true },
113
+ { argumentIndex: 4, entity: "agent", provider: "configured-agents", actionTarget: false }
113
114
  ]
114
115
  })),
115
116
  ...["record", "replace"].map((command) => ({
116
- commandPath: ["role", "session", command],
117
+ commandPath: ["session", command],
117
118
  selectors: [{
118
- argumentIndex: 3,
119
+ argumentIndex: 2,
119
120
  entity: "global-role",
120
121
  provider: "global-roles",
121
122
  actionTarget: true
@@ -125,7 +126,7 @@ export const INTERACTION_POLICIES = Object.freeze([
125
126
  : { "--native-id": "value" }
126
127
  })),
127
128
  {
128
- commandPath: ["profile", "add"],
129
+ commandPath: ["config", "profile", "add"],
129
130
  selectors: [],
130
131
  trailingOptions: {
131
132
  "--description": "value", "--instructions": "value",
@@ -133,9 +134,9 @@ export const INTERACTION_POLICIES = Object.freeze([
133
134
  }
134
135
  },
135
136
  ...["show", "update", "remove"].map((command) => ({
136
- commandPath: ["profile", command],
137
+ commandPath: ["config", "profile", command],
137
138
  selectors: [{
138
- argumentIndex: 2,
139
+ argumentIndex: 3,
139
140
  entity: "agent-profile",
140
141
  provider: "agent-profiles",
141
142
  actionTarget: true
@@ -151,7 +152,7 @@ export const INTERACTION_POLICIES = Object.freeze([
151
152
  }
152
153
  : {}),
153
154
  ...(command === "remove"
154
- ? { confirmation: { action: "Remove Agent Profile", targetArgumentIndex: 2 } }
155
+ ? { confirmation: { action: "Remove Agent Profile", targetArgumentIndex: 3 } }
155
156
  : {})
156
157
  })),
157
158
  taskTarget("show"),
@@ -360,8 +361,8 @@ export const INTERACTION_POLICIES = Object.freeze([
360
361
  trailingOptions: { "--reason": "value" },
361
362
  confirmation: { action: "Reset Task Role Session", targetArgumentIndex: 4 }
362
363
  },
363
- {
364
- commandPath: ["task", "role", "enter"],
364
+ ...["view", "takeover", "release"].map((command) => ({
365
+ commandPath: ["task", "role", command],
365
366
  selectors: [
366
367
  { argumentIndex: 3, entity: "task", provider: "tasks", actionTarget: true },
367
368
  {
@@ -371,9 +372,8 @@ export const INTERACTION_POLICIES = Object.freeze([
371
372
  dependsOn: 3,
372
373
  actionTarget: true
373
374
  }
374
- ],
375
- trailingOptions: { "--read-only": "flag", "--read-write": "flag" }
376
- },
375
+ ]
376
+ })),
377
377
  {
378
378
  commandPath: ["task", "work", "create"],
379
379
  selectors: [
@@ -533,11 +533,6 @@ export const INTERACTION_POLICIES = Object.freeze([
533
533
  ? { trailingOptions: { "--reason": "value" } }
534
534
  : {})
535
535
  })),
536
- {
537
- commandPath: ["task", "enter"],
538
- selectors: [{ argumentIndex: 2, entity: "task", provider: "tasks", actionTarget: true }],
539
- trailingOptions: { "--read-only": "flag", "--read-write": "flag" }
540
- },
541
536
  {
542
537
  commandPath: ["jobs", "retry"],
543
538
  selectors: [{ argumentIndex: 2, entity: "job", provider: "jobs", actionTarget: true }]
@@ -630,10 +625,30 @@ export function validateInteractionPolicies(policies = INTERACTION_POLICIES) {
630
625
  if (paths.has(path))
631
626
  throw new Error(`Duplicate interaction policy: ${path}`);
632
627
  paths.add(path);
628
+ const node = findCommandNode(policy.commandPath);
629
+ if (node === undefined || node.hidden) {
630
+ throw new Error(`Interaction policy references an unknown command: ${path}`);
631
+ }
633
632
  for (const selector of policy.selectors) {
634
633
  if ((selector.argumentIndex === undefined) === (selector.option === undefined)) {
635
634
  throw new Error(`Interaction selector must declare exactly one slot: ${path}`);
636
635
  }
636
+ if (selector.argumentIndex !== undefined && (!Number.isInteger(selector.argumentIndex)
637
+ || selector.argumentIndex < node.path.length - 1)) {
638
+ throw new Error(`Interaction selector has an invalid argument index: ${path}`);
639
+ }
640
+ if (selector.option !== undefined && !node.options.includes(selector.option)) {
641
+ throw new Error(`Interaction selector references an unknown option: ${path} ${selector.option}`);
642
+ }
643
+ }
644
+ for (const option of Object.keys(policy.trailingOptions ?? {})) {
645
+ if (!node.options.includes(option)) {
646
+ throw new Error(`Interaction policy references an unknown trailing option: ${path} ${option}`);
647
+ }
648
+ }
649
+ if (policy.confirmation !== undefined && !policy.selectors.some((selector) => selector.argumentIndex === policy.confirmation?.targetArgumentIndex
650
+ && selector.actionTarget)) {
651
+ throw new Error(`Interaction confirmation has no action target selector: ${path}`);
637
652
  }
638
653
  }
639
654
  }
@@ -53,7 +53,7 @@ export async function resolveInteractiveArguments(args, node, ports, io) {
53
53
  }
54
54
  export function allowsInteractiveSelection(args, globalJson) {
55
55
  return !globalJson && !args.includes("--json")
56
- && !(args[0] === "completion" && args[1] === "candidates");
56
+ && !(args[0] === "config" && args[1] === "completion" && args[2] === "candidates");
57
57
  }
58
58
  function missingSlot(args, selector, node) {
59
59
  if (selector.argumentIndex !== undefined) {
@@ -31,8 +31,9 @@ function resolveExecutionPath(args) {
31
31
  break;
32
32
  const child = findChild(node, args[index] ?? "");
33
33
  const internalExecutable = child !== undefined && ((node === ROOT_COMMAND && child.name === "internal")
34
- || (node.path.join(" ") === "yui completion" && child.name === "candidates")
35
- || (node.path.join(" ") === "yui task run" && child.name === "checkpoint")
34
+ || (node.path.join(" ") === "yui config completion" && child.name === "candidates")
35
+ || (node.path.join(" ") === "yui task run"
36
+ && (child.name === "checkpoint" || child.name === "context"))
36
37
  || (node.path.join(" ") === "yui controller"
37
38
  && (child.name === "identity" || child.name === "live-identity")));
38
39
  if (child === undefined || (child.hidden && !internalExecutable)) {
@@ -20,7 +20,7 @@ export async function resolveRoleWizardArguments(commandArgs, ports, io) {
20
20
  return { kind: "unchanged", args };
21
21
  }
22
22
  export async function resolveGlobalRoleAgentConfigurationArguments(roleName, agentId, ports, io) {
23
- const args = ["role", "update", roleName];
23
+ const args = ["config", "role", "update", roleName];
24
24
  if (!io.interactive || io.json)
25
25
  return { kind: "unchanged", args };
26
26
  const role = asRole(await ports.call("role.show", { name: roleName }));
@@ -31,7 +31,7 @@ export async function resolveGlobalRoleAgentConfigurationArguments(roleName, age
31
31
  return updateAgentBindingSettings(args, role, binding, ports, io);
32
32
  }
33
33
  function isGlobalRoleAdd(args) {
34
- return args[0] === "role" && args[1] === "add";
34
+ return args[0] === "config" && args[1] === "role" && args[2] === "add";
35
35
  }
36
36
  function isTaskRoleAdd(args) {
37
37
  return args[0] === "task" && args[1] === "role" && args[2] === "add";
@@ -39,18 +39,18 @@ function isTaskRoleAdd(args) {
39
39
  // Explicit update options always win. This keeps scripts and deliberate
40
40
  // non-interactive invocations out of the wizard even when run from a TTY.
41
41
  function isGlobalRoleUpdate(args) {
42
- return args.length === 3 && args[0] === "role" && args[1] === "update"
43
- && isValue(args[2]);
42
+ return args.length === 4 && args[0] === "config" && args[1] === "role"
43
+ && args[2] === "update" && isValue(args[3]);
44
44
  }
45
45
  function isTaskRoleUpdate(args) {
46
46
  return args.length === 5 && args[0] === "task" && args[1] === "role"
47
47
  && args[2] === "update" && isValue(args[3]) && isValue(args[4]);
48
48
  }
49
49
  async function addGlobalRole(args, ports, io) {
50
- const named = await ensureRoleName(args, 2, io);
50
+ const named = await ensureRoleName(args, 3, io);
51
51
  if (named === undefined)
52
52
  return { kind: "cancelled", args };
53
- const explicitSettings = hasExplicitAddSettings(named, 3);
53
+ const explicitSettings = hasExplicitAddSettings(named, 4);
54
54
  const agents = await loadAgentSelection(ports);
55
55
  const explicitAgent = optionValue(named, "--agent");
56
56
  const selected = explicitAgent ?? await selectConfiguredAgent(ports, io, "Create Global Role from Agent", agents);
@@ -236,7 +236,7 @@ async function configureNewAgentField(args, agent, ports, io) {
236
236
  : { kind: "resolved", args: [...args, selected.set, value] };
237
237
  }
238
238
  async function updateGlobalRole(args, ports, io) {
239
- const role = asRole(await ports.call("role.show", { name: args[2] }));
239
+ const role = asRole(await ports.call("role.show", { name: args[3] }));
240
240
  if (role === undefined)
241
241
  return { kind: "unchanged", args };
242
242
  return updateRole(args, role, ports, io, false);
@@ -286,7 +286,7 @@ async function updateRoleSettings(args, role, ports, io, taskRole) {
286
286
  return { kind: "cancelled", args };
287
287
  return taskRole
288
288
  ? { kind: "resolved", args: ["task", "role", "bind", args[3] ?? "", args[4] ?? "", target] }
289
- : { kind: "resolved", args: ["role", "bind", args[2] ?? "", target] };
289
+ : { kind: "resolved", args: ["config", "role", "bind", args[3] ?? "", target] };
290
290
  }
291
291
  if (field === "workspace") {
292
292
  const value = (await io.question(`Workspace [${roleDisplay(role.workspace)}]: `))?.trim();