@zq-silk/yui 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/README.md +4 -0
  2. package/dist/cli/commandCatalog.js +318 -289
  3. package/dist/cli/commandDiscovery.js +72 -0
  4. package/dist/cli/completion.js +22 -227
  5. package/dist/cli/dynamicCompletion.js +12 -6
  6. package/dist/cli/invocationAuthority.js +2 -2
  7. package/dist/cli/invocationRouter.js +18 -7
  8. package/dist/cli.js +23 -3030
  9. package/dist/commands/capabilityCommands.js +5 -5
  10. package/dist/commands/globalRoleCommands.js +2 -1
  11. package/dist/commands/taskCommands.js +90 -21
  12. package/dist/commands/taskIntegrationCommands.js +3 -1
  13. package/dist/commands/taskUpstreamCommands.js +3 -1
  14. package/dist/context/runContextPack.js +132 -5
  15. package/dist/context/sourceRunContext.js +4 -2
  16. package/dist/context/taskContext.js +12 -3
  17. package/dist/controlPlaneCli.js +3092 -0
  18. package/dist/controller/fileSchedulerStoreAdapter.js +19 -6
  19. package/dist/controller/jobControl.js +21 -0
  20. package/dist/executor/agentExecutor.js +1 -1
  21. package/dist/executor/effectiveLaunch.js +18 -5
  22. package/dist/executor/fileRoleLaunchPlanner.js +15 -19
  23. package/dist/integration/gitIntegrationService.js +50 -15
  24. package/dist/kernel/accessAssessment.js +1 -0
  25. package/dist/kernel/builtinCapabilities.js +28 -1
  26. package/dist/kernel/capabilityRegistry.js +64 -19
  27. package/dist/message/messageContinuation.js +7 -2
  28. package/dist/nativeAgent/agent.js +275 -0
  29. package/dist/nativeAgent/cliDemo.js +37 -0
  30. package/dist/nativeAgent/codingTools.js +11 -0
  31. package/dist/nativeAgent/commandTool.js +215 -0
  32. package/dist/nativeAgent/compactionDemo.js +158 -0
  33. package/dist/nativeAgent/composition.js +71 -0
  34. package/dist/nativeAgent/context/budget.js +44 -0
  35. package/dist/nativeAgent/context/index.js +339 -0
  36. package/dist/nativeAgent/context/providerCompressor.js +103 -0
  37. package/dist/nativeAgent/contracts.js +1 -0
  38. package/dist/nativeAgent/demo.js +40 -0
  39. package/dist/nativeAgent/evaluation/cases.js +38 -0
  40. package/dist/nativeAgent/evaluation/checks.js +91 -0
  41. package/dist/nativeAgent/evaluation/demo.js +19 -0
  42. package/dist/nativeAgent/evaluation/files.js +54 -0
  43. package/dist/nativeAgent/evaluation/fixture.js +36 -0
  44. package/dist/nativeAgent/evaluation/index.js +239 -0
  45. package/dist/nativeAgent/executionOwner.js +209 -0
  46. package/dist/nativeAgent/filePatterns.js +170 -0
  47. package/dist/nativeAgent/fileToolsSupport.js +202 -0
  48. package/dist/nativeAgent/index.js +16 -0
  49. package/dist/nativeAgent/interaction/cli.js +358 -0
  50. package/dist/nativeAgent/interaction/contracts.js +1 -0
  51. package/dist/nativeAgent/interaction/index.js +3 -0
  52. package/dist/nativeAgent/interaction/memoryDemo.js +115 -0
  53. package/dist/nativeAgent/interaction/renderer.js +34 -0
  54. package/dist/nativeAgent/localSafety.js +258 -0
  55. package/dist/nativeAgent/mockProvider.js +43 -0
  56. package/dist/nativeAgent/model/anthropicMessages.js +204 -0
  57. package/dist/nativeAgent/model/chatCompletions.js +210 -0
  58. package/dist/nativeAgent/model/errors.js +47 -0
  59. package/dist/nativeAgent/model/gateway.js +423 -0
  60. package/dist/nativeAgent/model/index.js +7 -0
  61. package/dist/nativeAgent/model/observationAdapter.js +21 -0
  62. package/dist/nativeAgent/model/protocols.js +19 -0
  63. package/dist/nativeAgent/model/responses.js +263 -0
  64. package/dist/nativeAgent/model/types.js +1 -0
  65. package/dist/nativeAgent/model/wire.js +73 -0
  66. package/dist/nativeAgent/observability/index.js +220 -0
  67. package/dist/nativeAgent/product/catalog.js +82 -0
  68. package/dist/nativeAgent/product/config.js +295 -0
  69. package/dist/nativeAgent/product/facts.js +30 -0
  70. package/dist/nativeAgent/product/index.js +62 -0
  71. package/dist/nativeAgent/product/location.js +44 -0
  72. package/dist/nativeAgent/product/runtime.js +276 -0
  73. package/dist/nativeAgent/product/storage.js +49 -0
  74. package/dist/nativeAgent/product/tools.js +47 -0
  75. package/dist/nativeAgent/product/transport.js +54 -0
  76. package/dist/nativeAgent/projectGuidance/index.js +425 -0
  77. package/dist/nativeAgent/searchTools.js +305 -0
  78. package/dist/nativeAgent/session/backends.js +293 -0
  79. package/dist/nativeAgent/session/catalog.js +97 -0
  80. package/dist/nativeAgent/session/catalogDemo.js +87 -0
  81. package/dist/nativeAgent/session/contracts.js +1 -0
  82. package/dist/nativeAgent/session/format.js +269 -0
  83. package/dist/nativeAgent/session/index.js +5 -0
  84. package/dist/nativeAgent/session/location.js +36 -0
  85. package/dist/nativeAgent/session/sqliteFormat.js +134 -0
  86. package/dist/nativeAgent/session/store.js +248 -0
  87. package/dist/nativeAgent/textTools.js +293 -0
  88. package/dist/nativeAgent/toolManager/executor.js +290 -0
  89. package/dist/nativeAgent/toolManager/index.js +4 -0
  90. package/dist/nativeAgent/validation.js +95 -0
  91. package/dist/plugins/pluginService.js +98 -8
  92. package/dist/resources/projectResourceService.js +23 -1
  93. package/dist/runtime/managedIdentity.js +6 -0
  94. package/dist/surface/surfaceContributions.js +3 -0
  95. package/dist/task/taskAuthority.js +61 -10
  96. package/dist/web/assets/assetManifest.js +38 -22
  97. package/dist/web/assets/client/api.js +115 -0
  98. package/dist/web/assets/client/app.js +615 -862
  99. package/dist/web/assets/client/components.js +323 -897
  100. package/dist/web/assets/client/detail.js +333 -0
  101. package/dist/web/assets/client/dock.js +225 -0
  102. package/dist/web/assets/client/dom.js +55 -3
  103. package/dist/web/assets/client/evidence.js +172 -0
  104. package/dist/web/assets/client/format.js +25 -14
  105. package/dist/web/assets/client/forms.js +230 -0
  106. package/dist/web/assets/client/i18n.js +1024 -791
  107. package/dist/web/assets/client/overview.js +118 -0
  108. package/dist/web/assets/client/records.js +63 -0
  109. package/dist/web/assets/client/sections.js +313 -0
  110. package/dist/web/assets/client/sidebar.js +146 -0
  111. package/dist/web/assets/client/theme.js +61 -22
  112. package/dist/web/assets/icons.js +39 -0
  113. package/dist/web/assets/shell.js +125 -118
  114. package/dist/web/assets/styles/base.js +41 -0
  115. package/dist/web/assets/styles/components.js +169 -0
  116. package/dist/web/assets/styles/layout.js +56 -77
  117. package/dist/web/assets/styles/markdown.js +16 -24
  118. package/dist/web/assets/styles/responsive.js +41 -44
  119. package/dist/web/assets/styles/tokens.js +65 -89
  120. package/dist/web/assets/styles/views.js +292 -0
  121. package/dist/web/webServer.js +2 -1
  122. package/docs/agent-result-consumption.md +16 -0
  123. package/docs/agent-result-consumption.zh-CN.md +13 -0
  124. package/docs/examples/agent-offline.mjs +194 -0
  125. package/docs/native-agent.md +283 -0
  126. package/docs/release-workflow.md +61 -0
  127. package/docs/release-workflow.zh-CN.md +46 -0
  128. package/docs/roles-and-configuration.md +32 -0
  129. package/docs/roles-and-configuration.zh-CN.md +26 -0
  130. package/package.json +1 -1
  131. package/skills/yui-leader/SKILL.md +9 -0
  132. package/skills/yui-reviewer/SKILL.md +5 -0
  133. package/skills/yui-runtime/SKILL.md +33 -0
  134. package/dist/web/assets/client/taskSummary.js +0 -350
  135. package/dist/web/assets/client/taskSurface.js +0 -616
  136. package/dist/web/assets/client/view.js +0 -608
  137. package/dist/web/assets/styles/cards.js +0 -247
  138. package/dist/web/assets/styles/widgets.js +0 -168
