@crouter/sdk 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 (84) hide show
  1. package/README.md +170 -0
  2. package/dist/client.d.ts +153 -0
  3. package/dist/client.js +491 -0
  4. package/dist/error-codes.d.ts +7 -0
  5. package/dist/error-codes.js +35 -0
  6. package/dist/errors.d.ts +43 -0
  7. package/dist/errors.js +76 -0
  8. package/dist/index.d.ts +33 -0
  9. package/dist/index.js +13 -0
  10. package/dist/keygen-cli.d.ts +2 -0
  11. package/dist/keygen-cli.js +6 -0
  12. package/dist/keygen-command.d.ts +6 -0
  13. package/dist/keygen-command.js +157 -0
  14. package/dist/oauth/index.d.ts +147 -0
  15. package/dist/oauth/index.js +377 -0
  16. package/dist/oauth/keygen.d.ts +18 -0
  17. package/dist/oauth/keygen.js +46 -0
  18. package/dist/resources/activity.d.ts +22 -0
  19. package/dist/resources/activity.js +43 -0
  20. package/dist/resources/attachments.d.ts +15 -0
  21. package/dist/resources/attachments.js +13 -0
  22. package/dist/resources/bash.d.ts +9 -0
  23. package/dist/resources/bash.js +15 -0
  24. package/dist/resources/canvas/history.d.ts +11 -0
  25. package/dist/resources/canvas/history.js +20 -0
  26. package/dist/resources/canvas.d.ts +19 -0
  27. package/dist/resources/canvas.js +42 -0
  28. package/dist/resources/crons.d.ts +15 -0
  29. package/dist/resources/crons.js +33 -0
  30. package/dist/resources/custom-objects.d.ts +20 -0
  31. package/dist/resources/custom-objects.js +84 -0
  32. package/dist/resources/files.d.ts +34 -0
  33. package/dist/resources/files.js +34 -0
  34. package/dist/resources/forward.d.ts +7 -0
  35. package/dist/resources/forward.js +64 -0
  36. package/dist/resources/human/inbox.d.ts +14 -0
  37. package/dist/resources/human/inbox.js +30 -0
  38. package/dist/resources/human/requests.d.ts +13 -0
  39. package/dist/resources/human/requests.js +26 -0
  40. package/dist/resources/human.d.ts +8 -0
  41. package/dist/resources/human.js +10 -0
  42. package/dist/resources/identifiers.d.ts +8 -0
  43. package/dist/resources/identifiers.js +33 -0
  44. package/dist/resources/memory.d.ts +69 -0
  45. package/dist/resources/memory.js +30 -0
  46. package/dist/resources/models/config.d.ts +8 -0
  47. package/dist/resources/models/config.js +9 -0
  48. package/dist/resources/models/credentials.d.ts +10 -0
  49. package/dist/resources/models/credentials.js +17 -0
  50. package/dist/resources/models.d.ts +8 -0
  51. package/dist/resources/models.js +10 -0
  52. package/dist/resources/node-stream.d.ts +34 -0
  53. package/dist/resources/node-stream.js +176 -0
  54. package/dist/resources/nodes/jobs.d.ts +9 -0
  55. package/dist/resources/nodes/jobs.js +14 -0
  56. package/dist/resources/nodes/result.d.ts +8 -0
  57. package/dist/resources/nodes/result.js +11 -0
  58. package/dist/resources/nodes/worktree.d.ts +9 -0
  59. package/dist/resources/nodes/worktree.js +14 -0
  60. package/dist/resources/nodes.d.ts +23 -0
  61. package/dist/resources/nodes.js +47 -0
  62. package/dist/resources/providers.d.ts +51 -0
  63. package/dist/resources/providers.js +15 -0
  64. package/dist/resources/questions.d.ts +49 -0
  65. package/dist/resources/questions.js +21 -0
  66. package/dist/resources/request.d.ts +3 -0
  67. package/dist/resources/request.js +11 -0
  68. package/dist/resources/run-reply.d.ts +79 -0
  69. package/dist/resources/run-reply.js +84 -0
  70. package/dist/resources/run-stream.d.ts +40 -0
  71. package/dist/resources/run-stream.js +206 -0
  72. package/dist/resources/runs.d.ts +184 -0
  73. package/dist/resources/runs.js +197 -0
  74. package/dist/resources/shares.d.ts +40 -0
  75. package/dist/resources/shares.js +19 -0
  76. package/dist/resources/uploads.d.ts +27 -0
  77. package/dist/resources/uploads.js +11 -0
  78. package/dist/schema.d.ts +7 -0
  79. package/dist/schema.js +10 -0
  80. package/dist/stores/postgres.d.ts +29 -0
  81. package/dist/stores/postgres.js +86 -0
  82. package/dist/types.d.ts +80 -0
  83. package/dist/types.js +1 -0
  84. package/package.json +55 -0
