@cotal-ai/manager 0.15.0 → 0.17.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 (53) hide show
  1. package/dist/attach-endpoint.d.ts +53 -59
  2. package/dist/attach-endpoint.d.ts.map +1 -1
  3. package/dist/attach-endpoint.js +120 -244
  4. package/dist/attach-endpoint.js.map +1 -1
  5. package/dist/commands.js +9 -4
  6. package/dist/commands.js.map +1 -1
  7. package/dist/console/app.js +68 -30
  8. package/dist/console/index.html +3 -2
  9. package/dist/console/session-bundle.js +9736 -0
  10. package/dist/console-crypto-shim.d.ts +16 -0
  11. package/dist/console-crypto-shim.d.ts.map +1 -0
  12. package/dist/console-crypto-shim.js +20 -0
  13. package/dist/console-crypto-shim.js.map +1 -0
  14. package/dist/console-session-entry.d.ts +2 -0
  15. package/dist/console-session-entry.d.ts.map +1 -0
  16. package/dist/console-session-entry.js +26 -0
  17. package/dist/console-session-entry.js.map +1 -0
  18. package/dist/endpoint-evict.d.ts +29 -0
  19. package/dist/endpoint-evict.d.ts.map +1 -0
  20. package/dist/endpoint-evict.js +80 -0
  21. package/dist/endpoint-evict.js.map +1 -0
  22. package/dist/manager-service-contract.d.ts +132 -0
  23. package/dist/manager-service-contract.d.ts.map +1 -0
  24. package/dist/manager-service-contract.js +332 -0
  25. package/dist/manager-service-contract.js.map +1 -0
  26. package/dist/manager.d.ts +504 -22
  27. package/dist/manager.d.ts.map +1 -1
  28. package/dist/manager.js +2193 -257
  29. package/dist/manager.js.map +1 -1
  30. package/dist/runtime/pty.d.ts.map +1 -1
  31. package/dist/runtime/pty.js +15 -2
  32. package/dist/runtime/pty.js.map +1 -1
  33. package/dist/session/bridge.d.ts +63 -0
  34. package/dist/session/bridge.d.ts.map +1 -0
  35. package/dist/session/bridge.js +157 -0
  36. package/dist/session/bridge.js.map +1 -0
  37. package/dist/session/establish.d.ts +212 -0
  38. package/dist/session/establish.d.ts.map +1 -0
  39. package/dist/session/establish.js +174 -0
  40. package/dist/session/establish.js.map +1 -0
  41. package/dist/session/index.d.ts +12 -0
  42. package/dist/session/index.d.ts.map +1 -0
  43. package/dist/session/index.js +15 -0
  44. package/dist/session/index.js.map +1 -0
  45. package/dist/session/plane.d.ts +120 -0
  46. package/dist/session/plane.d.ts.map +1 -0
  47. package/dist/session/plane.js +327 -0
  48. package/dist/session/plane.js.map +1 -0
  49. package/dist/static-lifecycle.d.ts +97 -0
  50. package/dist/static-lifecycle.d.ts.map +1 -0
  51. package/dist/static-lifecycle.js +262 -0
  52. package/dist/static-lifecycle.js.map +1 -0
  53. package/package.json +9 -5
@@ -1,13 +1,9 @@
1
- import type { AgentHandle } from "./runtime/index.js";
2
1
  /**
3
- * The address the attach endpoint binds and advertises: the host of the mesh broker this manager is
4
- * attached to. Keeping the two in step is the whole point — a client that reached the control plane
5
- * to request an attach URL demonstrably has a route to that address, whereas a hardcoded
6
- * `127.0.0.1` resolves to the client's own machine.
2
+ * The address the console endpoint binds and advertises, derived from a mesh broker URL.
7
3
  *
8
4
  * With no server URL there is no mesh address to follow, so this is loopback: the conservative
9
- * default and exactly the endpoint's previous behavior. An unparseable URL is a caller bug and
10
- * throws rather than quietly binding somewhere the operator did not ask for.
5
+ * default. An unparseable URL is a caller bug and throws rather than quietly binding somewhere the
6
+ * operator did not ask for.
11
7
  */