@@ -0,0 +1,72 @@
1
+ import { ROOT_COMMAND, findCommandNode } from "./commandCatalog.js";
2
+ import { hasManagedIdentity } from "../runtime/managedIdentity.js";
3
+ /** Offline presentation hints only. Execution still authenticates the original
4
+ * caller, including stale/incomplete identities, at its existing boundary. */
5
+ export function discoveryAudience(env) {
6
+ if (!hasManagedIdentity(env))
7
+ return "public";
8
+ const nativeSessionId = env.YUI_ADAPTER_ID === "codex"
9
+ ? env.CODEX_THREAD_ID ?? env.YUI_NATIVE_SESSION_ID : env.YUI_NATIVE_SESSION_ID;
10
+ if (!env.YUI_ROLE || !nativeSessionId || nativeSessionId.trim() !== nativeSessionId
11
+ || nativeSessionId.includes("\0"))
12
+ return "unbound";
13
+ if (env.YUI_SESSION_SCOPE === "global")
14
+ return env.YUI_ROLE === "operator" ? "operator" : "global";
15
+ if (env.YUI_SESSION_SCOPE === "task" && env.YUI_TASK_ID)
16
+ return env.YUI_ROLE === "leader" ? "leader" : "assignment";
17
+ return "unbound";
18
+ }
19
+ export function discoveryCommandTree(env) {
20
+ const audience = discoveryAudience(env);
21
+ const project = (node) => {
22
+ const children = node.children.map(project).filter((child) => child !== undefined);
23
+ const eligible = node.discovery?.surface !== "runtime" && node.discovery?.audiences.includes(audience);
24
+ if (!children.length && (!eligible || node.kind === "group") && node !== ROOT_COMMAND)
25
+ return undefined;
26
+ const executable = eligible && node.kind !== "group";
27
+ const kind = children.length ? executable ? "hybrid" : "group" : node.kind;
28
+ const template = `${node.path.join(" ")}${kind === "group" ? " <command>" : ""}`;
29
+ const omittedOptions = Object.entries(node.discovery?.optionAudiences ?? {})
30
+ .filter(([, audiences]) => !audiences.includes(audience)).map(([option]) => option);
31
+ const text = (value) => omittedOptions.reduce((line, option) => line.replace(new RegExp(`\\s*\\[${option}(?:\\s+[^\\]]*)?\\]`, "g"), ""), value);
32
+ const options = node.options.filter(option => !omittedOptions.includes(option));
33
+ // Group prose often contains concrete commands for several audiences.
34
+ // Generate its usage from the same retained children, not unfiltered text.
35
+ return {
36
+ ...node, children, hidden: false, kind,
37
+ usage: kind === "group" ? [template] : node.usage.map(text),
38
+ examples: kind === "group" ? children.slice(0, 3).map(child => child.usage[0]) : node.examples.map(text),
39
+ options, optionValues: Object.fromEntries(Object.entries(node.optionValues).filter(([option]) => options.includes(option))),
40
+ sections: node.sections.map(section => ({ ...section,
41
+ entries: section.entries.filter(entry => children.some(child => child.name === entry) || (executable && node.values.some(value => value.name === entry)))
42
+ })).filter(section => section.entries.length > 0),
43
+ ...(executable ? {} : { options: [], values: [], optionValues: {}, argumentValues: {} })
44
+ };
45
+ };
46
+ const tree = project(ROOT_COMMAND);
47
+ if (audience === "public") {
48
+ const sections = [
49
+ { id: "start", title: "Start work", entries: ["operator", "project"] },
50
+ { id: "progress", title: "Inspect progress", entries: ["task", "jobs", "execution", "telemetry"] },
51
+ { id: "participate", title: "Participate and control", entries: ["role", "session"] },
52
+ { id: "maintain", title: "Configure and maintain", entries: ["help", "version", "setup", "start", "doctor", "config", "web", "controller", "resources", "update", "upgrade", "release"] }
53
+ ];
54
+ return { ...tree, sections: sections.map(section => ({ ...section,
55
+ entries: section.entries.filter(entry => tree.children.some(child => child.name === entry))
56
+ })) };
57
+ }
58
+ // Help accepts catalog paths, and config describe accepts only retained domains.
59
+ const config = findCommandNode(["config"], tree);
60
+ if (config) {
61
+ const domains = config.children.filter(child => !["show", "describe"].includes(child.name)).map(child => child.name);
62
+ return {
63
+ ...tree, children: tree.children.map(child => child !== config ? child : {
64
+ ...config, children: config.children.map(node => node.name !== "describe" ? node : {
65
+ ...node, argumentValues: { 0: domains }, usage: ["yui config describe [domain]"],
66
+ examples: ["yui config describe"]
67
+ })
68
+ })
69
+ };
70
+ }
71
+ return tree;
72
+ }
@@ -1,235 +1,30 @@
1
- import { ROOT_COMMAND, listPublicCommandPaths, orderedImmediateTokens, visibleChildren } from "./commandCatalog.js";
2
- import { findInteractionPolicy } from "./interactionPolicy.js";
1
+ /** Resolve the current caller on every completion, never the installer's view.
2
+ * Command names are local; target selectors use authenticated scoped reads. */
3
3
  export function renderCompletion(shell) {
4
- const entries = collectEntries(ROOT_COMMAND);
5
4
  switch (shell) {
6
- case "bash": return renderBash(entries);
7
- case "zsh": return renderZsh(entries);
8
- case "fish": return renderFish(entries);
9
- default: throw new Error("Completion shell must be one of bash, zsh, fish.");
10
- }
11
- }
12
- function collectEntries(root) {
13
- const entries = [];
14
- const visit = (node) => {
15
- if (!node.hidden && !node.commandPathArguments) {
16
- const policy = findInteractionPolicy(node);
17
- entries.push({
18
- path: node.path.slice(1).join(" "),
19
- immediate: orderedImmediateTokens(node),
20
- options: node.options,
21
- dynamicArguments: policy?.selectors.flatMap((selector) => selector.argumentIndex === undefined ? [] : [selector.argumentIndex]) ?? [],
22
- dynamicOptions: policy?.selectors.flatMap((selector) => selector.option === undefined ? [] : [selector.option]) ?? []
23
- });
24
- }
25
- visibleChildren(node).forEach(visit);
26
- };
27
- visit(root);
28
- return entries;
29
- }
30
- function manifest(prefix) {
31
- return listPublicCommandPaths().map((path) => `${prefix} ${path}`).join("\n");
32
- }
33
- function renderBash(entries) {
34
- const functionName = "_yui";
35
- return `${manifest("# yui command:")}
36
- ${functionName}() {
37
- local current path previous dynamic_candidate dynamic=false
38
- local -a candidates dynamic_candidates
39
- current="\${COMP_WORDS[COMP_CWORD]}"
40
- path=""
41
- if (( COMP_CWORD > 1 )); then
42
- path="\${COMP_WORDS[*]:1:COMP_CWORD-1}"
43
- fi
44
- previous="\${COMP_WORDS[COMP_CWORD-1]}"
45
- if [[ "$current" != -* ]]; then
46
- case "$COMP_CWORD:$path" in
47
- ${bashDynamicArgumentCases(entries)}
48
- esac
49
- fi
50
- if [[ "$dynamic" == false ]]; then
51
- case "$previous:$path" in
52
- ${bashDynamicOptionCases(entries)}
53
- esac
54
- fi
55
- if [[ "$dynamic" == true ]]; then
56
- while IFS= read -r dynamic_candidate; do
57
- [[ -n "$dynamic_candidate" ]] && dynamic_candidates+=("$dynamic_candidate")
58
- done < <(command yui config completion candidates "$current" -- "\${COMP_WORDS[@]:1:COMP_CWORD-1}" 2>/dev/null)
59
- candidates=("\${dynamic_candidates[@]}")
60
- elif [[ "$current" == -* ]]; then
61
- case "$path" in
62
- ${bashStaticOptionCases(entries)}
63
- *) candidates=();;
64
- esac
65
- else
66
- case "$path" in
67
- ${entries.map((entry) => ` ${bashPattern(entry.path)}) candidates=(${[...entry.immediate, ...entry.options].map(shellQuote).join(" ")});;`).join("\n")}
68
- *) candidates=();;
69
- esac
70
- fi
71
- COMPREPLY=( $(compgen -W "\${candidates[*]}" -- "$current") )
72
- }
73
- complete -F ${functionName} yui
5
+ case "bash": return `_yui() {
6
+ local candidate current="\${COMP_WORDS[COMP_CWORD]}"
7
+ COMPREPLY=()
8
+ while IFS= read -r candidate; do
9
+ [[ -n "$candidate" ]] && COMPREPLY+=("$candidate")
10
+ done < <(command yui config completion candidates "$current" -- "\${COMP_WORDS[@]:1:COMP_CWORD-1}" 2>/dev/null)
11
+ }
12
+ complete -F _yui yui
74
13
  `;
75
- }
76
- function renderZsh(entries) {
77
- return `#compdef yui
78
- ${manifest("# yui command:")}
79
- local current command_path previous dynamic_output dynamic=false
14
+ case "zsh": return `#compdef yui
15
+ local output
80
16
  local -a candidates
81
- current="$words[CURRENT]"
82
- command_path=""
83
- if (( CURRENT > 2 )); then
84
- command_path="\${(j: :)words[2,CURRENT-1]}"
85
- fi
86
- previous="$words[CURRENT-1]"
87
- if [[ "$current" != -* ]]; then
88
- case "$CURRENT:$command_path" in
89
- ${zshDynamicArgumentCases(entries)}
90
- esac
91
- fi
92
- if [[ "$dynamic" == false ]]; then
93
- case "$previous:$command_path" in
94
- ${zshDynamicOptionCases(entries)}
95
- esac
96
- fi
97
- if [[ "$dynamic" == true ]]; then
98
- dynamic_output="$(command yui config completion candidates "$current" -- "\${(@)words[2,CURRENT-1]}" 2>/dev/null)"
99
- candidates=("\${(@f)dynamic_output}")
100
- elif [[ "$current" == -* ]]; then
101
- case "$command_path" in
102
- ${zshStaticOptionCases(entries)}
103
- *) candidates=();;
104
- esac
105
- else
106
- case "$command_path" in
107
- ${entries.map((entry) => ` ${zshPattern(entry.path)}) candidates=(${[...entry.immediate, ...entry.options].map(shellQuote).join(" ")});;`).join("\n")}
108
- *) candidates=();;
109
- esac
110
- fi
17
+ output="$(command yui config completion candidates "$words[CURRENT]" -- "\${(@)words[2,CURRENT-1]}" 2>/dev/null)"
18
+ candidates=("\${(@f)output}")
111
19
  (( \${#candidates[@]} > 0 )) && compadd -- "$candidates[@]"
112
20
  `;
