@north-light/crouter 0.3.320 → 0.3.322

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 (119) hide show
  1. package/bin/runtime-selector.mjs +52 -3
  2. package/dist/api/client.d.ts +31 -17
  3. package/dist/api/client.js +2 -2
  4. package/dist/api/dto/broker-ops.d.ts +0 -1
  5. package/dist/api/dto/modelauth.d.ts +15 -0
  6. package/dist/api/dto/node-outcomes.d.ts +6 -0
  7. package/dist/api/dto/nodes.d.ts +4 -3
  8. package/dist/api/dto/review-comments.d.ts +8 -0
  9. package/dist/api/errors.d.ts +6 -3
  10. package/dist/api/errors.js +1 -1
  11. package/dist/api/index.d.ts +2 -2
  12. package/dist/api/index.js +1 -1
  13. package/dist/api/node-transport.d.ts +18 -0
  14. package/dist/api/node-transport.js +1 -0
  15. package/dist/api/routes.d.ts +2 -0
  16. package/dist/api/routes.js +1 -1
  17. package/dist/builtin-memory/crouter-sdk.md +86 -0
  18. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +1 -1
  19. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +1 -1
  20. package/dist/cli.js +8 -2
  21. package/dist/clients/attach/render/chat-view.d.ts +5 -1
  22. package/dist/clients/attach/render/chat-view.js +1 -1
  23. package/dist/clients/attach/session/frames.d.ts +1 -0
  24. package/dist/clients/attach/session/frames.js +1 -1
  25. package/dist/clients/attach/viewer.js +606 -606
  26. package/dist/clients/inbox/review/comments-client.d.ts +8 -1
  27. package/dist/clients/inbox/review/comments-client.js +1 -1
  28. package/dist/clients/inbox/review/companion-pane.d.ts +17 -0
  29. package/dist/clients/inbox/review/companion-pane.js +1 -1
  30. package/dist/clients/inbox/review/document-surface.d.ts +10 -0
  31. package/dist/clients/inbox/review/document-surface.js +2 -2
  32. package/dist/clients/inbox/review/frame.js +1 -1
  33. package/dist/clients/inbox/review/keys.d.ts +2 -0
  34. package/dist/clients/inbox/review/keys.js +1 -1
  35. package/dist/commands/api-client.js +3 -3
  36. package/dist/commands/human/prompts.js +1 -1
  37. package/dist/commands/memory/read.js +2 -2
  38. package/dist/commands/sys/branch.js +1 -1
  39. package/dist/commands/sys/connect.d.ts +1 -0
  40. package/dist/commands/sys/connect.js +3 -0
  41. package/dist/commands/sys/daemon.js +1 -1
  42. package/dist/commands/sys/panels/provider-panel.js +1 -1
  43. package/dist/commands/sys/provider-login.d.ts +8 -0
  44. package/dist/commands/sys/provider-login.js +9 -0
  45. package/dist/commands/sys/setup-core.d.ts +4 -0
  46. package/dist/commands/sys/setup-core.js +4 -4
  47. package/dist/commands/sys.js +1 -1
  48. package/dist/core/canvas/browse/app.js +3 -3
  49. package/dist/core/canvas/canvas.d.ts +3 -3
  50. package/dist/core/canvas/canvas.js +17 -14
  51. package/dist/core/canvas/migrations.js +34 -27
  52. package/dist/core/canvas/node-sql-migration.d.ts +1 -0
  53. package/dist/core/canvas/node-sql-migration.js +28 -2
  54. package/dist/core/canvas/paths.d.ts +8 -4
  55. package/dist/core/canvas/paths.js +1 -1
  56. package/dist/core/canvas/recovery.d.ts +1 -0
  57. package/dist/core/canvas/recovery.js +1 -1
  58. package/dist/core/canvas/worktrees.d.ts +1 -0
  59. package/dist/core/canvas/worktrees.js +1 -1
  60. package/dist/core/config.js +1 -1
  61. package/dist/core/human/requests.d.ts +1 -0
  62. package/dist/core/human/requests.js +17 -13
  63. package/dist/core/review/fork.d.ts +8 -0
  64. package/dist/core/review/fork.js +5 -0
  65. package/dist/core/runtime/broker/daemon-ops.js +1 -1
  66. package/dist/core/runtime/broker/extension-abort.d.ts +3 -0
  67. package/dist/core/runtime/broker/extension-abort.js +1 -1
  68. package/dist/core/runtime/broker.js +1 -1
  69. package/dist/core/runtime/spawn.d.ts +5 -1
  70. package/dist/core/runtime/spawn.js +2 -2
  71. package/dist/core/runtime/stop-guard.d.ts +1 -3
  72. package/dist/core/runtime/stop-guard.js +2 -2
  73. package/dist/core/runtime/stop-signals.d.ts +0 -1
  74. package/dist/core/runtime/stop-signals.js +1 -1
  75. package/dist/core/secrets.d.ts +3 -0
  76. package/dist/core/secrets.js +2 -2
  77. package/dist/core/subscription-state.d.ts +1 -1
  78. package/dist/core/subscription-state.js +3 -3
  79. package/dist/core/termrender/termrender.d.ts +3 -1
  80. package/dist/core/termrender/termrender.js +13 -13
  81. package/dist/core/user-settings.d.ts +4 -0
  82. package/dist/core/user-settings.js +1 -1
  83. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  84. package/dist/daemon/api/handlers/health.d.ts +1 -1
  85. package/dist/daemon/api/handlers/health.js +14 -1
  86. package/dist/daemon/api/handlers/inbox.js +1 -1
  87. package/dist/daemon/api/handlers/modelauth.js +1 -1
  88. package/dist/daemon/api/handlers/review-comments.js +1 -1
  89. package/dist/daemon/api/map.d.ts +4 -2
  90. package/dist/daemon/api/map.js +2 -2
  91. package/dist/daemon/api/server.d.ts +5 -1
  92. package/dist/daemon/api/server.js +4 -4
  93. package/dist/daemon/companion-retire.d.ts +3 -1
  94. package/dist/daemon/companion-retire.js +1 -1
  95. package/dist/daemon/crtrd-cli.js +1 -1
  96. package/dist/daemon/crtrd.js +7 -7
  97. package/dist/daemon/human/finish.d.ts +4 -1
  98. package/dist/daemon/human/finish.js +7 -7
  99. package/dist/daemon/human/settle.d.ts +8 -6
  100. package/dist/daemon/human/settle.js +1 -1
  101. package/dist/daemon/manage.d.ts +1 -0
  102. package/dist/daemon/manage.js +2 -2
  103. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  104. package/dist/pi-extensions/canvas-inbox-watcher.js +1 -1
  105. package/dist/pi-extensions/canvas-stophook.js +1 -1
  106. package/dist/types.d.ts +7 -0
  107. package/dist/types.js +1 -1
  108. package/docs/sdk/README.md +54 -0
  109. package/docs/sdk/client.md +92 -0
  110. package/docs/sdk/docker.md +63 -0
  111. package/docs/sdk/errors.md +85 -0
  112. package/docs/sdk/getting-started.md +160 -0
  113. package/docs/sdk/memory.md +107 -0
  114. package/docs/sdk/migration.md +108 -0
  115. package/docs/sdk/nodes.md +193 -0
  116. package/docs/sdk/resources.md +71 -0
  117. package/docs/sdk/streaming.md +124 -0
  118. package/package.json +1 -1
  119. package/runtime.lock.json +6 -6
