@pleri/olam-cli 0.1.108 → 0.1.110
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/completion.d.ts +30 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +53 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/image-digests.json +1 -1
- package/dist/index.js +125 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/completion-generator.d.ts +107 -0
- package/dist/lib/completion-generator.d.ts.map +1 -0
- package/dist/lib/completion-generator.js +226 -0
- package/dist/lib/completion-generator.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* olam completion <shell> — emit shell completion script.
|
|
3
|
+
*
|
|
4
|
+
* Phase B2 of olam-operator-onboarding-parity (plan
|
|
5
|
+
* ~/.claude/plans/olam-operator-onboarding-parity.md).
|
|
6
|
+
*
|
|
7
|
+
* Wraps the runtime-emit generator at `../lib/completion-generator.ts`
|
|
8
|
+
* (Decision 4 — runtime-emit from commander tree, not static fixtures).
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* olam completion zsh # → stdout: #compdef olam + _olam() function
|
|
12
|
+
* olam completion bash # → stdout: _olam_completions() + complete -F binding
|
|
13
|
+
* olam completion fish # → stderr: "Unsupported shell..."; exit 1
|
|
14
|
+
*
|
|
15
|
+
* Pipe to `eval` in shell rc OR let Phase C's `olam setup` do the
|
|
16
|
+
* idempotent shell-rc append for you:
|
|
17
|
+
* echo 'eval "$(olam completion zsh)"' >> ~/.zshrc
|
|
18
|
+
*/
|
|
19
|
+
import type { Command } from 'commander';
|
|
20
|
+
/**
|
|
21
|
+
* Register `olam completion <shell>` on the given commander program.
|
|
22
|
+
*
|
|
23
|
+
* Captures `program` in the closure so the action handler can walk the
|
|
24
|
+
* full command tree at invoke time. Using `program.parent ?? program`
|
|
25
|
+
* keeps the implementation working when commands inject their subcommands
|
|
26
|
+
* via a different parent — though in olam's current shape, `program` IS
|
|
27
|
+
* always the root, so the parent fallback is defence-in-depth.
|
|
28
|
+
*/
|
|
29
|
+
export declare function registerCompletion(program: Command): void;
|
|
30
|
+
//# sourceMappingURL=completion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../src/commands/completion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwBzD"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* olam completion <shell> — emit shell completion script.
|
|
3
|
+
*
|
|
4
|
+
* Phase B2 of olam-operator-onboarding-parity (plan
|
|
5
|
+
* ~/.claude/plans/olam-operator-onboarding-parity.md).
|
|
6
|
+
*
|
|
7
|
+
* Wraps the runtime-emit generator at `../lib/completion-generator.ts`
|
|
8
|
+
* (Decision 4 — runtime-emit from commander tree, not static fixtures).
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* olam completion zsh # → stdout: #compdef olam + _olam() function
|
|
12
|
+
* olam completion bash # → stdout: _olam_completions() + complete -F binding
|
|
13
|
+
* olam completion fish # → stderr: "Unsupported shell..."; exit 1
|
|
14
|
+
*
|
|
15
|
+
* Pipe to `eval` in shell rc OR let Phase C's `olam setup` do the
|
|
16
|
+
* idempotent shell-rc append for you:
|
|
17
|
+
* echo 'eval "$(olam completion zsh)"' >> ~/.zshrc
|
|
18
|
+
*/
|
|
19
|
+
import { generateCompletion, UnsupportedShellError } from '../lib/completion-generator.js';
|
|
20
|
+
/**
|
|
21
|
+
* Register `olam completion <shell>` on the given commander program.
|
|
22
|
+
*
|
|
23
|
+
* Captures `program` in the closure so the action handler can walk the
|
|
24
|
+
* full command tree at invoke time. Using `program.parent ?? program`
|
|
25
|
+
* keeps the implementation working when commands inject their subcommands
|
|
26
|
+
* via a different parent — though in olam's current shape, `program` IS
|
|
27
|
+
* always the root, so the parent fallback is defence-in-depth.
|
|
28
|
+
*/
|
|
29
|
+
export function registerCompletion(program) {
|
|
30
|
+
program
|
|
31
|
+
.command('completion')
|
|
32
|
+
.description('Emit a POSIX shell completion script for zsh or bash. '
|
|
33
|
+
+ 'Pipe to `eval` in your shell rc, or let `olam setup` append it idempotently. '
|
|
34
|
+
+ 'Completes top-level commands + one nested level (`olam kg <Tab>`); deeper '
|
|
35
|
+
+ 'subcommand trees (`olam world snapshot <Tab>`) fall through without completion.')
|
|
36
|
+
.argument('<shell>', 'zsh | bash')
|
|
37
|
+
.action((shell) => {
|
|
38
|
+
const tree = program.parent ?? program;
|
|
39
|
+
try {
|
|
40
|
+
const output = generateCompletion(tree, shell);
|
|
41
|
+
process.stdout.write(output);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
if (err instanceof UnsupportedShellError) {
|
|
45
|
+
process.stderr.write(`${err.message}\n`);
|
|
46
|
+
process.exitCode = 1;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
throw err;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=completion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion.js","sourceRoot":"","sources":["../../src/commands/completion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAI3F;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IACjD,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CACV,wDAAwD;UACpD,+EAA+E;UAC/E,4EAA4E;UAC5E,iFAAiF,CACtF;SACA,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;SACjC,MAAM,CAAC,CAAC,KAAa,EAAE,EAAE;QACxB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,EAAE,KAAuB,CAAC,CAAC;YACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,qBAAqB,EAAE,CAAC;gBACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;gBACzC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;gBACrB,OAAO;YACT,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/dist/image-digests.json
CHANGED
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"host-cp": "sha256:0ad4bda950a29422125199a8b3aa6a83831f89c4fa8a8a94e0fd9d49446e743c",
|
|
6
6
|
"mcp-auth": "sha256:c82fcfca7ed1b139cbea252697487889b96b45a6575cfba076de7f57eaa943ac",
|
|
7
7
|
"$schema_version": 1,
|
|
8
|
-
"$published_version": "0.1.
|
|
8
|
+
"$published_version": "0.1.110",
|
|
9
9
|
"$registry": "ghcr.io/pleri"
|
|
10
10
|
}
|
package/dist/index.js
CHANGED
|
@@ -25369,6 +25369,130 @@ function registerDoctor(program2) {
|
|
|
25369
25369
|
});
|
|
25370
25370
|
}
|
|
25371
25371
|
|
|
25372
|
+
// src/lib/completion-generator.ts
|
|
25373
|
+
var UnsupportedShellError = class extends Error {
|
|
25374
|
+
constructor(shell) {
|
|
25375
|
+
super(`Unsupported shell: ${shell}. Supported shells: zsh, bash.`);
|
|
25376
|
+
this.name = "UnsupportedShellError";
|
|
25377
|
+
}
|
|
25378
|
+
};
|
|
25379
|
+
function extractCommandTree(program2) {
|
|
25380
|
+
return {
|
|
25381
|
+
name: program2.name(),
|
|
25382
|
+
description: program2.description() ?? "",
|
|
25383
|
+
subcommands: program2.commands.filter((c) => !isHidden(c)).map((c) => extractCommandTree(c))
|
|
25384
|
+
};
|
|
25385
|
+
}
|
|
25386
|
+
function isHidden(cmd) {
|
|
25387
|
+
const c = cmd;
|
|
25388
|
+
return c._hidden === true;
|
|
25389
|
+
}
|
|
25390
|
+
function escapeZsh(s) {
|
|
25391
|
+
return s.replace(/[\r\n]+/g, " ").replace(/'/g, "''").replace(/:/g, "\\:");
|
|
25392
|
+
}
|
|
25393
|
+
function escapeBash(s) {
|
|
25394
|
+
return s.replace(/[\r\n]+/g, " ").replace(/(["\\$`])/g, "\\$1");
|
|
25395
|
+
}
|
|
25396
|
+
function generateZshCompletion(tree) {
|
|
25397
|
+
const lines = [];
|
|
25398
|
+
lines.push(`#compdef ${tree.name}`);
|
|
25399
|
+
lines.push("");
|
|
25400
|
+
lines.push(`_${tree.name}() {`);
|
|
25401
|
+
lines.push(" local -a l1_subs");
|
|
25402
|
+
lines.push(" l1_subs=(");
|
|
25403
|
+
for (const sub of tree.subcommands) {
|
|
25404
|
+
lines.push(` '${sub.name}:${escapeZsh(sub.description)}'`);
|
|
25405
|
+
}
|
|
25406
|
+
lines.push(" )");
|
|
25407
|
+
lines.push("");
|
|
25408
|
+
lines.push(" if (( CURRENT == 2 )); then");
|
|
25409
|
+
lines.push(` _describe '${tree.name} command' l1_subs`);
|
|
25410
|
+
lines.push(" return");
|
|
25411
|
+
lines.push(" fi");
|
|
25412
|
+
lines.push("");
|
|
25413
|
+
const subsWithChildren = tree.subcommands.filter((s) => s.subcommands.length > 0);
|
|
25414
|
+
if (subsWithChildren.length > 0) {
|
|
25415
|
+
lines.push(" case $words[2] in");
|
|
25416
|
+
for (const sub of subsWithChildren) {
|
|
25417
|
+
lines.push(` ${sub.name})`);
|
|
25418
|
+
lines.push(" if (( CURRENT == 3 )); then");
|
|
25419
|
+
lines.push(" local -a l2_subs");
|
|
25420
|
+
lines.push(" l2_subs=(");
|
|
25421
|
+
for (const s2 of sub.subcommands) {
|
|
25422
|
+
lines.push(` '${s2.name}:${escapeZsh(s2.description)}'`);
|
|
25423
|
+
}
|
|
25424
|
+
lines.push(" )");
|
|
25425
|
+
lines.push(` _describe '${sub.name} subcommand' l2_subs`);
|
|
25426
|
+
lines.push(" fi");
|
|
25427
|
+
lines.push(" ;;");
|
|
25428
|
+
}
|
|
25429
|
+
lines.push(" esac");
|
|
25430
|
+
}
|
|
25431
|
+
lines.push("}");
|
|
25432
|
+
lines.push("");
|
|
25433
|
+
lines.push(`_${tree.name} "$@"`);
|
|
25434
|
+
lines.push("");
|
|
25435
|
+
return lines.join("\n");
|
|
25436
|
+
}
|
|
25437
|
+
function generateBashCompletion(tree) {
|
|
25438
|
+
const lines = [];
|
|
25439
|
+
lines.push(`_${tree.name}_completions() {`);
|
|
25440
|
+
lines.push(' local cur="${COMP_WORDS[COMP_CWORD]}"');
|
|
25441
|
+
lines.push(" local cword=$COMP_CWORD");
|
|
25442
|
+
lines.push("");
|
|
25443
|
+
lines.push(" if [[ $cword -eq 1 ]]; then");
|
|
25444
|
+
const l1Names = tree.subcommands.map((s) => s.name).join(" ");
|
|
25445
|
+
lines.push(` COMPREPLY=( $(compgen -W "${escapeBash(l1Names)}" -- "$cur") )`);
|
|
25446
|
+
lines.push(" return");
|
|
25447
|
+
lines.push(" fi");
|
|
25448
|
+
lines.push("");
|
|
25449
|
+
const subsWithChildren = tree.subcommands.filter((s) => s.subcommands.length > 0);
|
|
25450
|
+
if (subsWithChildren.length > 0) {
|
|
25451
|
+
lines.push(' case "${COMP_WORDS[1]}" in');
|
|
25452
|
+
for (const sub of subsWithChildren) {
|
|
25453
|
+
lines.push(` ${sub.name})`);
|
|
25454
|
+
lines.push(" if [[ $cword -eq 2 ]]; then");
|
|
25455
|
+
const l2Names = sub.subcommands.map((s) => s.name).join(" ");
|
|
25456
|
+
lines.push(` COMPREPLY=( $(compgen -W "${escapeBash(l2Names)}" -- "$cur") )`);
|
|
25457
|
+
lines.push(" fi");
|
|
25458
|
+
lines.push(" ;;");
|
|
25459
|
+
}
|
|
25460
|
+
lines.push(" esac");
|
|
25461
|
+
}
|
|
25462
|
+
lines.push("}");
|
|
25463
|
+
lines.push("");
|
|
25464
|
+
lines.push(`complete -F _${tree.name}_completions ${tree.name}`);
|
|
25465
|
+
lines.push("");
|
|
25466
|
+
return lines.join("\n");
|
|
25467
|
+
}
|
|
25468
|
+
function generateCompletion(program2, shell) {
|
|
25469
|
+
const tree = extractCommandTree(program2);
|
|
25470
|
+
if (shell === "zsh") return generateZshCompletion(tree);
|
|
25471
|
+
if (shell === "bash") return generateBashCompletion(tree);
|
|
25472
|
+
throw new UnsupportedShellError(shell);
|
|
25473
|
+
}
|
|
25474
|
+
|
|
25475
|
+
// src/commands/completion.ts
|
|
25476
|
+
function registerCompletion(program2) {
|
|
25477
|
+
program2.command("completion").description(
|
|
25478
|
+
"Emit a POSIX shell completion script for zsh or bash. Pipe to `eval` in your shell rc, or let `olam setup` append it idempotently. Completes top-level commands + one nested level (`olam kg <Tab>`); deeper subcommand trees (`olam world snapshot <Tab>`) fall through without completion."
|
|
25479
|
+
).argument("<shell>", "zsh | bash").action((shell) => {
|
|
25480
|
+
const tree = program2.parent ?? program2;
|
|
25481
|
+
try {
|
|
25482
|
+
const output = generateCompletion(tree, shell);
|
|
25483
|
+
process.stdout.write(output);
|
|
25484
|
+
} catch (err) {
|
|
25485
|
+
if (err instanceof UnsupportedShellError) {
|
|
25486
|
+
process.stderr.write(`${err.message}
|
|
25487
|
+
`);
|
|
25488
|
+
process.exitCode = 1;
|
|
25489
|
+
return;
|
|
25490
|
+
}
|
|
25491
|
+
throw err;
|
|
25492
|
+
}
|
|
25493
|
+
});
|
|
25494
|
+
}
|
|
25495
|
+
|
|
25372
25496
|
// src/commands/update.ts
|
|
25373
25497
|
import * as fs42 from "node:fs";
|
|
25374
25498
|
import * as os25 from "node:os";
|
|
@@ -27323,6 +27447,7 @@ registerRefresh(program);
|
|
|
27323
27447
|
registerBootstrap(program);
|
|
27324
27448
|
registerDiagnose(program);
|
|
27325
27449
|
registerDoctor(program);
|
|
27450
|
+
registerCompletion(program);
|
|
27326
27451
|
registerUpdate(program);
|
|
27327
27452
|
registerBegin(program);
|
|
27328
27453
|
registerStop(program);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* completion-generator.ts — Commander command-tree → POSIX shell completion script.
|
|
3
|
+
*
|
|
4
|
+
* Phase B1 of olam-operator-onboarding-parity (plan
|
|
5
|
+
* ~/.claude/plans/olam-operator-onboarding-parity.md).
|
|
6
|
+
*
|
|
7
|
+
* Decision 4 (plan): runtime-emit from the commander tree, NOT static
|
|
8
|
+
* fixtures in the tarball. One source of truth: new CLI commands auto-
|
|
9
|
+
* included in the next `olam completion <shell>` invocation.
|
|
10
|
+
*
|
|
11
|
+
* Supported shells: zsh + bash. Other shells throw `UnsupportedShellError`.
|
|
12
|
+
*
|
|
13
|
+
* Nesting depth: TWO levels of subcommand dispatch (top-level + one
|
|
14
|
+
* nested). Covers ~95% of olam's tree (`olam kg build`, `olam auth login`,
|
|
15
|
+
* `olam workspace list`, etc.). Deeper nesting (`olam world snapshot
|
|
16
|
+
* restore`) falls through gracefully — top + one level still complete.
|
|
17
|
+
*
|
|
18
|
+
* Escaping:
|
|
19
|
+
* - zsh: descriptions inside `name:description` syntax need `:` escaped
|
|
20
|
+
* (since `:` is the field separator) and `'` doubled (since strings
|
|
21
|
+
* are single-quoted).
|
|
22
|
+
* - bash: descriptions inside double-quoted strings need `"`, `\`, `$`,
|
|
23
|
+
* and backtick escaped.
|
|
24
|
+
*
|
|
25
|
+
* Hidden commands (commander's private `_hidden` flag) are excluded:
|
|
26
|
+
* - `olam crystallize` is registered with `{ hidden: !isPleriConfigured() }`
|
|
27
|
+
* for fresh-install operators.
|
|
28
|
+
*
|
|
29
|
+
* Determinism: commander preserves command-registration order in
|
|
30
|
+
* `Command.commands`. The walk is a pure-functional map → the output is
|
|
31
|
+
* a deterministic function of the program tree. Snapshot tests rely on
|
|
32
|
+
* this.
|
|
33
|
+
*/
|
|
34
|
+
import type { Command } from 'commander';
|
|
35
|
+
export interface CommandNode {
|
|
36
|
+
readonly name: string;
|
|
37
|
+
readonly description: string;
|
|
38
|
+
readonly subcommands: ReadonlyArray<CommandNode>;
|
|
39
|
+
}
|
|
40
|
+
export declare class UnsupportedShellError extends Error {
|
|
41
|
+
constructor(shell: string);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Walk a commander `Command` recursively, extracting (name, description,
|
|
45
|
+
* subcommands). Hidden commands (commander's private `_hidden` flag,
|
|
46
|
+
* set via `.command(..., { hidden: true })`) are excluded.
|
|
47
|
+
*/
|
|
48
|
+
export declare function extractCommandTree(program: Command): CommandNode;
|
|
49
|
+
/**
|
|
50
|
+
* Emit a zsh completion script.
|
|
51
|
+
*
|
|
52
|
+
* Format:
|
|
53
|
+
* #compdef <program>
|
|
54
|
+
*
|
|
55
|
+
* _<program>() {
|
|
56
|
+
* local -a l1_subs
|
|
57
|
+
* l1_subs=(
|
|
58
|
+
* '<sub>:<description>'
|
|
59
|
+
* ...
|
|
60
|
+
* )
|
|
61
|
+
* if (( CURRENT == 2 )); then
|
|
62
|
+
* _describe '<program> command' l1_subs
|
|
63
|
+
* return
|
|
64
|
+
* fi
|
|
65
|
+
* case $words[2] in
|
|
66
|
+
* <sub-with-children>)
|
|
67
|
+
* if (( CURRENT == 3 )); then
|
|
68
|
+
* local -a l2_subs
|
|
69
|
+
* l2_subs=(...)
|
|
70
|
+
* _describe '<sub> subcommand' l2_subs
|
|
71
|
+
* fi
|
|
72
|
+
* ;;
|
|
73
|
+
* ...
|
|
74
|
+
* esac
|
|
75
|
+
* }
|
|
76
|
+
*
|
|
77
|
+
* _<program> "$@"
|
|
78
|
+
*/
|
|
79
|
+
export declare function generateZshCompletion(tree: CommandNode): string;
|
|
80
|
+
/**
|
|
81
|
+
* Emit a bash completion script.
|
|
82
|
+
*
|
|
83
|
+
* Format:
|
|
84
|
+
* _<program>_completions() {
|
|
85
|
+
* local cur="${COMP_WORDS[COMP_CWORD]}"
|
|
86
|
+
* local cword=$COMP_CWORD
|
|
87
|
+
* if [[ $cword -eq 1 ]]; then
|
|
88
|
+
* COMPREPLY=( $(compgen -W "<sub1> <sub2> ..." -- "$cur") )
|
|
89
|
+
* return
|
|
90
|
+
* fi
|
|
91
|
+
* case "${COMP_WORDS[1]}" in
|
|
92
|
+
* <sub-with-children>)
|
|
93
|
+
* if [[ $cword -eq 2 ]]; then
|
|
94
|
+
* COMPREPLY=( $(compgen -W "<l2-1> <l2-2> ..." -- "$cur") )
|
|
95
|
+
* fi
|
|
96
|
+
* ;;
|
|
97
|
+
* esac
|
|
98
|
+
* }
|
|
99
|
+
* complete -F _<program>_completions <program>
|
|
100
|
+
*/
|
|
101
|
+
export declare function generateBashCompletion(tree: CommandNode): string;
|
|
102
|
+
/**
|
|
103
|
+
* Top-level API: walk the commander program + emit a completion script
|
|
104
|
+
* for the requested shell.
|
|
105
|
+
*/
|
|
106
|
+
export declare function generateCompletion(program: Command, shell: 'zsh' | 'bash'): string;
|
|
107
|
+
//# sourceMappingURL=completion-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion-generator.d.ts","sourceRoot":"","sources":["../../src/lib/completion-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;CAClD;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,KAAK,EAAE,MAAM;CAI1B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,CAQhE;AA0CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CA0C/D;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAgChE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAKlF"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* completion-generator.ts — Commander command-tree → POSIX shell completion script.
|
|
3
|
+
*
|
|
4
|
+
* Phase B1 of olam-operator-onboarding-parity (plan
|
|
5
|
+
* ~/.claude/plans/olam-operator-onboarding-parity.md).
|
|
6
|
+
*
|
|
7
|
+
* Decision 4 (plan): runtime-emit from the commander tree, NOT static
|
|
8
|
+
* fixtures in the tarball. One source of truth: new CLI commands auto-
|
|
9
|
+
* included in the next `olam completion <shell>` invocation.
|
|
10
|
+
*
|
|
11
|
+
* Supported shells: zsh + bash. Other shells throw `UnsupportedShellError`.
|
|
12
|
+
*
|
|
13
|
+
* Nesting depth: TWO levels of subcommand dispatch (top-level + one
|
|
14
|
+
* nested). Covers ~95% of olam's tree (`olam kg build`, `olam auth login`,
|
|
15
|
+
* `olam workspace list`, etc.). Deeper nesting (`olam world snapshot
|
|
16
|
+
* restore`) falls through gracefully — top + one level still complete.
|
|
17
|
+
*
|
|
18
|
+
* Escaping:
|
|
19
|
+
* - zsh: descriptions inside `name:description` syntax need `:` escaped
|
|
20
|
+
* (since `:` is the field separator) and `'` doubled (since strings
|
|
21
|
+
* are single-quoted).
|
|
22
|
+
* - bash: descriptions inside double-quoted strings need `"`, `\`, `$`,
|
|
23
|
+
* and backtick escaped.
|
|
24
|
+
*
|
|
25
|
+
* Hidden commands (commander's private `_hidden` flag) are excluded:
|
|
26
|
+
* - `olam crystallize` is registered with `{ hidden: !isPleriConfigured() }`
|
|
27
|
+
* for fresh-install operators.
|
|
28
|
+
*
|
|
29
|
+
* Determinism: commander preserves command-registration order in
|
|
30
|
+
* `Command.commands`. The walk is a pure-functional map → the output is
|
|
31
|
+
* a deterministic function of the program tree. Snapshot tests rely on
|
|
32
|
+
* this.
|
|
33
|
+
*/
|
|
34
|
+
export class UnsupportedShellError extends Error {
|
|
35
|
+
constructor(shell) {
|
|
36
|
+
super(`Unsupported shell: ${shell}. Supported shells: zsh, bash.`);
|
|
37
|
+
this.name = 'UnsupportedShellError';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Walk a commander `Command` recursively, extracting (name, description,
|
|
42
|
+
* subcommands). Hidden commands (commander's private `_hidden` flag,
|
|
43
|
+
* set via `.command(..., { hidden: true })`) are excluded.
|
|
44
|
+
*/
|
|
45
|
+
export function extractCommandTree(program) {
|
|
46
|
+
return {
|
|
47
|
+
name: program.name(),
|
|
48
|
+
description: program.description() ?? '',
|
|
49
|
+
subcommands: program.commands
|
|
50
|
+
.filter((c) => !isHidden(c))
|
|
51
|
+
.map((c) => extractCommandTree(c)),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function isHidden(cmd) {
|
|
55
|
+
// Commander stores hidden flag privately. Access defensively in case
|
|
56
|
+
// the field name changes across versions.
|
|
57
|
+
const c = cmd;
|
|
58
|
+
return c._hidden === true;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Escape a description string for zsh's `name:description` completion
|
|
62
|
+
* syntax. Three transformations:
|
|
63
|
+
* 1. Collapse newlines + carriage returns to single spaces (multi-line
|
|
64
|
+
* descriptions break single-quoted `'name:description'` syntax —
|
|
65
|
+
* a literal `\n` in the source string forces the next line to start
|
|
66
|
+
* a new entry without a leading quote → zsh parse error → operator's
|
|
67
|
+
* shell rc fails to load; audit finding B-ADV-3).
|
|
68
|
+
* 2. Double single quotes (single-quoted-string termination).
|
|
69
|
+
* 3. Backslash-escape colons (field separator in `name:description`).
|
|
70
|
+
*/
|
|
71
|
+
function escapeZsh(s) {
|
|
72
|
+
return s
|
|
73
|
+
.replace(/[\r\n]+/g, ' ')
|
|
74
|
+
.replace(/'/g, "''")
|
|
75
|
+
.replace(/:/g, '\\:');
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Escape a string for bash double-quoted contexts. Three transformations:
|
|
79
|
+
* 1. Collapse newlines + carriage returns to single spaces (bash
|
|
80
|
+
* double-quoted strings tolerate `\n` but `compgen -W` interprets
|
|
81
|
+
* whitespace as word boundaries — a newline silently splits the
|
|
82
|
+
* word list; audit finding B-ADV-3).
|
|
83
|
+
* 2. Backslash-escape `"`, `\`, `$`, backtick (the four chars bash
|
|
84
|
+
* interprets inside double quotes).
|
|
85
|
+
*/
|
|
86
|
+
function escapeBash(s) {
|
|
87
|
+
return s
|
|
88
|
+
.replace(/[\r\n]+/g, ' ')
|
|
89
|
+
.replace(/(["\\$`])/g, '\\$1');
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Emit a zsh completion script.
|
|
93
|
+
*
|
|
94
|
+
* Format:
|
|
95
|
+
* #compdef <program>
|
|
96
|
+
*
|
|
97
|
+
* _<program>() {
|
|
98
|
+
* local -a l1_subs
|
|
99
|
+
* l1_subs=(
|
|
100
|
+
* '<sub>:<description>'
|
|
101
|
+
* ...
|
|
102
|
+
* )
|
|
103
|
+
* if (( CURRENT == 2 )); then
|
|
104
|
+
* _describe '<program> command' l1_subs
|
|
105
|
+
* return
|
|
106
|
+
* fi
|
|
107
|
+
* case $words[2] in
|
|
108
|
+
* <sub-with-children>)
|
|
109
|
+
* if (( CURRENT == 3 )); then
|
|
110
|
+
* local -a l2_subs
|
|
111
|
+
* l2_subs=(...)
|
|
112
|
+
* _describe '<sub> subcommand' l2_subs
|
|
113
|
+
* fi
|
|
114
|
+
* ;;
|
|
115
|
+
* ...
|
|
116
|
+
* esac
|
|
117
|
+
* }
|
|
118
|
+
*
|
|
119
|
+
* _<program> "$@"
|
|
120
|
+
*/
|
|
121
|
+
export function generateZshCompletion(tree) {
|
|
122
|
+
const lines = [];
|
|
123
|
+
lines.push(`#compdef ${tree.name}`);
|
|
124
|
+
lines.push('');
|
|
125
|
+
lines.push(`_${tree.name}() {`);
|
|
126
|
+
lines.push(' local -a l1_subs');
|
|
127
|
+
lines.push(' l1_subs=(');
|
|
128
|
+
for (const sub of tree.subcommands) {
|
|
129
|
+
lines.push(` '${sub.name}:${escapeZsh(sub.description)}'`);
|
|
130
|
+
}
|
|
131
|
+
lines.push(' )');
|
|
132
|
+
lines.push('');
|
|
133
|
+
lines.push(' if (( CURRENT == 2 )); then');
|
|
134
|
+
lines.push(` _describe '${tree.name} command' l1_subs`);
|
|
135
|
+
lines.push(' return');
|
|
136
|
+
lines.push(' fi');
|
|
137
|
+
lines.push('');
|
|
138
|
+
const subsWithChildren = tree.subcommands.filter((s) => s.subcommands.length > 0);
|
|
139
|
+
if (subsWithChildren.length > 0) {
|
|
140
|
+
lines.push(' case $words[2] in');
|
|
141
|
+
for (const sub of subsWithChildren) {
|
|
142
|
+
lines.push(` ${sub.name})`);
|
|
143
|
+
lines.push(' if (( CURRENT == 3 )); then');
|
|
144
|
+
lines.push(' local -a l2_subs');
|
|
145
|
+
lines.push(' l2_subs=(');
|
|
146
|
+
for (const s2 of sub.subcommands) {
|
|
147
|
+
lines.push(` '${s2.name}:${escapeZsh(s2.description)}'`);
|
|
148
|
+
}
|
|
149
|
+
lines.push(' )');
|
|
150
|
+
lines.push(` _describe '${sub.name} subcommand' l2_subs`);
|
|
151
|
+
lines.push(' fi');
|
|
152
|
+
lines.push(' ;;');
|
|
153
|
+
}
|
|
154
|
+
lines.push(' esac');
|
|
155
|
+
}
|
|
156
|
+
lines.push('}');
|
|
157
|
+
lines.push('');
|
|
158
|
+
lines.push(`_${tree.name} "$@"`);
|
|
159
|
+
lines.push('');
|
|
160
|
+
return lines.join('\n');
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Emit a bash completion script.
|
|
164
|
+
*
|
|
165
|
+
* Format:
|
|
166
|
+
* _<program>_completions() {
|
|
167
|
+
* local cur="${COMP_WORDS[COMP_CWORD]}"
|
|
168
|
+
* local cword=$COMP_CWORD
|
|
169
|
+
* if [[ $cword -eq 1 ]]; then
|
|
170
|
+
* COMPREPLY=( $(compgen -W "<sub1> <sub2> ..." -- "$cur") )
|
|
171
|
+
* return
|
|
172
|
+
* fi
|
|
173
|
+
* case "${COMP_WORDS[1]}" in
|
|
174
|
+
* <sub-with-children>)
|
|
175
|
+
* if [[ $cword -eq 2 ]]; then
|
|
176
|
+
* COMPREPLY=( $(compgen -W "<l2-1> <l2-2> ..." -- "$cur") )
|
|
177
|
+
* fi
|
|
178
|
+
* ;;
|
|
179
|
+
* esac
|
|
180
|
+
* }
|
|
181
|
+
* complete -F _<program>_completions <program>
|
|
182
|
+
*/
|
|
183
|
+
export function generateBashCompletion(tree) {
|
|
184
|
+
const lines = [];
|
|
185
|
+
lines.push(`_${tree.name}_completions() {`);
|
|
186
|
+
lines.push(' local cur="${COMP_WORDS[COMP_CWORD]}"');
|
|
187
|
+
lines.push(' local cword=$COMP_CWORD');
|
|
188
|
+
lines.push('');
|
|
189
|
+
lines.push(' if [[ $cword -eq 1 ]]; then');
|
|
190
|
+
const l1Names = tree.subcommands.map((s) => s.name).join(' ');
|
|
191
|
+
lines.push(` COMPREPLY=( $(compgen -W "${escapeBash(l1Names)}" -- "$cur") )`);
|
|
192
|
+
lines.push(' return');
|
|
193
|
+
lines.push(' fi');
|
|
194
|
+
lines.push('');
|
|
195
|
+
const subsWithChildren = tree.subcommands.filter((s) => s.subcommands.length > 0);
|
|
196
|
+
if (subsWithChildren.length > 0) {
|
|
197
|
+
lines.push(' case "${COMP_WORDS[1]}" in');
|
|
198
|
+
for (const sub of subsWithChildren) {
|
|
199
|
+
lines.push(` ${sub.name})`);
|
|
200
|
+
lines.push(' if [[ $cword -eq 2 ]]; then');
|
|
201
|
+
const l2Names = sub.subcommands.map((s) => s.name).join(' ');
|
|
202
|
+
lines.push(` COMPREPLY=( $(compgen -W "${escapeBash(l2Names)}" -- "$cur") )`);
|
|
203
|
+
lines.push(' fi');
|
|
204
|
+
lines.push(' ;;');
|
|
205
|
+
}
|
|
206
|
+
lines.push(' esac');
|
|
207
|
+
}
|
|
208
|
+
lines.push('}');
|
|
209
|
+
lines.push('');
|
|
210
|
+
lines.push(`complete -F _${tree.name}_completions ${tree.name}`);
|
|
211
|
+
lines.push('');
|
|
212
|
+
return lines.join('\n');
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Top-level API: walk the commander program + emit a completion script
|
|
216
|
+
* for the requested shell.
|
|
217
|
+
*/
|
|
218
|
+
export function generateCompletion(program, shell) {
|
|
219
|
+
const tree = extractCommandTree(program);
|
|
220
|
+
if (shell === 'zsh')
|
|
221
|
+
return generateZshCompletion(tree);
|
|
222
|
+
if (shell === 'bash')
|
|
223
|
+
return generateBashCompletion(tree);
|
|
224
|
+
throw new UnsupportedShellError(shell);
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=completion-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion-generator.js","sourceRoot":"","sources":["../../src/lib/completion-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAUH,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,KAAa;QACvB,KAAK,CAAC,sBAAsB,KAAK,gCAAgC,CAAC,CAAC;QACnE,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IACjD,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;QACpB,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,IAAI,EAAE;QACxC,WAAW,EAAE,OAAO,CAAC,QAAQ;aAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;aAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;KACrC,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,GAAY;IAC5B,qEAAqE;IACrE,0CAA0C;IAC1C,MAAM,CAAC,GAAG,GAAuC,CAAC;IAClD,OAAO,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC;AAC5B,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC;SACL,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;SACxB,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;SACnB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC;SACL,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;SACxB,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAiB;IACrD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACpC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,MAAM,CAAC,CAAC;IAChC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACjC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC1B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,IAAI,IAAI,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAChE,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAC5C,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,IAAI,mBAAmB,CAAC,CAAC;IAC3D,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,MAAM,gBAAgB,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAClF,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAClC,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;YAChD,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YAChC,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;gBACjC,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,IAAI,IAAI,SAAS,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YACpE,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,sBAAsB,GAAG,CAAC,IAAI,sBAAsB,CAAC,CAAC;YACjE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACzB,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC;IACjC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAiB;IACtD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,kBAAkB,CAAC,CAAC;IAC5C,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;IACtD,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACxC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9D,KAAK,CAAC,IAAI,CAAC,iCAAiC,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACjF,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,MAAM,gBAAgB,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAClF,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC3C,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;YAChD,MAAM,OAAO,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC7D,KAAK,CAAC,IAAI,CAAC,qCAAqC,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YACrF,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACzB,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,gBAAgB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACjE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAgB,EAAE,KAAqB;IACxE,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,KAAK,KAAK,KAAK;QAAE,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACxD,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,IAAI,qBAAqB,CAAC,KAAe,CAAC,CAAC;AACnD,CAAC"}
|