113
- }
114
- function renderFish(entries) {
115
- const prefix = "__yui";
116
- const lines = [
117
- manifest("# yui command:"),
118
- `function ${prefix}_at_path`,
119
- " set -l actual (commandline -opc)",
120
- " set -e actual[1]",
121
- " test (count $actual) -eq (count $argv); or return 1",
122
- " for index in (seq (count $argv))",
123
- " test \"$actual[$index]\" = \"$argv[$index]\"; or return 1",
124
- " end",
125
- "end",
126
- `function ${prefix}_at_command_options`,
127
- " string match -q -- '-*' (commandline -ct); or return 1",
128
- " set -l actual (commandline -opc)",
129
- " set -e actual[1]",
130
- " test (count $actual) -ge (count $argv); or return 1",
131
- " for index in (seq (count $argv))",
132
- " test \"$actual[$index]\" = \"$argv[$index]\"; or return 1",
133
- " end",
134
- "end",
135
- `function ${prefix}_needs_dynamic`,
136
- " set -l mode $argv[1]",
137
- " set -l expected $argv[2]",
138
- " set -l expected_path $argv[3..-1]",
139
- " set -l actual (commandline -opc)",
140
- " set -e actual[1]",
141
- " test (count $actual) -ge (count $expected_path); or return 1",
142
- " for index in (seq (count $expected_path))",
143
- " test \"$actual[$index]\" = \"$expected_path[$index]\"; or return 1",
144
- " end",
145
- " if test \"$mode\" = argument",
146
- " string match -q -- '-*' (commandline -ct); and return 1",
147
- " test (count $actual) -eq \"$expected\"",
148
- " else",
149
- " test \"$actual[-1]\" = \"$expected\"",
150
- " end",
151
- "end",
152
- `function ${prefix}_dynamic`,
153
- " set -l words (commandline -opc)",
154
- " yui config completion candidates (commandline -ct) -- $words[2..-1] 2>/dev/null",
155
- "end"
156
- ];
157
- for (const entry of entries) {
158
- for (const argument of entry.dynamicArguments) {
159
- const condition = `${prefix}_needs_dynamic argument ${argument} ${fishPath(entry.path)}`;
160
- lines.push(`complete -c yui -f -n ${fishQuote(condition)} -a '(${prefix}_dynamic)'`);
161
- }
162
- for (const option of entry.dynamicOptions) {
163
- const condition = `${prefix}_needs_dynamic option ${option} ${fishPath(entry.path)}`;
164
- lines.push(`complete -c yui -f -n ${fishQuote(condition)} -a '(${prefix}_dynamic)'`);
165
- }
166
- }
167
- for (const entry of entries) {
168
- if (entry.immediate.length > 0) {
169
- const condition = entry.path.length === 0
170
- ? "__fish_use_subcommand"
171
- : `${prefix}_at_path ${fishPath(entry.path)}${fishInitialDynamicExclusion(entry, prefix)}`;
172
- lines.push(`complete -c yui -f -n ${fishQuote(condition)} -a '${escapeSingle(entry.immediate.join(" "))}'`);
173
- }
174
- if (entry.options.length > 0) {
175
- const path = fishPath(entry.path);
176
- const exact = `${prefix}_at_path ${path}${fishInitialDynamicExclusion(entry, prefix)}`;
177
- const condition = `begin; ${exact}; end; or ${prefix}_at_command_options ${path}`;
178
- lines.push(`complete -c yui -f -n ${fishQuote(condition)} -a '${escapeSingle(entry.options.join(" "))}'`);
179
- }
21
+ case "fish": return `function __yui_candidates
22
+ set -l words (commandline -opc)
23
+ set -l current (commandline -ct)
24
+ command yui config completion candidates "$current" -- $words[2..-1] 2>/dev/null
25
+ end
26
+ complete -c yui -f -a '(__yui_candidates)'
27
+ `;
28
+ default: throw new Error("Completion shell must be one of bash, zsh, fish.");
180
29
  }
181
- return `${lines.join("\n")}\n`;
182
- }
183
- function bashDynamicArgumentCases(entries) {
184
- return entries.flatMap((entry) => entry.dynamicArguments.map((argument) => ` ${dynamicArgumentPattern(argument + 1, entry.path)}) dynamic=true;;`)).join("\n");
185
- }
186
- function zshDynamicArgumentCases(entries) {
187
- return entries.flatMap((entry) => entry.dynamicArguments.map((argument) => ` ${dynamicArgumentPattern(argument + 2, entry.path)}) dynamic=true;;`)).join("\n");
188
- }
189
- function dynamicArgumentPattern(position, path) {
190
- return `${position}:${shellQuote(path)}|${position}:${shellQuote(`${path} `)}*`;
191
- }
192
- function bashDynamicOptionCases(entries) {
193
- return entries.flatMap((entry) => entry.dynamicOptions.map((option) => ` ${dynamicOptionPattern(option, entry.path)}) dynamic=true;;`)).join("\n");
194
- }
195
- function zshDynamicOptionCases(entries) {
196
- return entries.flatMap((entry) => entry.dynamicOptions.map((option) => ` ${dynamicOptionPattern(option, entry.path)}) dynamic=true;;`)).join("\n");
197
- }
198
- function dynamicOptionPattern(option, path) {
199
- return `${shellQuote(`${option}:${path}`)}|${shellQuote(`${option}:${path} `)}*`;
200
- }
201
- function bashStaticOptionCases(entries) {
202
- return staticOptionEntries(entries).map((entry) => ` ${commandPrefixPattern(entry.path)}) candidates=(${entry.options.map(shellQuote).join(" ")});;`).join("\n");
203
- }
204
- function zshStaticOptionCases(entries) {
205
- return staticOptionEntries(entries).map((entry) => ` ${commandPrefixPattern(entry.path)}) candidates=(${entry.options.map(shellQuote).join(" ")});;`).join("\n");
206
- }
207
- function staticOptionEntries(entries) {
208
- return entries.filter((entry) => entry.options.length > 0)
209
- .sort((left, right) => right.path.split(" ").length - left.path.split(" ").length);
210
- }
211
- function commandPrefixPattern(path) {
212
- return `${shellQuote(path)}|${shellQuote(`${path} `)}*`;
213
- }
214
- function fishInitialDynamicExclusion(entry, prefix) {
215
- const initial = entry.dynamicArguments.filter((position) => position === entry.path.split(" ").filter(Boolean).length);
216
- return initial.map((position) => `; and not ${prefix}_needs_dynamic argument ${position} ${fishPath(entry.path)}`).join("");
217
- }
218
- function fishPath(path) {
219
- return path.split(" ").filter(Boolean).join(" ");
220
- }
221
- function bashPattern(path) {
222
- return path.length === 0 ? '""' : shellQuote(path);
223
- }
224
- function zshPattern(path) {
225
- return path.length === 0 ? '""' : shellQuote(path);
226
- }
227
- function shellQuote(value) {
228
- return `'${escapeSingle(value)}'`;
229
- }
230
- function fishQuote(value) {
231
- return `'${escapeSingle(value)}'`;
232
- }
233
- function escapeSingle(value) {
234
- return value.replaceAll("'", "'\\''");
235
30
  }
