@cotal-ai/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/LICENSE +202 -0
  2. package/dist/command.d.ts +5 -0
  3. package/dist/command.d.ts.map +1 -0
  4. package/dist/command.js +34 -0
  5. package/dist/command.js.map +1 -0
  6. package/dist/commands/console.d.ts +2 -0
  7. package/dist/commands/console.d.ts.map +1 -0
  8. package/dist/commands/console.js +45 -0
  9. package/dist/commands/console.js.map +1 -0
  10. package/dist/commands/join.d.ts +2 -0
  11. package/dist/commands/join.d.ts.map +1 -0
  12. package/dist/commands/join.js +201 -0
  13. package/dist/commands/join.js.map +1 -0
  14. package/dist/commands/mint.d.ts +4 -0
  15. package/dist/commands/mint.d.ts.map +1 -0
  16. package/dist/commands/mint.js +52 -0
  17. package/dist/commands/mint.js.map +1 -0
  18. package/dist/commands/spawn.d.ts +15 -0
  19. package/dist/commands/spawn.d.ts.map +1 -0
  20. package/dist/commands/spawn.js +112 -0
  21. package/dist/commands/spawn.js.map +1 -0
  22. package/dist/commands/up.d.ts +2 -0
  23. package/dist/commands/up.d.ts.map +1 -0
  24. package/dist/commands/up.js +75 -0
  25. package/dist/commands/up.js.map +1 -0
  26. package/dist/commands/watch.d.ts +2 -0
  27. package/dist/commands/watch.d.ts.map +1 -0
  28. package/dist/commands/watch.js +63 -0
  29. package/dist/commands/watch.js.map +1 -0
  30. package/dist/commands/web.d.ts +5 -0
  31. package/dist/commands/web.d.ts.map +1 -0
  32. package/dist/commands/web.js +187 -0
  33. package/dist/commands/web.js.map +1 -0
  34. package/dist/index.d.ts +3 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +67 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/render.d.ts +32 -0
  39. package/dist/render.d.ts.map +1 -0
  40. package/dist/render.js +0 -0
  41. package/dist/render.js.map +1 -0
  42. package/dist/ui.d.ts +15 -0
  43. package/dist/ui.d.ts.map +1 -0
  44. package/dist/ui.js +25 -0
  45. package/dist/ui.js.map +1 -0
  46. package/package.json +27 -0
