@cello-protocol/cli 0.0.44 → 0.0.45
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/arg-parse.d.ts +20 -0
- package/dist/arg-parse.d.ts.map +1 -0
- package/dist/arg-parse.js +30 -0
- package/dist/arg-parse.js.map +1 -0
- package/dist/bin/cello.d.ts +8 -5
- package/dist/bin/cello.d.ts.map +1 -1
- package/dist/bin/cello.js +42 -197
- package/dist/bin/cello.js.map +1 -1
- package/dist/cli-args.d.ts +27 -19
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +47 -102
- package/dist/cli-args.js.map +1 -1
- package/dist/json-out.d.ts +41 -0
- package/dist/json-out.d.ts.map +1 -0
- package/dist/json-out.js +60 -0
- package/dist/json-out.js.map +1 -0
- package/dist/parity-commands.d.ts +161 -0
- package/dist/parity-commands.d.ts.map +1 -0
- package/dist/parity-commands.js +317 -0
- package/dist/parity-commands.js.map +1 -0
- package/dist/registry.d.ts +69 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +641 -0
- package/dist/registry.js.map +1 -0
- package/package.json +2 -2
package/dist/cli-args.js
CHANGED
|
@@ -1,133 +1,78 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* CLI argument handling — validation that runs BEFORE dispatch, kept out of src/bin/cello.ts so the
|
|
3
3
|
* usage surface is testable without spawning the binary.
|
|
4
4
|
*
|
|
5
|
-
* F1: USAGE lists EVERY dispatchable command
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* M8B riders F1/F2 (原): USAGE lists EVERY dispatchable command; every subcommand answers --help/-h;
|
|
6
|
+
* an unrecognized flag is REJECTED rather than coerced into a positional (previously
|
|
7
|
+
* `cello register --help` tried to register an agent literally named "--help").
|
|
8
|
+
*
|
|
9
|
+
* DOD-CLI-PARITY-1 Phase 0: this module no longer OWNS the command list, the help text, or the flag
|
|
10
|
+
* table — it DERIVES all three from the registry (registry.ts), the single source of truth. That is
|
|
11
|
+
* what makes drift between dispatch, `cello --help`, and `cello <cmd> --help` structurally
|
|
12
|
+
* impossible rather than merely discouraged.
|
|
13
|
+
*/
|
|
14
|
+
import { COMMANDS, commandNames, findCommand, flagsFor, renderCommandsTable } from "./registry.js";
|
|
15
|
+
// Re-exported for the dispatch layer and existing callers (its home is arg-parse.ts, which both
|
|
16
|
+
// this module and the registry depend on — see the import-cycle note there).
|
|
17
|
+
export { splitAgentFlag } from "./arg-parse.js";
|
|
18
|
+
/** Every dispatchable command — derived, so it cannot fall out of step with the registry. */
|
|
19
|
+
export const KNOWN_COMMANDS = new Set(commandNames());
|
|
20
|
+
/**
|
|
21
|
+
* The top-level `cello --help`.
|
|
22
|
+
*
|
|
23
|
+
* CC-7 (P2-5 / DOD-ONBOARD-HELP-1): opens with what CELLO is + the onboarding path a first-time
|
|
24
|
+
* user needs. DOD-CLI-PARITY-1 §7 closes the remaining gap — the command list is now a DESCRIBED
|
|
25
|
+
* table rendered from each registry entry's `summary` (it used to be a single pipe-delimited blob
|
|
26
|
+
* with no per-command descriptions). Arguments stay in per-command `--help`.
|
|
9
27
|
*/
|
|
10
|
-
import { MONIKER_RE } from "@cello-protocol/protocol-types";
|
|
11
|
-
export const KNOWN_COMMANDS = new Set([
|
|
12
|
-
"login",
|
|
13
|
-
"logout",
|
|
14
|
-
"status",
|
|
15
|
-
"register",
|
|
16
|
-
"create-agent",
|
|
17
|
-
"remove-agent",
|
|
18
|
-
"refresh",
|
|
19
|
-
"receipts",
|
|
20
|
-
"sessions",
|
|
21
|
-
"contact",
|
|
22
|
-
"settings",
|
|
23
|
-
"moniker",
|
|
24
|
-
"telegram",
|
|
25
|
-
"install",
|
|
26
|
-
]);
|
|
27
|
-
// CC-7 (P2-5 / DOD-ONBOARD-HELP-1): the top level opens with what CELLO is + the onboarding path a
|
|
28
|
-
// first-time user needs, then the command list. (Per-command `cello <cmd> --help` was already good.)
|
|
29
28
|
export const USAGE = "CELLO — a peer-to-peer identity & trust layer for agent-to-agent communication.\n" +
|
|
30
29
|
"\n" +
|
|
31
30
|
"First-time setup: cello login → cello create-agent <name> → cello register <name> <token> → cello status\n" +
|
|
32
31
|
" (get <token> from the CELLO Operations Agent on Telegram; 'cello login' starts the local daemon.)\n" +
|
|
33
32
|
"\n" +
|
|
34
|
-
"Usage: cello <
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"create-agent": "Usage: cello create-agent <name> — create a new LOCAL agent identity (does not touch the directory).\n" +
|
|
48
|
-
// MONIKER-0 AC2: the regex text is DERIVED from the shared constant, never hand-typed.
|
|
49
|
-
` Name rule: 1–64 characters, letters/digits/'-'/'_' only, no spaces (regex ${MONIKER_RE.source}).\n` +
|
|
50
|
-
" Next step: 'cello register <name> <pre-auth-token>' to register it with the directory.",
|
|
51
|
-
"remove-agent": "Usage: cello remove-agent <name> — retires a local agent (one-way) and frees its name.",
|
|
52
|
-
refresh: "Usage: cello refresh <name> — proactively refresh the agent's threshold shares (new epoch).",
|
|
53
|
-
receipts: "Usage: cello receipts <name> — list the agent's stored relay ordering receipts.",
|
|
54
|
-
sessions: "Usage: cello sessions [--open|--closed|--failed|--all] [--limit N] — list session history (defaults to open).",
|
|
55
|
-
contact: "Usage: cello contact add <pubkey> [--agent <name>] | cello contact remove <pubkey> [--agent <name>] | cello contact list [--agent <name>] | cello contact tier <pubkey> <0..4> [--agent <name>]\n" +
|
|
56
|
-
" Per-agent contact whitelist (M8C-CONTACT-1). --agent defaults to the current/sole-online agent.\n" +
|
|
57
|
-
" Contacts are added automatically too: initiating a session to X, or accepting X's inbound request, adds X.\n" +
|
|
58
|
-
" Example: cello contact list --agent alice",
|
|
59
|
-
settings: "Usage: cello settings get [key] [--agent <name>] | cello settings set <key> <value> [--agent <name>]\n" +
|
|
60
|
-
" Per-agent reachability policy (DOD-SETTINGS-1). Keys: bounds.<tier>.max_sessions, bounds.<tier>.max_bytes\n" +
|
|
61
|
-
" (tier = unknown|known|whitelisted|vip; a finite positive integer), away.default, away.tier.<tier> (away text).\n" +
|
|
62
|
-
" An unset key uses the built-in default. Example: cello settings set bounds.known.max_sessions 8 --agent alice",
|
|
63
|
-
moniker: "Usage: cello moniker set <name> [--agent <agent>] | cello moniker clear [--agent <agent>]\n" +
|
|
64
|
-
" The agent's OUTBOUND name — what a counterparty's doorbell shows (MONIKER-1). Defaults to the agent name; 'set' stores an override, 'clear' restores the default.\n" +
|
|
65
|
-
// MONIKER-0 AC2: the regex text is DERIVED from the shared constant, never hand-typed.
|
|
66
|
-
` Name rule: 1–64 characters, letters/digits/'-'/'_' only, no spaces (regex ${MONIKER_RE.source}).\n` +
|
|
67
|
-
" Local-only: never sent to the directory; the receiver treats it as an unverified hint (like caller ID).\n" +
|
|
68
|
-
" Example: cello moniker set Wonderland_Alice --agent alice",
|
|
69
|
-
telegram: "Usage: cello telegram set-token <bot_token> <allowlisted_chat_id> — configure the daemon-owned Telegram doorbell (M8C-TGDOOR-1).\n" +
|
|
70
|
-
" Starts a single long-lived poller immediately; the operator chat given is the ONLY one that ever receives doorbell events.",
|
|
71
|
-
install: "Usage: cello install hermes --agent <name> [--hermes-home <path>] — wire the local CELLO daemon into a Hermes Agent installation.\n" +
|
|
72
|
-
" Scaffolds the CELLO platform-adapter plugin into the Hermes home (default ~/.hermes), binds CELLO_AGENT_NAME in its .env,\n" +
|
|
73
|
-
" and registers via 'hermes plugins enable cello' + 'hermes mcp add cello'. Idempotent — re-run to upgrade.\n" +
|
|
74
|
-
" After installing, restart the gateway: hermes gateway restart",
|
|
75
|
-
};
|
|
33
|
+
"Usage: cello <command> [args]\n" +
|
|
34
|
+
"\n" +
|
|
35
|
+
renderCommandsTable() +
|
|
36
|
+
"\n" +
|
|
37
|
+
"\n" +
|
|
38
|
+
"Run 'cello <command> --help' for details on any command.\n" +
|
|
39
|
+
// Scoped deliberately: only the parity commands (jsonOut) honor the full §3 contract — JSON on
|
|
40
|
+
// stdout, structured error on stderr. The older commands (login, register, …) still print human
|
|
41
|
+
// text, and their failures go to stdout. Claiming the contract for EVERY command would be a
|
|
42
|
+
// promise the binary does not keep, made to precisely the reader who would script against it.
|
|
43
|
+
"The session and agent commands (agents, use-agent, initiate, send, receive, close, …) print JSON\n" +
|
|
44
|
+
"and exit non-zero on failure, so any bash-capable agent can drive CELLO with no MCP dependency.";
|
|
45
|
+
/** Per-command help — the registry entry's own text, verbatim. */
|
|
76
46
|
export function helpForCommand(command) {
|
|
77
|
-
return
|
|
47
|
+
return findCommand(command)?.help ?? USAGE;
|
|
78
48
|
}
|
|
79
|
-
/** Flags each command recognizes. `--limit` consumes the following value. */
|
|
80
|
-
const COMMAND_FLAGS = {
|
|
81
|
-
sessions: new Set(["--open", "--closed", "--failed", "--all", "--limit"]),
|
|
82
|
-
contact: new Set(["--agent"]),
|
|
83
|
-
settings: new Set(["--agent"]),
|
|
84
|
-
moniker: new Set(["--agent"]),
|
|
85
|
-
install: new Set(["--agent", "--hermes-home"]),
|
|
86
|
-
};
|
|
87
49
|
/**
|
|
88
50
|
* F2: validate a subcommand's arguments BEFORE dispatch.
|
|
89
51
|
* - --help / -h ANYWHERE → help. This is a dedicated pre-scan so help wins even when it
|
|
90
|
-
* follows an unknown flag or sits where
|
|
52
|
+
* follows an unknown flag or sits where a value-consuming flag would swallow it — asking for
|
|
91
53
|
* help must never be masked by another argument error.
|
|
92
54
|
* - any other dash-prefixed token the command does not recognize → unknown_flag
|
|
93
55
|
* (never silently coerced into a positional).
|
|
56
|
+
* - after a POSIX `--` terminator, everything is a positional VALUE, verbatim.
|
|
94
57
|
*/
|
|
95
|
-
/**
|
|
96
|
-
* Split a subcommand's argv into the `--agent <name>` flag and the remaining positionals.
|
|
97
|
-
* Extracted (MONIKER-1 review Finding 1) because the old inline filter used
|
|
98
|
-
* `i === agentIdx + 1` unguarded: with --agent ABSENT, agentIdx is -1 and the predicate
|
|
99
|
-
* silently dropped positional index 0 — `cello moniker set Bob` / `cello contact list`
|
|
100
|
-
* printed usage instead of dispatching. The flag's value is excluded ONLY when the flag exists.
|
|
101
|
-
*/
|
|
102
|
-
export function splitAgentFlag(args) {
|
|
103
|
-
// POSIX `--` end-of-flags terminator (review F1): everything after the first `--` is a positional
|
|
104
|
-
// VALUE, verbatim — so a value that starts with `-` (a negative number, or an away text like
|
|
105
|
-
// "- back Monday") can be passed. --agent is recognized only BEFORE the terminator.
|
|
106
|
-
const ddIdx = args.indexOf("--");
|
|
107
|
-
const flagScan = ddIdx === -1 ? args : args.slice(0, ddIdx);
|
|
108
|
-
const afterTerminator = ddIdx === -1 ? [] : args.slice(ddIdx + 1);
|
|
109
|
-
const agentIdx = flagScan.indexOf("--agent");
|
|
110
|
-
const agent = agentIdx !== -1 ? flagScan[agentIdx + 1] : undefined;
|
|
111
|
-
const positional = flagScan
|
|
112
|
-
.filter((a, i) => !(a === "--agent" || (agentIdx !== -1 && i === agentIdx + 1)))
|
|
113
|
-
.concat(afterTerminator);
|
|
114
|
-
return { agent, positional };
|
|
115
|
-
}
|
|
116
58
|
export function checkArgs(command, args) {
|
|
117
59
|
if (args.some((a) => a === "--help" || a === "-h"))
|
|
118
60
|
return { kind: "help" };
|
|
119
|
-
const known =
|
|
61
|
+
const known = flagsFor(command);
|
|
120
62
|
for (let i = 0; i < args.length; i++) {
|
|
121
63
|
const arg = args[i];
|
|
122
64
|
if (arg === "--")
|
|
123
|
-
break; // POSIX end-of-flags — everything after is a positional value
|
|
65
|
+
break; // POSIX end-of-flags — everything after is a positional value
|
|
124
66
|
if (arg.startsWith("-")) {
|
|
125
|
-
|
|
67
|
+
const spec = known.get(arg);
|
|
68
|
+
if (!spec)
|
|
126
69
|
return { kind: "unknown_flag", flag: arg };
|
|
127
|
-
if (
|
|
128
|
-
i++; //
|
|
70
|
+
if (spec.consumesValue)
|
|
71
|
+
i++; // its value is not itself a flag
|
|
129
72
|
}
|
|
130
73
|
}
|
|
131
74
|
return { kind: "ok" };
|
|
132
75
|
}
|
|
76
|
+
/** The registry, re-exported for callers that want to enumerate commands (e.g. the dispatcher). */
|
|
77
|
+
export { COMMANDS };
|
|
133
78
|
//# sourceMappingURL=cli-args.js.map
|
package/dist/cli-args.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-args.js","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cli-args.js","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEnG,gGAAgG;AAChG,6EAA6E;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,6FAA6F;AAC7F,MAAM,CAAC,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC;AAI3E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,KAAK,GAChB,mFAAmF;IACnF,IAAI;IACJ,mHAAmH;IACnH,uGAAuG;IACvG,IAAI;IACJ,iCAAiC;IACjC,IAAI;IACJ,mBAAmB,EAAE;IACrB,IAAI;IACJ,IAAI;IACJ,4DAA4D;IAC5D,+FAA+F;IAC/F,gGAAgG;IAChG,4FAA4F;IAC5F,8FAA8F;IAC9F,oGAAoG;IACpG,iGAAiG,CAAC;AAEpG,kEAAkE;AAClE,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,OAAO,WAAW,CAAC,OAAO,CAAC,EAAE,IAAI,IAAI,KAAK,CAAC;AAC7C,CAAC;AAOD;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,IAAc;IACvD,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC5E,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,KAAK,IAAI;YAAE,MAAM,CAAC,8DAA8D;QACvF,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC5B,IAAI,CAAC,IAAI;gBAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;YACtD,IAAI,IAAI,CAAC,aAAa;gBAAE,CAAC,EAAE,CAAC,CAAC,iCAAiC;QAChE,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC;AAED,mGAAmG;AACnG,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOD-CLI-PARITY-1 §3 — the bash-adapter contract.
|
|
3
|
+
*
|
|
4
|
+
* This is what makes `cello` a real programmatic interface rather than a human-only UI: any
|
|
5
|
+
* bash-capable agent can drive a CELLO node with `cello <cmd> | jq` + `$?`, with no MCP dependency.
|
|
6
|
+
*
|
|
7
|
+
* The contract, applied identically by every parity command:
|
|
8
|
+
* - stdout = the daemon's IPC response as JSON, one object per invocation (compact by default —
|
|
9
|
+
* scripts and agents are the first-class consumer; `--pretty` for humans).
|
|
10
|
+
* - exit 0 when the response is ok:true; non-zero otherwise.
|
|
11
|
+
* - a FAILED response goes to stderr, VERBATIM — every field the daemon sent (reason, guidance,
|
|
12
|
+
* and extras like the read-before-write cursor) survives untouched, and stdout stays EMPTY so a
|
|
13
|
+
* piping script can never mistake an error body for a result.
|
|
14
|
+
*
|
|
15
|
+
* The verbatim rule is the DOD-SENDRAW-1 / DOD-LOGOUT-WAIT-1 lesson at the CLI surface: report the
|
|
16
|
+
* outcome, never the intent. A command that reports success for a failed IPC call is a lie, and
|
|
17
|
+
* absence of ok:true is NOT evidence of success — an unrecognized shape fails loud rather than
|
|
18
|
+
* being optimistically passed off as a result.
|
|
19
|
+
*/
|
|
20
|
+
export interface EmittedOutput {
|
|
21
|
+
stdout: string;
|
|
22
|
+
stderr: string;
|
|
23
|
+
exitCode: number;
|
|
24
|
+
}
|
|
25
|
+
export interface EmitOptions {
|
|
26
|
+
/** Human-readable indented JSON. JSON stays the default so scripts come first. */
|
|
27
|
+
pretty?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Turn a daemon IPC response into the (stdout, stderr, exitCode) triple the contract demands.
|
|
31
|
+
* The response is passed through UNMODIFIED in both directions — this function decides the stream
|
|
32
|
+
* and the exit code, and is never allowed to rewrite, summarize, or invent the body.
|
|
33
|
+
*/
|
|
34
|
+
export declare function emitIpcResult(result: Record<string, unknown>, opts?: EmitOptions): EmittedOutput;
|
|
35
|
+
/**
|
|
36
|
+
* A transport/daemon-level failure (socket unreachable, daemon not running, thrown error) — still
|
|
37
|
+
* a structured, machine-parseable JSON error on stderr, so a bash agent branches on the same shape
|
|
38
|
+
* whether the daemon rejected the call or never received it.
|
|
39
|
+
*/
|
|
40
|
+
export declare function emitTransportError(reason: string, guidance: string, opts?: EmitOptions): EmittedOutput;
|
|
41
|
+
//# sourceMappingURL=json-out.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-out.d.ts","sourceRoot":"","sources":["../src/json-out.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,kFAAkF;IAClF,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAMD;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,GAAE,WAAgB,GACrB,aAAa,CAmBf;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,aAAa,CAM1G"}
|
package/dist/json-out.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOD-CLI-PARITY-1 §3 — the bash-adapter contract.
|
|
3
|
+
*
|
|
4
|
+
* This is what makes `cello` a real programmatic interface rather than a human-only UI: any
|
|
5
|
+
* bash-capable agent can drive a CELLO node with `cello <cmd> | jq` + `$?`, with no MCP dependency.
|
|
6
|
+
*
|
|
7
|
+
* The contract, applied identically by every parity command:
|
|
8
|
+
* - stdout = the daemon's IPC response as JSON, one object per invocation (compact by default —
|
|
9
|
+
* scripts and agents are the first-class consumer; `--pretty` for humans).
|
|
10
|
+
* - exit 0 when the response is ok:true; non-zero otherwise.
|
|
11
|
+
* - a FAILED response goes to stderr, VERBATIM — every field the daemon sent (reason, guidance,
|
|
12
|
+
* and extras like the read-before-write cursor) survives untouched, and stdout stays EMPTY so a
|
|
13
|
+
* piping script can never mistake an error body for a result.
|
|
14
|
+
*
|
|
15
|
+
* The verbatim rule is the DOD-SENDRAW-1 / DOD-LOGOUT-WAIT-1 lesson at the CLI surface: report the
|
|
16
|
+
* outcome, never the intent. A command that reports success for a failed IPC call is a lie, and
|
|
17
|
+
* absence of ok:true is NOT evidence of success — an unrecognized shape fails loud rather than
|
|
18
|
+
* being optimistically passed off as a result.
|
|
19
|
+
*/
|
|
20
|
+
function render(value, pretty) {
|
|
21
|
+
return pretty ? JSON.stringify(value, null, 2) : JSON.stringify(value);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Turn a daemon IPC response into the (stdout, stderr, exitCode) triple the contract demands.
|
|
25
|
+
* The response is passed through UNMODIFIED in both directions — this function decides the stream
|
|
26
|
+
* and the exit code, and is never allowed to rewrite, summarize, or invent the body.
|
|
27
|
+
*/
|
|
28
|
+
export function emitIpcResult(result, opts = {}) {
|
|
29
|
+
// The exit code keys on `ok === false`, not on `ok === true`, because the daemon has TWO response
|
|
30
|
+
// conventions and only one of them carries `ok`:
|
|
31
|
+
// (a) ok-bearing — { ok: true, … } / { ok: false, reason, guidance }
|
|
32
|
+
// (b) payload-only — a bare result with NO `ok` at all: cello_list_agents returns { agents: [] },
|
|
33
|
+
// cello_await_session returns { type: "timeout" | … }. (Verified against daemon.ts, not
|
|
34
|
+
// assumed.)
|
|
35
|
+
// `ok: false` is the daemon's ONE failure convention; a genuine transport/daemon failure THROWS
|
|
36
|
+
// and is handled by the caller as a transport error. So a payload without `ok` is a result, and
|
|
37
|
+
// routing it to stderr (as an earlier draft of this contract did) would report working commands
|
|
38
|
+
// as broken — `cello agents` would exit 1 on success.
|
|
39
|
+
//
|
|
40
|
+
// This does NOT weaken the no-fabricated-success rule: we never synthesize an ok:true, never
|
|
41
|
+
// rewrite a body, and never swallow an ok:false. We report exactly what the daemon said.
|
|
42
|
+
const failed = result.ok === false;
|
|
43
|
+
if (failed) {
|
|
44
|
+
return { stdout: "", stderr: render(result, opts.pretty), exitCode: 1 };
|
|
45
|
+
}
|
|
46
|
+
return { stdout: render(result, opts.pretty), stderr: "", exitCode: 0 };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A transport/daemon-level failure (socket unreachable, daemon not running, thrown error) — still
|
|
50
|
+
* a structured, machine-parseable JSON error on stderr, so a bash agent branches on the same shape
|
|
51
|
+
* whether the daemon rejected the call or never received it.
|
|
52
|
+
*/
|
|
53
|
+
export function emitTransportError(reason, guidance, opts = {}) {
|
|
54
|
+
return {
|
|
55
|
+
stdout: "",
|
|
56
|
+
stderr: render({ ok: false, reason, guidance }, opts.pretty),
|
|
57
|
+
exitCode: 1,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=json-out.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-out.js","sourceRoot":"","sources":["../src/json-out.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAaH,SAAS,MAAM,CAAC,KAAc,EAAE,MAA2B;IACzD,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AACzE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,MAA+B,EAC/B,OAAoB,EAAE;IAEtB,kGAAkG;IAClG,iDAAiD;IACjD,wEAAwE;IACxE,oGAAoG;IACpG,8FAA8F;IAC9F,kBAAkB;IAClB,gGAAgG;IAChG,gGAAgG;IAChG,gGAAgG;IAChG,sDAAsD;IACtD,EAAE;IACF,6FAA6F;IAC7F,yFAAyF;IACzF,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,KAAK,KAAK,CAAC;IACnC,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IAC1E,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AAC1E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,QAAgB,EAAE,OAAoB,EAAE;IACzF,OAAO;QACL,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC;QAC5D,QAAQ,EAAE,CAAC;KACZ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOD-CLI-PARITY-1 Phases 1-2 — every daemon capability that was MCP-only, reachable from `cello`.
|
|
3
|
+
*
|
|
4
|
+
* Bash is the universal agent adapter: with these commands any bash-capable agent (not just Claude
|
|
5
|
+
* Code or Hermes) operates a CELLO node — connect, send, receive, seal — with no MCP dependency.
|
|
6
|
+
*
|
|
7
|
+
* Each command is a THIN PASS-THROUGH: parse args → call the SAME daemon IPC handler the
|
|
8
|
+
* corresponding cello_* MCP tool calls → emit the response under the §3 contract (json-out.ts).
|
|
9
|
+
* No daemon changes, no second IPC client, no logic that the daemon owns (validation, tier bounds,
|
|
10
|
+
* agent_id resolution) is duplicated here — the CLI surfaces the daemon's verdict, verbatim.
|
|
11
|
+
*
|
|
12
|
+
* ── The per-invocation current-agent problem (why `use-agent` persists) ──────────────────────
|
|
13
|
+
* The daemon's "current agent" is PER-CONNECTION state. The MCP shim holds one long-lived socket,
|
|
14
|
+
* so `cello_use_agent` sticks for the whole session. The CLI is the opposite: a fresh process and a
|
|
15
|
+
* fresh connection per invocation, torn down microseconds later. A naive `cello use-agent alice`
|
|
16
|
+
* pass-through would therefore set state on a dying socket and report ok:true while changing NOTHING
|
|
17
|
+
* for the next command — a fabricated success of exactly the kind §3 forbids.
|
|
18
|
+
*
|
|
19
|
+
* So the selection is DURABLE: `use-agent` calls the real handler (which validates the agent and
|
|
20
|
+
* auto-starts it — AUTOSTART-1) and, only if the daemon says ok, persists the name. Every
|
|
21
|
+
* agent-scoped command then REPLAYS `cello_use_agent` on its new connection before dispatching.
|
|
22
|
+
* That is not a parallel path — it is the same replay the MCP proxy performs after a reconnect
|
|
23
|
+
* (ipc-proxy.ts invariant 1), reusing the existing handler.
|
|
24
|
+
*
|
|
25
|
+
* Agent resolution, in order: explicit `--agent` > the persisted selection > (omitted, so the
|
|
26
|
+
* daemon applies its own sole-online-agent fallback, and stays ambiguous → no_current_agent when
|
|
27
|
+
* two or more are online). If a replay FAILS, the command STOPS and surfaces that error — it never
|
|
28
|
+
* shrugs and lets the daemon's fallback quietly run the work as a different agent.
|
|
29
|
+
*/
|
|
30
|
+
import { type EmittedOutput, type EmitOptions } from "./json-out.js";
|
|
31
|
+
export type CliOutput = EmittedOutput;
|
|
32
|
+
/** Options every parity command accepts. */
|
|
33
|
+
export interface ParityOptions extends EmitOptions {
|
|
34
|
+
/** `--agent <name>` — overrides the persisted selection for this invocation only. */
|
|
35
|
+
agent?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The persisted agent selection, or undefined if none was ever made.
|
|
39
|
+
*
|
|
40
|
+
* ENOENT — never selected — is the ONLY swallowed error (review F4). A blanket catch here would let
|
|
41
|
+
* an unreadable file (EACCES, EISDIR, a corrupt mount) read as "no selection", after which the
|
|
42
|
+
* daemon's sole-online fallback would quietly run the command as whatever agent happens to be up:
|
|
43
|
+
* the operator's selection silently replaced by a different identity, exit 0. Anything that is not
|
|
44
|
+
* "the file isn't there" is a real failure and is thrown.
|
|
45
|
+
*/
|
|
46
|
+
export declare function readCurrentAgent(celloDir: string): Promise<string | undefined>;
|
|
47
|
+
/**
|
|
48
|
+
* The ONE place a CLI command's daemon IPC method is named (review T2).
|
|
49
|
+
*
|
|
50
|
+
* The registry's `ipcMethod` field is set FROM this map, and every function below dispatches FROM
|
|
51
|
+
* this map — so the field that DoD §9's parity test audits is, by construction, the literal that is
|
|
52
|
+
* actually sent. Previously the two were independent strings: the registry could say
|
|
53
|
+
* `cello_contact_set_moniker` while the code called `cello_contact_set_away`, and the audit — which
|
|
54
|
+
* only read the metadata — would happily pass. A comment-in-a-field is not a guarantee; this is.
|
|
55
|
+
*/
|
|
56
|
+
export declare const IPC_METHODS: {
|
|
57
|
+
readonly agents: "cello_list_agents";
|
|
58
|
+
readonly "start-agent": "cello_start_agent";
|
|
59
|
+
readonly "stop-agent": "cello_stop_agent";
|
|
60
|
+
readonly "use-agent": "cello_use_agent";
|
|
61
|
+
readonly inbox: "cello_check_notifications";
|
|
62
|
+
readonly transcript: "cello_get_transcript";
|
|
63
|
+
readonly "sealed-receipt": "cello_get_sealed_receipt";
|
|
64
|
+
readonly initiate: "cello_initiate_session";
|
|
65
|
+
readonly send: "cello_send";
|
|
66
|
+
readonly receive: "cello_receive";
|
|
67
|
+
readonly "receive-session": "cello_receive_session";
|
|
68
|
+
readonly close: "cello_close_session";
|
|
69
|
+
readonly "await-session": "cello_await_session";
|
|
70
|
+
readonly "contact-add": "cello_contact_add";
|
|
71
|
+
readonly "contact-remove": "cello_contact_remove";
|
|
72
|
+
readonly "contact-list": "cello_contact_list";
|
|
73
|
+
readonly "contact-set-tier": "cello_contact_set_tier";
|
|
74
|
+
readonly "contact-set-away": "cello_contact_set_away";
|
|
75
|
+
readonly "contact-set-moniker": "cello_contact_set_moniker";
|
|
76
|
+
};
|
|
77
|
+
/** `cello agents` → cello_list_agents. Daemon-wide, not agent-scoped. */
|
|
78
|
+
export declare function listAgents(celloDir: string, opts: ParityOptions): Promise<CliOutput>;
|
|
79
|
+
/** `cello start-agent <name>` → cello_start_agent. Brings an agent online WITHOUT claiming current. */
|
|
80
|
+
export declare function startAgent(celloDir: string, name: string, opts: ParityOptions): Promise<CliOutput>;
|
|
81
|
+
/**
|
|
82
|
+
* `cello stop-agent <name>` → cello_stop_agent.
|
|
83
|
+
*
|
|
84
|
+
* Also CLEARS the persisted selection when it names this agent (review F1). The daemon clears a
|
|
85
|
+
* stopped agent from every connection's current-agent state; the CLI's durable mirror of that state
|
|
86
|
+
* must follow, or the next command would try to act as an agent the operator just stopped.
|
|
87
|
+
*/
|
|
88
|
+
export declare function stopAgent(celloDir: string, name: string, opts: ParityOptions): Promise<CliOutput>;
|
|
89
|
+
/**
|
|
90
|
+
* `cello use-agent <name>` → cello_use_agent, and — only if the daemon accepts it — persists the
|
|
91
|
+
* selection so it survives this process. The handler auto-starts the agent if offline (AUTOSTART-1).
|
|
92
|
+
* A rejected selection is NEVER written: a later command must not silently act as an agent the
|
|
93
|
+
* daemon refused.
|
|
94
|
+
*/
|
|
95
|
+
export declare function useAgent(celloDir: string, name: string, opts: ParityOptions): Promise<CliOutput>;
|
|
96
|
+
/** `cello inbox [--scope current|all]` → cello_check_notifications (the push-loss reconciler). */
|
|
97
|
+
export declare function inbox(celloDir: string, opts: ParityOptions & {
|
|
98
|
+
scope?: "current" | "all";
|
|
99
|
+
}): Promise<CliOutput>;
|
|
100
|
+
/** `cello transcript <session-id>` → cello_get_transcript (durable, survives a daemon restart). */
|
|
101
|
+
export declare function transcript(celloDir: string, sessionId: string, opts: ParityOptions): Promise<CliOutput>;
|
|
102
|
+
/**
|
|
103
|
+
* `cello sealed-receipt <session-id>` → cello_get_sealed_receipt.
|
|
104
|
+
*
|
|
105
|
+
* NOT in the brief's mapping table, which listed cello_get_sealed_receipt as "already covered by
|
|
106
|
+
* `receipts`". It is not: `cello receipts <name>` calls cello_get_relay_receipts — a DIFFERENT
|
|
107
|
+
* handler (relay ordering receipts). The notarized bilateral SEAL receipt — the artifact the whole
|
|
108
|
+
* close ceremony exists to produce, and the one an arbitrator reads — had no CLI surface at all.
|
|
109
|
+
* Added under the standing rule: a real, non-stub handler with no CLI command gets one.
|
|
110
|
+
*/
|
|
111
|
+
export declare function sealedReceipt(celloDir: string, sessionId: string, opts: ParityOptions): Promise<CliOutput>;
|
|
112
|
+
/** `cello contact add <pubkey>` → cello_contact_add. */
|
|
113
|
+
export declare function contactAdd(celloDir: string, pubkey: string, opts: ParityOptions): Promise<CliOutput>;
|
|
114
|
+
/** `cello contact remove <pubkey>` → cello_contact_remove. */
|
|
115
|
+
export declare function contactRemove(celloDir: string, pubkey: string, opts: ParityOptions): Promise<CliOutput>;
|
|
116
|
+
/** `cello contact list` → cello_contact_list. */
|
|
117
|
+
export declare function contactList(celloDir: string, opts: ParityOptions): Promise<CliOutput>;
|
|
118
|
+
/** `cello contact set-tier <pubkey> <tier>` → cello_contact_set_tier. */
|
|
119
|
+
export declare function contactSetTier(celloDir: string, pubkey: string, tier: number, opts: ParityOptions): Promise<CliOutput>;
|
|
120
|
+
/** `cello contact set-away <pubkey> <message>` → cello_contact_set_away (empty message clears it). */
|
|
121
|
+
export declare function contactSetAway(celloDir: string, pubkey: string, message: string | null, opts: ParityOptions): Promise<CliOutput>;
|
|
122
|
+
/** `cello contact set-moniker <pubkey> <moniker>` → cello_contact_set_moniker (per-CONTACT pet name). */
|
|
123
|
+
export declare function contactSetMoniker(celloDir: string, pubkey: string, moniker: string | null, opts: ParityOptions): Promise<CliOutput>;
|
|
124
|
+
/** `cello initiate <target-pubkey>` → cello_initiate_session. Prints the session_id. */
|
|
125
|
+
export declare function initiate(celloDir: string, targetPubkey: string, opts: ParityOptions): Promise<CliOutput>;
|
|
126
|
+
/**
|
|
127
|
+
* `cello send <session-id> <message>` → cello_send.
|
|
128
|
+
*
|
|
129
|
+
* Honors read-before-write exactly as the MCP tool does: if the daemon returns session_not_current
|
|
130
|
+
* (with its cursor), that verdict is surfaced VERBATIM and the command exits non-zero. It is never
|
|
131
|
+
* auto-fixed by silently reading the transcript first — the operator/agent must catch up explicitly,
|
|
132
|
+
* because a send that "worked" after a hidden read is a send whose ordering guarantees are a fiction.
|
|
133
|
+
*/
|
|
134
|
+
export declare function send(celloDir: string, sessionId: string, content: string, opts: ParityOptions & {
|
|
135
|
+
governanceDecisions?: Record<string, string>;
|
|
136
|
+
}): Promise<CliOutput>;
|
|
137
|
+
/**
|
|
138
|
+
* `cello receive <session-id> [--since-seq N] [--timeout-ms N]` → cello_receive.
|
|
139
|
+
* Mirrors the MCP semantics exactly: with since_seq it is a stateless catch-up BATCH (no replay
|
|
140
|
+
* race, timeout ignored); without it, it BLOCKS for the next live message until timeout_ms.
|
|
141
|
+
*/
|
|
142
|
+
export declare function receive(celloDir: string, sessionId: string, opts: ParityOptions & {
|
|
143
|
+
sinceSeq?: number;
|
|
144
|
+
timeoutMs?: number;
|
|
145
|
+
}): Promise<CliOutput>;
|
|
146
|
+
/** `cello receive-session <session-id> [--timeout-ms N]` → cello_receive_session. */
|
|
147
|
+
export declare function receiveSession(celloDir: string, sessionId: string, opts: ParityOptions & {
|
|
148
|
+
timeoutMs?: number;
|
|
149
|
+
}): Promise<CliOutput>;
|
|
150
|
+
/**
|
|
151
|
+
* `cello close <session-id> [--force]` → cello_close_session. Normally triggers the bilateral seal
|
|
152
|
+
* ceremony. --force is passed ONLY when asked for (mirroring the shim), since it forfeits the seal.
|
|
153
|
+
*/
|
|
154
|
+
export declare function closeSession(celloDir: string, sessionId: string, opts: ParityOptions & {
|
|
155
|
+
force?: boolean;
|
|
156
|
+
}): Promise<CliOutput>;
|
|
157
|
+
/** `cello await-session [--timeout-ms N]` → cello_await_session. Blocks for an inbound doorbell. */
|
|
158
|
+
export declare function awaitSession(celloDir: string, opts: ParityOptions & {
|
|
159
|
+
timeoutMs?: number;
|
|
160
|
+
}): Promise<CliOutput>;
|
|
161
|
+
//# sourceMappingURL=parity-commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parity-commands.d.ts","sourceRoot":"","sources":["../src/parity-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAKH,OAAO,EAAqC,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAExG,MAAM,MAAM,SAAS,GAAG,aAAa,CAAC;AAEtC,4CAA4C;AAC5C,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD,qFAAqF;IACrF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAQpF;AAkJD;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;CAoBd,CAAC;AAIX,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAEpF;AAED,uGAAuG;AACvG,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAElG;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAMvG;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAItG;AAED,kGAAkG;AAClG,wBAAgB,KAAK,CACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,aAAa,GAAG;IAAE,KAAK,CAAC,EAAE,SAAS,GAAG,KAAK,CAAA;CAAE,GAClD,OAAO,CAAC,SAAS,CAAC,CAEpB;AAED,mGAAmG;AACnG,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAEvG;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAE1G;AASD,wDAAwD;AACxD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAEpG;AAED,8DAA8D;AAC9D,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAEvG;AAED,iDAAiD;AACjD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAErF;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAEtH;AAED,sGAAsG;AACtG,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAEhI;AAED,yGAAyG;AACzG,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAEnI;AAID,wFAAwF;AACxF,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAExG;AAED;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAClB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,aAAa,GAAG;IAAE,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACrE,OAAO,CAAC,SAAS,CAAC,CAOpB;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CACrB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,aAAa,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9D,OAAO,CAAC,SAAS,CAAC,CAOpB;AAED,qFAAqF;AACrF,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,aAAa,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C,OAAO,CAAC,SAAS,CAAC,CAOpB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,aAAa,GAAG;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GACxC,OAAO,CAAC,SAAS,CAAC,CAGpB;AAED,oGAAoG;AACpG,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,aAAa,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C,OAAO,CAAC,SAAS,CAAC,CAEpB"}
|