moshcode 0.24.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 (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +580 -0
  3. package/bin/moshcode.mjs +674 -0
  4. package/bin/moshscript.mjs +29 -0
  5. package/examples/alive.mosh +6 -0
  6. package/examples/scripting-the-cli.mosh +21 -0
  7. package/examples/team-secrets.mosh +20 -0
  8. package/examples/templates/bun-caddy-sqlite/.env.example +14 -0
  9. package/examples/templates/bun-caddy-sqlite/Caddyfile +18 -0
  10. package/examples/templates/bun-caddy-sqlite/README.md +97 -0
  11. package/examples/templates/bun-caddy-sqlite/deploy/moshcode-dns.service +39 -0
  12. package/examples/templates/bun-caddy-sqlite/deploy/moshpit-service.service +38 -0
  13. package/examples/templates/bun-caddy-sqlite/package.json +15 -0
  14. package/examples/templates/bun-caddy-sqlite/src/db.ts +47 -0
  15. package/examples/templates/bun-caddy-sqlite/src/server.ts +44 -0
  16. package/examples/templates/bun-caddy-sqlite/template.json +10 -0
  17. package/examples/templates/caddy-proxy/Caddyfile +36 -0
  18. package/examples/templates/caddy-proxy/README.md +104 -0
  19. package/examples/templates/caddy-proxy/deploy/moshcode-dns.service +39 -0
  20. package/examples/templates/caddy-proxy/template.json +8 -0
  21. package/examples/templates/caddy-static/Caddyfile +16 -0
  22. package/examples/templates/caddy-static/README.md +90 -0
  23. package/examples/templates/caddy-static/deploy/moshcode-dns.service +39 -0
  24. package/examples/templates/caddy-static/site/index.html +11 -0
  25. package/examples/templates/caddy-static/template.json +8 -0
  26. package/install.sh +194 -0
  27. package/package.json +28 -0
  28. package/prd/0000-template.md +49 -0
  29. package/prd/0001-wrap-ugig-and-coinpay-clis.md +121 -0
  30. package/prd/0002-separate-agent-and-raw-engine-launches.md +113 -0
  31. package/prd/0003-cross-engine-mcp-and-skill-installation.md +165 -0
  32. package/prd/0004-moshscript-run-programmable-moshcode.md +344 -0
  33. package/prd/0005-hosted-moshpit-resolver.md +192 -0
  34. package/prd/0006-help.md +359 -0
  35. package/prd/0007-profullstack-site-init.md +1183 -0
  36. package/prd/README.md +26 -0
  37. package/src/ads.mjs +58 -0
  38. package/src/auth.mjs +193 -0
  39. package/src/cli-schema.mjs +533 -0
  40. package/src/cli.mjs +118 -0
  41. package/src/commands.mjs +259 -0
  42. package/src/completion.mjs +594 -0
  43. package/src/console.mjs +244 -0
  44. package/src/dns-system.mjs +404 -0
  45. package/src/dns.mjs +2872 -0
  46. package/src/doh-server.mjs +256 -0
  47. package/src/doh.mjs +218 -0
  48. package/src/engines.mjs +385 -0
  49. package/src/escalate.mjs +85 -0
  50. package/src/help.mjs +443 -0
  51. package/src/integrations.mjs +265 -0
  52. package/src/mcp-catalog.mjs +50 -0
  53. package/src/mcp.mjs +155 -0
  54. package/src/mirror.mjs +187 -0
  55. package/src/notify.mjs +86 -0
  56. package/src/open-url.mjs +34 -0
  57. package/src/parking-http.mjs +65 -0
  58. package/src/pins.mjs +190 -0
  59. package/src/pit-url.mjs +13 -0
  60. package/src/prd.mjs +341 -0
  61. package/src/pty.mjs +176 -0
  62. package/src/pwd.mjs +103 -0
  63. package/src/registry.mjs +37 -0
  64. package/src/release-install.mjs +191 -0
  65. package/src/runtime.mjs +161 -0
  66. package/src/selfupdate.mjs +215 -0
  67. package/src/serve.mjs +502 -0
  68. package/src/skills.mjs +93 -0
  69. package/src/tabs.mjs +144 -0
  70. package/src/templates.mjs +456 -0
  71. package/src/tools.mjs +231 -0
  72. package/src/trade.mjs +137 -0
  73. package/src/trust.mjs +712 -0
  74. package/src/tui.mjs +736 -0
  75. package/src/ui.mjs +49 -0
  76. package/src/uninstall.mjs +113 -0
  77. package/src/upgrade.mjs +217 -0
@@ -0,0 +1,594 @@
1
+ import {
2
+ CORE_CLI_COMMANDS,
3
+ MCP_VERBS,
4
+ SKILL_VERBS,
5
+ TRADE_VERBS,
6
+ UPGRADE_TARGETS,
7
+ } from "./cli-schema.mjs";
8
+ import { ENGINES, ENGINE_ALIASES } from "./engines.mjs";
9
+ import { TOOLS } from "./tools.mjs";
10
+ import { moshVocabulary } from "./commands.mjs";
11
+
12
+ export const COMPLETION_SHELLS = ["bash", "zsh", "fish", "powershell"];
13
+
14
+ function entry(name, description) {
15
+ const value = String(name);
16
+ if (!/^-{0,2}[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(value)) {
17
+ throw new Error(`completion name is not shell-safe: ${JSON.stringify(value)}`);
18
+ }
19
+ return { name: value, description: String(description).replace(/\s+/g, " ").trim() };
20
+ }
21
+
22
+ function uniqueEntries(entries) {
23
+ const found = new Map();
24
+ for (const item of entries) {
25
+ const normalized = entry(item.name, item.description);
26
+ if (!found.has(normalized.name)) found.set(normalized.name, normalized);
27
+ }
28
+ return [...found.values()].sort((a, b) => a.name.localeCompare(b.name));
29
+ }
30
+
31
+ export function completionModel() {
32
+ const engines = Object.entries(ENGINES).map(([name, engine]) => entry(name, engine.desc));
33
+ const engineAliases = Object.entries(ENGINE_ALIASES).map(([name, target]) => (
34
+ entry(name, `alias for ${target}`)
35
+ ));
36
+ const tools = Object.entries(TOOLS).map(([name, tool]) => entry(name, tool.desc));
37
+ const install = uniqueEntries([...engines, ...tools]);
38
+
39
+ return {
40
+ top: uniqueEntries([...CORE_CLI_COMMANDS, ...engines, ...engineAliases, ...tools]),
41
+ engines: uniqueEntries([...engines, ...engineAliases]),
42
+ install,
43
+ // `uninstall <engine|tool>` resolves its target against the same ENGINES and
44
+ // TOOLS rosters `install` does, so it offers the same targets. Kept as its
45
+ // own key rather than reusing `install` so the two can diverge without a
46
+ // silent surprise in one of them.
47
+ uninstall: install,
48
+ upgrade: uniqueEntries([
49
+ ...UPGRADE_TARGETS,
50
+ ...engines,
51
+ ...engineAliases,
52
+ ...tools,
53
+ ]),
54
+ mcp: uniqueEntries(MCP_VERBS),
55
+ mcpServerSpecs: uniqueEntries(MCP_VERBS.filter(({ acceptsServerSpec }) => acceptsServerSpec)),
56
+ skills: uniqueEntries(SKILL_VERBS),
57
+ trade: uniqueEntries(TRADE_VERBS),
58
+ tradeOrderOptions: uniqueEntries([
59
+ entry("--submit", "place the order instead of previewing"),
60
+ entry("--qty", "share quantity"),
61
+ entry("--notional", "dollar amount"),
62
+ entry("--type", "market, limit, stop, stop_limit, or trailing_stop"),
63
+ entry("--limit-price", "limit price"),
64
+ entry("--stop-price", "stop price"),
65
+ entry("--time-in-force", "order time in force"),
66
+ ]),
67
+ skillSources: uniqueEntries(SKILL_VERBS.filter(({ acceptsSource }) => acceptsSource)),
68
+ shells: COMPLETION_SHELLS.map((name) => entry(name, `generate ${name} completion`)),
69
+ // `moshcode help <topic>` accepts anything help can answer for: a command,
70
+ // an engine, a tool, or a moshscript verb (PRD 0006 R16). Offering the same
71
+ // set here is what keeps tab-completion and help one discoverability
72
+ // surface rather than two that disagree.
73
+ helpTopics: uniqueEntries([
74
+ ...CORE_CLI_COMMANDS.filter(({ name }) => !name.startsWith("-")),
75
+ ...engines,
76
+ ...tools,
77
+ ...moshVocabulary().all().map((c) => entry(c.name, c.summary || "moshscript verb")),
78
+ ]),
79
+ };
80
+ }
81
+
82
+ function names(entries) {
83
+ return entries.map(({ name }) => name).join(" ");
84
+ }
85
+
86
+ function shellQuote(value) {
87
+ return `'${String(value).replaceAll("'", "'\\''")}'`;
88
+ }
89
+
90
+ function zshValues(entries) {
91
+ return entries.map(({ name, description }) => shellQuote(`${name}:${description}`)).join(" ");
92
+ }
93
+
94
+ function shellMatches(variable, entries) {
95
+ return `[[ ${entries.map(({ name }) => `"$${variable}" == "${name}"`).join(" || ")} ]]`;
96
+ }
97
+
98
+ function fishQuote(value) {
99
+ return `'${String(value).replaceAll("\\", "\\\\").replaceAll("'", "\\'")}'`;
100
+ }
101
+
102
+ function fishEntries(condition, entries) {
103
+ return entries.map(({ name, description }) => (
104
+ `complete -c moshcode -n ${fishQuote(condition)} -a ${fishQuote(name)} -d ${fishQuote(description)}`
105
+ )).join("\n");
106
+ }
107
+
108
+ function powershellQuote(value) {
109
+ return `'${String(value).replaceAll("'", "''")}'`;
110
+ }
111
+
112
+ function powershellEntries(variable, entries) {
113
+ const rows = entries.map(({ name, description }) => (
114
+ ` [pscustomobject]@{ Name = ${powershellQuote(name)}; Description = ${powershellQuote(description)} }`
115
+ ));
116
+ return `$script:${variable} = @(\n${rows.join("\n")}\n)`;
117
+ }
118
+
119
+ function powershellCompletion(model) {
120
+ const optionEntries = (values, description = "option") => (
121
+ values.split(" ").filter(Boolean).map((name) => entry(name, description))
122
+ );
123
+
124
+ return `# PowerShell completion for moshcode
125
+ ${powershellEntries("MoshcodeCompletionTop", model.top)}
126
+ ${powershellEntries("MoshcodeCompletionEngines", model.engines)}
127
+ ${powershellEntries("MoshcodeCompletionInstall", model.install)}
128
+ ${powershellEntries("MoshcodeCompletionUninstall", model.uninstall)}
129
+ ${powershellEntries("MoshcodeCompletionUpgrade", model.upgrade)}
130
+ ${powershellEntries("MoshcodeCompletionMcp", model.mcp)}
131
+ ${powershellEntries("MoshcodeCompletionMcpServerSpecs", model.mcpServerSpecs)}
132
+ ${powershellEntries("MoshcodeCompletionSkills", model.skills)}
133
+ ${powershellEntries("MoshcodeCompletionTrade", model.trade)}
134
+ ${powershellEntries("MoshcodeCompletionTradeOrderOptions", model.tradeOrderOptions)}
135
+ ${powershellEntries("MoshcodeCompletionSkillSources", model.skillSources)}
136
+ ${powershellEntries("MoshcodeCompletionShells", model.shells)}
137
+ ${powershellEntries("MoshcodeCompletionHelpTopics", model.helpTopics)}
138
+ ${powershellEntries("MoshcodeCompletionJson", optionEntries("--json", "print JSON"))}
139
+ ${powershellEntries("MoshcodeCompletionLogin", optionEntries("--browser -b --device -d", "authentication mode"))}
140
+ ${powershellEntries("MoshcodeCompletionRun", optionEntries("--dry-run --max -n", "run option"))}
141
+ ${powershellEntries("MoshcodeCompletionUninstallOptions", optionEntries("--yes -y --dry-run", "uninstall option"))}
142
+ ${powershellEntries("MoshcodeCompletionConsole", optionEntries("serve --url", "console command"))}
143
+ ${powershellEntries("MoshcodeCompletionConsoleServe", optionEntries("--port --ttyd --bind", "console serve option"))}
144
+ ${powershellEntries("MoshcodeCompletionTemplate", optionEntries("list install", "template command"))}
145
+ ${powershellEntries("MoshcodeCompletionTemplateInstall", optionEntries("--into --force --dry-run", "template install option"))}
146
+ ${powershellEntries("MoshcodeCompletionMcpOptions", optionEntries("--name --transport -t --env -e --header -H", "MCP option"))}
147
+ ${powershellEntries("MoshcodeCompletionSkillOptions", optionEntries("--name", "skill option"))}
148
+
149
+ Register-ArgumentCompleter -Native -CommandName moshcode -ScriptBlock {
150
+ param($wordToComplete, $commandAst, $cursorPosition)
151
+
152
+ $tokens = @($commandAst.CommandElements | ForEach-Object { $_.Extent.Text })
153
+ $argumentIndex = if ([string]::IsNullOrEmpty($wordToComplete)) {
154
+ $tokens.Count
155
+ } else {
156
+ $tokens.Count - 1
157
+ }
158
+ $command = if ($tokens.Count -gt 1) { $tokens[1] } else { '' }
159
+ $nested = if ($tokens.Count -gt 2) { $tokens[2] } else { '' }
160
+ $choices = @()
161
+
162
+ if ($argumentIndex -eq 1) {
163
+ $choices = $script:MoshcodeCompletionTop
164
+ } else {
165
+ switch ($command) {
166
+ { $_ -in @('agents', 'start') } {
167
+ if ($argumentIndex -eq 2) {
168
+ $choices = if ($command -eq 'agents' -and $wordToComplete.StartsWith('-')) {
169
+ $script:MoshcodeCompletionJson
170
+ } else { $script:MoshcodeCompletionEngines }
171
+ }
172
+ }
173
+ 'install' {
174
+ if ($argumentIndex -eq 2) { $choices = $script:MoshcodeCompletionInstall }
175
+ }
176
+ { $_ -in @('uninstall', 'remove') } {
177
+ if ($argumentIndex -eq 2 -and -not $wordToComplete.StartsWith('-')) {
178
+ $choices = $script:MoshcodeCompletionUninstall
179
+ } elseif ($wordToComplete.StartsWith('-')) {
180
+ $choices = $script:MoshcodeCompletionUninstallOptions
181
+ }
182
+ }
183
+ { $_ -in @('upgrade', 'update') } {
184
+ $choices = $script:MoshcodeCompletionUpgrade
185
+ }
186
+ 'help' {
187
+ if ($argumentIndex -eq 2) { $choices = $script:MoshcodeCompletionHelpTopics }
188
+ }
189
+ 'completion' {
190
+ if ($argumentIndex -eq 2) { $choices = $script:MoshcodeCompletionShells }
191
+ }
192
+ 'mcp' {
193
+ if ($argumentIndex -eq 2) {
194
+ $choices = $script:MoshcodeCompletionMcp
195
+ } elseif ($nested -eq 'list' -and $wordToComplete.StartsWith('-')) {
196
+ $choices = $script:MoshcodeCompletionJson
197
+ } elseif ($script:MoshcodeCompletionMcpServerSpecs.Name -contains $nested -and $wordToComplete.StartsWith('-')) {
198
+ $choices = $script:MoshcodeCompletionMcpOptions
199
+ }
200
+ }
201
+ { $_ -in @('skill', 'skills') } {
202
+ if ($argumentIndex -eq 2) {
203
+ $choices = $script:MoshcodeCompletionSkills
204
+ } elseif ($nested -eq 'list' -and $wordToComplete.StartsWith('-')) {
205
+ $choices = $script:MoshcodeCompletionJson
206
+ } elseif ($script:MoshcodeCompletionSkillSources.Name -contains $nested -and $wordToComplete.StartsWith('-')) {
207
+ $choices = $script:MoshcodeCompletionSkillOptions
208
+ }
209
+ }
210
+ 'trade' {
211
+ if ($argumentIndex -eq 2) {
212
+ $choices = $script:MoshcodeCompletionTrade
213
+ } elseif ($nested -in @('buy', 'sell') -and $wordToComplete.StartsWith('-')) {
214
+ $choices = $script:MoshcodeCompletionTradeOrderOptions
215
+ }
216
+ }
217
+ 'login' { if ($wordToComplete.StartsWith('-')) { $choices = $script:MoshcodeCompletionLogin } }
218
+ { $_ -in @('engines', 'tools', 'commands') } {
219
+ if ($wordToComplete.StartsWith('-')) { $choices = $script:MoshcodeCompletionJson }
220
+ }
221
+ 'run' { if ($wordToComplete.StartsWith('-')) { $choices = $script:MoshcodeCompletionRun } }
222
+ 'console' {
223
+ if ($argumentIndex -eq 2) {
224
+ $choices = $script:MoshcodeCompletionConsole
225
+ } elseif ($nested -eq 'serve' -and $wordToComplete.StartsWith('-')) {
226
+ $choices = $script:MoshcodeCompletionConsoleServe
227
+ }
228
+ }
229
+ { $_ -in @('template', 'templates') } {
230
+ if ($argumentIndex -eq 2) {
231
+ $choices = $script:MoshcodeCompletionTemplate
232
+ } elseif ($nested -eq 'list' -and $wordToComplete.StartsWith('-')) {
233
+ $choices = $script:MoshcodeCompletionJson
234
+ } elseif ($nested -eq 'install' -and $wordToComplete.StartsWith('-')) {
235
+ $choices = $script:MoshcodeCompletionTemplateInstall
236
+ }
237
+ }
238
+ }
239
+ }
240
+
241
+ foreach ($candidate in $choices) {
242
+ if ($candidate.Name.StartsWith($wordToComplete, [System.StringComparison]::OrdinalIgnoreCase)) {
243
+ [System.Management.Automation.CompletionResult]::new(
244
+ $candidate.Name,
245
+ $candidate.Name,
246
+ [System.Management.Automation.CompletionResultType]::ParameterValue,
247
+ $candidate.Description
248
+ )
249
+ }
250
+ }
251
+ }
252
+ `;
253
+ }
254
+
255
+ function bashCompletion(model) {
256
+ return `# bash completion for moshcode
257
+ _moshcode_completion() {
258
+ local cur subcommand nested choices
259
+ COMPREPLY=()
260
+ cur="\${COMP_WORDS[COMP_CWORD]-}"
261
+ subcommand="\${COMP_WORDS[1]-}"
262
+ nested="\${COMP_WORDS[2]-}"
263
+ choices=""
264
+
265
+ if (( COMP_CWORD == 1 )); then
266
+ choices="${names(model.top)}"
267
+ else
268
+ case "$subcommand" in
269
+ agents)
270
+ if (( COMP_CWORD == 2 )); then
271
+ if [[ "$cur" == -* ]]; then choices="--json"; else choices="${names(model.engines)}"; fi
272
+ fi
273
+ ;;
274
+ start)
275
+ (( COMP_CWORD == 2 )) && choices="${names(model.engines)}"
276
+ ;;
277
+ install)
278
+ (( COMP_CWORD == 2 )) && choices="${names(model.install)}"
279
+ ;;
280
+ uninstall|remove)
281
+ if (( COMP_CWORD == 2 )); then
282
+ choices="${names(model.uninstall)}"
283
+ elif [[ "$cur" == -* ]]; then
284
+ choices="--yes -y --dry-run"
285
+ fi
286
+ ;;
287
+ upgrade|update)
288
+ choices="${names(model.upgrade)}"
289
+ ;;
290
+ completion)
291
+ (( COMP_CWORD == 2 )) && choices="${names(model.shells)}"
292
+ ;;
293
+ help)
294
+ (( COMP_CWORD == 2 )) && choices="${names(model.helpTopics)}"
295
+ ;;
296
+ mcp)
297
+ if (( COMP_CWORD == 2 )); then
298
+ choices="${names(model.mcp)}"
299
+ elif [[ "$nested" == "list" && "$cur" == -* ]]; then
300
+ choices="--json"
301
+ elif ${shellMatches("nested", model.mcpServerSpecs)} && [[ "$cur" == -* ]]; then
302
+ choices="--name --transport -t --env -e --header -H --"
303
+ fi
304
+ ;;
305
+ skill|skills)
306
+ if (( COMP_CWORD == 2 )); then
307
+ choices="${names(model.skills)}"
308
+ elif [[ "$nested" == "list" && "$cur" == -* ]]; then
309
+ choices="--json"
310
+ elif ${shellMatches("nested", model.skillSources)} && [[ "$cur" == -* ]]; then
311
+ choices="--name"
312
+ fi
313
+ ;;
314
+ trade)
315
+ if (( COMP_CWORD == 2 )); then
316
+ choices="${names(model.trade)}"
317
+ elif [[ "$nested" == "buy" || "$nested" == "sell" ]] && [[ "$cur" == -* ]]; then
318
+ choices="${names(model.tradeOrderOptions)}"
319
+ fi
320
+ ;;
321
+ login)
322
+ [[ "$cur" == -* ]] && choices="--browser -b --device -d"
323
+ ;;
324
+ engines|tools|commands)
325
+ [[ "$cur" == -* ]] && choices="--json"
326
+ ;;
327
+ run)
328
+ [[ "$cur" == -* ]] && choices="--dry-run --max -n"
329
+ ;;
330
+ console)
331
+ if (( COMP_CWORD == 2 )); then
332
+ choices="serve --url"
333
+ elif [[ "$nested" == "serve" && "$cur" == -* ]]; then
334
+ choices="--port --ttyd --bind"
335
+ fi
336
+ ;;
337
+ dns)
338
+ if (( COMP_CWORD == 2 )); then
339
+ choices="enable disable status tlds resolve start install trust"
340
+ elif [[ "$nested" == "resolve" && "$cur" == -* ]]; then
341
+ choices="--json --open --registry"
342
+ fi
343
+ ;;
344
+ template|templates)
345
+ if (( COMP_CWORD == 2 )); then
346
+ choices="list install"
347
+ elif [[ "$nested" == "list" && "$cur" == -* ]]; then
348
+ choices="--json"
349
+ elif [[ "$nested" == "install" && "$cur" == -* ]]; then
350
+ choices="--into --force --dry-run"
351
+ fi
352
+ ;;
353
+ esac
354
+ fi
355
+
356
+ if [[ -n "$choices" ]]; then
357
+ COMPREPLY=( $(compgen -W "$choices" -- "$cur") )
358
+ fi
359
+ }
360
+ complete -o bashdefault -o default -F _moshcode_completion moshcode
361
+ `;
362
+ }
363
+
364
+ function zshCompletion(model) {
365
+ return `#compdef moshcode
366
+ # zsh completion for moshcode
367
+ _moshcode() {
368
+ local -a choices
369
+
370
+ if (( CURRENT == 2 )); then
371
+ choices=(${zshValues(model.top)})
372
+ _describe "moshcode command" choices
373
+ return
374
+ fi
375
+
376
+ case "\${words[2]}" in
377
+ agents)
378
+ if (( CURRENT == 3 )); then
379
+ if [[ "$PREFIX" == -* ]]; then
380
+ _values "agent option" --json
381
+ else
382
+ choices=(${zshValues(model.engines)})
383
+ _describe "engine" choices
384
+ fi
385
+ else
386
+ _files
387
+ fi
388
+ ;;
389
+ start)
390
+ if (( CURRENT == 3 )); then
391
+ choices=(${zshValues(model.engines)})
392
+ _describe "engine" choices
393
+ else
394
+ _files
395
+ fi
396
+ ;;
397
+ install)
398
+ if (( CURRENT == 3 )); then
399
+ choices=(${zshValues(model.install)})
400
+ _describe "install target" choices
401
+ else
402
+ _files
403
+ fi
404
+ ;;
405
+ uninstall|remove)
406
+ if (( CURRENT == 3 )); then
407
+ choices=(${zshValues(model.uninstall)})
408
+ _describe "uninstall target" choices
409
+ else
410
+ _values "uninstall option" --yes -y --dry-run
411
+ fi
412
+ ;;
413
+ upgrade|update)
414
+ choices=(${zshValues(model.upgrade)})
415
+ _describe "upgrade target" choices
416
+ ;;
417
+ completion)
418
+ if (( CURRENT == 3 )); then
419
+ choices=(${zshValues(model.shells)})
420
+ _describe "shell" choices
421
+ fi
422
+ ;;
423
+ help)
424
+ if (( CURRENT == 3 )); then
425
+ choices=(${zshValues(model.helpTopics)})
426
+ _describe "help topic" choices
427
+ fi
428
+ ;;
429
+ mcp)
430
+ if (( CURRENT == 3 )); then
431
+ choices=(${zshValues(model.mcp)})
432
+ _describe "mcp command" choices
433
+ elif [[ "\${words[3]}" == "list" && "$PREFIX" == -* ]]; then
434
+ _values "mcp list option" --json
435
+ elif ${shellMatches("{words[3]}", model.mcpServerSpecs)}; then
436
+ if [[ "$PREFIX" == -* ]]; then
437
+ _values "mcp option" --name --transport -t --env -e --header -H --
438
+ else
439
+ _files
440
+ fi
441
+ fi
442
+ ;;
443
+ skill|skills)
444
+ if (( CURRENT == 3 )); then
445
+ choices=(${zshValues(model.skills)})
446
+ _describe "skill command" choices
447
+ elif [[ "\${words[3]}" == "list" && "$PREFIX" == -* ]]; then
448
+ _values "skill list option" --json
449
+ elif ${shellMatches("{words[3]}", model.skillSources)}; then
450
+ if [[ "$PREFIX" == -* ]]; then _values "skill option" --name; else _files; fi
451
+ fi
452
+ ;;
453
+ trade)
454
+ if (( CURRENT == 3 )); then
455
+ choices=(${zshValues(model.trade)})
456
+ _describe "trade command" choices
457
+ elif [[ "\${words[3]}" == "buy" || "\${words[3]}" == "sell" ]] && [[ "$PREFIX" == -* ]]; then
458
+ choices=(${zshValues(model.tradeOrderOptions)})
459
+ _describe "trade order option" choices
460
+ else
461
+ _files
462
+ fi
463
+ ;;
464
+ login)
465
+ _values "login option" --browser -b --device -d
466
+ ;;
467
+ engines|tools|commands)
468
+ _values "option" --json
469
+ ;;
470
+ run)
471
+ if [[ "$PREFIX" == -* ]]; then
472
+ _values "run option" --dry-run --max -n
473
+ else
474
+ _files
475
+ fi
476
+ ;;
477
+ console)
478
+ if (( CURRENT == 3 )); then
479
+ _values "console command" serve --url
480
+ elif [[ "\${words[3]}" == "serve" && "$PREFIX" == -* ]]; then
481
+ _values "console option" --port --ttyd --bind
482
+ else
483
+ _files
484
+ fi
485
+ ;;
486
+ dns)
487
+ if (( CURRENT == 3 )); then
488
+ _values "dns command" enable disable status tlds resolve start install trust
489
+ elif [[ "\${words[3]}" == "resolve" && "$PREFIX" == -* ]]; then
490
+ _values "dns resolve option" --json --open --registry
491
+ else
492
+ _files
493
+ fi
494
+ ;;
495
+ template|templates)
496
+ if (( CURRENT == 3 )); then
497
+ _values "template command" list install
498
+ elif [[ "\${words[3]}" == "list" && "$PREFIX" == -* ]]; then
499
+ _values "template list option" --json
500
+ elif [[ "\${words[3]}" == "install" && "$PREFIX" == -* ]]; then
501
+ _values "template install option" --into --force --dry-run
502
+ else
503
+ _files
504
+ fi
505
+ ;;
506
+ *)
507
+ _files
508
+ ;;
509
+ esac
510
+ }
511
+
512
+ if (( ! $+functions[compdef] )); then
513
+ autoload -Uz compinit
514
+ compinit
515
+ fi
516
+ compdef _moshcode moshcode
517
+ `;
518
+ }
519
+
520
+ function fishCompletion(model) {
521
+ const atFirstArgument = "__fish_use_subcommand";
522
+ const atSecondToken = (commands) => (
523
+ `__moshcode_command_is ${commands}; and __moshcode_arg_index 2`
524
+ );
525
+ const nestedCondition = (command, entries) => (
526
+ entries.map(({ name }) => `__moshcode_nested_is ${command} ${name}`).join("; or ")
527
+ );
528
+
529
+ return `# fish completion for moshcode
530
+ function __moshcode_command_is
531
+ set -l tokens (commandline -opc)
532
+ test (count $tokens) -ge 2; and contains -- $tokens[2] $argv
533
+ end
534
+
535
+ function __moshcode_nested_is
536
+ set -l tokens (commandline -opc)
537
+ test (count $tokens) -ge 3; and test "$tokens[2]" = "$argv[1]"; and test "$tokens[3]" = "$argv[2]"
538
+ end
539
+
540
+ function __moshcode_arg_index
541
+ test (count (commandline -opc)) -eq $argv[1]
542
+ end
543
+
544
+ ${fishEntries(atFirstArgument, model.top)}
545
+ ${fishEntries(atSecondToken("agents start"), model.engines)}
546
+ ${fishEntries(atSecondToken("install"), model.install)}
547
+ ${fishEntries(atSecondToken("uninstall remove"), model.uninstall)}
548
+ ${fishEntries("__moshcode_command_is upgrade update", model.upgrade)}
549
+ ${fishEntries(atSecondToken("completion"), model.shells)}
550
+ ${fishEntries(atSecondToken("help"), model.helpTopics)}
551
+ ${fishEntries(atSecondToken("mcp"), model.mcp)}
552
+ ${fishEntries(atSecondToken("skill skills"), model.skills)}
553
+ ${fishEntries(atSecondToken("trade"), model.trade)}
554
+ ${fishEntries("__moshcode_nested_is trade buy; or __moshcode_nested_is trade sell", model.tradeOrderOptions)}
555
+ complete -c moshcode -n '__moshcode_nested_is mcp list' -l json -d 'print JSON'
556
+ complete -c moshcode -n '__moshcode_nested_is skill list; or __moshcode_nested_is skills list' -l json -d 'print JSON'
557
+ complete -c moshcode -n '__moshcode_command_is login' -l browser -s b -d 'use browser authentication'
558
+ complete -c moshcode -n '__moshcode_command_is login' -l device -s d -d 'use device-code authentication'
559
+ complete -c moshcode -n '${atSecondToken("agents engines tools commands")}' -l json -d 'print JSON'
560
+ complete -c moshcode -n '__moshcode_command_is run' -l dry-run -d 'show actions without executing'
561
+ complete -c moshcode -n '__moshcode_command_is run' -l max -s n -r -d 'maximum loop count'
562
+ complete -c moshcode -n '__moshcode_command_is uninstall remove' -l yes -s y -d 'confirm deleting a binary'
563
+ complete -c moshcode -n '__moshcode_command_is uninstall remove' -l dry-run -d 'show the plan without removing'
564
+ complete -c moshcode -n '${atSecondToken("console")}' -a 'serve' -d 'serve a browser terminal'
565
+ complete -c moshcode -n '${atSecondToken("console")}' -a '--url' -d 'print a gateway URL'
566
+ complete -c moshcode -n '__moshcode_nested_is console serve' -l port -r -d 'local HTTP port'
567
+ complete -c moshcode -n '__moshcode_nested_is console serve' -l ttyd -r -d 'ttyd host and port'
568
+ complete -c moshcode -n '__moshcode_nested_is console serve' -l bind -r -d 'bind address'
569
+ complete -c moshcode -n '${atSecondToken("dns")}' -a 'enable disable status tlds resolve start install trust' -d 'dns command'
570
+ complete -c moshcode -n '__moshcode_nested_is dns resolve' -l json -d 'print JSON'
571
+ complete -c moshcode -n '__moshcode_nested_is dns resolve' -l open -d 'open a parked name in the Pit'
572
+ complete -c moshcode -n '__moshcode_nested_is dns resolve' -l registry -r -d 'registry base URL'
573
+ complete -c moshcode -n '${atSecondToken("template templates")}' -a 'list install' -d 'template command'
574
+ complete -c moshcode -n '__moshcode_nested_is template list; or __moshcode_nested_is templates list' -l json -d 'print JSON'
575
+ complete -c moshcode -n '__moshcode_nested_is template install; or __moshcode_nested_is templates install' -l into -r -d 'target directory'
576
+ complete -c moshcode -n '__moshcode_nested_is template install; or __moshcode_nested_is templates install' -l force -d 'overwrite existing files'
577
+ complete -c moshcode -n '__moshcode_nested_is template install; or __moshcode_nested_is templates install' -l dry-run -d 'preview without writing'
578
+ complete -c moshcode -n '${nestedCondition("mcp", model.mcpServerSpecs)}' -l name -r -d 'server name'
579
+ complete -c moshcode -n '${nestedCondition("mcp", model.mcpServerSpecs)}' -l transport -s t -r -d 'MCP transport'
580
+ complete -c moshcode -n '${nestedCondition("mcp", model.mcpServerSpecs)}' -l env -s e -r -d 'environment KEY=VALUE'
581
+ complete -c moshcode -n '${nestedCondition("mcp", model.mcpServerSpecs)}' -l header -s H -r -d 'HTTP Name: Value header'
582
+ complete -c moshcode -n '${nestedCondition("skill", model.skillSources)}; or ${nestedCondition("skills", model.skillSources)}' -l name -r -d 'installed skill name'
583
+ `;
584
+ }
585
+
586
+ export function completionScript(shell) {
587
+ const normalized = String(shell || "").trim().toLowerCase();
588
+ const model = completionModel();
589
+ if (normalized === "bash") return bashCompletion(model);
590
+ if (normalized === "zsh") return zshCompletion(model);
591
+ if (normalized === "fish") return fishCompletion(model);
592
+ if (normalized === "powershell" || normalized === "pwsh") return powershellCompletion(model);
593
+ throw new Error(`unsupported shell ${JSON.stringify(shell)}; choose: ${COMPLETION_SHELLS.join(", ")}`);
594
+ }