@@ -0,0 +1,112 @@
1
+ import { spawn as spawnProcess } from "node:child_process";
2
+ import { mkdirSync, writeFileSync } from "node:fs";
3
+ import { join, dirname } from "node:path";
4
+ import { parseArgs } from "node:util";
5
+ import { DEFAULT_SERVER, agentFilePath, authDir, loadAgentFile, loadSpaceAuth, mintCreds, newIdentity, provisionAgent, registry, CotalEndpoint, } from "@cotal-ai/core";
6
+ /**
7
+ * `cotal spawn <name-or-path>` — launch an agent in the FOREGROUND of this
8
+ * terminal from a local agent file, joined to the mesh with its persona.
9
+ *
10
+ * Unlike `cotal start` (the manager spawns into a detached PTY you attach to),
11
+ * `cotal spawn` hands the terminal straight to the agent: run it in your shell,
12
+ * or inside a cmux/tmux pane, and the real Claude TUI takes over.
13
+ *
14
+ * The launch recipe is the connector's `buildLaunch` (the single source of truth,
15
+ * shared with the manager); only *how the spec runs* differs — foreground exec
16
+ * here vs. a supervised runtime in the manager. The connector is resolved from
17
+ * the registry by agent type, composed at the root.
18
+ */
19
+ export async function spawn(argv) {
20
+ const { values, positionals } = parseArgs({
21
+ args: argv,
22
+ allowPositionals: true,
23
+ options: {
24
+ name: { type: "string" },
25
+ config: { type: "string" },
26
+ space: { type: "string" },
27
+ server: { type: "string" },
28
+ agent: { type: "string" },
29
+ role: { type: "string" },
30
+ },
31
+ });
32
+ // Where the config lives: --config, else the positional <name-or-path>, else
33
+ // discover by --name (.cotal/agents/<name>.md). Same flags as `cotal start`.
34
+ const ref = values.config ?? positionals[0] ?? values.name;
35
+ if (!ref) {
36
+ console.error("usage: cotal spawn <name-or-path> | --config <path> | --name <n> [--agent <a>] [--role <r>] [--space <s>] [--server <url>]");
37
+ process.exit(1);
38
+ }
39
+ const path = agentFilePath(process.cwd(), ref);
40
+ let def;
41
+ try {
42
+ def = loadAgentFile(path);
43
+ }
44
+ catch (e) {
45
+ console.error(`✗ ${e.message}`);
46
+ process.exit(1);
47
+ }
48
+ // --name / --role override the file (name defaults from the file's frontmatter).
49
+ const name = values.name ?? def.name;
50
+ const role = values.role ?? def.role;
51
+ const space = values.space ?? "demo";
52
+ const server = values.server ?? DEFAULT_SERVER;
53
+ // Auth mode (`.cotal/auth` present): mint a stable identity + scoped creds for this agent
54
+ // and pre-create its bind-only durables, via a short-lived privileged provisioner — the
55
+ // same onboarding the manager does, so the foreground launch joins the authed mesh too.
56
+ // Open mode (no `.cotal/auth`): unchanged — the session connects without creds.
57
+ let id;
58
+ let credsPath;
59
+ const auth = loadSpaceAuth(authDir(process.cwd()));
60
+ if (auth) {
61
+ const identity = newIdentity();
62
+ const prov = new CotalEndpoint({
63
+ space,
64
+ servers: server,
65
+ creds: await mintCreds(auth, newIdentity(), "manager"),
66
+ channels: [],
67
+ consume: false,
68
+ registerPresence: false,
69
+ watchPresence: false,
70
+ card: { name: "spawn-provisioner", role: "manager", kind: "endpoint" },
71
+ });
72
+ prov.on("error", (e) => console.error(`! provisioner: ${e.message}`));
73
+ await prov.start();
74
+ const creds = await provisionAgent(prov, auth, identity, {
75
+ channels: def.publish ?? def.channels,
76
+ role,
77
+ });
78
+ await prov.stop();
79
+ credsPath = join(authDir(process.cwd()), "creds", `${name}.creds`);
80
+ mkdirSync(dirname(credsPath), { recursive: true });
81
+ writeFileSync(credsPath, creds, { mode: 0o600 });
82
+ id = identity.id;
83
+ console.error(`minted creds for ${name} (auth mode) → ${credsPath}`);
84
+ }
85
+ const connector = registry.resolve("connector", values.agent ?? "claude");
86
+ const spec = connector.buildLaunch({
87
+ space,
88
+ name,
89
+ role,
90
+ id,
91
+ creds: credsPath,
92
+ servers: server,
93
+ configPath: path,
94
+ });
95
+ console.error(`spawning ${name}${role ? ` (${role})` : ""} on the mesh — press Enter at the dev-channels prompt`);
96
+ const child = spawnProcess(spec.command, spec.args, {
97
+ stdio: "inherit",
98
+ env: { ...process.env, ...spec.env },
99
+ });
100
+ await new Promise((resolve) => {
101
+ child.on("error", (e) => {
102
+ console.error(`✗ failed to launch ${spec.command}: ${e.message}`);
103
+ process.exitCode = 1;
104
+ resolve();
105
+ });
106
+ child.on("exit", (code) => {
107
+ process.exitCode = code ?? 0;
108
+ resolve();
109
+ });
110
+ });
111
+ }
112
+ //# sourceMappingURL=spawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.js","sourceRoot":"","sources":["../../src/commands/spawn.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function up(argv: string[]): Promise<void>;
2
+ //# sourceMappingURL=up.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"up.d.ts","sourceRoot":"","sources":["../../src/commands/up.ts"],"names":[],"mappings":"AAmBA,wBAAsB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwDtD"}
@@ -0,0 +1,75 @@
1
+ import { spawn } from "node:child_process";
2
+ import { mkdirSync, writeFileSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+ import { parseArgs } from "node:util";
5
+ import { isReachable, DEFAULT_SERVER, authDir, createSpaceAuth, loadSpaceAuth, saveSpaceAuth, serverConfig, mintCreds, newIdentity, setupSpaceStreams, } from "@cotal-ai/core";
6
+ import { c } from "../ui.js";
7
+ export async function up(argv) {
8
+ const { values } = parseArgs({
9
+ args: argv,
10
+ allowPositionals: true,
11
+ options: {
12
+ server: { type: "string" },
13
+ "store-dir": { type: "string" },
14
+ space: { type: "string" },
15
+ open: { type: "boolean" }, // disable auth — run an open dev mesh
16
+ },
17
+ });
18
+ const server = values.server ?? DEFAULT_SERVER;
19
+ if (await isReachable(server)) {
20
+ console.log(c.green(`✓ NATS already running at ${server}`));
21
+ return;
22
+ }
23
+ const storeDir = resolve(values["store-dir"] ?? ".cotal/nats");
24
+ mkdirSync(storeDir, { recursive: true });
25
+ // Secure by default: start the server in decentralized-JWT mode so agents must present
26
+ // minted creds. `--open` runs the unauthenticated dev mesh instead.
27
+ const useAuth = !values.open;
28
+ const space = values.space ?? "demo";
29
+ const setup = useAuth ? await authSetup(storeDir, server, space) : undefined;
30
+ const args = setup ? ["-c", setup.confPath] : ["-js", "-sd", storeDir];
31
+ console.log(c.dim(useAuth
32
+ ? `Starting nats-server (JetStream, JWT auth) — store: ${storeDir}`
33
+ : `Starting nats-server (JetStream, OPEN/no-auth) — store: ${storeDir}`));
34
+ console.log(c.dim("Press Ctrl-C to stop.\n"));
35
+ const child = spawn("nats-server", args, { stdio: "inherit" });
36
+ child.on("error", (err) => {
37
+ console.error(c.red(`Failed to start nats-server: ${err.message}`));
38
+ console.error(c.dim("Install it with: brew install nats-server"));
39
+ process.exit(1);
40
+ });
41
+ const stop = () => child.kill("SIGTERM");
42
+ process.on("SIGINT", stop);
43
+ process.on("SIGTERM", stop);
44
+ child.on("exit", (code) => process.exit(code ?? 0));
45
+ // Auth mode: streams are space infrastructure that agents are denied STREAM.CREATE for,
46
+ // so pre-create them here (once, privileged) as soon as the server accepts connections.
47
+ if (setup) {
48
+ for (let i = 0; i < 50; i++) {
49
+ if (await isReachable(server, { creds: setup.creds }))
50
+ break;
51
+ await new Promise((r) => setTimeout(r, 200));
52
+ }
53
+ await setupSpaceStreams({ servers: server, space, creds: setup.creds });
54
+ console.log(c.dim("Pre-created CHAT/DM/TASK streams for the space."));
55
+ }
56
+ await new Promise(() => { });
57
+ }
58
+ /** Ensure the space's trust material exists, render a server config, and mint a privileged
59
+ * setup creds (used to pre-create streams once the server is up). The account signing key
60
+ * in `.cotal/auth` is what `cotal mint` and the manager later use to issue per-agent creds. */
61
+ async function authSetup(storeDir, server, space) {
62
+ const dir = authDir(process.cwd());
63
+ let auth = loadSpaceAuth(dir);
64
+ if (!auth) {
65
+ auth = await createSpaceAuth(space);
66
+ saveSpaceAuth(dir, auth);
67
+ console.log(c.dim(`Generated space auth for "${space}" → ${dir}/auth.json (keep the signing key safe)`));
68
+ }
69
+ const port = Number(new URL(server).port) || 4222;
70
+ const confPath = resolve(dir, "server.conf");
71
+ writeFileSync(confPath, serverConfig(auth, { port, storeDir }));
72
+ const creds = await mintCreds(auth, newIdentity(), "manager"); // privileged, ephemeral
73
+ return { confPath, creds };
74
+ }
75
+ //# sourceMappingURL=up.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"up.js","sourceRoot":"","sources":["../../src/commands/up.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function watch(argv: string[]): Promise<void>;
2
+ //# sourceMappingURL=watch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAKA,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmEzD"}
@@ -0,0 +1,63 @@
1
+ import { parseArgs } from "node:util";
2
+ import { readFileSync } from "node:fs";
3
+ import { CotalEndpoint, isReachable, DEFAULT_SERVER, chatWildcard } from "@cotal-ai/core";
4
+ import { c, statusBadge } from "../ui.js";
5
+ export async function watch(argv) {
6
+ const { values } = parseArgs({
7
+ args: argv,
8
+ allowPositionals: true,
9
+ options: { space: { type: "string" }, server: { type: "string" }, creds: { type: "string" } },
10
+ });
11
+ const space = values.space ?? "demo";
12
+ const server = values.server ?? DEFAULT_SERVER;
13
+ const creds = values.creds ? readFileSync(values.creds, "utf8") : undefined;
14
+ if (!(await isReachable(server, { creds }))) {
15
+ console.error(c.red(`Can't reach NATS at ${server}. Run: pnpm cotal up`));
16
+ process.exit(1);
17
+ }
18
+ const ep = new CotalEndpoint({
19
+ space,
20
+ servers: server,
21
+ creds,
22
+ channels: [],
23
+ consume: false, // observer: reads via tap + presence-watch, binds no durables
24
+ registerPresence: false,
25
+ watchPresence: true,
26
+ card: { name: "watch", kind: "endpoint" },
27
+ });
28
+ const ts = () => c.dim(new Date().toLocaleTimeString());
29
+ const who = (name, role) => `${c.bold(name)}${role ? c.dim("/" + role) : ""}`;
30
+ ep.on("presence", (ev) => {
31
+ const label = ev.type === "join"
32
+ ? c.green("join ")
33
+ : ev.type === "offline"
34
+ ? c.dim("offline")
35
+ : c.yellow("update ");
36
+ const activity = ev.presence.activity ? c.dim(" — " + ev.presence.activity) : "";
37
+ console.log(`${ts()} ${label} ${who(ev.presence.card.name, ev.presence.card.role)} ${statusBadge(ev.presence.status)}${activity}`);
38
+ });
39
+ ep.on("error", (e) => console.error(c.red("! " + e.message)));
40
+ await ep.start();
41
+ ep.tap((subject, msg) => {
42
+ if (!msg)
43
+ return;
44
+ const kind = subject.includes(".inst.")
45
+ ? c.magenta("unicast")
46
+ : subject.includes(".svc.")
47
+ ? c.yellow("anycast")
48
+ : c.cyan("chat ");
49
+ const text = msg.parts
50
+ ?.map((p) => (p.kind === "text" ? p.text : JSON.stringify(p.data)))
51
+ .join(" ");
52
+ const arrow = msg.to
53
+ ? c.dim(" → " + msg.to.slice(0, 8))
54
+ : msg.toService
55
+ ? c.dim(" → @" + msg.toService)
56
+ : "";
57
+ console.log(`${ts()} ${kind} ${who(msg.from?.name ?? "?", msg.from?.role)}${arrow}: ${text}`);
58
+ }, creds ? { subject: chatWildcard(space) } : undefined);
59
+ console.log(c.dim(`watching space ${c.bold(space)} — Ctrl-C to stop\n`));
60
+ process.on("SIGINT", () => void ep.stop().then(() => process.exit(0)));
61
+ await new Promise(() => { });
62
+ }
63
+ //# sourceMappingURL=watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** A live observability dashboard for a space, served over HTTP + SSE. A read-only
2
+ * observer endpoint (invisible to peers) feeds the page presence, channel history,
3
+ * and a live message stream — no manager required. Bound to loopback. */
4
+ export declare function web(argv: string[]): Promise<void>;
5
+ //# sourceMappingURL=web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/commands/web.ts"],"names":[],"mappings":"AA2BA;;0EAE0E;AAC1E,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyJvD"}
@@ -0,0 +1,187 @@
1
+ import { parseArgs } from "node:util";
2
+ import { spawn } from "node:child_process";
3
+ import { createServer } from "node:http";
4
+ import { readFileSync } from "node:fs";
5
+ import { fileURLToPath } from "node:url";
6
+ import { dirname, join } from "node:path";
7
+ import { CotalEndpoint, isReachable, DEFAULT_SERVER, deliveryOf, parseSubject, spaceWildcard, authDir, loadSpaceAuth, mintCreds, newIdentity, } from "@cotal-ai/core";
8
+ import { c } from "../ui.js";
9
+ const here = dirname(fileURLToPath(import.meta.url));
10
+ const PAGE = {
11
+ "/": { path: join(here, "../web/index.html"), type: "text/html; charset=utf-8" },
12
+ "/app.js": { path: join(here, "../web/app.js"), type: "text/javascript; charset=utf-8" },
13
+ };
14
+ /** A live observability dashboard for a space, served over HTTP + SSE. A read-only
15
+ * observer endpoint (invisible to peers) feeds the page presence, channel history,
16
+ * and a live message stream — no manager required. Bound to loopback. */
17
+ export async function web(argv) {
18
+ const { values } = parseArgs({
19
+ args: argv,
20
+ allowPositionals: true,
21
+ options: {
22
+ space: { type: "string" },
23
+ server: { type: "string" },
24
+ port: { type: "string" },
25
+ "no-open": { type: "boolean" },
26
+ creds: { type: "string" },
27
+ },
28
+ });
29
+ const space = values.space ?? "demo";
30
+ const server = values.server ?? DEFAULT_SERVER;
31
+ const port = values.port ? Number(values.port) : 7799;
32
+ // The dashboard is always an admin god-view (no read-only viewer mode) so it can show DMs
33
+ // and anycast. Auth mode (`.cotal/auth` present): self-mint an `admin` cred so it joins the
34
+ // authed mesh with no manual --creds — like `cotal spawn`, it holds the space signing key.
35
+ // An explicit --creds still wins. Open mode (no auth): connect bare.
36
+ let creds = values.creds ? readFileSync(values.creds, "utf8") : undefined;
37
+ if (!creds) {
38
+ const auth = loadSpaceAuth(authDir(process.cwd()));
39
+ if (auth) {
40
+ if (auth.space !== space) {
41
+ console.error(c.red(`Auth here is for space "${auth.space}", not "${space}". Use --space ${auth.space} (or pass --creds).`));
42
+ process.exit(1);
43
+ }
44
+ creds = await mintCreds(auth, newIdentity(), "admin");
45
+ }
46
+ }
47
+ if (!(await isReachable(server, { creds }))) {
48
+ console.error(c.red(`Can't reach NATS at ${server}. Run: pnpm cotal up`));
49
+ process.exit(1);
50
+ }
51
+ // Observer: never registers presence, never consumes an inbox — invisible to peers.
52
+ const ep = new CotalEndpoint({
53
+ space,
54
+ servers: server,
55
+ creds,
56
+ channels: [],
57
+ consume: false, // observer: reads via tap + history + presence-watch, binds no durables
58
+ registerPresence: false,
59
+ watchPresence: true,
60
+ card: { name: "web", kind: "endpoint" },
61
+ });
62
+ ep.on("error", (e) => console.error(c.red("! " + e.message)));
63
+ await ep.start();
64
+ const clients = new Set();
65
+ const send = (res, event, data) => res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
66
+ const broadcast = (event, data) => {
67
+ for (const res of clients)
68
+ if (!res.writableEnded)
69
+ send(res, event, data);
70
+ };
71
+ // Presence changes → push the whole roster; the client just re-renders it.
72
+ ep.on("presence", () => broadcast("roster", ep.getRoster()));
73
+ // Every comm on the mesh (chat / unicast / anycast) → push to the live feed. The admin cred
74
+ // allows the whole space, so the observer taps everything — DMs + anycast included.
75
+ const tapSubject = spaceWildcard(space);
76
+ ep.tap((subject, msg) => {
77
+ const mode = deliveryOf(subject);
78
+ if (!mode || !msg)
79
+ return;
80
+ // senderId is the subject's sender token — the *verified* publisher (the server
81
+ // policed who could publish it), vs the advisory `from` in the payload.
82
+ const senderId = parseSubject(subject)?.sender;
83
+ broadcast("message", { mode, senderId, msg });
84
+ }, { subject: tapSubject });
85
+ const httpServer = createServer(async (req, res) => {
86
+ const path = (req.url ?? "/").split("?")[0];
87
+ const query = new URLSearchParams((req.url ?? "").split("?")[1] ?? "");
88
+ if (path === "/feed") {
89
+ res.writeHead(200, {
90
+ "content-type": "text/event-stream",
91
+ "cache-control": "no-cache",
92
+ connection: "keep-alive",
93
+ });
94
+ clients.add(res);
95
+ send(res, "roster", ep.getRoster());
96
+ req.on("close", () => clients.delete(res));
97
+ return;
98
+ }
99
+ if (path === "/api/meta")
100
+ return json(res, { space });
101
+ if (path === "/api/roster")
102
+ return json(res, ep.getRoster());
103
+ if (path === "/api/channels")
104
+ return json(res, await ep.listChannels());
105
+ if (path === "/api/activity") {
106
+ // Backfill the all-activity feed: merge recent channel history with DM history (the live
107
+ // SSE tap only carries messages from after a client connects). Entries are mode-tagged
108
+ // ({mode, msg}) to match the live feed so DMs render as DMs.
109
+ const limit = query.get("limit") ? Number(query.get("limit")) : 200;
110
+ const chans = await ep.listChannels();
111
+ const chat = (await Promise.all(chans.map((ch) => ep.channelHistory(ch.channel, { limit }))))
112
+ .flat()
113
+ .map((msg) => ({ mode: "chat", msg }));
114
+ const dms = (await ep.dmHistory({ limit })).map((msg) => ({ mode: "unicast", msg }));
115
+ const all = [...chat, ...dms].sort((a, b) => a.msg.ts - b.msg.ts);
116
+ return json(res, all.slice(-limit));
117
+ }
118
+ if (path === "/api/dms") {
119
+ // DM history for the Direct-messages lens (god-view); the client groups it by peer/pair.
120
+ const limit = query.get("limit") ? Number(query.get("limit")) : 500;
121
+ return json(res, await ep.dmHistory({ limit }));
122
+ }
123
+ if (path.startsWith("/api/channels/") && path.endsWith("/history")) {
124
+ const name = decodeURIComponent(path.slice("/api/channels/".length, -"/history".length));
125
+ const limit = query.get("limit") ? Number(query.get("limit")) : 200;
126
+ return json(res, await ep.channelHistory(name, { limit }));
127
+ }
128
+ const file = PAGE[path];
129
+ if (file) {
130
+ res.writeHead(200, { "content-type": file.type });
131
+ res.end(readFileSync(file.path));
132
+ return;
133
+ }
134
+ res.writeHead(404).end("not found");
135
+ });
136
+ // Comment ping keeps idle SSE connections alive through proxies.
137
+ const ping = setInterval(() => {
138
+ for (const res of clients)
139
+ if (!res.writableEnded)
140
+ res.write(": ping\n\n");
141
+ }, 20_000);
142
+ httpServer.on("error", (e) => {
143
+ if (e.code === "EADDRINUSE")
144
+ console.error(c.red(`Port ${port} is in use. Pass --port <n>.`));
145
+ else
146
+ console.error(c.red("! " + e.message));
147
+ process.exit(1);
148
+ });
149
+ await new Promise((resolve) => httpServer.listen(port, "127.0.0.1", resolve));
150
+ const url = `http://127.0.0.1:${port}/`;
151
+ console.log(`${c.bold("Cotal web")} — observing space ${c.bold(space)}`);
152
+ console.log(c.dim(" god-view — DMs + anycast visible"));
153
+ console.log(` ${c.cyan(url)} ${c.dim("(Ctrl-C to stop)")}`);
154
+ if (!values["no-open"])
155
+ openBrowser(url);
156
+ const shutdown = async () => {
157
+ clearInterval(ping);
158
+ for (const res of clients)
159
+ res.end();
160
+ httpServer.close();
161
+ await ep.stop();
162
+ process.exit(0);
163
+ };
164
+ process.on("SIGINT", () => void shutdown());
165
+ process.on("SIGTERM", () => void shutdown());
166
+ await new Promise(() => { });
167
+ }
168
+ function json(res, data) {
169
+ res.writeHead(200, { "content-type": "application/json" });
170
+ res.end(JSON.stringify(data));
171
+ }
172
+ /** Best-effort open of the dashboard in the default browser. The URL is already
173
+ * printed, so a failure here is harmless — never block startup on it. */
174
+ function openBrowser(url) {
175
+ const [cmd, args] = process.platform === "darwin"
176
+ ? ["open", [url]]
177
+ : process.platform === "win32"
178
+ ? ["cmd", ["/c", "start", "", url]]
179
+ : ["xdg-open", [url]];
180
+ try {
181
+ spawn(cmd, args, { stdio: "ignore", detached: true }).unref();
182
+ }
183
+ catch {
184
+ /* no opener on this platform — the printed URL is the fallback */
185
+ }
186
+ }
187
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/commands/web.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { runCli } from "./command.js";
2
+ export { c, statusBadge } from "./ui.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoEA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,67 @@
1
+ import { registry } from "@cotal-ai/core";
2
+ import { up } from "./commands/up.js";
3
+ import { join } from "./commands/join.js";
4
+ import { watch } from "./commands/watch.js";
5
+ import { console_ } from "./commands/console.js";
6
+ import { web } from "./commands/web.js";
7
+ import { spawn } from "./commands/spawn.js";
8
+ import { mint } from "./commands/mint.js";
9
+ /** The minimal mesh CLI: thin NATS clients (up/join/watch), plus `spawn` — a
10
+ * foreground agent launch that reuses the connector's launch recipe. Self-registers
11
+ * on import; heavier surfaces (the manager's control plane) register the same way
12
+ * and are composed at a root. */
13
+ const baseCommands = [
14
+ {
15
+ kind: "command",
16
+ name: "up",
17
+ group: "Mesh",
18
+ summary: "start a local nats-server (JetStream, JWT auth by default; --open for an unauthenticated dev mesh)",
19
+ run: up,
20
+ },
21
+ {
22
+ kind: "command",
23
+ name: "join",
24
+ group: "Mesh",
25
+ summary: "join a space (interactive) — --space <s> --name <n> [--role <r>]",
26
+ run: join,
27
+ },
28
+ {
29
+ kind: "command",
30
+ name: "watch",
31
+ group: "Mesh",
32
+ summary: "observe all activity in a space — --space <s>",
33
+ run: watch,
34
+ },
35
+ {
36
+ kind: "command",
37
+ name: "console",
38
+ group: "Mesh",
39
+ summary: "live agent dashboard for a space — --space <s> [--plain]",
40
+ run: console_,
41
+ },
42
+ {
43
+ kind: "command",
44
+ name: "web",
45
+ group: "Mesh",
46
+ summary: "browser observability dashboard — presence, channels, live feed — --space <s> [--port <n>] [--no-open]",
47
+ run: web,
48
+ },
49
+ {
50
+ kind: "command",
51
+ name: "spawn",
52
+ group: "Agents",
53
+ summary: "launch an agent in this terminal from a file — spawn <name-or-path> | --name <n> --config <path> [--agent <a>] [--role <r>]",
54
+ run: spawn,
55
+ },
56
+ {
57
+ kind: "command",
58
+ name: "mint",
59
+ group: "Mesh",
60
+ summary: "mint a creds file for a space (auth mode) — mint <name> --profile <agent|observer> [--out <path>]",
61
+ run: mint,
62
+ },
63
+ ];
64
+ registry.register(...baseCommands);
65
+ export { runCli } from "./command.js";
66
+ export { c, statusBadge } from "./ui.js";
67
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAgB,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C;;;kCAGkC;AAClC,MAAM,YAAY,GAAc;IAC9B;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,oGAAoG;QAC7G,GAAG,EAAE,EAAE;KACR;IACD;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,kEAAkE;QAC3E,GAAG,EAAE,IAAI;KACV;IACD;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,+CAA+C;QACxD,GAAG,EAAE,KAAK;KACX;IACD;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,0DAA0D;QACnE,GAAG,EAAE,QAAQ;KACd;IACD;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,wGAAwG;QACjH,GAAG,EAAE,GAAG;KACT;IACD;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,QAAQ;QACf,OAAO,EACL,6HAA6H;QAC/H,GAAG,EAAE,KAAK;KACX;IACD;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,mGAAmG;QAC5G,GAAG,EAAE,IAAI;KACV;CACF,CAAC;AAEF,QAAQ,CAAC,QAAQ,CAAC,GAAG,YAAY,CAAC,CAAC;AAEnC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { CotalEndpoint, Presence, CotalMessage } from "@cotal-ai/core";
2
+ export declare function agentColor(name: string): (s: string) => string;
3
+ export declare function ago(epochMs: number): string;
4
+ export declare class RosterIndex {
5
+ list: Presence[];
6
+ private byId;
7
+ constructor(ep: CotalEndpoint, onChange?: () => void);
8
+ nameOf(id: string): string;
9
+ }
10
+ /** A rendered message split into pieces so consumers can lay it out (e.g. hanging wrap). */
11
+ export interface LogEntry {
12
+ /** Raw timestamp (no ANSI) — its visible width sets the hanging indent. */
13
+ time: string;
14
+ /** Colored `sender → target:` prefix. */
15
+ head: string;
16
+ /** The message body. */
17
+ body: string;
18
+ }
19
+ /** Groups same-sender, same-text unicast bursts into one line; passes everything else through. */
20
+ export declare class Fanout {
21
+ private onEntry;
22
+ private nameOf;
23
+ private pending;
24
+ constructor(onEntry: (e: LogEntry) => void, nameOf: (id: string) => string);
25
+ add(subject: string, msg: CotalMessage): void;
26
+ private flush;
27
+ stop(): void;
28
+ }
29
+ /** Wires the endpoint (not yet started) into the classic log and parks until SIGINT. */
30
+ export declare function runLog(ep: CotalEndpoint, space: string, tapSubject?: string): Promise<void>;
31
+ export declare function runDashboard(ep: CotalEndpoint, space: string, tapSubject?: string): Promise<void>;
32
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAiB,YAAY,EAAe,MAAM,gBAAgB,CAAC;AAWxG,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAS9D;AASD,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG3C;AAUD,qBAAa,WAAW;IACtB,IAAI,EAAE,QAAQ,EAAE,CAAM;IACtB,OAAO,CAAC,IAAI,CAA6B;gBAC7B,EAAE,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,MAAM,IAAI;IAWpD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;CAG3B;AAMD,4FAA4F;AAC5F,MAAM,WAAW,QAAQ;IACvB,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,kGAAkG;AAClG,qBAAa,MAAM;IAMf,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,MAAM;IANhB,OAAO,CAAC,OAAO,CAGX;gBAEM,OAAO,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,IAAI,EAC9B,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM;IAGxC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,IAAI;IAwB7C,OAAO,CAAC,KAAK;IASb,IAAI,IAAI,IAAI;CAIb;AAiBD,wFAAwF;AACxF,wBAAsB,MAAM,CAAC,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBjG;AA4CD,wBAAsB,YAAY,CAAC,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsKvG"}
package/dist/render.js ADDED
Binary file