@north-light/crouter-api 0.3.220 → 0.3.222

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.
@@ -12,11 +12,13 @@ import type { AttachEnsureRequest, AttachEnsureResultDTO } from './dto/attach.js
12
12
  import type { DeleteProfileRequest, DeleteProfileResultDTO, EnsureProfileRequest, ProfileDTO } from './dto/profiles.js';
13
13
  import type { FilePeekDTO } from './dto/files.js';
14
14
  import type { MemoryDocRefDTO } from './dto/memory.js';
15
+ import type { ChatInventoryDTO, ProspectiveChatInventoryDTO, ProspectiveChatInventoryQuery } from './dto/chat-inventory.js';
15
16
  import type { CredentialRemovalResultDTO, CredentialResultDTO, InstallCredentialRequest, ModelAuthListDTO } from './dto/modelauth.js';
16
17
  import type { CreateHumanBridgeRequest, HumanBridgeResultDTO, HumanCancelRequest, HumanCancelResultDTO, HumanResolveRequest, HumanResolveResultDTO } from './dto/human.js';
17
18
  import type { CancelReviewRequest, CreateReviewRequest, ListReviewsQuery, ReviewCancelResultDTO, ReviewDocumentBaseDTO, ReviewDTO, ReviewListDTO, ReviewSubmitResultDTO } from './dto/reviews.js';
18
19
  import type { CreateReviewCommentRequest, EditReviewCommentRequest, ListReviewCommentsQuery, ReadReviewCommentEventsQuery, ReviewCommentActionRequest, ReviewCommentDetailDTO, ReviewCommentEventsDTO, ReviewCommentListDTO, ReviewCommentMutationDTO, ReviewCommentRangeBatchRequest, ReviewCommentRangeBatchResultDTO } from './dto/review-comments.js';
19
20
  import type { CancelInboxTicketRequest, CanceledTicketResultDTO, InboxListDTO, InboxPageDTO, InboxPageHistoryDTO, InboxPageResponseDTO, InboxTicketIdDTO, PageFeedbackResolutionDTO, PageResponsesDTO, PageTicketResultDTO, RespondInboxPageRequest } from './dto/inbox.js';
21
+ import type { CreateHumanRequestDTO, CreateHumanRequestRequest, HumanRequestDTO, HumanRequestIdDTO, ReplaceHumanRequestRequest, RespondHumanRequestRequest, SettleHumanRequestRequest } from './dto/human-requests.js';
20
22
  import type { AttentionCountsDTO, AttentionDTO, DashboardDTO, DashboardQuery, HistoryGrepQuery, HistoryGrepResultDTO, HistoryReadQuery, HistoryReadResultDTO, HistorySearchQuery, HistorySearchResultDTO, PruneRequest, PruneResultDTO, RebuildIndexResultDTO, RosterDTO, SnapshotDTO } from './dto/canvas.js';
21
23
  import type { CloseWorktreeResultDTO } from './dto/worktree.js';
22
24
  import type { BrokerExtensionStateDTO, BrokerGeneratedNameRequest, BrokerGeneratedNameResultDTO, BrokerInboxCursorDirective, BrokerInboxCursorRequest, BrokerModelCommitRequest, BrokerModelCommitResultDTO, BrokerPersonaAckRequest, BrokerSessionBoundRequest, BrokerSessionBoundResultDTO, BrokerSettleDirective, BrokerSettleRequest } from './dto/broker-ops.js';