@@ -0,0 +1,42 @@
1
+ import { routes, } from '@crouter/api';
2
+ import { CanvasHistory } from './canvas/history.js';
3
+ import { withQuery } from './request.js';
4
+ export class Canvas {
5
+ request;
6
+ history;
7
+ constructor(request) {
8
+ this.request = request;
9
+ this.history = new CanvasHistory(request);
10
+ }
11
+ attention(options) {
12
+ return this.request('GET', routes.canvasAttention(), undefined, options);
13
+ }
14
+ attentionCounts(body, options) {
15
+ return this.request('POST', routes.canvasAttentionCounts(), body, options);
16
+ }
17
+ snapshot(options) {
18
+ return this.request('GET', routes.canvasSnapshot(), undefined, options);
19
+ }
20
+ roster(options) {
21
+ return this.request('GET', routes.canvasRoster(), undefined, options);
22
+ }
23
+ async dashboard(query, options) {
24
+ const nodeQuery = query?.under === undefined ? undefined : { under: query.under };
25
+ const [nodes, status] = await Promise.all([
26
+ this.request('GET', withQuery(routes.nodes(), nodeQuery), undefined, options),
27
+ this.request('GET', routes.status(), undefined, options),
28
+ ]);
29
+ return { nodes, counts: status.node_counts, generated_at: new Date().toISOString() };
30
+ }
31
+ /** Watch an object; `watcher` makes a custom object the receiver instead of the caller's node. */
32
+ watch(ref, body = {}, options) {
33
+ return this.request('POST', routes.objectWatch(ref), body, options);
34
+ }
35
+ /** Remove a watch. `watcher` identifies the custom object whose watch is removed. */
36
+ unwatch(ref, query, options) {
37
+ return this.request('DELETE', withQuery(routes.objectWatch(ref), query), undefined, options);
38
+ }
39
+ prune(body, options) {
40
+ return this.request('POST', routes.canvasPrune(), body, options);
41
+ }
42
+ }
@@ -0,0 +1,15 @@
1
+ import { type ArmCronRequest, type CancelCronQuery, type CronDTO, type CronRunDTO, type CronScopeQuery, type CronShowDTO, type ListCronsQuery, type PokeCronsResult } from '@crouter/api';
2
+ import type { RequestOptions } from '../types.js';
3
+ import type { Request } from './request.js';
4
+ export declare class Crons {
5
+ private readonly request;
6
+ constructor(request: Request);
7
+ create(body: ArmCronRequest, options?: RequestOptions): Promise<CronDTO>;
8
+ retrieve(id: string, query?: CronScopeQuery, options?: RequestOptions): Promise<CronShowDTO>;
9
+ list(query?: ListCronsQuery, options?: RequestOptions): Promise<CronDTO[]>;
10
+ pause(id: string, query?: CronScopeQuery, options?: RequestOptions): Promise<CronDTO>;
11
+ resume(id: string, query?: CronScopeQuery, options?: RequestOptions): Promise<CronDTO>;
12
+ run(id: string, query?: CronScopeQuery, options?: RequestOptions): Promise<CronRunDTO>;
13
+ delete(id: string, query?: CancelCronQuery, options?: RequestOptions): Promise<void>;
14
+ poke(options?: RequestOptions): Promise<PokeCronsResult>;
15
+ }
@@ -0,0 +1,33 @@
1
+ import { routes, } from '@crouter/api';
2
+ import { cronId } from './identifiers.js';
3
+ import { withQuery } from './request.js';
4
+ export class Crons {
5
+ request;
6
+ constructor(request) {
7
+ this.request = request;
8
+ }
9
+ create(body, options) {
10
+ return this.request('POST', routes.crons(), body, options);
11
+ }
12
+ async retrieve(id, query, options) {
13
+ return this.request('GET', withQuery(routes.cron(cronId(id)), query), undefined, options);
14
+ }
15
+ list(query, options) {
16
+ return this.request('GET', withQuery(routes.crons(), query), undefined, options);
17
+ }
18
+ async pause(id, query, options) {
19
+ return this.request('POST', withQuery(routes.cronPause(cronId(id)), query), {}, options);
20
+ }
21
+ async resume(id, query, options) {
22
+ return this.request('POST', withQuery(routes.cronResume(cronId(id)), query), {}, options);
23
+ }
24
+ async run(id, query, options) {
25
+ return this.request('POST', withQuery(routes.cronRun(cronId(id)), query), {}, options);
26
+ }
27
+ async delete(id, query, options) {
28
+ return this.request('DELETE', withQuery(routes.cron(cronId(id)), query), undefined, options);
29
+ }
30
+ poke(options) {
31
+ return this.request('POST', routes.cronsPoke(), {}, options);
32
+ }
33
+ }
@@ -0,0 +1,20 @@
1
+ import { type AckCustomDeliveriesResponseDTO, type PublishCustomObjectRequestDTO, type PublishCustomObjectResponseDTO, type QueueLineDTO, type RegisterCustomObjectRequestDTO, type RegisterCustomObjectResponseDTO } from '@crouter/api';
2
+ import type { RequestOptions } from '../types.js';
3
+ import type { Request } from './request.js';
4
+ /** Queue streams replay every pending delivery on connect. `after` is accepted for compatibility but ignored for pending work. */
5
+ export type ReceiveOptions = Pick<RequestOptions, 'signal' | 'headers' | 'maxRetries'> & {
6
+ after?: number;
7
+ };
8
+ /** A single queue connection. EOF (including rotate/unregister/receiver change) ends iteration; reconnect to replay unacknowledged work. */
9
+ export interface CustomDeliveryStream extends AsyncIterableIterator<QueueLineDTO> {
10
+ }
11
+ export declare class CustomObjects {
12
+ private readonly request;
13
+ private readonly open;
14
+ constructor(request: Request, open: (path: string, options: ReceiveOptions) => Promise<Response>);
15
+ register(body: RegisterCustomObjectRequestDTO, options?: RequestOptions): Promise<RegisterCustomObjectResponseDTO>;
16
+ publish(ref: string, body: PublishCustomObjectRequestDTO, options?: RequestOptions): Promise<PublishCustomObjectResponseDTO>;
17
+ unregister(ref: string, options?: RequestOptions): Promise<void>;
18
+ ack(ref: string, deliveryIds: string[], options?: RequestOptions): Promise<AckCustomDeliveriesResponseDTO>;
19
+ receive(ref: string, options?: ReceiveOptions): CustomDeliveryStream;
20
+ }
@@ -0,0 +1,84 @@
1
+ import { routes, } from '@crouter/api';
2
+ import { APIConnectionError, APIError, APIUserAbortError } from '../errors.js';
3
+ import { withQuery } from './request.js';
4
+ export class CustomObjects {
5
+ request;
6
+ open;
7
+ constructor(request, open) {
8
+ this.request = request;
9
+ this.open = open;
10
+ }
11
+ register(body, options) {
12
+ return this.request('POST', routes.customObjects(), body, options);
13
+ }
14
+ publish(ref, body, options) {
15
+ return this.request('POST', routes.customObjectEvents(ref), body, options);
16
+ }
17
+ unregister(ref, options) {
18
+ return this.request('DELETE', routes.customObject(ref), undefined, options);
19
+ }
20
+ ack(ref, deliveryIds, options) {
21
+ return this.request('POST', routes.customObjectAck(ref), { delivery_ids: deliveryIds }, options);
22
+ }
23
+ receive(ref, options = {}) {
24
+ const { after, ...requestOptions } = options;
25
+ if (after !== undefined && (!Number.isSafeInteger(after) || after < 0)) {
26
+ throw new RangeError('after must be a non-negative safe integer');
27
+ }
28
+ const path = withQuery(routes.customObjectDeliveries(ref), { after });
29
+ const iterate = async function* (open) {
30
+ const controller = new AbortController();
31
+ const abort = () => controller.abort(options.signal?.reason);
32
+ if (options.signal?.aborted)
33
+ abort();
34
+ else
35
+ options.signal?.addEventListener('abort', abort, { once: true });
36
+ let reader;
37
+ try {
38
+ const response = await open(path, { ...requestOptions, signal: controller.signal });
39
+ if (response.body === null)
40
+ return;
41
+ reader = response.body.getReader();
42
+ const decoder = new TextDecoder();
43
+ let buffer = '';
44
+ for (;;) {
45
+ const { done, value } = await reader.read();
46
+ buffer += decoder.decode(value, { stream: !done });
47
+ const lines = buffer.split(/\r?\n/);
48
+ buffer = lines.pop() ?? '';
49
+ if (done && buffer !== '')
50
+ lines.push(buffer);
51
+ for (const line of lines) {
52
+ if (line.trim() === '')
53
+ continue; // heartbeat
54
+ const delivery = JSON.parse(line);
55
+ yield delivery;
56
+ }
57
+ if (done)
58
+ return; // server deliberately closes on rotate/unregister/receiver change
59
+ }
60
+ }
61
+ catch (error) {
62
+ if (controller.signal.aborted && options.signal?.aborted) {
63
+ throw new APIUserAbortError(0, 'request_aborted', 'request aborted by caller signal');
64
+ }
65
+ if (error instanceof Error && !(error instanceof SyntaxError) && !(error instanceof APIError)) {
66
+ throw new APIConnectionError(0, 'connection_error', error.message);
67
+ }
68
+ throw error;
69
+ }
70
+ finally {
71
+ options.signal?.removeEventListener('abort', abort);
72
+ controller.abort();
73
+ if (reader !== undefined) {
74
+ try {
75
+ await reader.cancel();
76
+ }
77
+ catch { /* the server may have already closed */ }
78
+ reader.releaseLock();
79
+ }
80
+ }
81
+ };
82
+ return iterate(this.open);
83
+ }
84
+ }
@@ -0,0 +1,34 @@
1
+ import { type FileEncoding, type FileListDTO, type FilePeekDTO, type FileWriteDTO } from '@crouter/api';
2
+ import type { RequestOptions } from '../types.js';
3
+ import type { Request } from './request.js';
4
+ /** Options for `files.download`. */
5
+ export interface FileDownloadOptions {
6
+ /** A single `Range` header value, e.g. `bytes=0-0` or `bytes=-500`; the answer is then 206 with `Content-Range`. */
7
+ range?: string;
8
+ /** Aborts the request and the body stream. */
9
+ signal?: AbortSignal;
10
+ }
11
+ /** Opens a raw download; the client supplies the bearer token and refresh. */
12
+ export type FileDownloadOpener = (path: string, options: FileDownloadOptions) => Promise<Response>;
13
+ export declare class Files {
14
+ private readonly request;
15
+ private readonly openDownload?;
16
+ constructor(request: Request, openDownload?: FileDownloadOpener | undefined);
17
+ read(path: string, options?: {
18
+ encoding?: FileEncoding;
19
+ } & RequestOptions): Promise<FilePeekDTO>;
20
+ write(path: string, content: string, options?: {
21
+ encoding?: FileEncoding;
22
+ } & RequestOptions): Promise<FileWriteDTO>;
23
+ list(path: string, options?: {
24
+ limit?: number;
25
+ } & RequestOptions): Promise<FileListDTO>;
26
+ /**
27
+ * The raw bytes of a file the caller may read (app listener only). Answers the `Response`
28
+ * itself (200, or 206 for `range`) with `Content-Type`, `Content-Length`, and `Content-Range`,
29
+ * so its body can be piped on. A non-2xx answer is thrown as `APIError` — a bad range is
30
+ * 416 `invalid_request` with `param: 'range'` — and never returned as bytes. A body cut
31
+ * short mid-stream means the file could not be read to the end.
32
+ */
33
+ download(path: string, options?: FileDownloadOptions): Promise<Response>;
34
+ }
@@ -0,0 +1,34 @@
1
+ import { routes, } from '@crouter/api';
2
+ import { withQuery } from './request.js';
3
+ export class Files {
4
+ request;
5
+ openDownload;
6
+ constructor(request, openDownload) {
7
+ this.request = request;
8
+ this.openDownload = openDownload;
9
+ }
10
+ read(path, options) {
11
+ const { encoding, ...requestOptions } = options ?? {};
12
+ return this.request('GET', withQuery(routes.filePeek(), { path, encoding }), undefined, requestOptions);
13
+ }
14
+ write(path, content, options) {
15
+ const { encoding, ...requestOptions } = options ?? {};
16
+ return this.request('POST', routes.fileWrite(), { path, content, encoding }, requestOptions);
17
+ }
18
+ list(path, options) {
19
+ const { limit, ...requestOptions } = options ?? {};
20
+ return this.request('GET', withQuery(routes.fileList(), { path, limit }), undefined, requestOptions);
21
+ }
22
+ /**
23
+ * The raw bytes of a file the caller may read (app listener only). Answers the `Response`
24
+ * itself (200, or 206 for `range`) with `Content-Type`, `Content-Length`, and `Content-Range`,
25
+ * so its body can be piped on. A non-2xx answer is thrown as `APIError` — a bad range is
26
+ * 416 `invalid_request` with `param: 'range'` — and never returned as bytes. A body cut
27
+ * short mid-stream means the file could not be read to the end.
28
+ */
29
+ async download(path, options = {}) {
30
+ if (!this.openDownload)
31
+ throw new TypeError('files.download requires a Crouter client');
32
+ return this.openDownload(path, options);
33
+ }
34
+ }
@@ -0,0 +1,7 @@
1
+ import type { Crouter } from '../client.js';
2
+ /** Native EventSource sends Last-Event-ID on reconnect; it takes precedence over the URL cursor. */
3
+ export declare function cursorFromRequest(request: Request): number;
4
+ export declare function forwardRunEvents(crouter: Crouter, runId: string, options: {
5
+ after: number;
6
+ signal?: AbortSignal;
7
+ }): Response;
@@ -0,0 +1,64 @@
1
+ import { APIError } from '../errors.js';
2
+ /** Native EventSource sends Last-Event-ID on reconnect; it takes precedence over the URL cursor. */
3
+ export function cursorFromRequest(request) {
4
+ const header = request.headers.get('Last-Event-ID');
5
+ const value = header !== null ? header : new URL(request.url).searchParams.get('after') ?? '0';
6
+ const cursor = Number(value);
7
+ if (!/^(0|[1-9]\d*)$/.test(value) || !Number.isSafeInteger(cursor))
8
+ throw new RangeError('Invalid event cursor');
9
+ return cursor;
10
+ }
11
+ export function forwardRunEvents(crouter, runId, options) {
12
+ const encoder = new TextEncoder();
13
+ const envelope = (failure) => ({
14
+ code: failure.code, message: failure.message,
15
+ ...(failure.type !== undefined ? { type: failure.type } : {}),
16
+ ...(failure.param !== undefined ? { param: failure.param } : {}),
17
+ ...(failure.details !== undefined ? { details: failure.details } : {}),
18
+ ...(failure.retryable !== undefined ? { retryable: failure.retryable } : {}),
19
+ ...(failure.retryAfterS !== undefined ? { retry_after_s: failure.retryAfterS } : {}),
20
+ ...(failure.resetAt !== undefined ? { reset_at: failure.resetAt } : {}),
21
+ ...(failure.userAction !== undefined ? { user_action: failure.userAction } : {}),
22
+ ...(failure.requestId !== undefined ? { request_id: failure.requestId } : {}),
23
+ ...(failure.runId !== undefined ? { run_id: failure.runId } : {}),
24
+ ...(failure.questionId !== undefined ? { question_id: failure.questionId } : {}),
25
+ ...(failure.scope !== undefined ? { scope: failure.scope } : {}),
26
+ ...(failure.origin !== undefined ? { origin: failure.origin } : {}),
27
+ });
28
+ const failureEnvelope = (error) => envelope(error instanceof APIError ? error : new APIError(0, 'transport_error', String(error), undefined, undefined, { retryable: true }));
29
+ let notify = () => undefined;
30
+ const source = crouter.runs.events(runId, { ...options, onReconnect: (state, error) => notify(state, error) });
31
+ let closed = false;
32
+ const stream = new ReadableStream({
33
+ start(controller) {
34
+ const write = (text) => { if (!closed)
35
+ controller.enqueue(encoder.encode(text)); };
36
+ notify = (state, error) => write(`data: ${JSON.stringify(state === 'reconnected' ? { type: 'stream.reconnected' } : { type: 'stream.reconnecting', error: failureEnvelope(error) })}\n\n`);
37
+ const keepalive = setInterval(() => write(': keepalive\n\n'), 15_000);
38
+ void (async () => {
39
+ try {
40
+ for await (const event of source) {
41
+ write(`id: ${event.sequence_number}\ndata: ${JSON.stringify(event)}\n\n`);
42
+ if (event.type === 'node.settled')
43
+ break;
44
+ }
45
+ }
46
+ catch (error) {
47
+ if (options.signal?.aborted)
48
+ return;
49
+ write(`data: ${JSON.stringify({ type: 'stream.refused', error: failureEnvelope(error) })}\n\n`);
50
+ }
51
+ finally {
52
+ source.abort();
53
+ clearInterval(keepalive);
54
+ if (!closed) {
55
+ closed = true;
56
+ controller.close();
57
+ }
58
+ }
59
+ })();
60
+ },
61
+ cancel() { closed = true; source.abort(); },
62
+ });
63
+ return new Response(stream, { headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'X-Accel-Buffering': 'no' } });
64
+ }
@@ -0,0 +1,14 @@
1
+ import { type CancelInboxTicketRequest, type CanceledTicketResultDTO, type InboxListDTO, type InboxPageDTO, type InboxPageHistoryDTO, type InboxPageProgressDTO, type InboxPageResponseDTO, type PageTicketResultDTO, type RespondInboxPageRequest } from '@crouter/api';
2
+ import type { RequestOptions } from '../../types.js';
3
+ import type { Request } from '../request.js';
4
+ export declare class HumanInbox {
5
+ private readonly request;
6
+ constructor(request: Request);
7
+ list(options?: RequestOptions): Promise<InboxListDTO>;
8
+ retrieve(ticketId: string, options?: RequestOptions): Promise<InboxPageDTO>;
9
+ respond(ticketId: string, body: RespondInboxPageRequest, options?: RequestOptions): Promise<PageTicketResultDTO>;
10
+ progress(ticketId: string, body: InboxPageProgressDTO, options?: RequestOptions): Promise<Record<string, unknown>>;
11
+ cancel(ticketId: string, body?: CancelInboxTicketRequest, options?: RequestOptions): Promise<CanceledTicketResultDTO>;
12
+ history(nodeId?: string, options?: RequestOptions): Promise<InboxPageHistoryDTO>;
13
+ response(ticketId: string, options?: RequestOptions): Promise<InboxPageResponseDTO>;
14
+ }
@@ -0,0 +1,30 @@
1
+ import { routes, } from '@crouter/api';
2
+ import { inboxTicketId } from '../identifiers.js';
3
+ import { withQuery } from '../request.js';
4
+ export class HumanInbox {
5
+ request;
6
+ constructor(request) {
7
+ this.request = request;
8
+ }
9
+ list(options) {
10
+ return this.request('GET', routes.humanInbox(), undefined, options);
11
+ }
12
+ async retrieve(ticketId, options) {
13
+ return this.request('GET', routes.humanInboxTicket(inboxTicketId(ticketId)), undefined, options);
14
+ }
15
+ async respond(ticketId, body, options) {
16
+ return this.request('POST', routes.humanInboxRespond(inboxTicketId(ticketId)), body, options);
17
+ }
18
+ async progress(ticketId, body, options) {
19
+ return this.request('POST', routes.humanInboxProgress(inboxTicketId(ticketId)), body, options);
20
+ }
21
+ async cancel(ticketId, body, options) {
22
+ return this.request('POST', routes.humanInboxCancel(inboxTicketId(ticketId)), body ?? {}, options);
23
+ }
24
+ history(nodeId, options) {
25
+ return this.request('GET', withQuery('/v1/human/inbox/history', nodeId === undefined ? undefined : { node_id: nodeId }), undefined, options);
26
+ }
27
+ async response(ticketId, options) {
28
+ return this.request('GET', routes.humanInboxResponse(inboxTicketId(ticketId)), undefined, options);
29
+ }
30
+ }
@@ -0,0 +1,13 @@
1
+ import { type CreateHumanRequestDTO, type CreateHumanRequestRequest, type HumanRequestDTO, type ReplaceHumanRequestRequest, type RespondHumanRequestRequest, type SettleHumanRequestRequest } from '@crouter/api';
2
+ import type { RequestOptions } from '../../types.js';
3
+ import type { Request } from '../request.js';
4
+ export declare class HumanRequests {
5
+ private readonly request;
6
+ constructor(request: Request);
7
+ create(body: CreateHumanRequestRequest, options?: RequestOptions): Promise<CreateHumanRequestDTO>;
8
+ retrieve(id: string, options?: RequestOptions): Promise<HumanRequestDTO>;
9
+ replace(id: string, body: ReplaceHumanRequestRequest, options?: RequestOptions): Promise<HumanRequestDTO>;
10
+ respond(id: string, body: RespondHumanRequestRequest, options?: RequestOptions): Promise<HumanRequestDTO>;
11
+ dismiss(id: string, body?: SettleHumanRequestRequest, options?: RequestOptions): Promise<HumanRequestDTO>;
12
+ cancel(id: string, body?: SettleHumanRequestRequest, options?: RequestOptions): Promise<HumanRequestDTO>;
13
+ }
@@ -0,0 +1,26 @@
1
+ import { routes, } from '@crouter/api';
2
+ import { requestId } from '../identifiers.js';
3
+ export class HumanRequests {
4
+ request;
5
+ constructor(request) {
6
+ this.request = request;
7
+ }
8
+ create(body, options) {
9
+ return this.request('POST', routes.humanRequests(), body, options);
10
+ }
11
+ async retrieve(id, options) {
12
+ return this.request('GET', routes.humanRequest(requestId(id)), undefined, options);
13
+ }
14
+ async replace(id, body, options) {
15
+ return this.request('POST', routes.humanRequestReplace(requestId(id)), body, options);
16
+ }
17
+ async respond(id, body, options) {
18
+ return this.request('POST', routes.humanRequestRespond(requestId(id)), body, options);
19
+ }
20
+ async dismiss(id, body, options) {
21
+ return this.request('POST', routes.humanRequestDismiss(requestId(id)), body ?? {}, options);
22
+ }
23
+ async cancel(id, body, options) {
24
+ return this.request('POST', routes.humanRequestCancel(requestId(id)), body ?? {}, options);
25
+ }
26
+ }
@@ -0,0 +1,8 @@
1
+ import { HumanInbox } from './human/inbox.js';
2
+ import { HumanRequests } from './human/requests.js';
3
+ import type { Request } from './request.js';
4
+ export declare class Human {
5
+ readonly requests: HumanRequests;
6
+ readonly inbox: HumanInbox;
7
+ constructor(request: Request);
8
+ }
@@ -0,0 +1,10 @@
1
+ import { HumanInbox } from './human/inbox.js';
2
+ import { HumanRequests } from './human/requests.js';
3
+ export class Human {
4
+ requests;
5
+ inbox;
6
+ constructor(request) {
7
+ this.requests = new HumanRequests(request);
8
+ this.inbox = new HumanInbox(request);
9
+ }
10
+ }
@@ -0,0 +1,8 @@
1
+ export declare class ResourceIdentifierError extends TypeError {
2
+ }
3
+ export declare function nodeId(value: string): string;
4
+ export declare function requestId(value: string): string;
5
+ export declare function cronId(value: string): string;
6
+ export declare function jobId(value: string): string;
7
+ export declare function inboxTicketId(value: string): string;
8
+ export declare function pathSegment(value: string, label: string): string;
@@ -0,0 +1,33 @@
1
+ import { isSafeBashJobId, isSafeCronId, isSafeNodeId } from '@crouter/api';
2
+ export class ResourceIdentifierError extends TypeError {
3
+ }
4
+ function validated(value, label, validator) {
5
+ if (!validator(value) || !isSafePathSegment(value)) {
6
+ throw new ResourceIdentifierError(`invalid ${label}: ${JSON.stringify(value)}`);
7
+ }
8
+ return value;
9
+ }
10
+ function isSafePathSegment(value) {
11
+ return typeof value === 'string'
12
+ && value !== '' && value !== '.' && value !== '..'
13
+ && !/[\\/\0\s?#%]/u.test(value)
14
+ && new TextEncoder().encode(value).byteLength <= 128;
15
+ }
16
+ export function nodeId(value) {
17
+ return validated(value, 'node id', isSafeNodeId);
18
+ }
19
+ export function requestId(value) {
20
+ return validated(value, 'request id', isSafeNodeId);
21
+ }
22
+ export function cronId(value) {
23
+ return validated(value, 'cron id', isSafeCronId);
24
+ }
25
+ export function jobId(value) {
26
+ return validated(value, 'job id', isSafeBashJobId);
27
+ }
28
+ export function inboxTicketId(value) {
29
+ return validated(value, 'inbox ticket id', (ticketId) => /^[a-f0-9]{64}$/u.test(ticketId));
30
+ }
31
+ export function pathSegment(value, label) {
32
+ return validated(value, label, isSafePathSegment);
33
+ }
@@ -0,0 +1,69 @@
1
+ import type { RequestOptions } from '../types.js';
2
+ import { type Request } from './request.js';
3
+ /** `memory.list` input. Only the documents the person owns (`store: 'user'`) are served in this release. */
4
+ export interface MemoryListParams {
5
+ store: 'user';
6
+ /** A folder: documents whose name starts with `<path>/`, at any depth. */
7
+ path?: string;
8
+ kind?: 'knowledge' | 'preference';
9
+ /** 1 to 100; default 50. */
10
+ limit?: number;
11
+ /** The previous page's `next_cursor`, unchanged, with the same `store`, `path` and `kind`. */
12
+ cursor?: string;
13
+ }
14
+ /** `memory.get` input. */
15
+ export interface MemoryGetParams {
16
+ store: 'user';
17
+ /** The document's full name, as `memory.list` returns it. */
18
+ name: string;
19
+ }
20
+ /** One document the person owns, as listed. */
21
+ export interface MemoryListItem {
22
+ /** The full name without the `user/` owner prefix. */
23
+ name: string;
24
+ /** The name up to its last `/`; `""` for a top-level document. */
25
+ folder: string;
26
+ kind: 'knowledge' | 'preference';
27
+ preview: string;
28
+ summary: string | null;
29
+ /** Without a `crtr:memory:manage:user` grant an app only ever sees `public`. */
30
+ privacy: 'public' | 'friends' | 'private';
31
+ /** The current revision number. */
32
+ revision: number;
33
+ /** The time of revision 1. */
34
+ created_at: string;
35
+ /** The time of the current revision. */
36
+ updated_at: string;
37
+ }
38
+ /** A page of `memory.list`, ordered by name. */
39
+ export interface MemoryListPage {
40
+ items: MemoryListItem[];
41
+ /** `null` on the last page. */
42
+ next_cursor: string | null;
43
+ }
44
+ /** A document with its body, from `memory.get`. */
45
+ export interface MemoryDocument extends MemoryListItem {
46
+ /** The current markdown body as stored; links are not resolved. At most 1 MiB. */
47
+ body: string;
48
+ /** The full body's length in UTF-8 bytes. */
49
+ size: number;
50
+ /** `true` when `size` is over 1 MiB and `body` is its prefix. */
51
+ truncated: boolean;
52
+ /** `app:<id>` of the app whose node wrote revision 1; `null` when the person wrote it. */
53
+ grantee: string | null;
54
+ }
55
+ /**
56
+ * Reads the documents the person owns. The daemon filters each one by the caller's
57
+ * grant: an app reads `public` documents with no scope, and every privacy level with
58
+ * `crtr:memory:manage:user`; without it a `friends` or `private` document reads
59
+ * exactly as an absent one (`NotFoundError`). Reading records nothing.
60
+ */
61
+ export declare class Memory {
62
+ private readonly request;
63
+ constructor(request: Request);
64
+ list(params: MemoryListParams, options?: RequestOptions): Promise<MemoryListPage>;
65
+ /** Every document across pages, ordered by name: `for await (const item of memory.listAll({store: 'user'}))`.
66
+ * Fetches the next page (`limit` per page) only as you iterate; `break` stops fetching. */
67
+ listAll(params: Omit<MemoryListParams, 'cursor'>, options?: RequestOptions): AsyncGenerator<MemoryListItem, void, undefined>;
68
+ get(params: MemoryGetParams, options?: RequestOptions): Promise<MemoryDocument>;
69
+ }
@@ -0,0 +1,30 @@
1
+ import { withQuery } from './request.js';
2
+ /**
3
+ * Reads the documents the person owns. The daemon filters each one by the caller's
4
+ * grant: an app reads `public` documents with no scope, and every privacy level with
5
+ * `crtr:memory:manage:user`; without it a `friends` or `private` document reads
6
+ * exactly as an absent one (`NotFoundError`). Reading records nothing.
7
+ */
8
+ export class Memory {
9
+ request;
10
+ constructor(request) {
11
+ this.request = request;
12
+ }
13
+ list(params, options) {
14
+ return this.request('GET', withQuery('/v1/memory', params), undefined, options);
15
+ }
16
+ /** Every document across pages, ordered by name: `for await (const item of memory.listAll({store: 'user'}))`.
17
+ * Fetches the next page (`limit` per page) only as you iterate; `break` stops fetching. */
18
+ async *listAll(params, options) {
19
+ for (let cursor;;) {
20
+ const page = await this.list({ ...params, ...(cursor === undefined ? {} : { cursor }) }, options);
21
+ yield* page.items;
22
+ if (!page.next_cursor)
23
+ return;
24
+ cursor = page.next_cursor;
25
+ }
26
+ }
27
+ get(params, options) {
28
+ return this.request('GET', withQuery('/v1/memory/document', params), undefined, options);
29
+ }
30
+ }
@@ -0,0 +1,8 @@
1
+ import { type PutModelConfigRequest, type PutModelConfigResponse } from '@crouter/api';
2
+ import type { RequestOptions } from '../../types.js';
3
+ import type { Request } from '../request.js';
4
+ export declare class ModelConfig {
5
+ private readonly request;
6
+ constructor(request: Request);
7
+ update(body: PutModelConfigRequest, options?: RequestOptions): Promise<PutModelConfigResponse>;
8
+ }
@@ -0,0 +1,9 @@
1
+ export class ModelConfig {
2
+ request;
3
+ constructor(request) {
4
+ this.request = request;
5
+ }
6
+ update(body, options) {
7
+ return this.request('PUT', '/v1/model-config', body, options);
8
+ }
9
+ }
@@ -0,0 +1,10 @@
1
+ import { type CredentialRemovalResultDTO, type CredentialResultDTO, type InstallCredentialRequest, type ModelAuthListDTO } from '@crouter/api';
2
+ import type { RequestOptions } from '../../types.js';
3
+ import type { Request } from '../request.js';
4
+ export declare class ModelCredentials {
5
+ private readonly request;
6
+ constructor(request: Request);
7
+ list(options?: RequestOptions): Promise<ModelAuthListDTO>;
8
+ install(provider: string, body: InstallCredentialRequest, options?: RequestOptions): Promise<CredentialResultDTO>;
9
+ remove(provider: string, options?: RequestOptions): Promise<CredentialRemovalResultDTO>;
10
+ }
@@ -0,0 +1,17 @@
1
+ import { routes, } from '@crouter/api';
2
+ import { pathSegment } from '../identifiers.js';
3
+ export class ModelCredentials {
4
+ request;
5
+ constructor(request) {
6
+ this.request = request;
7
+ }
8
+ list(options) {
9
+ return this.request('GET', routes.modelAuths(), undefined, options);
10
+ }
11
+ async install(provider, body, options) {
12
+ return this.request('PUT', routes.modelAuth(pathSegment(provider, 'provider')), body, options);
13
+ }
14
+ async remove(provider, options) {
15
+ return this.request('DELETE', routes.modelAuth(pathSegment(provider, 'provider')), undefined, options);
16
+ }
17
+ }