@@ -5,7 +5,16 @@ export async function resolveCompletionCandidates(input) {
5
5
  const words = input.words[0] === "yui"
6
6
  ? input.words.slice(1)
7
7
  : [...input.words];
8
- const { node, consumed } = resolveCommand(words);
8
+ const root = input.root ?? ROOT_COMMAND;
9
+ if (words[0] === "help") {
10
+ const { node, consumed } = resolveCommand(words.slice(1), root);
11
+ return consumed === words.length - 1 ? prefix(visibleChildren(node).map(child => child.name), input.current) : [];
12
+ }
13
+ const { node, consumed } = resolveCommand(words, root);
14
+ if (node.kind === "group" && consumed < words.length)
15
+ return [];
16
+ if (input.current.startsWith("-"))
17
+ return prefix(node.options, input.current);
9
18
  if (consumed === words.length && node.children.length > 0) {
10
19
  return prefix(visibleChildren(node).map((child) => child.name), input.current);
11
20
  }
@@ -13,9 +22,6 @@ export async function resolveCompletionCandidates(input) {
13
22
  if (previous !== undefined && Object.hasOwn(node.optionValues, previous)) {
14
23
  return prefix(node.optionValues[previous] ?? [], input.current);
15
24
  }
16
- if (input.current.startsWith("-")) {
17
- return prefix(node.options, input.current);
18
- }
19
25
  const argumentPosition = words.length;
20
26
  const policy = findInteractionPolicy(node);
21
27
  const selector = policy?.selectors.find((candidate) => selectorApplies(candidate, previous, argumentPosition));
@@ -31,8 +37,8 @@ function selectorApplies(selector, previous, argumentPosition) {
31
37
  return selector.option === previous;
32
38
  return selector.argumentIndex === argumentPosition;
33
39
  }
34
- function resolveCommand(words) {
35
- let node = ROOT_COMMAND;
40
+ function resolveCommand(words, root) {
41
+ let node = root;
36
42
  let consumed = 0;
37
43
  while (consumed < words.length && node.kind !== "leaf") {
38
44
  const child = findChild(node, words[consumed] ?? "");
@@ -1,4 +1,5 @@
1
1
  import { usageError } from "../errors/cliError.js";
2
+ import { hasManagedIdentity } from "../runtime/managedIdentity.js";
2
3
  import { requireManagedGlobalCaller } from "../runtime/managedCaller.js";
3
4
  import { routeInvocation } from "./invocationRouter.js";
4
5
  import { findInteractionPolicy } from "./interactionPolicy.js";
@@ -17,8 +18,7 @@ export function assertConfigurationAuthority(args, store, env) {
17
18
  requireManagedGlobalCaller(store, env);
18
19
  return;
19
20
  }
20
- if (env.YUI_SESSION_SCOPE !== undefined || env.YUI_ROLE !== undefined
21
- || env.YUI_AGENT_ID !== undefined || env.YUI_NATIVE_SESSION_ID !== undefined) {
21
+ if (hasManagedIdentity(env)) {
22
22
  throw usageError("Home configuration and resource mutations require the user or current Operator, not a Task Assignment.");
23
23
  }
24
24
  }
@@ -1,16 +1,27 @@
1
1
  import { findChild, ROOT_COMMAND } from "./commandCatalog.js";
2
- export function routeInvocation(args) {
2
+ export function routeInvocation(args, discoveryRoot = ROOT_COMMAND) {
3
3
  if (args.length === 0)
4
4
  return { kind: "execute", node: ROOT_COMMAND };
5
5
  if (args[0] === "help")
6
- return resolveHelpPath(args.slice(1));
7
- return resolveExecutionPath(args);
6
+ return resolveHelpPath(args.slice(1), discoveryRoot);
7
+ const result = resolveExecutionPath(args);
8
+ if (result.kind === "execute" || result.kind === "help")
9
+ return result;
10
+ const path = result.helpNode.path.slice(1);
11
+ let helpNode = discoveryRoot;
12
+ for (const segment of path) {
13
+ const child = findChild(helpNode, segment);
14
+ if (!child)
15
+ break;
16
+ helpNode = child;
17
+ }
18
+ return { ...result, helpNode };
8
19
  }
9
- function resolveHelpPath(path) {
20
+ function resolveHelpPath(path, root) {
10
21
  if (path.length === 0)
11
- return { kind: "help", node: ROOT_COMMAND };
12
- let node = ROOT_COMMAND;
13
- let nearestGroup = ROOT_COMMAND;
22
+ return { kind: "help", node: root };
23
+ let node = root;
24
+ let nearestGroup = root;
14
25
  for (const segment of path) {
15
26
  const child = findChild(node, segment);
16
27
  if (child === undefined || child.hidden) {