12
8
  export declare function attachHost(servers: string | undefined): string;
13
9
  /** One Server-Sent-Events frame: a named event carrying JSON data. */
@@ -15,81 +11,79 @@ export interface FeedEvent {
15
11
  event: string;
16
12
  data: unknown;
17
13
  }
14
+ /** What `POST /session/<name>` returns: the console's mesh §13.6 session establishment (P2 item 6).
15
+ * The `grant` is the holder-bound offer (no ws:// URL, non-bearer); `wsUrl` is the broker's
16
+ * localhost websocket listener; `creds` is the per-session, rails-only session-caller credential the
17
+ * browser connects with. NO 127.0.0.1 terminal transport — the terminal rides the mesh session. */
18
+ export interface SessionEstablishment {
19
+ grant: unknown;
20
+ wsUrl: string;
21
+ creds: string;
22
+ }
23
+ /** The manager-injected session establisher (P2 item 6): given a managed agent name, mint the offer
24
+ * through the ONE {@link import("./session/plane.js").ManagerSessionPlane} + the per-session caller
25
+ * credential, and return what the browser needs to connect. INJECTED — the face never constructs a
26
+ * plane; the manager wires the single plane + the cred mint at boot (6b-2). Absent ⇒ the route 503s
27
+ * (an open mesh with no console session client, or the pre-6b-2 stub). */
28
+ export type SessionEstablisher = (name: string) => Promise<SessionEstablishment>;
18
29
  /**
19
- * The manager's local HTTP + WebSocket face. It hosts the **console** (a
20
- * lightweight xterm.js page) and bridges each agent's PTY to the browser and to
21
- * `cotal attach` over a direct socket, never the mesh, so owning the terminal
22
- * keeps the manager off the message hot path.
23
- *
24
- * **Where it binds, and why it is credentialed.** A mesh can span machines: the manager that owns an
25
- * agent's PTY may sit on another host than the operator running `cotal attach`. Hardcoding
26
- * `127.0.0.1` made every remote attach fail with ECONNREFUSED against the *client's own* loopback.
27
- * The bind address is therefore an explicit option (default loopback, so nothing is exposed by
28
- * accident); `cotal up` passes the address it bound the broker to. A broker DIAL address is
29
- * deliberately NOT used as the bind: a manager may supervise a broker on another host and could not
30
- * bind that address at all. Where the manager can only name loopback (a wildcard bind), the CLIENT
31
- * substitutes the broker address its own control connection reached.
30
+ * The manager's local HTTP face. It serves the **console** (a lightweight xterm.js page + its
31
+ * assets) and is the browser's credential broker: `POST /session/<name>` mints a mesh §13.6 session
32
+ * for the console to drive the terminal over the broker's WebSocket listener. The terminal never
33
+ * rides a manager-hosted socket (P2 item 6 replaced the loopback `ws://.../attach/` transport with
34
+ * the mesh session, closing the bearer-less-local hole) — `cotal attach` reaches a manager on
35
+ * another machine over the mesh, not by dialing this face.
32
36
  *
33
- * Reachability is why the surface is credentialed, in two tiers. This face carries terminal READ AND
34
- * WRITE for every managed agent, plus the roster and the live feed, so once it can leave the box
35
- * "unauthenticated but loopback-only" stops being a safe position.
37
+ * **Where it binds, and why it is credentialed.** The bind address is an explicit option (default
38
+ * loopback, so nothing is exposed by accident); `cotal up` passes the address it bound the broker
39
+ * to when the operator asked for an exposed console. A broker DIAL address is deliberately NOT used
40
+ * as the bind: a manager may supervise a broker on another host and could not bind that address at
41
+ * all. Where the manager can only name loopback (a wildcard bind), it advertises loopback.
36
42
  *
37
- * - **Attach tickets** are what a mesh caller gets: minted per authorized `attach` request, bound to
38
- * the ONE agent the manager just authorized, single-use, short-lived. This is what makes the
39
- * per-agent/owner check real a manager-wide token would let a caller authorized for its own
40
- * agent swap the path and take over anyone's terminal.
41
- * - **The console token** is the operator's own: it reaches every agent, because the console
42
- * legitimately drives all of them, and it is printed solely to this manager process's output
43
- * (so it is as sensitive as `.cotal/manager.log`, and never handed to a mesh caller).
43
+ * Reachability is why the surface is credentialed. It carries the managed roster, the live mesh
44
+ * feed, and — through `POST /session/<name>` — the mint of a real §13.6 session grant plus its
45
+ * per-session caller credential. Once the face can leave the box, "unauthenticated but
46
+ * loopback-only" stops being a safe position, so every DATA route requires the manager's console
47
+ * token. The console SHELL (its HTML, its script, the vendored xterm assets) is static and carries
48
+ * nothing about this mesh, so it stays open — that is what lets the page load and then present the
49
+ * token, held in memory from its own URL, on the requests that do matter.
44
50
  *
45
- * Credentials travel in `?t=` or a bearer header, never a cookie: cookies are host-scoped, not
51
+ * The credential travels in `?t=` or a bearer header, never a cookie: cookies are host-scoped, not
46
52
  * port-scoped, so one set here would be sent to every other HTTP service on this host and would
47
53
  * collide between two managers on one box. The console URL carries its token in the FRAGMENT, which
48
54
  * a browser never sends to a server.
49
55
  *
50
- * Routes: `GET /` console page, `GET /agents` the managed roster (JSON),
51
- * `GET /feed` the live mesh feed (SSE: presence roster + comms), static assets
52
- * under `/assets`, and `WS /attach/<name>` the PTY stream.
53
- *
54
- * Attach protocol: server → client sends raw terminal bytes (binary). client →
55
- * server: binary frames are keystrokes; a text frame `r:<cols>,<rows>` resizes.
56
+ * Routes: `GET /` console page + `/app.js` + `/session-bundle.js` + `/assets/*`; `GET /agents` the
57
+ * managed roster (JSON); `GET /feed` the live mesh feed (SSE: presence roster + comms);
58
+ * `POST /session/<name>` the mesh session establishment.
56
59
  */