@@ -0,0 +1,124 @@
1
+ > **Phase 2 — not shipped.** Nothing on this page exists yet. There is no HTTP streaming route on the daemon today, and `client.nodes.stream` and `client.nodes.events` are not on the client. Until phase 2 lands, an application shows progress with `client.nodes.reports.list` and gets the result with `client.nodes.waitForOutcome`.
2
+
3
+ # Streaming
4
+
5
+ Watch a run as it works: assistant text as it is produced, tool calls as they start and finish, reports as they are pushed, and the settled outcome.
6
+
7
+ ## The SDK surface
8
+
9
+ <!-- TODO(verify): run against a live daemon once phase 2 lands. -->
10
+
11
+ ```ts
12
+ const stream = client.nodes.stream({ prompt: 'Fix the failing test', cwd });
13
+
14
+ stream.on('node.output_text.delta', (e) => process.stdout.write(e.delta));
15
+
16
+ for await (const event of stream) {
17
+ // the same events, typed by `type`
18
+ }
19
+
20
+ const outcome = await stream.finalOutcome(); // resolves on node.settled
21
+ stream.abort(); // ends the HTTP response; the node keeps running
22
+ ```
23
+
24
+ | Member | Behaviour |
25
+ |---|---|
26
+ | `client.nodes.stream(params)` | Creates the node, then opens its event stream. Returns **synchronously**; `stream.node` is a promise for the created node. |
27
+ | `client.nodes.events(id, { after?, signal? })` | Streams a node that already exists. |
28
+ | `.on(type, cb)` / `.off(type, cb)` | Typed event emitter. |
29
+ | `[Symbol.asyncIterator]` | Yields the same typed events. |
30
+ | `.finalOutcome()` | Resolves with the `NodeOutcome` from `node.settled`; rejects on a terminal `error` event. |
31
+ | `.abort()` / `signal` | Aborts the underlying `fetch`. Raises `APIUserAbortError` in an in-flight iteration. |
32
+
33
+ The method is called `events`, not `subscribe`: a subscription is already a push-delivery edge between two nodes on the canvas, and one word must not mean two things.
34
+
35
+ **A stream is an observer, never a lifecycle hold.** Disconnecting drops your subscriber and leaves the node running. Opening a stream never revives a dormant node — call `client.nodes.revive(id)` first if that is what you want.
36
+
37
+ ## Events
38
+
39
+ Each event carries `node_id` and a `sequence_number` in addition to the fields listed.
40
+
41
+ | Event | `data` |
42
+ |---|---|
43
+ | `node.output_text.delta` | `{ node_id, sequence_number, delta }` |
44
+ | `node.output_text.done` | `{ node_id, sequence_number, text }` |
45
+ | `node.tool_call.started` | `{ node_id, sequence_number, tool_call_id, tool, summary }` |
46
+ | `node.tool_call.completed` | `{ node_id, sequence_number, tool_call_id, tool, status: 'ok' \| 'error', summary }` |
47
+ | `node.turn.started` | `{ node_id, sequence_number }` |
48
+ | `node.turn.completed` | `{ node_id, sequence_number }` |
49
+ | `node.report.pushed` | `{ node_id, sequence_number, report }` |
50
+ | `node.status.changed` | `{ node_id, sequence_number, status }` |
51
+ | `node.settled` | `{ node_id, sequence_number, outcome }` — terminal; the daemon ends the response after it |
52
+ | `error` | `{ error: { code, message, details? } }` — terminal |
53
+
54
+ `summary` on a tool-call event is a capped rendering of the arguments, never the raw arguments.
55
+
56
+ **Deliberately not carried:** thinking deltas, the model's tool-call construction deltas, raw tool output, and the system prompt. Those belong to the owner's viewer, not to an application's run stream.
57
+
58
+ ## The route
59
+
60
+ ```
61
+ GET /v1/nodes/{id}/events Accept: text/event-stream
62
+ ?after=<sequence_number> resume from a cursor (optional)
63
+ ```
64
+
65
+ Server-sent events: one record per event as `event: <type>`, `data: <JSON>`, blank line, plus `: keepalive` comment lines every 15 s. Authentication is the daemon's existing rule — filesystem permission on the unix socket, bearer token over TCP.
66
+
67
+ ### What you get depending on the node's state
68
+
69
+ | Node state when you call | What the stream does |
70
+ |---|---|
71
+ | Already settled | Writes `node.settled` with the outcome and ends. Nothing is revived. |
72
+ | Running | Streams live, seeded as described below. |
73
+ | Dormant and not settled | Writes `node.status.changed { status: 'dormant' }` and holds the response open with keepalives. It starts streaming if and when the daemon brings a broker up for that node. |
74
+
75
+ A node can settle between your `create` and your `events` call, so both branches are ordinary. Either way the terminal event is `node.settled`, read from the same outcome row `nodes.outcome` reads — a client that joins after settlement and a client that was live at settlement see the same event.
76
+
77
+ ## Sequence, resume, and failure
78
+
79
+ `sequence_number` is monotonic per node. The daemon keeps one in-memory ring per streamed node holding the last 512 events or 256 KiB, whichever binds first.
80
+
81
+ | Situation | Behaviour |
82
+ |---|---|
83
+ | You join a run already in progress | Seeded from the broker's snapshot: one `node.output_text.done` per completed assistant message, then one `node.output_text.delta` carrying the accumulated partial, then live. No content is lost — only delta granularity. |
84
+ | A second subscriber joins | Seeded from the ring, so both subscribers see the same sequence numbers. |
85
+ | `after=N` within the ring | Replays from `N+1`. |
86
+ | `after=N` older than the ring floor | An `error` event with code **`stream_gap`** carrying the earliest available sequence, **then the stream continues from the floor**. It never silently skips; you learn exactly what you lost. |
87
+ | Your reader is too slow | The broker drops a client past 1000 queued frames or 32 MiB. You get an `error` with code **`stream_dropped`** and the response ends. One slow reader cannot stall the engine. |
88
+ | The node's broker is replaced (revive, respawn) | The daemon reconnects and emits `node.status.changed`. Sequence continues. |
89
+ | The daemon restarts | The ring is gone. A resuming client gets `stream_gap` from sequence 1. There is no durable event log. |
90
+ | You disconnect | Your subscriber is dropped. The node keeps running. |
91
+
92
+ ### Resuming
93
+
94
+ <!-- TODO(verify): run against a live daemon once phase 2 lands; confirm the field carrying the earliest available sequence on a `stream_gap` error. -->
95
+
96
+ ```ts
97
+ let cursor: number | undefined;
98
+
99
+ for (;;) {
100
+ const stream = client.nodes.events(id, { after: cursor });
101
+ try {
102
+ for await (const event of stream) {
103
+ if (event.type === 'error' && event.error.code === 'stream_gap') {
104
+ console.warn('missed events before', event.error.details?.earliest_sequence);
105
+ continue; // the stream continues from the floor
106
+ }
107
+ cursor = event.sequence_number;
108
+ handle(event);
109
+ }
110
+ return; // ended on node.settled
111
+ } catch (e) {
112
+ if (isDropped(e)) continue; // stream_dropped — reconnect from the cursor
113
+ throw e;
114
+ }
115
+ }
116
+ ```
117
+
118
+ `stream_gap` is recoverable and the stream continues after it. `stream_dropped` is terminal for that HTTP response — reconnect with the cursor you last saw.
119
+
120
+ ## Event shapes depend on the pinned pi version
121
+
122
+ The delta and tool-call shapes come from the installed `@earendil-works/pi-agent-core` and `pi-ai` packages, not from crouter. The daemon's translator is the one place that depends on them. A pi version bump must be checked against it.
123
+
124
+ <!-- TODO(verify): record the pi version the phase-2 event table was verified against once streaming lands. -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/crouter",
3
- "version": "0.3.320",
3
+ "version": "0.3.322",
4
4
  "description": "crtr — agent runtime with memory, plugins, and marketplaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/runtime.lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@north-light/crouter",
