@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.
Files changed (208) hide show
  1. package/ARCHITECTURE.md +603 -133
  2. package/README.md +806 -31
  3. package/dist/agent/agent.js +2 -1
  4. package/dist/agent/argumentPolicy.js +3 -1
  5. package/dist/agent/launchEnvironment.js +106 -0
  6. package/dist/agent/managedRuntimeEnvironment.js +34 -0
  7. package/dist/brief/taskBrief.js +11 -1
  8. package/dist/cli/agentConfigurationPicker.js +287 -0
  9. package/dist/cli/commandCatalog.js +488 -60
  10. package/dist/cli/completion.js +146 -22
  11. package/dist/cli/helpRenderer.js +3 -1
  12. package/dist/cli/interactionCandidates.js +53 -15
  13. package/dist/cli/interactionPolicy.js +267 -30
  14. package/dist/cli/interactiveSelection.js +6 -2
  15. package/dist/cli/invocationRouter.js +5 -1
  16. package/dist/cli/operatorWizard.js +87 -0
  17. package/dist/cli/roleOptionCatalog.js +1 -0
  18. package/dist/cli/roleWizard.js +185 -21
  19. package/dist/cli/updateCommand.js +62 -19
  20. package/dist/cli/updateOrchestrator.js +539 -0
  21. package/dist/cli/updatePorts.js +1119 -0
  22. package/dist/cli/upgradeCommand.js +112 -0
  23. package/dist/cli.js +1420 -86
  24. package/dist/commands/agentCommands.js +146 -3
  25. package/dist/commands/configCommands.js +126 -0
  26. package/dist/commands/controllerCommands.js +365 -0
  27. package/dist/commands/globalRoleCommands.js +168 -126
  28. package/dist/commands/jobCommands.js +18 -8
  29. package/dist/commands/operatorCommands.js +159 -9
  30. package/dist/commands/profileCommands.js +203 -0
  31. package/dist/commands/projectCommands.js +650 -0
  32. package/dist/commands/roleConfiguration.js +85 -24
  33. package/dist/commands/roleRuntimeGuard.js +12 -0
  34. package/dist/commands/roleSkillValidation.js +47 -0
  35. package/dist/commands/taskActor.js +127 -0
  36. package/dist/commands/taskCommands.js +4201 -313
  37. package/dist/commands/taskCompletionGate.js +131 -0
  38. package/dist/commands/taskContextCommand.js +244 -30
  39. package/dist/commands/taskInputCommands.js +177 -59
  40. package/dist/commands/taskIntegrationCommands.js +303 -0
  41. package/dist/commands/taskOverviewCommand.js +363 -0
  42. package/dist/commands/taskRoleRuntimeStatus.js +125 -19
  43. package/dist/commands/textInput.js +15 -0
  44. package/dist/completion/completionInstaller.js +26 -22
  45. package/dist/config/yuiConfig.js +4 -3
  46. package/dist/context/dispatchContext.js +90 -38
  47. package/dist/context/roleSessionContext.js +119 -0
  48. package/dist/controller/claudeLifecycleHook.js +203 -0
  49. package/dist/controller/clientRuntime.js +408 -56
  50. package/dist/controller/codexLifecycleHook.js +108 -0
  51. package/dist/controller/controller.js +1089 -32
  52. package/dist/controller/domainIdentity.js +505 -0
  53. package/dist/controller/ephemeralResourceReaper.js +131 -0
  54. package/dist/controller/fileSchedulerStoreAdapter.js +2153 -103
  55. package/dist/controller/providerHookRunFence.js +127 -0
  56. package/dist/controller/resourceCleanupLinux.js +286 -0
  57. package/dist/controller/resourceInventory.js +531 -0
  58. package/dist/controller/resourceInventoryLinux.js +610 -0
  59. package/dist/controller/runtime.js +629 -10
  60. package/dist/controller/runtimeEventInbox.js +564 -0
  61. package/dist/controller/runtimeEventProcessor.js +248 -0
  62. package/dist/controller/runtimeLaunchCoordinator.js +477 -0
  63. package/dist/controller/sessionNotify.js +121 -78
  64. package/dist/coordination/deadlineScheduler.js +15 -0
  65. package/dist/coordination/mailboxScheduler.js +108 -0
  66. package/dist/coordination/workMailbox.js +329 -0
  67. package/dist/coordination/workMailboxQueue.js +86 -0
  68. package/dist/core/controllerClient.js +19 -5
  69. package/dist/core/controllerEndpoint.js +37 -0
  70. package/dist/core/controllerServer.js +218 -10
  71. package/dist/core/protocol.js +6 -2
  72. package/dist/decision/decision.js +2 -1
  73. package/dist/doctor/doctor.js +681 -32
  74. package/dist/domain/validation.js +53 -0
  75. package/dist/errors/cliError.js +5 -3
  76. package/dist/event/taskEvent.js +7 -3
  77. package/dist/execution/codexThreadNaming.js +160 -0
  78. package/dist/execution/executionGroup.js +579 -0
  79. package/dist/executor/agentAdapter.js +255 -40
  80. package/dist/executor/agentConfigurationCatalog.js +326 -0
  81. package/dist/executor/agentConfigurationProbe.js +506 -0
  82. package/dist/executor/agentExecutor.js +625 -10
  83. package/dist/executor/codexConfigConflict.js +290 -0
  84. package/dist/executor/effectiveLaunch.js +340 -0
  85. package/dist/executor/executorRegistry.js +238 -36
  86. package/dist/executor/fileRoleLaunchPlanner.js +550 -40
  87. package/dist/executor/turnCompletion.js +126 -0
  88. package/dist/input/inputRequest.js +30 -9
  89. package/dist/integration/changeSet.js +36 -0
  90. package/dist/integration/checkResult.js +24 -0
  91. package/dist/integration/gitIntegrationService.js +695 -0
  92. package/dist/integration/integrationAttempt.js +142 -0
  93. package/dist/interaction/operatorPresentation.js +96 -0
  94. package/dist/lifecycle/canonicalLifecycleEvent.js +342 -0
  95. package/dist/lifecycle/exactRunTerminalization.js +572 -0
  96. package/dist/lifecycle/providerLifecycleMapping.js +190 -0
  97. package/dist/lifecycle/taskRoleSessionReset.js +124 -0
  98. package/dist/message/message.js +23 -7
  99. package/dist/milestone/milestone.js +2 -1
  100. package/dist/operator/operatorSessionHistory.js +124 -0
  101. package/dist/output/agentConfigurationPresentation.js +43 -0
  102. package/dist/output/rolePresentation.js +34 -10
  103. package/dist/output/terminal.js +8 -0
  104. package/dist/output/timePresentation.js +55 -0
  105. package/dist/profile/agentProfile.js +128 -0
  106. package/dist/repository/gitWorkspace.js +578 -24
  107. package/dist/repository/project.js +213 -0
  108. package/dist/repository/taskWorkspaceCoordinator.js +392 -0
  109. package/dist/repository/taskWorkspacePreparer.js +1688 -191
  110. package/dist/review/reviewConfig.js +11 -0
  111. package/dist/review/reviewRound.js +399 -0
  112. package/dist/review/taskFinalReviewContract.js +90 -0
  113. package/dist/role/role.js +124 -23
  114. package/dist/run/agentRun.js +155 -12
  115. package/dist/run/runIdentity.js +82 -0
  116. package/dist/runtime/exactControlPlane.js +472 -0
  117. package/dist/runtime/index.js +8 -0
  118. package/dist/runtime/lifecycleReservation.js +38 -0
  119. package/dist/runtime/ports.js +11 -0
  120. package/dist/runtime/preallocatedNativeSession.js +13 -0
  121. package/dist/runtime/promptEnvelope.js +30 -0
  122. package/dist/runtime/runtimeBinding.js +31 -0
  123. package/dist/runtime/runtimeOwner.js +14 -0
  124. package/dist/runtime/sessionLaunchRequest.js +62 -0
  125. package/dist/runtime/sessionTitle.js +54 -0
  126. package/dist/runtime/taskRuntimeIsolation.js +643 -0
  127. package/dist/runtime/tmuxAdapters.js +315 -0
  128. package/dist/runtime/turnCompletion.js +3 -0
  129. package/dist/runtime/validation.js +23 -0
  130. package/dist/scheduler/activeRoleRunDelivery.js +342 -32
  131. package/dist/scheduler/activeTaskProgress.js +63 -0
  132. package/dist/scheduler/leaderFailure.js +2 -1
  133. package/dist/scheduler/leaderWakeupProcessor.js +307 -66
  134. package/dist/scheduler/operatorInputNotificationProcessor.js +109 -46
  135. package/dist/scheduler/operatorNotification.js +44 -2
  136. package/dist/scheduler/ports.js +28 -1
  137. package/dist/scheduler/roleRunLiveness.js +131 -25
  138. package/dist/scheduler/roleRunStall.js +951 -0
  139. package/dist/scheduler/taskExecutionProjection.js +544 -0
  140. package/dist/scheduler/wakeupQueue.js +3 -0
  141. package/dist/setup/setupCommand.js +302 -52
  142. package/dist/storage/compatibleTaskStore.js +102 -0
  143. package/dist/storage/migration/baseline.js +78 -0
  144. package/dist/storage/migration/classifier.js +51 -0
  145. package/dist/storage/migration/compatibleCodec.js +53 -0
  146. package/dist/storage/migration/engine.js +147 -0
  147. package/dist/storage/migration/index.js +33 -0
  148. package/dist/storage/migration/planner.js +154 -0
  149. package/dist/storage/migration/productionRegistry.js +486 -0
  150. package/dist/storage/migration/registry.js +169 -0
  151. package/dist/storage/migration/report.js +54 -0
  152. package/dist/storage/migration/types.js +31 -0
  153. package/dist/storage/storageSchema.js +147 -123
  154. package/dist/storage/storageVersions.js +11 -0
  155. package/dist/storage/taskStore.js +1793 -197
  156. package/dist/storage/upgrade/homeClassification.js +156 -0
  157. package/dist/storage/upgrade/homeMigrationTarget.js +595 -0
  158. package/dist/storage/upgrade/offlineUpgradeInventory.js +315 -0
  159. package/dist/storage/upgrade/productionMigrationRegistry.js +6 -0
  160. package/dist/storage/upgrade/recordVersionScan.js +176 -0
  161. package/dist/storage/upgrade/recordVersions.js +159 -0
  162. package/dist/storage/upgrade/switchProgress.js +80 -0
  163. package/dist/storage/upgrade/upgradeOrchestrator.js +948 -0
  164. package/dist/storage/upgrade/upgradeReceipt.js +161 -0
  165. package/dist/storage/upgradeCoordination.js +186 -0
  166. package/dist/storage/upgradeFence.js +366 -0
  167. package/dist/task/task.js +132 -26
  168. package/dist/task/taskRecordReference.js +66 -0
  169. package/dist/tmux/commandExecutor.js +75 -2
  170. package/dist/tmux/tmuxManager.js +747 -49
  171. package/dist/version.js +23 -0
  172. package/dist/web/assets/assetManifest.js +62 -0
  173. package/dist/web/assets/client/app.js +631 -0
  174. package/dist/web/assets/client/components.js +605 -0
  175. package/dist/web/assets/client/dom.js +14 -0
  176. package/dist/web/assets/client/format.js +28 -0
  177. package/dist/web/assets/client/i18n.js +494 -0
  178. package/dist/web/assets/client/markdown.js +114 -0
  179. package/dist/web/assets/client/theme.js +32 -0
  180. package/dist/web/assets/client/view.js +458 -0
  181. package/dist/web/assets/fontData.js +12 -0
  182. package/dist/web/assets/fonts.js +12 -0
  183. package/dist/web/assets/shell.js +114 -0
  184. package/dist/web/assets/styles/cards.js +135 -0
  185. package/dist/web/assets/styles/layout.js +47 -0
  186. package/dist/web/assets/styles/markdown.js +29 -0
  187. package/dist/web/assets/styles/responsive.js +39 -0
  188. package/dist/web/assets/styles/tokens.js +101 -0
  189. package/dist/web/assets/styles/widgets.js +147 -0
  190. package/dist/web/tmuxWebTerminal.js +158 -0
  191. package/dist/web/webServer.js +463 -0
  192. package/dist/web/webSnapshot.js +148 -0
  193. package/dist/workItem/workItem.js +642 -23
  194. package/dist/workspace/gitChangeSetCapture.js +86 -0
  195. package/dist/workspace/workItemChangeSetManager.js +445 -0
  196. package/dist/worktree/managedWorkspace.js +202 -0
  197. package/docs/task-local-identity.md +62 -0
  198. package/i18n/README.zh-CN.md +406 -31
  199. package/package.json +10 -2
  200. package/skills/yui-leader/SKILL.md +601 -39
  201. package/skills/yui-operator/SKILL.md +255 -34
  202. package/skills/yui-reviewer/SKILL.md +57 -0
  203. package/skills/yui-worker/SKILL.md +214 -17
  204. package/dist/commands/repositoryCommands.js +0 -86
  205. package/dist/operator/operatorContext.js +0 -66
  206. package/dist/repository/repository.js +0 -55
  207. package/dist/scheduler/archivedTaskRuntime.js +0 -12
  208. package/dist/worktree/roleWorkspace.js +0 -62