@@ -151,6 +153,12 @@ export declare class CrtrClient {
151
153
  /** The node's conversation exactly as it ran — raw `.jsonl` bytes plus the
152
154
  * assembled system prompt. For exports; `getSnapshot` is for renderers. */
153
155
  getSession(id: string): Promise<NodeSessionDTO>;
156
+ /** What a non-terminal chat surface may offer for this node: the chat-capable
157
+ * slash commands its live engine registered, and the memory documents an
158
+ * inline `/name` token resolves to. Never revives — a node whose broker is
159
+ * not live answers `broker_live: false` with empty arrays. */
160
+ getChatInventory(id: string): Promise<ChatInventoryDTO>;
161
+ getProspectiveChatInventory(q?: ProspectiveChatInventoryQuery): Promise<ProspectiveChatInventoryDTO>;
154
162
  getArtifacts(id: string, q?: ArtifactsQuery): Promise<ArtifactListDTO>;
155
163
  getContext(id: string): Promise<ContextListDTO>;
156
164
  /** Read an absolute host path as UTF-8 (capped, `truncated` when clipped) for
@@ -160,6 +168,9 @@ export declare class CrtrClient {
160
168
  * node would read — the node's own precedence chain, not this process's.
161
169
  * Pair with `peekFile` to render the document. */
162
170
  resolveMemoryDoc(name: string, nodeId: string): Promise<MemoryDocRefDTO>;
171
+ /** Create-or-return by name. Supplied `projects` are shape-checked even when
172
+ * the profile already exists; their directories are only required to exist
173
+ * when this call creates the profile. */
163
174
  ensureProfile(name: string, req?: EnsureProfileRequest): Promise<ProfileDTO>;
164
175
  listProfiles(): Promise<ProfileDTO[]>;
165
176
  getProfile(name: string): Promise<ProfileDTO>;
@@ -211,6 +222,24 @@ export declare class CrtrClient {
211
222
  getInboxResponse(ticketId: InboxTicketIdDTO): Promise<InboxPageResponseDTO>;
212
223
  /** Cancel a ticket (terminal response, never deletion). */
213
224
  cancelHumanInboxTicket(ticketId: InboxTicketIdDTO, request?: CancelInboxTicketRequest): Promise<CanceledTicketResultDTO>;
225
+ /** Create one durable human request. Its `request_id` is the same opaque id
226
+ * the inbox routes address, so the request and the inbox ticket are one
227
+ * record. An unresolvable `action.name` is rejected before the page is
228
+ * published, leaving no inbox row behind. */
229
+ createHumanRequest(request: CreateHumanRequestRequest): Promise<CreateHumanRequestDTO>;
230
+ /** Read one request: its current state, its answer when answered, and the
231
+ * delivery state of its completion action when it bound one. */
232
+ getHumanRequest(requestId: HumanRequestIdDTO): Promise<HumanRequestDTO>;
233
+ /** Revise a pending request's page in place. Identity, provenance, and the
234
+ * frozen action binding are preserved; a settled request refuses. */
235
+ replaceHumanRequest(requestId: HumanRequestIdDTO, request: ReplaceHumanRequestRequest): Promise<HumanRequestDTO>;
236
+ /** Settle a request `answered` programmatically. Races a human answer to the
237
+ * same first-writer-wins result. */
238
+ respondHumanRequest(requestId: HumanRequestIdDTO, request: RespondHumanRequestRequest): Promise<HumanRequestDTO>;
239
+ /** The recipient surface closing a request without answering. */
240
+ dismissHumanRequest(requestId: HumanRequestIdDTO, request?: SettleHumanRequestRequest): Promise<HumanRequestDTO>;
241
+ /** The requester withdrawing its own request. */
242
+ cancelHumanRequest(requestId: HumanRequestIdDTO, request?: SettleHumanRequestRequest): Promise<HumanRequestDTO>;
214
243
  /** Resolve one page feedback comment — the bound companion's report that it
215
244
  * has been dealt with. `nodeId` names the caller; the daemon refuses any
216
245
  * node but the ticket's companion. Terminal for the comment; appends no
@@ -267,6 +267,16 @@ export class CrtrClient {
267
267
  getSession(id) {
268
268
  return this.request('GET', routes.nodeSession(this.nodePath(id)));
269
269
  }
270
+ /** What a non-terminal chat surface may offer for this node: the chat-capable
271
+ * slash commands its live engine registered, and the memory documents an
272
+ * inline `/name` token resolves to. Never revives — a node whose broker is
273
+ * not live answers `broker_live: false` with empty arrays. */
274
+ getChatInventory(id) {
275
+ return this.request('GET', routes.nodeChatInventory(this.nodePath(id)));
276
+ }
277
+ getProspectiveChatInventory(q) {
278
+ return this.request('GET', withQuery(routes.prospectiveChatInventory(), q));
279
+ }
270
280
  getArtifacts(id, q) {
271
281
  return this.request('GET', withQuery(routes.nodeArtifacts(this.nodePath(id)), q));
272
282
  }
@@ -287,6 +297,9 @@ export class CrtrClient {
287
297
  return this.request('GET', withQuery(routes.memoryResolve(), { name, node: nodeId }));
288
298
  }
289
299
  // ---- Profiles ----------------------------------------------------------
300
+ /** Create-or-return by name. Supplied `projects` are shape-checked even when
301
+ * the profile already exists; their directories are only required to exist
302
+ * when this call creates the profile. */
290
303
  ensureProfile(name, req) {
291
304
  return this.request('PUT', routes.profile(name), req ?? {});
292
305
  }
@@ -416,6 +429,37 @@ export class CrtrClient {
416
429
  cancelHumanInboxTicket(ticketId, request) {
417
430
  return this.request('POST', routes.humanInboxCancel(this.ticketId(ticketId)), request ?? {});
418
431
  }
432
+ // ---- Durable programmatic human requests -------------------------------
433
+ /** Create one durable human request. Its `request_id` is the same opaque id
434
+ * the inbox routes address, so the request and the inbox ticket are one
435
+ * record. An unresolvable `action.name` is rejected before the page is
436
+ * published, leaving no inbox row behind. */
437
+ createHumanRequest(request) {
438
+ return this.request('POST', routes.humanRequests(), request);
439
+ }
440
+ /** Read one request: its current state, its answer when answered, and the
441
+ * delivery state of its completion action when it bound one. */
442
+ getHumanRequest(requestId) {
443
+ return this.request('GET', routes.humanRequest(this.ticketId(requestId)));
444
+ }
445
+ /** Revise a pending request's page in place. Identity, provenance, and the
446
+ * frozen action binding are preserved; a settled request refuses. */
447
+ replaceHumanRequest(requestId, request) {
448
+ return this.request('POST', routes.humanRequestReplace(this.ticketId(requestId)), request);
449
+ }
450
+ /** Settle a request `answered` programmatically. Races a human answer to the
451
+ * same first-writer-wins result. */
452
+ respondHumanRequest(requestId, request) {
453
+ return this.request('POST', routes.humanRequestRespond(this.ticketId(requestId)), request);
454
+ }
455
+ /** The recipient surface closing a request without answering. */
456
+ dismissHumanRequest(requestId, request = {}) {
457
+ return this.request('POST', routes.humanRequestDismiss(this.ticketId(requestId)), request);
458
+ }
459
+ /** The requester withdrawing its own request. */
460
+ cancelHumanRequest(requestId, request = {}) {
461
+ return this.request('POST', routes.humanRequestCancel(this.ticketId(requestId)), request);
462
+ }
419
463
  /** Resolve one page feedback comment — the bound companion's report that it
420
464
  * has been dealt with. `nodeId` names the caller; the daemon refuses any
421
465
  * node but the ticket's companion. Terminal for the comment; appends no
@@ -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,88 @@
1
+ import type { IsoTime } from './common.js';
2
+ import type { InboxTicketIdDTO, PageResponsesDTO, TicketSourceDTO } from './inbox.js';
3
+ /** A request id IS an opaque inbox ticket id: lowercase 64-hex. */
4
+ export type HumanRequestIdDTO = InboxTicketIdDTO;
5
+ /** The complete authored page text, inline — never a path. */
6
+ export interface HumanRequestPageDTO {
7
+ dialect: 'jsx' | 'html';
8
+ source: string;
9
+ }
10
+ export interface HumanRequestDeliveryDTO {
11
+ placement: 'inline' | 'panel';
12
+ inbox: boolean;
13
+ reply: boolean;
14
+ }
15
+ /** Frozen at creation: the action name and its opaque payload. An omitted
16
+ * `payload` is frozen as JSON null, so the completion document always carries it. */
17
+ export interface HumanRequestActionDTO {
18
+ name: string;
19
+ payload?: unknown;
20
+ }
21
+ export interface CreateHumanRequestRequest {
22
+ page: HumanRequestPageDTO;
23
+ delivery?: HumanRequestDeliveryDTO;
24
+ source?: TicketSourceDTO;
25
+ creator_cwd: string;
26
+ action?: HumanRequestActionDTO;
27
+ }
28
+ export type HumanRequestState = 'pending' | 'answered' | 'dismissed' | 'canceled';
29
+ export type HumanRequestDeliveryState = 'none' | 'pending' | 'running' | 'accepted' | 'permanent_failed';
30
+ export interface CreateHumanRequestDTO {
31
+ request_id: HumanRequestIdDTO;
32
+ state: 'pending';
33
+ /** Omitted entirely when the request carries no action binding. */
34
+ action?: {
35
+ name: string;
36
+ };
37
+ delivery_state: HumanRequestDeliveryState;
38
+ }
39
+ export interface HumanRequestDeliveryFailureDTO {
40
+ kind: 'exit' | 'signal' | 'timeout' | 'spawn_error';
41
+ exit_code?: number;
42
+ signal?: string;
43
+ message?: string;
44
+ /** A bounded tail, not full output. */
45
+ stderr?: string;
46
+ }
47
+ export interface HumanRequestDeliveryDetailDTO {
48
+ state: HumanRequestDeliveryState;
49
+ /** Attempts started. */
50
+ attempt: number;
51
+ /** Present only while pending after a retryable failure. */
52
+ next_attempt_at?: IsoTime;
53
+ accepted_at?: IsoTime;
54
+ permanent_failed_at?: IsoTime;
55
+ last_failure?: HumanRequestDeliveryFailureDTO;
56
+ }
57
+ export interface HumanRequestDTO {
58
+ request_id: HumanRequestIdDTO;
59
+ state: HumanRequestState;
60
+ title: string;
61
+ subtitle?: string;
62
+ source: TicketSourceDTO;
63
+ emitted_at: IsoTime;
64
+ /** Present unless pending. */
65
+ settled_at?: IsoTime;
66
+ /** Present only when `state` is `answered`. */
67
+ responses?: PageResponsesDTO;
68
+ reason?: string;
69
+ actor?: string;
70
+ /** `action` and `delivery` are both omitted when no action is bound. */
71
+ action?: {
72
+ name: string;
73
+ payload: unknown;
74
+ };
75
+ delivery?: HumanRequestDeliveryDetailDTO;
76
+ }
77
+ export interface ReplaceHumanRequestRequest {
78
+ page: HumanRequestPageDTO;
79
+ delivery?: HumanRequestDeliveryDTO;
80
+ }
81
+ export interface RespondHumanRequestRequest {
82
+ responses: PageResponsesDTO;
83
+ actor?: string;
84
+ }
85
+ export interface SettleHumanRequestRequest {
86
+ reason?: string;
87
+ actor?: string;
88
+ }
@@ -0,0 +1,4 @@
1
+ // Durable programmatic human-request DTOs — crtrd `/v1/human/requests`. The
2
+ // envelope is snake_case; nested page-protocol objects keep their canonical
3
+ // camelCase names, matching the inbox DTOs.
4
+ export {};
@@ -44,6 +44,9 @@ export interface HumanResolveRequest {
44
44
  export interface HumanCancelRequest {
45
45
  reason?: string;
46
46
  actor?: string;
47
+ /** The recipient surface closing it sends `dismissed`; a requester retracting
48
+ * it sends `canceled` or omits the field. */
49
+ disposition?: 'canceled' | 'dismissed';
47
50
  }
48
51
  /** `POST /v1/human/tickets/{ticket_id}/resolve` result. */
49
52
  export interface HumanResolveResultDTO {
@@ -1,8 +1,22 @@
1
+ /** The disclosure ladder, lowest to highest. Index order is the ordering. */
2
+ export declare const PROFILE_PROJECT_MEMORY_VALUES: readonly ["none", "name", "preview", "content"];
3
+ /** How much of a project's memory stores the profile relationship lets an
4
+ * automatic delivery disclose. */
5
+ export type ProfileProjectMemory = (typeof PROFILE_PROJECT_MEMORY_VALUES)[number];
6
+ /** One project directory in a profile's purview. */
7
+ export interface ProfileProject {
8
+ /** Absolute, real-path-resolved directory. */
9
+ path: string;
10
+ /** Maximum rung automatic boot and workspace-open delivery may reach from
11
+ * this project's memory stores, regardless of the node's working directory.
12
+ * An authored lower rung stays lower; targeted reads are never capped. */
13
+ memory: ProfileProjectMemory;
14
+ }
1
15
  /** `PUT /v1/profiles/{name}` body — idempotent ensure. Every field applies
2
16
  * only at create; an existing same-named profile is returned untouched. */
3
17
  export interface EnsureProfileRequest {
4
- /** Absolute project directories in the profile's purview. */
5
- projects?: string[];
18
+ /** Project directories in the profile's purview, each with its memory cap. */
19
+ projects?: ProfileProject[];
6
20
  /** Persona kind for node creates under the profile that omit kind. */
7
21
  default_kind?: string;
8
22
  /** Profile facts (identity, role); each entry reaches every broker
@@ -37,9 +51,9 @@ export interface ProfileDTO {
37
51
  /** Stable profile-directory id (`<slug>-<id>`). */
38
52
  id: string;
39
53
  name: string;
40
- projects: string[];
41
- /** Where nodes under this profile run — one of `projects` (the first unless
42
- * re-pointed), or null when the profile owns none. */
54
+ projects: ProfileProject[];
55
+ /** Where nodes under this profile run — one of `projects[].path` (the first
56
+ * unless re-pointed), or null when the profile owns none. */
43
57
  home: string | null;
44
58
  /** ISO timestamp when the profile was paused, or null while active. */
45
59
  paused_at: string | null;
@@ -1,3 +1,4 @@
1
1
  // Profile DTOs (spec §6.6). Profile deletion crosses profile, canvas, cron,
2
2
  // inbox, and review state, so every consumer routes it through crtrd.
3
- export {};
3
+ /** The disclosure ladder, lowest to highest. Index order is the ordering. */
4
+ export const PROFILE_PROJECT_MEMORY_VALUES = ['none', 'name', 'preview', 'content'];
@@ -93,6 +93,8 @@ export interface ReviewCancelResultDTO {
93
93
  export interface CancelReviewRequest {
94
94
  reason?: string;
95
95
  actor?: string;
96
+ /** Recipient surfaces send `dismissed`; a requester withdrawal defaults to `canceled`. */
97
+ disposition?: 'canceled' | 'dismissed';
96
98
  }
97
99
  /** Daemon-derived coordinate base for the terminal review surface. */
98
100
  export interface ReviewDocumentBaseDTO {
@@ -25,5 +25,7 @@ export * from './dto/human.js';
25
25
  export * from './dto/files.js';
26
26
  export * from './dto/memory.js';
27
27
  export * from './dto/inbox.js';
28
+ export * from './dto/human-requests.js';
28
29
  export * from './dto/reviews.js';
29
30
  export * from './dto/review-comments.js';
31
+ export * from './dto/chat-inventory.js';
package/dist/api/index.js CHANGED
@@ -26,5 +26,7 @@ export * from './dto/human.js';
26
26
  export * from './dto/files.js';
27
27
  export * from './dto/memory.js';
28
28
  export * from './dto/inbox.js';
29
+ export * from './dto/human-requests.js';
29
30
  export * from './dto/reviews.js';
30
31
  export * from './dto/review-comments.js';
32
+ export * from './dto/chat-inventory.js';
@@ -11,6 +11,8 @@ export declare const routes: {
11
11
  readonly nodeSnapshot: (id: string) => string;
12
12
  readonly nodeSubject: (id: string) => string;
13
13
  readonly nodeSession: (id: string) => string;
14
+ readonly nodeChatInventory: (id: string) => string;
15
+ readonly prospectiveChatInventory: () => string;
14
16
  readonly nodeTranscript: (id: string) => string;
15
17
  readonly nodeContext: (id: string) => string;
16
18
  readonly nodeArtifacts: (id: string) => string;
@@ -83,6 +85,12 @@ export declare const routes: {
83
85
  readonly humanInboxResponse: (ticketId: string) => string;
84
86
  readonly humanInboxCancel: (ticketId: string) => string;
85
87
  readonly humanInboxFeedbackResolve: (ticketId: string, commentId: string) => string;
88
+ readonly humanRequests: () => string;
89
+ readonly humanRequest: (requestId: string) => string;
90
+ readonly humanRequestReplace: (requestId: string) => string;
91
+ readonly humanRequestRespond: (requestId: string) => string;
92
+ readonly humanRequestDismiss: (requestId: string) => string;
93
+ readonly humanRequestCancel: (requestId: string) => string;
86
94
  readonly profiles: () => string;
87
95
  readonly profile: (name: string) => string;
88
96
  readonly modelAuths: () => string;
@@ -27,6 +27,8 @@ export const routes = {
27
27
  nodeSnapshot: (id) => `${V}/nodes/${id}/snapshot`,
28
28
  nodeSubject: (id) => `${V}/nodes/${id}/subject`,
29
29
  nodeSession: (id) => `${V}/nodes/${id}/session`,
30
+ nodeChatInventory: (id) => `${V}/nodes/${id}/chat-inventory`,
31
+ prospectiveChatInventory: () => `${V}/prospective-chat-inventory`,
30
32
  nodeTranscript: (id) => `${V}/nodes/${id}/transcript`,
31
33
  nodeContext: (id) => `${V}/nodes/${id}/context`,
32
34
  nodeArtifacts: (id) => `${V}/nodes/${id}/artifacts`,
@@ -110,6 +112,15 @@ export const routes = {
110
112
  humanInboxResponse: (ticketId) => `${V}/human/inbox/${ticketId}/response`,
111
113
  humanInboxCancel: (ticketId) => `${V}/human/inbox/${ticketId}/cancel`,
112
114
  humanInboxFeedbackResolve: (ticketId, commentId) => `${V}/human/inbox/${ticketId}/feedback-comments/${commentId}/resolve`,
115
+ // Durable programmatic human requests. `request_id` is the same opaque
116
+ // inbox ticket id the `/v1/human/inbox` routes address, so one request is one
117
+ // record across both surfaces.
118
+ humanRequests: () => `${V}/human/requests`,
119
+ humanRequest: (requestId) => `${V}/human/requests/${requestId}`,
120
+ humanRequestReplace: (requestId) => `${V}/human/requests/${requestId}/replace`,
121
+ humanRequestRespond: (requestId) => `${V}/human/requests/${requestId}/respond`,
122
+ humanRequestDismiss: (requestId) => `${V}/human/requests/${requestId}/dismiss`,
123
+ humanRequestCancel: (requestId) => `${V}/human/requests/${requestId}/cancel`,
113
124
  // Profiles (deletion is daemon-owned because it crosses canvas state)
114
125
  profiles: () => `${V}/profiles`,
115
126
  profile: (name) => `${V}/profiles/${name}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/crouter-api",
3
- "version": "0.3.220",
3
+ "version": "0.3.222",
4
4
  "description": "Typed crtrd /v1 API contract — DTOs, route builders, the error contract, and the CrtrClient. Zero runtime dependencies.",
5
5
  "type": "module",
6
6
  "main": "./dist/api/index.js",