@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/cli-args.js CHANGED
@@ -1,133 +1,78 @@
1
1
  /**
2
- * M8B riders F1/F2 — CLI argument handling, extracted from src/bin/cello.ts so the
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 (refresh and receipts were missing).
6
- * F2: every subcommand answers --help/-h, and an unrecognized flag is REJECTED
7
- * instead of being coerced into a positional argument (previously
8
- * `cello register --help` tried to register an agent literally named "--help").
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 <login|logout|status|register|create-agent|remove-agent|refresh|receipts|sessions|contact|settings|moniker|telegram|install>\n" +
35
- "Run 'cello <command> --help' for details on any command.";
36
- /** Per-command usage lines (the same text the commands print on bad input). */
37
- const COMMAND_HELP = {
38
- login: "Usage: cello login — start the daemon (or connect to an existing one).",
39
- logout: "Usage: cello logout — send shutdown to the running daemon.",
40
- status: "Usage: cello status — query the daemon and print the structured status JSON.",
41
- register: "Usage: cello register <agent> <pre-auth-token> — register a LOCAL agent with the directory.\n" +
42
- " The two-step onboarding: (1) 'cello create-agent <name>' makes the local identity; (2) 'cello register <name> <token>' registers it with the directory.\n" +
43
- " The token is a single-use pre-authorization ticket from the CELLO Operations Agent on Telegram, format 'CELLO-' + 33 characters, valid 24h.\n" +
44
- " Example: cello register alice CELLO-3xY7...\n" +
45
- " Env-var form (avoids retyping): CELLO_PREAUTH_TOKEN=CELLO-3xY7... cello register alice\n" +
46
- " Quoting is only needed if a value contains spaces (agent names and tokens never do).",
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 COMMAND_HELP[command] ?? USAGE;
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 --limit would consume its value — asking for
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 = COMMAND_FLAGS[command] ?? new Set();
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 (review F1)
65
+ break; // POSIX end-of-flags — everything after is a positional value
124
66
  if (arg.startsWith("-")) {
125
- if (!known.has(arg))
67
+ const spec = known.get(arg);
68
+ if (!spec)
126
69
  return { kind: "unknown_flag", flag: arg };
127
- if (arg === "--limit")
128
- i++; // consumes its value
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
@@ -1 +1 @@
1
- {"version":3,"file":"cli-args.js","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"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"}
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"}
@@ -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":"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"}