@@ -1,4 +1,5 @@
1
1
  import { ROOT_COMMAND, listPublicCommandPaths, orderedImmediateTokens, visibleChildren } from "./commandCatalog.js";
2
+ import { findInteractionPolicy } from "./interactionPolicy.js";
2
3
  export function renderCompletion(shell, identity = "yui") {
3
4
  const entries = collectEntries(ROOT_COMMAND);
4
5
  switch (shell) {
@@ -12,10 +13,13 @@ function collectEntries(root) {
12
13
  const entries = [];
13
14
  const visit = (node) => {
14
15
  if (!node.hidden && !node.commandPathArguments) {
16
+ const policy = findInteractionPolicy(node);
15
17
  entries.push({
16
18
  path: node.path.slice(1).join(" "),
17
19
  immediate: orderedImmediateTokens(node),
18
- options: node.options
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]) ?? []
19
23
  });
20
24
  }
21
25
  visibleChildren(node).forEach(visit);
@@ -30,18 +34,34 @@ function renderBash(entries, identity) {
30
34
  const functionName = identity === "yui" ? "_yui" : "_yui_dev";
31
35
  return `${manifest("# yui command:")}
32
36
  ${functionName}() {
33
- local current path dynamic_candidate
37
+ local current path previous dynamic_candidate dynamic=false
34
38
  local -a candidates dynamic_candidates
35
39
  current="\${COMP_WORDS[COMP_CWORD]}"
36
40
  path=""
37
41
  if (( COMP_CWORD > 1 )); then
38
42
  path="\${COMP_WORDS[*]:1:COMP_CWORD-1}"
39
43
  fi
40
- while IFS= read -r dynamic_candidate; do
41
- [[ -n "$dynamic_candidate" ]] && dynamic_candidates+=("$dynamic_candidate")
42
- done < <(command ${identity} completion candidates "$current" -- "\${COMP_WORDS[@]:1:COMP_CWORD-1}" 2>/dev/null)
43
- if (( \${#dynamic_candidates[@]} > 0 )); then
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 ${identity} completion candidates "$current" -- "\${COMP_WORDS[@]:1:COMP_CWORD-1}" 2>/dev/null)
44
59
  candidates=("\${dynamic_candidates[@]}")
60
+ elif [[ "$current" == -* ]]; then
61
+ case "$path" in
62
+ ${bashStaticOptionCases(entries)}
63
+ *) candidates=();;
64
+ esac
45
65
  else
46
66
  case "$path" in
47
67
  ${entries.map((entry) => ` ${bashPattern(entry.path)}) candidates=(${[...entry.immediate, ...entry.options].map(shellQuote).join(" ")});;`).join("\n")}
@@ -56,18 +76,34 @@ complete -F ${functionName} ${identity}
56
76
  function renderZsh(entries, identity) {
57
77
  return `#compdef ${identity}
58
78
  ${manifest("# yui command:")}
59
- local current path dynamic_output
79
+ local current command_path previous dynamic_output dynamic=false
60
80
  local -a candidates
61
81
  current="$words[CURRENT]"
62
- path=""
82
+ command_path=""
63
83
  if (( CURRENT > 2 )); then
64
- path="\${(j: :)words[2,CURRENT-1]}"
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
65
91
  fi
66
- dynamic_output="$(command ${identity} completion candidates "$current" -- "\${(@)words[2,CURRENT-1]}" 2>/dev/null)"
67
- if [[ -n "$dynamic_output" ]]; then
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 ${identity} completion candidates "$current" -- "\${(@)words[2,CURRENT-1]}" 2>/dev/null)"
68
99
  candidates=("\${(@f)dynamic_output}")
100
+ elif [[ "$current" == -* ]]; then
101
+ case "$command_path" in
102
+ ${zshStaticOptionCases(entries)}
103
+ *) candidates=();;
104
+ esac
69
105
  else