57
60
  export declare class AttachEndpoint {
58
61
  #private;
59
- private readonly lookup;
60
62
  private readonly list;
61
63
  /** Events replayed to each console as it connects to `/feed` (e.g. the current roster). */
62
64
  private readonly snapshot;
63
- /** The endpoint credential. Generated per manager process; required on every route. */
65
+ /** P2 item 6: the manager-injected mesh-session establisher backing `POST /session/<name>`
66
+ * (the console's session-client transport). Absent ⇒ the route 503s. Wired at 6b-2. */
67
+ private readonly establishSession?;
68
+ /** The endpoint credential. Generated per manager process; required on every data route. */
64
69
  private readonly token;
65
- constructor(lookup: (name: string) => AgentHandle | undefined, list: () => unknown,
70
+ constructor(list: () => unknown,
66
71
  /** Events replayed to each console as it connects to `/feed` (e.g. the current roster). */
67
72
  snapshot: () => FeedEvent[], port?: number,
68
- /** Bind address, and the host advertised in {@link url} / {@link consoleUrl}. Defaults to
69
- * loopback; the manager passes the mesh broker's host so attach is reachable from wherever the
70
- * mesh is. A wildcard bind still advertises loopback, since a wildcard is not a dialable name. */
73
+ /** P2 item 6: the manager-injected mesh-session establisher backing `POST /session/<name>`
74
+ * (the console's session-client transport). Absent the route 503s. Wired at 6b-2. */
75
+ establishSession?: SessionEstablisher | undefined,
76
+ /** Bind address, and the host advertised in {@link consoleUrl}. Defaults to loopback; the
77
+ * manager passes an operator-chosen address when the console is meant to be reachable from
78
+ * another machine. A wildcard bind still advertises loopback, since a wildcard is not a
79
+ * dialable name. */
71
80
  host?: string,
72
- /** The endpoint credential. Generated per manager process; required on every route. */
81
+ /** The endpoint credential. Generated per manager process; required on every data route. */
73
82
  token?: string);
74
83
  start(): Promise<void>;
75
84
  stop(): Promise<void>;
76
85
  /** Push a named event to every connected console (SSE). */
77
86
  publish(event: string, data: unknown): void;
78
- /**
79
- * The ws URL a client uses to attach to `name`, carrying a capability bound to THAT agent.
80
- *
81
- * Called once per authorized control-plane `attach` request, so the ticket inherits exactly the
82
- * authorization the manager just performed for this caller and this agent. It is single-use and
83
- * short-lived: the client redeems it immediately, and a leaked URL (shell history, a log, a
84
- * `Referer`) is spent or expired rather than a standing key to someone's terminal.
85
- *
86
- * `expected` is the handle the caller actually authorized, and it is REQUIRED. A name is a reusable
87
- * slot, and authorization is async (a user-mode ledger read), so between the caller resolving the
88
- * name and arriving here the slot can have been stopped and refilled by a same-name successor.
89
- * Re-resolving the name would then mint a valid ticket for an agent nobody authorized. Binding to
90
- * the caller's own handle closes that window: if the slot moved, there is no capability to issue.
91
- */
92
- url(name: string, expected: AgentHandle): string;
93
87
  /** The console page URL. The token rides the FRAGMENT, which a browser never sends to a server:
94
88
  * it stays out of this endpoint's request handling, out of any proxy's logs, and out of the
95
89
  * `Referer` a click on the page would otherwise leak. The page reads it from `location.hash` and
@@ -1 +1 @@
1
- {"version":3,"file":"attach-endpoint.d.ts","sourceRoot":"","sources":["../src/attach-endpoint.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAmBtD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAW9D;AAOD,sEAAsE;AACtE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,qBAAa,cAAc;;IAYvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,2FAA2F;IAC3F,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAMzB,uFAAuF;IACvF,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAVL,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,EACjD,IAAI,EAAE,MAAM,OAAO;IACpC,2FAA2F;IAC1E,QAAQ,EAAE,MAAM,SAAS,EAAE,EAC5C,IAAI,SAAI;IACR;;uGAEmG;IACnG,IAAI,SAAc;IAClB,uFAAuF;IACtE,KAAK,GAAE,MAAwC;IA4F5D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkCtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,2DAA2D;IAC3D,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI;IAW3C;;;;;;;;;;;;;OAaG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,MAAM;IAWhD;;;;sCAIkC;IAClC,UAAU,IAAI,MAAM;CAmKrB"}
1
+ {"version":3,"file":"attach-endpoint.d.ts","sourceRoot":"","sources":["../src/attach-endpoint.ts"],"names":[],"mappings":"AA4BA;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAW9D;AAED,sEAAsE;AACtE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;oGAGoG;AACpG,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;2EAI2E;AAC3E,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAEjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,cAAc;;IAQvB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,2FAA2F;IAC3F,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAEzB;4FACwF;IACxF,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAMlC,4FAA4F;IAC5F,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAbL,IAAI,EAAE,MAAM,OAAO;IACpC,2FAA2F;IAC1E,QAAQ,EAAE,MAAM,SAAS,EAAE,EAC5C,IAAI,SAAI;IACR;4FACwF;IACvE,gBAAgB,CAAC,EAAE,kBAAkB,YAAA;IACtD;;;yBAGqB;IACrB,IAAI,SAAc;IAClB,4FAA4F;IAC3E,KAAK,GAAE,MAAwC;IAsC5D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgCtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,2DAA2D;IAC3D,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI;IAW3C;;;;sCAIkC;IAClC,UAAU,IAAI,MAAM;CA8IrB"}