@crouter/api 0.3.377

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 (112) hide show
  1. package/README.md +67 -0
  2. package/dist/api/__tests__/error-codes.test.d.ts +1 -0
  3. package/dist/api/__tests__/error-codes.test.js +78 -0
  4. package/dist/api/__tests__/integration/client.test.d.ts +1 -0
  5. package/dist/api/__tests__/integration/client.test.js +179 -0
  6. package/dist/api/client.d.ts +467 -0
  7. package/dist/api/client.js +1179 -0
  8. package/dist/api/command-manifest/index.d.ts +3 -0
  9. package/dist/api/command-manifest/index.js +3 -0
  10. package/dist/api/command-manifest/manifest.d.ts +51 -0
  11. package/dist/api/command-manifest/manifest.js +332 -0
  12. package/dist/api/command-manifest/result.d.ts +25 -0
  13. package/dist/api/command-manifest/result.js +97 -0
  14. package/dist/api/command-manifest/schema.d.ts +28 -0
  15. package/dist/api/command-manifest/schema.js +856 -0
  16. package/dist/api/dto/analytics.d.ts +184 -0
  17. package/dist/api/dto/analytics.js +3 -0
  18. package/dist/api/dto/attach.d.ts +22 -0
  19. package/dist/api/dto/attach.js +13 -0
  20. package/dist/api/dto/bash-jobs.d.ts +24 -0
  21. package/dist/api/dto/bash-jobs.js +9 -0
  22. package/dist/api/dto/bash.d.ts +17 -0
  23. package/dist/api/dto/bash.js +1 -0
  24. package/dist/api/dto/broker-ops.d.ts +187 -0
  25. package/dist/api/dto/broker-ops.js +6 -0
  26. package/dist/api/dto/broker-signals.d.ts +25 -0
  27. package/dist/api/dto/broker-signals.js +1 -0
  28. package/dist/api/dto/broker.d.ts +86 -0
  29. package/dist/api/dto/broker.js +20 -0
  30. package/dist/api/dto/canvas.d.ts +359 -0
  31. package/dist/api/dto/canvas.js +2 -0
  32. package/dist/api/dto/chat-inventory.d.ts +56 -0
  33. package/dist/api/dto/chat-inventory.js +11 -0
  34. package/dist/api/dto/common.d.ts +29 -0
  35. package/dist/api/dto/common.js +15 -0
  36. package/dist/api/dto/config.d.ts +36 -0
  37. package/dist/api/dto/config.js +3 -0
  38. package/dist/api/dto/crons.d.ts +150 -0
  39. package/dist/api/dto/crons.js +10 -0
  40. package/dist/api/dto/custom-objects.d.ts +66 -0
  41. package/dist/api/dto/custom-objects.js +1 -0
  42. package/dist/api/dto/delivery.d.ts +71 -0
  43. package/dist/api/dto/delivery.js +7 -0
  44. package/dist/api/dto/docs.d.ts +135 -0
  45. package/dist/api/dto/docs.js +8 -0
  46. package/dist/api/dto/files.d.ts +21 -0
  47. package/dist/api/dto/files.js +1 -0
  48. package/dist/api/dto/focus.d.ts +24 -0
  49. package/dist/api/dto/focus.js +10 -0
  50. package/dist/api/dto/grants.d.ts +14 -0
  51. package/dist/api/dto/grants.js +1 -0
  52. package/dist/api/dto/health.d.ts +106 -0
  53. package/dist/api/dto/health.js +2 -0
  54. package/dist/api/dto/human-requests.d.ts +113 -0
  55. package/dist/api/dto/human-requests.js +4 -0
  56. package/dist/api/dto/human.d.ts +28 -0
  57. package/dist/api/dto/human.js +4 -0
  58. package/dist/api/dto/inbox.d.ts +273 -0
  59. package/dist/api/dto/inbox.js +4 -0
  60. package/dist/api/dto/lifecycle.d.ts +88 -0
  61. package/dist/api/dto/lifecycle.js +3 -0
  62. package/dist/api/dto/mail.d.ts +44 -0
  63. package/dist/api/dto/mail.js +1 -0
  64. package/dist/api/dto/messages.d.ts +88 -0
  65. package/dist/api/dto/messages.js +2 -0
  66. package/dist/api/dto/model-config.d.ts +25 -0
  67. package/dist/api/dto/model-config.js +1 -0
  68. package/dist/api/dto/modelauth.d.ts +132 -0
  69. package/dist/api/dto/modelauth.js +4 -0
  70. package/dist/api/dto/node-events.d.ts +65 -0
  71. package/dist/api/dto/node-events.js +4 -0
  72. package/dist/api/dto/node-outcomes.d.ts +88 -0
  73. package/dist/api/dto/node-outcomes.js +2 -0
  74. package/dist/api/dto/node-records.d.ts +35 -0
  75. package/dist/api/dto/node-records.js +5 -0
  76. package/dist/api/dto/nodes.d.ts +368 -0
  77. package/dist/api/dto/nodes.js +3 -0
  78. package/dist/api/dto/objects.d.ts +172 -0
  79. package/dist/api/dto/objects.js +5 -0
  80. package/dist/api/dto/profiles.d.ts +117 -0
  81. package/dist/api/dto/profiles.js +4 -0
  82. package/dist/api/dto/recovery.d.ts +104 -0
  83. package/dist/api/dto/recovery.js +1 -0
  84. package/dist/api/dto/reports.d.ts +93 -0
  85. package/dist/api/dto/reports.js +2 -0
  86. package/dist/api/dto/review-comments.d.ts +146 -0
  87. package/dist/api/dto/review-comments.js +5 -0
  88. package/dist/api/dto/reviews.d.ts +113 -0
  89. package/dist/api/dto/reviews.js +5 -0
  90. package/dist/api/dto/run-events.d.ts +293 -0
  91. package/dist/api/dto/run-events.js +6 -0
  92. package/dist/api/dto/subscriptions.d.ts +14 -0
  93. package/dist/api/dto/subscriptions.js +2 -0
  94. package/dist/api/dto/worktree.d.ts +55 -0
  95. package/dist/api/dto/worktree.js +6 -0
  96. package/dist/api/error-codes.d.ts +254 -0
  97. package/dist/api/error-codes.js +54 -0
  98. package/dist/api/errors.d.ts +47 -0
  99. package/dist/api/errors.js +66 -0
  100. package/dist/api/index.d.ts +42 -0
  101. package/dist/api/index.js +41 -0
  102. package/dist/api/node-transport.d.ts +18 -0
  103. package/dist/api/node-transport.js +105 -0
  104. package/dist/api/plugin-manifest-schema.d.ts +233 -0
  105. package/dist/api/plugin-manifest-schema.js +23 -0
  106. package/dist/api/routes.d.ts +160 -0
  107. package/dist/api/routes.js +193 -0
  108. package/dist/shared/generated-context.d.ts +79 -0
  109. package/dist/shared/generated-context.js +232 -0
  110. package/dist/shared/predicates.d.ts +2 -0
  111. package/dist/shared/predicates.js +4 -0
  112. package/package.json +49 -0