3
- "version": "0.3.320",
3
+ "version": "0.3.322",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@north-light/crouter",
9
- "version": "0.3.320",
9
+ "version": "0.3.322",
10
10
  "hasInstallScript": true,
11
11
  "license": "MIT",
12
12
  "workspaces": [
@@ -5206,20 +5206,20 @@
5206
5206
  },
5207
5207
  "packages/crouter-api": {
5208
5208
  "name": "@north-light/crouter-api",
5209
- "version": "0.3.320",
5209
+ "version": "0.3.322",
5210
5210
  "license": "UNLICENSED"
5211
5211
  },
5212
5212
  "packages/crouter-env-docker": {
5213
5213
  "name": "@north-light/crouter-env-docker",
5214
- "version": "0.3.320",
5214
+ "version": "0.3.322",
5215
5215
  "license": "UNLICENSED"
5216
5216
  },
5217
5217
  "packages/crouter-sdk": {
5218
5218
  "name": "@north-light/crouter-sdk",
5219
- "version": "0.3.320",
5219
+ "version": "0.3.322",
5220
5220
  "license": "UNLICENSED",
5221
5221
  "dependencies": {
5222
- "@north-light/crouter-api": "^0.3.295"
5222
+ "@north-light/crouter-api": "^0.3.321"
5223
5223
  }
5224
5224
  }
5225
5225
  }