70
- case "$path" in
106
+ case "$command_path" in
71
107
  ${entries.map((entry) => ` ${zshPattern(entry.path)}) candidates=(${[...entry.immediate, ...entry.options].map(shellQuote).join(" ")});;`).join("\n")}
72
108
  *) candidates=();;
73
109
  esac
@@ -76,24 +112,112 @@ fi
76
112
  `;
77
113
  }
78
114
  function renderFish(entries, identity) {
115
+ const prefix = `__${identity.replaceAll("-", "_")}`;
79
116
  const lines = [
80
117
  manifest("# yui command:"),
81
- `function __${identity.replaceAll("-", "_")}_dynamic`,
82
- ` ${identity} completion candidates (commandline -ct) -- (commandline -opc | string split ' ' | tail -n +2) 2>/dev/null`,
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",
83
125
  "end",
84
- `complete -c ${identity} -f -a '(__${identity.replaceAll("-", "_")}_dynamic)'`
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
+ ` ${identity} completion candidates (commandline -ct) -- $words[2..-1] 2>/dev/null`,
155
+ "end"
85
156
  ];
86
157
  for (const entry of entries) {
87
- const candidates = [...entry.immediate, ...entry.options].join(" ");
88
- if (candidates.length === 0)
89
- continue;
90
- const condition = entry.path.length === 0
91
- ? "__fish_use_subcommand"
92
- : `__fish_seen_subcommand_from ${entry.path.split(" ").map(fishQuote).join(" ")}`;
93
- lines.push(`complete -c ${identity} -n '${condition}' -a '${escapeSingle(candidates)}'`);
158
+ for (const argument of entry.dynamicArguments) {
159
+ const condition = `${prefix}_needs_dynamic argument ${argument} ${fishPath(entry.path)}`;
160
+ lines.push(`complete -c ${identity} -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 ${identity} -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 ${identity} -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 ${identity} -f -n ${fishQuote(condition)} -a '${escapeSingle(entry.options.join(" "))}'`);
179
+ }
94
180
  }
95
181
  return `${lines.join("\n")}\n`;
96
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
+ }
97
221
  function bashPattern(path) {
98
222
  return path.length === 0 ? '""' : shellQuote(path);
99
223
  }
@@ -22,8 +22,10 @@ function describeOption(option) {
22
22
  "--agent": "Select an Agent.",
23
23
  "--base": "Set the base Git reference.",
24
24
  "--input": "Set dispatch input.",
25
+ "--host": "Set the loopback listen address.",
26
+ "--port": "Set the local listen port.",
25
27
  "--json": "Emit machine-readable JSON.",
26
- "--repository": "Select a repository.",
28
+ "--project": "Select a Project.",
27
29
  "--role": "Select a Task role.",
28
30
  "--summary": "Set summary text.",
29
31
  "--task": "Select a Task."
@@ -4,38 +4,47 @@ export async function getSelectionCandidates(selector, ports, args) {
4
4
  case "tasks":
5
5
  return entities("task", "Select task", (await list(ports, "task.list", {})).filter((task) => selector.statuses === undefined
6
6
  || selector.statuses.includes(stringField(task, "status") ?? "")), ["id", "title", "status"]);
7
- case "repositories":
8
- return entities("repository", "Select repository", await list(ports, "repository.list", {}), ["id", "name", "path"]);
7
+ case "projects":
8
+ return entities("project", "Select Project", await list(ports, "project.list", {}), ["id", "name", "path"]);
9
9
  case "configured-agents": {
10
- const agents = await list(ports, "agent.list", {});
10
+ const agents = (await list(ports, "agent.list", {})).filter((agent) => selector.adapterIds === undefined
11
+ || selector.adapterIds.includes(stringField(agent, "adapterId") ?? ""));
11
12
  const config = await optionalEntity(ports, "config.get", {});
12
- const defaultValue = config === undefined
13
+ const configuredDefault = config === undefined
13
14
  ? undefined
14
15
  : stringField(config, "defaultAgent");
16
+ const defaultValue = agents.some((agent) => stringField(agent, "id") === configuredDefault) ? configuredDefault : undefined;
15
17
  const set = entities("agent", "Select Agent", agents.map((agent) => ({
16
18
  ...agent,
17
19
  default: stringField(agent, "id") === defaultValue ? "default" : ""
18
20
  })), ["id", "adapterId", "command", "default"]);
19
21
  return { ...set, defaultValue };
20
22
  }
23
+ case "agent-profiles":
24
+ return entities("Agent Profile", "Select Agent Profile", await list(ports, "profile.list", {}), ["id", "revision", "defaultAccess", "agentId"]);
21
25
  case "global-roles":
22
26
  return entities("global role", "Select global Role", await list(ports, "role.list", {}), ["name", "activeAgentId", "workspace"]);
23
27
  case "jobs":
24
28
  return entities("job", "Select job", await list(ports, "jobs.list", {}), ["id", "type", "status"]);
25
29
  case "input-requests": {
26
30
  const taskId = dependencyValue(selector, args);
27
- return entities("input request", taskId === undefined ? "Select input request" : `Select input request: ${taskId}`, (await list(ports, "task.input.list", {
31
+ const requests = (await list(ports, "task.input.list", {
28
32
  ...(taskId === undefined ? {} : { taskId }),
29
33
  all: true
30
34
  })).filter((request) => selector.statuses === undefined
31
- || selector.statuses.includes(stringField(request, "status") ?? "")), ["id", "taskId", "status", "question"]);
35
+ || selector.statuses.includes(stringField(request, "status") ?? ""));
36
+ return entities("input request", taskId === undefined ? "Select input request" : `Select input request: ${taskId}`, taskId === undefined ? qualifyTaskRecords(requests) : requests, taskId === undefined
37
+ ? ["qualifiedId", "status", "question"]
38
+ : ["id", "status", "question"]);
32
39
  }
33
40
  case "task-roles": {
34
41
  const taskId = dependencyValue(selector, args);
35
42
  if (taskId === undefined)
36
43
  return null;
37
44
  const roles = orderRoleOptions(await list(ports, "task.role.list", { taskId }));
38
- return entities("task role", `Select Task role: ${taskId}`, roles, ["name", "kind", "agentId"]);
45
+ return entities("task role", `Select Task role: ${taskId}`, roles, [
46
+ "name", "kind", "activeAgentId"
47
+ ]);
39
48
  }
40
49
  case "task-decisions": {
41
50
  const taskId = dependencyValue(selector, args);
@@ -58,11 +67,40 @@ export async function getSelectionCandidates(selector, ports, args) {
58
67
  return entities("event", `Select Event: ${taskId}`, await list(ports, "task.event.list", { taskId }), ["id", "type", "createdAt"]);
59
68
  }
60
69
  case "work-items":
61
- return entities("work item", "Select work item", await listAllWorkItems(ports), ["id", "title", "status"]);
62
- case "runs":
63
- return entities("run", "Select run", await listAllRuns(ports), ["id", "status", "workItemId"]);
70
+ return entities("work item", "Select work item", qualifyTaskRecords(await listAllWorkItems(ports)), ["qualifiedId", "title", "status"]);
71
+ case "runs": {
72
+ const workItemId = dependencyValue(selector, args);
73
+ const runs = await listAllByTask(ports, "task.run.list", "runs");
74
+ return entities("run", workItemId === undefined ? "Select Run" : `Select Run: ${workItemId}`, qualifyTaskRecords(runs.filter((run) => workItemId === undefined
75
+ || matchesTaskRecordReference(run, "workItemId", workItemId))), ["qualifiedId", "roleName", "status", "summary"]);
76
+ }
77
+ case "integration-attempts":
78
+ return entities("Integration Attempt", "Select Integration Attempt", qualifyTaskRecords((await listAllByTask(ports, "task.integration.list", "integrations")).filter((attempt) => selector.statuses === undefined
79
+ || selector.statuses.includes(stringField(attempt, "status") ?? ""))), ["qualifiedId", "status", "targetRef"]);
80
+ case "change-sets": {
81
+ const taskId = dependencyValue(selector, args);
82
+ if (taskId === undefined)
83
+ return null;
84
+ return entities("ChangeSet", `Select ChangeSet: ${taskId}`, await list(ports, "task.change-set.list", { taskId }), ["id", "workItemId", "baseCommit", "headCommit"]);
85
+ }
64
86
  }
65
87
  }
88
+ function qualifyTaskRecords(input) {
89
+ return input.flatMap((entity) => {
90
+ const taskId = stringField(entity, "taskId");
91
+ const id = stringField(entity, "id");
92
+ return taskId === undefined || id === undefined
93
+ ? []
94
+ : [{ ...entity, qualifiedId: `${taskId}/${id}` }];
95
+ });
96
+ }
97
+ function matchesTaskRecordReference(entity, field, reference) {
98
+ const separator = reference.indexOf("/");
99
+ if (separator < 0)
100
+ return false;
101
+ return stringField(entity, "taskId") === reference.slice(0, separator)
102
+ && stringField(entity, field) === reference.slice(separator + 1);
103
+ }
66
104
  async function listAllWorkItems(ports) {
67
105
  const tasks = await list(ports, "task.list", {});
68
106
  const groups = await Promise.all(tasks.flatMap((task) => {
@@ -71,11 +109,11 @@ async function listAllWorkItems(ports) {
71
109
  }));
72
110
  return groups.flat();
73
111
  }
74
- async function listAllRuns(ports) {
75
- const workItems = await listAllWorkItems(ports);
76
- const groups = await Promise.all(workItems.flatMap((item) => {
77
- const workItemId = stringField(item, "id");
78
- return workItemId === undefined ? [] : [list(ports, "task.run.list", { workItemId })];
112
+ async function listAllByTask(ports, method, resultKey) {
113
+ const tasks = await list(ports, "task.list", {});
114
+ const groups = await Promise.all(tasks.flatMap((task) => {
115
+ const taskId = stringField(task, "id");
116
+ return taskId === undefined ? [] : [list(ports, method, { taskId, resultKey })];
79
117
  }));
80
118
  return groups.flat();
81
119
  }