@@ -0,0 +1,359 @@
1
+ import type { Cursor, IsoTime, NodeIdDTO, NodeStatusDTO } from './common.js';
2
+ import type { NodeFaultDTO, NodeSummaryDTO } from './nodes.js';
3
+ /** `GET /v1/nodes` + `GET /v1/status` composed for the dashboard view. */
4
+ export interface DashboardQuery {
5
+ /** Restrict to the subtree under this node. */
6
+ under?: NodeIdDTO;
7
+ }
8
+ export interface DashboardDTO {
9
+ nodes: NodeSummaryDTO[];
10
+ /** Node counts keyed by status. */
11
+ counts: Partial<Record<NodeStatusDTO, number>>;
12
+ generated_at: IsoTime;
13
+ }
14
+ /** A node needing attention (tickets across the canvas). Projected from the
15
+ * `TicketEntry` reader — one entry per node with open human tickets. */
16
+ export interface AttentionItemDTO {
17
+ node_id: NodeIdDTO;
18
+ name: string;
19
+ cwd: string;
20
+ /** Number of open tickets on this node. */
21
+ count: number;
22
+ /** Open ticket titles for this node, newest first — one per counted ticket. */
23
+ subjects: string[];
24
+ }
25
+ /** `GET /v1/canvas/attention` result. */
26
+ export interface AttentionDTO {
27
+ items: AttentionItemDTO[];
28
+ }
29
+ /** `POST /v1/canvas/attention/counts` request. Restrict the synchronous inbox
30
+ * scan to the nodes a viewer is actually rendering instead of enriching the
31
+ * entire canvas roster. */
32
+ export interface AttentionCountsRequest {
33
+ node_ids: NodeIdDTO[];
34
+ }
35
+ /** `POST /v1/canvas/attention/counts` result, keyed by requested node id. */
36
+ export interface AttentionCountsDTO {
37
+ counts: Record<NodeIdDTO, number>;
38
+ }
39
+ /** `POST /v1/canvas/history/search` body — the ranked/filtered search over the
40
+ * per-cwd conversation corpus (inboxes and transcripts), backing `crtr canvas history search` (optional
41
+ * query: ranked when present, recency browse when omitted). The CLI parses +
42
+ * validates flags (`--type` set, `--since`/`--until` → epoch ms) and sends
43
+ * this normalized query; the server runs `buildCorpus` + ranking + pagination
44
+ * (closures like `loadBody` cannot cross the boundary, so the whole search
45
+ * executes server-side). Sent as POST — the query carries arrays and
46
+ * free-text that do not serialize cleanly as GET params. */
47
+ export interface HistorySearchQuery {
48
+ /** Whitespace-separated terms, ranked; omit to browse by recency. */
49
+ query?: string;
50
+ cwd?: string;
51
+ all_cwds?: boolean;
52
+ under?: string;
53
+ /** Restrict to specific node ids. */
54
+ nodes?: string[];
55
+ /** Corpus types: inbox | transcript. */
56
+ types?: string[];
57
+ kinds?: string[];
58
+ statuses?: string[];
59
+ /** Lower bound on artifact timestamp (epoch ms), parsed CLI-side. */
60
+ since_ms?: number;
61
+ /** Upper bound on artifact timestamp (epoch ms), parsed CLI-side. */
62
+ until_ms?: number;
63
+ /** Inbound-message narrowing (transcript + inbox): what drove arrival. */
64
+ origins?: string[];
65
+ /** Transcript-message roles: user | assistant | toolResult. */
66
+ roles?: string[];
67
+ /** Case-insensitive substring against sender attribution. */
68
+ from?: string;
69
+ /** Weigh full body text in ranking (`--body`). */
70
+ weigh_body?: boolean;
71
+ /** relevance | recency | oldest — already resolved to the effective sort. */
72
+ sort?: string;
73
+ snippet_lines?: number;
74
+ full?: boolean;
75
+ limit?: number;
76
+ cursor?: Cursor;
77
+ }
78
+ /** `POST /v1/canvas/history/search` result. `hits` is heterogeneous by mode
79
+ * (with/without a relevance score, snippet vs full body), so it stays a
80
+ * loose object list — the CLI's renderer already treats hits as
81
+ * `Record<string, unknown>[]`. The static `follow_up` line is appended
82
+ * CLI-side. */
83
+ export interface HistorySearchResultDTO {
84
+ hits: Record<string, unknown>[];
85
+ next_cursor: Cursor | null;
86
+ total: number;
87
+ }
88
+ /** `POST /v1/canvas/history/grep` body — the required-pattern line-hit search
89
+ * over the per-cwd conversation corpus (inboxes and transcripts), backing `crtr canvas history grep`.
90
+ * Shares scope/corpus filters with `HistorySearchQuery` but is a distinct
91
+ * wire contract: `pattern` is mandatory (an ECMAScript regex) and there is no
92
+ * ranking/snippet/full-body shape. */
93
+ export interface HistoryGrepQuery {
94
+ /** Required ECMAScript regex, matched per body line (case-insensitive). */
95
+ pattern: string;
96
+ cwd?: string;
97
+ all_cwds?: boolean;
98
+ under?: string;
99
+ /** Restrict to specific node ids. */
100
+ nodes?: string[];
101
+ /** Corpus types: inbox | transcript. */
102
+ types?: string[];
103
+ kinds?: string[];
104
+ statuses?: string[];
105
+ /** Lower bound on artifact timestamp (epoch ms), parsed CLI-side. */
106
+ since_ms?: number;
107
+ /** Upper bound on artifact timestamp (epoch ms), parsed CLI-side. */
108
+ until_ms?: number;
109
+ /** Inbound-message narrowing (transcript + inbox): what drove arrival. */
110
+ origins?: string[];
111
+ /** Transcript-message roles: user | assistant | toolResult. */
112
+ roles?: string[];
113
+ /** Case-insensitive substring against sender attribution. */
114
+ from?: string;
115
+ limit?: number;
116
+ cursor?: Cursor;
117
+ }
118
+ /** `POST /v1/canvas/history/stats` body — the grouped-count projection over
119
+ * the same corpus search and grep scan, backing `crtr canvas history stats`.
120
+ * Shares every scope/corpus/message filter; carries no query, pattern, or
121
+ * pagination because the result is an aggregate, not a hit list. */
122
+ export interface HistoryStatsQuery {
123
+ /** origin | node | kind | day | type | role. Defaults to type. */
124
+ group_by?: string;
125
+ cwd?: string;
126
+ all_cwds?: boolean;
127
+ under?: string;
128
+ nodes?: string[];
129
+ types?: string[];
130
+ kinds?: string[];
131
+ statuses?: string[];
132
+ since_ms?: number;
133
+ until_ms?: number;
134
+ origins?: string[];
135
+ roles?: string[];
136
+ from?: string;
137
+ }
138
+ /** `POST /v1/canvas/history/stats` result — counts by the grouped dimension,
139
+ * descending. `total` counts the artifacts that carried the dimension, so it
140
+ * can be lower than the corpus size when grouping by one not every artifact
141
+ * has (origin, role). */
142
+ export interface HistoryStatsResultDTO {
143
+ group_by: string;
144
+ groups: Array<{
145
+ key: string;
146
+ count: number;
147
+ }>;
148
+ total: number;
149
+ /** Artifacts scanned before the grouping dimension was applied. */
150
+ scanned: number;
151
+ }
152
+ /** One matching body line from `crtr canvas history grep`. */
153
+ export interface HistoryGrepHitDTO {
154
+ ref: string;
155
+ /** "name (id)". */
156
+ node: string;
157
+ ts: IsoTime;
158
+ line: number;
159
+ text: string;
160
+ }
161
+ /** `POST /v1/canvas/history/grep` result — a stable line-hit schema, distinct
162
+ * from `HistorySearchResultDTO`'s heterogeneous ranked/browse shape. */
163
+ export interface HistoryGrepResultDTO {
164
+ hits: HistoryGrepHitDTO[];
165
+ next_cursor: Cursor | null;
166
+ total: number;
167
+ }
168
+ /** `GET /v1/canvas/history/read` query — resolve one `<node-id>:inbox/<n>`,
169
+ * `<node-id>:session` or `<node-id>:session/<n>` ref. */
170
+ export interface HistoryReadQuery {
171
+ ref: string;
172
+ /** `rendered` (default) or `raw` — the verbatim bytes behind the ref: the
173
+ * session file for a bare `session` ref, the one jsonl line for a message. */
174
+ format?: string;
175
+ }
176
+ /** `GET /v1/canvas/history/read` result — one hit's full body. */
177
+ export interface HistoryReadResultDTO {
178
+ ref: string;
179
+ /** "name (id)". */
180
+ node: string;
181
+ /** inbox | transcript. */
182
+ source: string;
183
+ ts: IsoTime;
184
+ content: string;
185
+ }
186
+ /** One node row in the browser canvas roster (`GET /v1/canvas/snapshot`). A
187
+ * richer projection than `NodeSummaryDTO`: it carries the enriched viewer
188
+ * fields (`dashboardRowsAll` + `enrichRows`) the browser canvas renders —
189
+ * attention counts, ctx tokens, streaming/hanging/viewed state, last activity. */
190
+ export interface SnapshotNodeDTO {
191
+ node_id: NodeIdDTO;
192
+ name: string;
193
+ /** Caller-supplied node title, kept separate from the enriched full label. */
194
+ title: string;
195
+ /** Caller-supplied node brief, or null when absent. */
196
+ description: string | null;
197
+ kind: string;
198
+ mode: string;
199
+ lifecycle?: string;
200
+ status: NodeStatusDTO;
201
+ cwd: string;
202
+ /** The profile this node runs under; null for a historical no-profile row.
203
+ * Carried here because it is the only field that says WHOSE work a node is —
204
+ * a snapshot consumer grouping nodes by agent has nothing else to key on. */
205
+ profile_id: string | null;
206
+ parent: NodeIdDTO | null;
207
+ created: IsoTime;
208
+ host_kind: string;
209
+ /** True when the node hosts an enterable broker (`host_kind === 'broker'`). */
210
+ enterable: boolean;
211
+ attention_count: number;
212
+ cycles?: number;
213
+ last_activity?: IsoTime;
214
+ ctx_tokens?: number;
215
+ streaming: boolean;
216
+ /** Number of active background bash jobs, reported only for a live broker. */
217
+ jobs_active: number;
218
+ /** Controller node this node is durably waiting for, or null. */
219
+ waiting_for: string | null;
220
+ /** The node's active fault projection (structurally a `Fault`), or null. Kept
221
+ * as a loose object to keep this DTO free of a `core` type import. */
222
+ hanging: Record<string, unknown> | null;
223
+ viewed: boolean;
224
+ /** Basename of the node's final report, or null when it never pushed one.
225
+ * Presence — not `status === 'done'` — is what distinguishes finished work
226
+ * from clean parking. */
227
+ final_report: string | null;
228
+ finalized_at: IsoTime | null;
229
+ }
230
+ /** `GET /v1/canvas/snapshot` result — the machine-readable browser canvas
231
+ * roster (`crtr canvas snapshot`). Distinct from the per-node `NodeSnapshotDTO`
232
+ * (nodes.ts). `subscriptions` is the authoritative `subscribes_to` adjacency
233
+ * map: each node id → its publisher/child node ids in edge order. */
234
+ export interface SnapshotDTO {
235
+ generated_at: IsoTime;
236
+ nodes: SnapshotNodeDTO[];
237
+ subscriptions: Record<string, NodeIdDTO[]>;
238
+ }
239
+ /** One node row in the lean roster (`GET /v1/canvas/roster`). Carries only
240
+ * stored node fields, without a process-liveness probe. `attention_count`/`last_activity`/`ctx_tokens`/
241
+ * `streaming`/`hanging`/`viewed` stay on `SnapshotNodeDTO`; a roster consumer
242
+ * that needs attention counts fetches them separately via the existing
243
+ * `POST /v1/canvas/attention/counts` (already scoped to exactly the ids it
244
+ * renders, never the whole canvas). */
245
+ export interface RosterNodeDTO {
246
+ node_id: NodeIdDTO;
247
+ name: string;
248
+ kind: string;
249
+ mode: string;
250
+ lifecycle?: string;
251
+ status: NodeStatusDTO;
252
+ cwd: string;
253
+ host_kind: string;
254
+ /** True when the node hosts an enterable broker (`host_kind === 'broker'`). */
255
+ enterable: boolean;
256
+ parent: NodeIdDTO | null;
257
+ created: IsoTime;
258
+ }
259
+ /** One `subscribes_to` edge in the roster's topology half. Every edge is kept
260
+ * (passive + multiple per node) — never collapsed to one edge per node. */
261
+ export interface RosterEdgeDTO {
262
+ from_id: NodeIdDTO;
263
+ to_id: NodeIdDTO;
264
+ active: boolean;
265
+ created: IsoTime;
266
+ }
267
+ /** `GET /v1/canvas/roster` result — the lean, set-based topology read shared by
268
+ * the attach viewer and the browser canvas: exactly two indexed queries
269
+ * (`rosterNodes()` + `rosterEdges()`), no `enrichRows`, no per-row
270
+ * `getNode`/`subscriptionsOf` loop, no synchronous liveness probe. The
271
+ * recurring poll target that replaces the enriched `/v1/canvas/snapshot`
272
+ * storm; that endpoint remains for genuinely on-demand rich views. */
273
+ export interface RosterDTO {
274
+ generated_at: IsoTime;
275
+ nodes: RosterNodeDTO[];
276
+ edges: RosterEdgeDTO[];
277
+ }
278
+ /** Browse's initial frame needs the dashboard fields and topology, not the full
279
+ * node detail/list projection. Transported as gzip JSON (application/gzip) over
280
+ * the local socket; other /v1/nodes consumers keep their original response. */
281
+ export interface BrowseNodeDTO {
282
+ node_id: string;
283
+ name: string;
284
+ description?: string;
285
+ kind: string;
286
+ mode: string;
287
+ lifecycle: string;
288
+ status: NodeStatusDTO;
289
+ cwd: string;
290
+ profile_id: string | null;
291
+ grantee: string;
292
+ parent: string | null;
293
+ created: IsoTime;
294
+ frozen_at: IsoTime | null;
295
+ terminal_reason: string | null;
296
+ final_report: string | null;
297
+ telemetry_tokens_in: number | null;
298
+ telemetry_updated_at: IsoTime | null;
299
+ fault: import('./nodes.js').NodeFaultDTO | null;
300
+ streaming: boolean;
301
+ }
302
+ export interface BrowseCanvasDTO {
303
+ nodes: BrowseNodeDTO[];
304
+ edges: RosterEdgeDTO[];
305
+ }
306
+ /** One row in `GET /v1/canvas/graph`: exactly the node fields the attach graph displays. */
307
+ export interface GraphNodeDTO {
308
+ node_id: NodeIdDTO;
309
+ name: string;
310
+ description: string | null;
311
+ cycles: number | null;
312
+ kind: string;
313
+ status: NodeStatusDTO;
314
+ frozen_at: IsoTime | null;
315
+ pi_pid: number | null;
316
+ telemetry_context_tokens: number | null;
317
+ telemetry_last_activity: string | null;
318
+ fault: NodeFaultDTO | null;
319
+ streaming: boolean;
320
+ }
321
+ /** `GET /v1/canvas/graph` — the attach graph's one-read projection: display rows, subscription topology, and the current local viewer-focus set. */
322
+ export interface GraphDTO {
323
+ generated_at: IsoTime;
324
+ nodes: GraphNodeDTO[];
325
+ edges: RosterEdgeDTO[];
326
+ focused_node_ids: NodeIdDTO[];
327
+ }
328
+ /** `POST /v1/canvas/prune` body — the three exclusive prune modes of
329
+ * `crtr canvas prune`, precedence COUNT (`limit`) > EMPTY (`empty`) > TTL sweep. */
330
+ export interface PruneRequest {
331
+ /** COUNT mode: keep the N most-recently-active nodes, prune the oldest
332
+ * remaining terminal nodes (protected nodes always survive). */
333
+ limit?: number;
334
+ /** TTL sweep retention window in days (default 14). */
335
+ ttl_days?: number;
336
+ /** TTL sweep: also prune stale active/idle nodes past the TTL whose process
337
+ * is provably gone. */
338
+ include_stale?: boolean;
339
+ /** EMPTY mode: reap nodes whose engine never produced an assistant message. */
340
+ empty?: boolean;
341
+ /** Report what would be pruned without mutating. */
342
+ dry_run?: boolean;
343
+ }
344
+ /** One node in a prune result (pruned, or candidate under `dry_run`). */
345
+ export interface PrunedNodeDTO {
346
+ node_id: NodeIdDTO;
347
+ /** Lifecycle status, or `empty` for EMPTY-mode reaps. */
348
+ status: string;
349
+ /** ISO created timestamp (empty string for EMPTY-mode reaps). */
350
+ created: string;
351
+ }
352
+ /** `POST /v1/canvas/prune` result. `pruned` is the pruned set (or, under
353
+ * `dry_run`, the candidate set — nothing deleted). `ttl_days` echoes the
354
+ * retention window used. */
355
+ export interface PruneResultDTO {
356
+ pruned: PrunedNodeDTO[];
357
+ dry_run: boolean;
358
+ ttl_days: number;
359
+ }
@@ -0,0 +1,2 @@
1
+ // Canvas-wide read + maintenance DTOs (spec §6.3).
2
+ export {};
@@ -0,0 +1,56 @@
1
+ /** One command a chat surface may advertise. Builtin and non-opted-in rows are
2
+ * dropped before this DTO exists, so `source` never carries `'builtin'`. */
3
+ export interface ChatInventoryCommandDTO {
4
+ /** No leading slash, exactly as the engine dispatches it. */
5
+ name: string;
6
+ description: string;
7
+ source: 'command' | 'template';
8
+ /** Argument shape to display beside the name, when the command supplies one. */
9
+ argument_hint?: string;
10
+ /** Deterministic expansion metadata for a memory-slash command — the same
11
+ * material the terminal preview uses, so a chat preview cannot drift from
12
+ * what submission sends. */
13
+ expansion?: {
14
+ kind: 'memory-slash';
15
+ commandName: string;
16
+ body: string;
17
+ };
18
+ /** Raw prompt-template content (frontmatter stripped), for `source: 'template'`. */
19
+ template?: string;
20
+ }
21
+ /** One resolvable inline memory reference. Metadata only — never the document
22
+ * body or its source path. `shortForm` stays camelCase to mirror the broker's
23
+ * own `RefMeta`, which is where these rows come from. */
24
+ export interface ChatInventoryMemoryRefDTO {
25
+ /** Canonical `/`-joined name, e.g. `taste/writing`. */
26
+ name: string;
27
+ kind: 'knowledge' | 'preference';
28
+ scope: 'node' | 'project' | 'profile' | 'user' | 'builtin';
29
+ shortForm: string;
30
+ }
31
+ /** `GET /v1/nodes/{id}/chat-inventory` result.
32
+ *
33
+ * `broker_live` reports whether the node's engine was reachable at all. There
34
+ * is no per-part error flag: a part that failed and a part that is genuinely
35
+ * empty both arrive as an empty array, and a client's behavior is identical
36
+ * for both. A dormant node answers 200 with `broker_live: false` — this read
37
+ * never revives an engine. */
38
+ export interface ChatInventoryDTO {
39
+ node_id: string;
40
+ broker_live: boolean;
41
+ commands: ChatInventoryCommandDTO[];
42
+ memory_refs: ChatInventoryMemoryRefDTO[];
43
+ }
44
+ /** Session-less inventory for the launch target a create would resolve. */
45
+ export interface ProspectiveChatInventoryDTO {
46
+ profile_id: string | null;
47
+ cwd: string;
48
+ commands: ChatInventoryCommandDTO[];
49
+ memory_refs: ChatInventoryMemoryRefDTO[];
50
+ }
51
+ export interface ProspectiveChatInventoryQuery {
52
+ profile?: string;
53
+ cwd?: string;
54
+ /** Same optional kind operand as POST /v1/nodes. */
55
+ kind?: string;
56
+ }
@@ -0,0 +1,11 @@
1
+ // Chat-inventory DTO. Backs `GET /v1/nodes/{id}/chat-inventory` — the one read
2
+ // a non-terminal chat surface makes to learn what the node's live engine will
3
+ // accept: the slash commands that can complete their outcome from a chat
4
+ // conversation, and the memory documents an inline `/name` token resolves to.
5
+ //
6
+ // Eligibility is decided in crouter and disclosed here. A client never filters
7
+ // by name, infers capability, or invents a row: what is absent from these
8
+ // arrays is not offered.
9
+ //
10
+ // PURITY (spec §3.1): Node built-ins + `src/api/*` only.
11
+ export {};
@@ -0,0 +1,29 @@
1
+ /** ISO-8601 timestamp string (matches the runtime's `nowIso()` output). */
2
+ export type IsoTime = string;
3
+ /** A node id — the existing `<slug>-<hash>` string. Typed as a nominal alias so
4
+ * DTOs read as thin projections; validated at the boundary by `isSafeNodeId`. */
5
+ export type NodeIdDTO = string;
6
+ /** Opaque pagination cursor (server-defined; clients pass it back verbatim). */
7
+ export type Cursor = string;
8
+ /** Standard list-pagination inputs shared by paged queries. */
9
+ export interface Pagination {
10
+ limit?: number;
11
+ cursor?: Cursor;
12
+ }
13
+ /** Runtime status of a node (mirrors the runtime `NodeStatus` union; declared
14
+ * locally to keep `/api` free of any `core/*` import). */
15
+ export type NodeStatusDTO = 'active' | 'idle' | 'done' | 'dead' | 'canceled';
16
+ /** Lifecycle class of a node (mirrors the runtime `Lifecycle` union). */
17
+ export type LifecycleDTO = 'terminal' | 'resident';
18
+ /** Execution mode of a node (mirrors the runtime `Mode` union). */
19
+ export type ModeDTO = 'base' | 'orchestrator';
20
+ /** Why a node last stopped (mirrors the runtime `ExitIntent` union). */
21
+ export type ExitIntentDTO = 'done' | 'refresh' | 'idle-release' | 'parked' | null;
22
+ /** Why a terminal node ended (mirrors the runtime `TerminalReason` union). */
23
+ export type TerminalReasonDTO = 'finalized' | 'finished' | 'parked' | 'closed' | 'retired' | 'crashed' | 'stranded' | 'boot_failed' | 'crash_looped' | 'launch_failed' | 'context_overflow' | 'deadline_exceeded' | 'provider_fatal' | 'declined';
24
+ /** Inbox urgency tier for a delivered message (mirrors feed/inbox `InboxTier`). */
25
+ export type InboxTierDTO = 'critical' | 'urgent' | 'normal' | 'deferred';
26
+ /** Whether a node id is a safe single filesystem path segment. Re-declared here
27
+ * (not imported from `core/canvas/paths.ts`) to keep the exported `/api`
28
+ * contract dependency-light; kept byte-for-byte equivalent to the runtime's. */
29
+ export declare function isSafeNodeId(id: string): boolean;
@@ -0,0 +1,15 @@
1
+ // Shared scalars and cross-cutting DTO primitives.
2
+ //
3
+ // PURITY (spec §3.1): this file — like every file under `src/api/` — imports
4
+ // ONLY other `src/api/*` modules and Node built-ins. Never `core/*`,
5
+ // `node:sqlite`, TUI, or any heavy runtime module.
6
+ const MAX_NODE_ID_BYTES = 128;
7
+ /** Whether a node id is a safe single filesystem path segment. Re-declared here
8
+ * (not imported from `core/canvas/paths.ts`) to keep the exported `/api`
9
+ * contract dependency-light; kept byte-for-byte equivalent to the runtime's. */
10
+ export function isSafeNodeId(id) {
11
+ return typeof id === 'string'
12
+ && id !== '' && id !== '.' && id !== '..'
13
+ && !/[\\/\0]/u.test(id)
14
+ && Buffer.byteLength(id, 'utf8') <= MAX_NODE_ID_BYTES;
15
+ }
@@ -0,0 +1,36 @@
1
+ import type { LifecycleDTO, ModeDTO } from './common.js';
2
+ /** `PATCH /v1/nodes/{id}/config` body. All fields optional; a set field is
3
+ * applied, an absent field is untouched. */
4
+ export interface NodeConfigPatch {
5
+ /** Model tier or exact selection override. */
6
+ model?: string;
7
+ /** Ambient situational-context text override. */
8
+ situational_context?: string;
9
+ /** Persona kind respecialization — rebuilds the launch spec server-side. */
10
+ kind?: string;
11
+ /** Persona mode; setting `orchestrator` seeds a roadmap scaffold if absent. */
12
+ mode?: ModeDTO;
13
+ /** Lifecycle flip (terminal↔resident), rebuilding the launch spec. */
14
+ lifecycle?: LifecycleDTO;
15
+ /** Rename the node (and, when it has a live viewer window, that window). */
16
+ name?: string;
17
+ /** Repair-only replacement launch directory; exclusive of every other field. */
18
+ cwd?: string;
19
+ /** Per-run allow-list. A patch may only remove scopes; it applies to a live broker on its next revive. */
20
+ scopes?: string[];
21
+ /** The node's default listening configuration: event level ("1".."10") → delivery
22
+ * (`interrupt`|`steer`|`after-turn`|`next-turn`) for watches with no config of their own.
23
+ * `null` resets it to the global default. */
24
+ listen?: Record<string, 'interrupt' | 'steer' | 'after-turn' | 'next-turn'> | null;
25
+ }
26
+ /** One installed persona kind, as the daemon resolves kinds for node creation. */
27
+ export interface KindDTO {
28
+ kind: string;
29
+ when_to_use: string | null;
30
+ /** Top-level kinds a sub-kind is offered to; null takes the default (its own ancestor). */
31
+ available_to: string[] | null;
32
+ }
33
+ /** `GET /v1/kinds` — every kind the daemon accepts on create, sorted by name. */
34
+ export interface KindListDTO {
35
+ kinds: KindDTO[];
36
+ }
@@ -0,0 +1,3 @@
1
+ // Node config-patch DTO (spec §6.2). Dormant → row write; live → `view.sock`
2
+ // `set_model` — the liveness branch runs server-side; the CLI just PATCHes.
3
+ export {};
@@ -0,0 +1,150 @@
1
+ import type { IsoTime, NodeIdDTO } from './common.js';
2
+ export type CronScopeDTO = 'profile' | 'global';
3
+ export type CronOverlapDTO = 'skip' | 'queue' | 'replace';
4
+ export type CronOnOutputDTO = 'silent' | 'on-failure' | 'always' | 'on-change';
5
+ export type CronStateDTO = 'active' | 'paused';
6
+ export type CronRunStateDTO = 'idle' | 'running';
7
+ /** Is this a safe single path segment for `routes.cron*()` interpolation?
8
+ * Cron ids are server-minted UUIDs, but the route builders carry no logic, so
9
+ * every interpolated id is gated here first (the `isSafeNodeId` discipline). */
10
+ export declare function isSafeCronId(id: string): boolean;
11
+ /** The last settled run, carried on every cron projection so `cron list` shows
12
+ * recent health without a `cron show` per row. Null until the first run. */
13
+ export interface CronLastRunDTO {
14
+ /** When the run settled (UTC). */
15
+ finished: IsoTime | null;
16
+ /** -1 = timeout kill; null = no exit observed (process error / skip marker). */
17
+ exit_code: number | null;
18
+ /** What the sink did with the output, or why it didn't. */
19
+ delivered: string | null;
20
+ }
21
+ /** A cron row projection (`GET /v1/crons`). */
22
+ export interface CronDTO {
23
+ cron_id: string;
24
+ /** Agent-legible label; how the cron shows in list. */
25
+ name: string;
26
+ /** Provenance only — the node that armed it, if any; never a cascade anchor. */
27
+ created_by: NodeIdDTO | null;
28
+ /** The bash command each fire runs. */
29
+ command: string;
30
+ /** The shell and any spawned node stay isolated when armed from an isolated node. */
31
+ isolated: boolean;
32
+ /** Next occurrence (UTC). */
33
+ fire_at: IsoTime;
34
+ /** Recur JSON (interval or cron); null for a one-shot. */
35
+ recur: string | null;
36
+ /** IANA zone for a calendar cadence; null otherwise. */
37
+ tz: string | null;
38
+ /** Clock bound; the row is deleted when passed. Null = no bound. */
39
+ expires_at: IsoTime | null;
40
+ /** Opt-in node coupling (cascades on that node's deletion); null = detached. */
41
+ anchor_node: NodeIdDTO | null;
42
+ cancel_on_wake: boolean;
43
+ /** Execution context, snapshotted at arm time. */
44
+ cwd: string;
45
+ profile: string | null;
46
+ scope: CronScopeDTO;
47
+ /** Names of the extra env vars snapshotted onto the row — KEYS ONLY: the
48
+ * values are the caller's to know and may be secrets. */
49
+ env_keys: string[];
50
+ run_timeout_s: number;
51
+ overlap: CronOverlapDTO;
52
+ on_output: CronOnOutputDTO;
53
+ /** Where deliveries go — the raw sink spec (`node:<id>` | `spawn:<kind>` |
54
+ * `human`), or null when the disposition never delivers. */
55
+ sink: string | null;
56
+ tier: string;
57
+ state: CronStateDTO;
58
+ /** True while the row is parked by the exit-75 owed-gate disposition: the
59
+ * last scheduled run declared "owed but not currently eligible", so the
60
+ * occurrence was not spent. A daemon poke re-dues it now; otherwise a
61
+ * recurring row re-checks at its natural `fire_at` slot (the backstop) and
62
+ * a held one-shot waits for a poke until `expires_at` deletes it. `state`
63
+ * stays honest (active|paused) — renderers derive; an active held row must
64
+ * never present as paused. */
65
+ held: boolean;
66
+ run_state: CronRunStateDTO;
67
+ /** Recent health: the most recent settled run, or null if it never ran. */
68
+ last_run: CronLastRunDTO | null;
69
+ created: IsoTime;
70
+ updated: IsoTime;
71
+ }
72
+ /** `GET /v1/crons` query. `profile` is the CALLER's profile, which is what
73
+ * scoping means here: a profile-scoped cron belongs to its profile, a global
74
+ * one is canvas-home-wide. Omitting `profile` means the caller stands outside
75
+ * every profile (a plain shell, or a provenance read such as "which crons did
76
+ * node X arm") and sees the whole canvas home. This is a namespacing
77
+ * boundary between profiles, not a security boundary. */
78
+ export interface ListCronsQuery {
79
+ profile?: string;
80
+ }
81
+ /** Caller identity for the per-cron routes (show/pause/resume/run/cancel).
82
+ * Same rule as `ListCronsQuery`: a cron outside the caller's scope is 404,
83
+ * and an absent profile sees everything. */
84
+ export interface CronScopeQuery {
85
+ profile?: string | null;
86
+ }
87
+ /** Cancellation-only query. `run_id` is set automatically inside a cron run,
88
+ * letting crtrd distinguish a run ending itself from an external cancellation
89
+ * that must terminate an in-flight process. */
90
+ export interface CancelCronQuery extends CronScopeQuery {
91
+ run_id?: string;
92
+ }
93
+ /** One settled run-log entry (`GET /v1/crons/:cronId`, `POST /v1/crons/:cronId/run`). */
94
+ export interface CronRunDTO {
95
+ run_id: string;
96
+ started: IsoTime;
97
+ finished: IsoTime | null;
98
+ duration_ms: number | null;
99
+ /** null = no exit observed (spawn/process error, or a skip marker); -1 = timeout kill. */
100
+ exit_code: number | null;
101
+ stdout_head: string | null;
102
+ stderr_head: string | null;
103
+ /** What the sink did with this run's output, or why it didn't. */
104
+ delivered: string | null;
105
+ }
106
+ /** `POST /v1/crons/poke` — the bare daemon-level eligibility poke. Re-dues
107
+ * every held active cron now; paused rows keep their held state. Idempotent
108
+ * and free when nothing is held. */
109
+ export interface PokeCronsResult {
110
+ /** How many held rows were re-dued — for the caller's log line. */
111
+ unparked: number;
112
+ /** The poke receipt instant (UTC). */
113
+ at: IsoTime;
114
+ }
115
+ /** `GET /v1/crons/:cronId` — one cron with its run-log ring (most recent first). */
116
+ export interface CronShowDTO {
117
+ cron: CronDTO;
118
+ runs: CronRunDTO[];
119
+ }
120
+ /** `POST /v1/crons` — arm one cron. The CLI resolves timing client-side
121
+ * (parseWhen/parseCadence) and sends the settled `fire_at`/`recur`/`tz`;
122
+ * the server mints the cron_id and applies spec defaults for everything
123
+ * omitted. */
124
+ export interface ArmCronRequest {
125
+ name: string;
126
+ command: string;
127
+ fire_at: IsoTime;
128
+ recur?: string | null;
129
+ tz?: string | null;
130
+ created_by?: NodeIdDTO | null;
131
+ isolated?: boolean;
132
+ /** Execution context, snapshotted at arm time — chosen by the client, else
133
+ * inherited from the creating node; never re-resolved at run time. */
134
+ cwd: string;
135
+ /** Extra env for every run, as a JSON object of string values. */
136
+ env_json?: string | null;
137
+ profile?: string | null;
138
+ /** `profile` (default when a profile is resolved) requires a profile. */
139
+ scope?: CronScopeDTO;
140
+ on_output?: CronOnOutputDTO;
141
+ /** Raw sink spec: `node:<id>` | `spawn:<kind>` | `human`. Required by the
142
+ * always/on-change dispositions; meaningless otherwise. */
143
+ sink?: string | null;
144
+ tier?: string;
145
+ expires_at?: IsoTime | null;
146
+ anchor_node?: NodeIdDTO | null;
147
+ cancel_on_wake?: boolean;
148
+ run_timeout_s?: number;
149
+ overlap?: CronOverlapDTO;
150
+ }