@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,254 @@
1
+ export declare const errorCodes: {
2
+ readonly unauthorized: {
3
+ readonly type: "authentication_error";
4
+ readonly status: 401;
5
+ readonly retryable: false;
6
+ };
7
+ readonly grant_revoked: {
8
+ readonly type: "authentication_error";
9
+ readonly status: 401;
10
+ readonly retryable: false;
11
+ };
12
+ readonly grant_removed: {
13
+ readonly type: "authentication_error";
14
+ readonly status: 401;
15
+ readonly retryable: false;
16
+ };
17
+ readonly grant_suspended: {
18
+ readonly type: "authentication_error";
19
+ readonly status: 401;
20
+ readonly retryable: false;
21
+ };
22
+ readonly refresh_token_expired: {
23
+ readonly type: "authentication_error";
24
+ readonly status: 401;
25
+ readonly retryable: false;
26
+ };
27
+ readonly refresh_token_reused: {
28
+ readonly type: "authentication_error";
29
+ readonly status: 401;
30
+ readonly retryable: false;
31
+ };
32
+ readonly scope_missing: {
33
+ readonly type: "permission_error";
34
+ readonly status: 403;
35
+ readonly retryable: false;
36
+ };
37
+ readonly owner_only: {
38
+ readonly type: "permission_error";
39
+ readonly status: 403;
40
+ readonly retryable: false;
41
+ };
42
+ readonly other_app_run: {
43
+ readonly type: "permission_error";
44
+ readonly status: 403;
45
+ readonly retryable: false;
46
+ };
47
+ readonly payer_not_app: {
48
+ readonly type: "permission_error";
49
+ readonly status: 403;
50
+ readonly retryable: false;
51
+ };
52
+ readonly approval_pending: {
53
+ readonly type: "permission_error";
54
+ readonly status: 403;
55
+ readonly retryable: false;
56
+ };
57
+ readonly user_denied: {
58
+ readonly type: "permission_error";
59
+ readonly status: 403;
60
+ readonly retryable: false;
61
+ };
62
+ readonly provider_refused: {
63
+ readonly type: "permission_error";
64
+ readonly status: 403;
65
+ readonly retryable: false;
66
+ };
67
+ readonly provider_not_connected: {
68
+ readonly type: "permission_error";
69
+ readonly status: 403;
70
+ readonly retryable: false;
71
+ };
72
+ readonly question_pages_off: {
73
+ readonly type: "permission_error";
74
+ readonly status: 403;
75
+ readonly retryable: false;
76
+ };
77
+ readonly isolated_run: {
78
+ readonly type: "permission_error";
79
+ readonly status: 403;
80
+ readonly retryable: false;
81
+ };
82
+ readonly provider_version_retired: {
83
+ readonly type: "permission_error";
84
+ readonly status: 403;
85
+ readonly retryable: false;
86
+ };
87
+ readonly invalid_scope: {
88
+ readonly type: "invalid_request_error";
89
+ readonly status: 400;
90
+ readonly retryable: false;
91
+ };
92
+ readonly invalid_request: {
93
+ readonly type: "invalid_request_error";
94
+ readonly status: 400;
95
+ readonly retryable: false;
96
+ };
97
+ readonly range_not_satisfiable: {
98
+ readonly type: "invalid_request_error";
99
+ readonly status: 416;
100
+ readonly retryable: false;
101
+ };
102
+ readonly conflict: {
103
+ readonly type: "invalid_request_error";
104
+ readonly status: 409;
105
+ readonly retryable: false;
106
+ };
107
+ readonly not_found: {
108
+ readonly type: "invalid_request_error";
109
+ readonly status: 404;
110
+ readonly retryable: false;
111
+ };
112
+ readonly model_unavailable: {
113
+ readonly type: "invalid_request_error";
114
+ readonly status: 404;
115
+ readonly retryable: false;
116
+ };
117
+ readonly upstream_model_unavailable: {
118
+ readonly type: "server_error";
119
+ readonly status: 503;
120
+ readonly retryable: true;
121
+ };
122
+ readonly substitution_refused: {
123
+ readonly type: "invalid_request_error";
124
+ readonly status: 400;
125
+ readonly retryable: false;
126
+ };
127
+ readonly idempotency_conflict: {
128
+ readonly type: "invalid_request_error";
129
+ readonly status: 409;
130
+ readonly retryable: false;
131
+ };
132
+ readonly run_settled: {
133
+ readonly type: "invalid_request_error";
134
+ readonly status: 409;
135
+ readonly retryable: false;
136
+ };
137
+ readonly cap_exhausted: {
138
+ readonly type: "rate_limit_error";
139
+ readonly status: 402;
140
+ readonly retryable: false;
141
+ };
142
+ readonly concurrency_limit: {
143
+ readonly type: "rate_limit_error";
144
+ readonly status: 429;
145
+ readonly retryable: true;
146
+ };
147
+ readonly all_routes_exhausted: {
148
+ readonly type: "rate_limit_error";
149
+ readonly status: 429;
150
+ readonly retryable: true;
151
+ };
152
+ readonly provider_rate_limited: {
153
+ readonly type: "rate_limit_error";
154
+ readonly status: 429;
155
+ readonly retryable: true;
156
+ };
157
+ readonly rate_limited: {
158
+ readonly type: "rate_limit_error";
159
+ readonly status: 429;
160
+ readonly retryable: true;
161
+ };
162
+ readonly runtime_unreachable: {
163
+ readonly type: "server_error";
164
+ readonly status: 503;
165
+ readonly retryable: true;
166
+ };
167
+ readonly isolated_unavailable: {
168
+ readonly type: "server_error";
169
+ readonly status: 503;
170
+ readonly retryable: true;
171
+ };
172
+ readonly runtime_starting: {
173
+ readonly type: "server_error";
174
+ readonly status: 503;
175
+ readonly retryable: true;
176
+ };
177
+ readonly runtime_provisioning: {
178
+ readonly type: "server_error";
179
+ readonly status: 503;
180
+ readonly retryable: true;
181
+ };
182
+ readonly provider_unavailable: {
183
+ readonly type: "server_error";
184
+ readonly status: 503;
185
+ readonly retryable: true;
186
+ };
187
+ readonly upstream_refused: {
188
+ readonly type: "server_error";
189
+ readonly status: 502;
190
+ readonly retryable: false;
191
+ };
192
+ readonly provider_bad_response: {
193
+ readonly type: "server_error";
194
+ readonly status: 502;
195
+ readonly retryable: false;
196
+ };
197
+ readonly service_unavailable: {
198
+ readonly type: "server_error";
199
+ readonly status: 503;
200
+ readonly retryable: true;
201
+ };
202
+ readonly not_implemented: {
203
+ readonly type: "server_error";
204
+ readonly status: 501;
205
+ readonly retryable: false;
206
+ };
207
+ readonly permission_error: {
208
+ readonly type: "permission_error";
209
+ readonly status: 403;
210
+ readonly retryable: false;
211
+ };
212
+ readonly storage_unavailable: {
213
+ readonly type: "server_error";
214
+ readonly status: 503;
215
+ readonly retryable: true;
216
+ };
217
+ readonly server_error: {
218
+ readonly type: "server_error";
219
+ readonly status: 500;
220
+ readonly retryable: true;
221
+ };
222
+ readonly server_failure: {
223
+ readonly type: "server_error";
224
+ readonly status: 500;
225
+ readonly retryable: false;
226
+ };
227
+ readonly wake_timeout: {
228
+ readonly type: "server_error";
229
+ readonly status: 504;
230
+ readonly retryable: true;
231
+ };
232
+ };
233
+ export type ErrorCode = keyof typeof errorCodes;
234
+ export type ErrorType = (typeof errorCodes)[ErrorCode]['type'];
235
+ export type ErrorOrigin = 'directory' | 'router' | 'runtime' | 'provider' | 'app';
236
+ /** Full app-facing HTTP error body; the HTTP status is in the status line. */
237
+ export interface ErrorEnvelope {
238
+ error: {
239
+ code: string;
240
+ message: string;
241
+ details?: unknown;
242
+ type: ErrorType;
243
+ param?: string;
244
+ origin: ErrorOrigin;
245
+ retryable: boolean;
246
+ retry_after_s?: number;
247
+ reset_at?: string;
248
+ request_id: string;
249
+ run_id?: string;
250
+ question_id?: string;
251
+ user_action?: string;
252
+ scope?: string;
253
+ };
254
+ }
@@ -0,0 +1,54 @@
1
+ // Contract 2, "Error envelope". This is the fixed-tuple subset of the
2
+ // app-facing code table; codes with a variable status or a transport-specific
3
+ // shape (provider_error, usage, stream_*) do not have a fixed tuple.
4
+ export const errorCodes = {
5
+ unauthorized: { type: 'authentication_error', status: 401, retryable: false },
6
+ // A refusal that names no reason (runtime validation step 5, or the directory's bare invalid_grant). Not deprecated.
7
+ grant_revoked: { type: 'authentication_error', status: 401, retryable: false },
8
+ // The directory's reasons for refusing a refresh token (D2-ERR-49..51), carried in its invalid_grant error_description.
9
+ grant_removed: { type: 'authentication_error', status: 401, retryable: false },
10
+ grant_suspended: { type: 'authentication_error', status: 401, retryable: false },
11
+ refresh_token_expired: { type: 'authentication_error', status: 401, retryable: false },
12
+ refresh_token_reused: { type: 'authentication_error', status: 401, retryable: false },
13
+ scope_missing: { type: 'permission_error', status: 403, retryable: false },
14
+ owner_only: { type: 'permission_error', status: 403, retryable: false },
15
+ other_app_run: { type: 'permission_error', status: 403, retryable: false },
16
+ payer_not_app: { type: 'permission_error', status: 403, retryable: false },
17
+ approval_pending: { type: 'permission_error', status: 403, retryable: false },
18
+ user_denied: { type: 'permission_error', status: 403, retryable: false },
19
+ provider_refused: { type: 'permission_error', status: 403, retryable: false },
20
+ provider_not_connected: { type: 'permission_error', status: 403, retryable: false },
21
+ question_pages_off: { type: 'permission_error', status: 403, retryable: false },
22
+ isolated_run: { type: 'permission_error', status: 403, retryable: false },
23
+ provider_version_retired: { type: 'permission_error', status: 403, retryable: false },
24
+ invalid_scope: { type: 'invalid_request_error', status: 400, retryable: false },
25
+ invalid_request: { type: 'invalid_request_error', status: 400, retryable: false },
26
+ range_not_satisfiable: { type: 'invalid_request_error', status: 416, retryable: false },
27
+ conflict: { type: 'invalid_request_error', status: 409, retryable: false },
28
+ not_found: { type: 'invalid_request_error', status: 404, retryable: false },
29
+ model_unavailable: { type: 'invalid_request_error', status: 404, retryable: false },
30
+ upstream_model_unavailable: { type: 'server_error', status: 503, retryable: true },
31
+ substitution_refused: { type: 'invalid_request_error', status: 400, retryable: false },
32
+ idempotency_conflict: { type: 'invalid_request_error', status: 409, retryable: false },
33
+ run_settled: { type: 'invalid_request_error', status: 409, retryable: false },
34
+ cap_exhausted: { type: 'rate_limit_error', status: 402, retryable: false },
35
+ concurrency_limit: { type: 'rate_limit_error', status: 429, retryable: true },
36
+ all_routes_exhausted: { type: 'rate_limit_error', status: 429, retryable: true },
37
+ provider_rate_limited: { type: 'rate_limit_error', status: 429, retryable: true },
38
+ rate_limited: { type: 'rate_limit_error', status: 429, retryable: true },
39
+ runtime_unreachable: { type: 'server_error', status: 503, retryable: true },
40
+ isolated_unavailable: { type: 'server_error', status: 503, retryable: true },
41
+ runtime_starting: { type: 'server_error', status: 503, retryable: true },
42
+ runtime_provisioning: { type: 'server_error', status: 503, retryable: true },
43
+ provider_unavailable: { type: 'server_error', status: 503, retryable: true },
44
+ upstream_refused: { type: 'server_error', status: 502, retryable: false },
45
+ provider_bad_response: { type: 'server_error', status: 502, retryable: false },
46
+ service_unavailable: { type: 'server_error', status: 503, retryable: true },
47
+ not_implemented: { type: 'server_error', status: 501, retryable: false },
48
+ permission_error: { type: 'permission_error', status: 403, retryable: false },
49
+ storage_unavailable: { type: 'server_error', status: 503, retryable: true },
50
+ server_error: { type: 'server_error', status: 500, retryable: true },
51
+ server_failure: { type: 'server_error', status: 500, retryable: false },
52
+ // Hosted router sleep/wake stage, not emitted by the always-on v1 runtime.
53
+ wake_timeout: { type: 'server_error', status: 504, retryable: true },
54
+ };
@@ -0,0 +1,47 @@
1
+ /** The uniform JSON body crtrd returns on any non-2xx response. */
2
+ export interface ErrorBody {
3
+ error: {
4
+ code: string;
5
+ message: string;
6
+ details?: unknown;
7
+ type?: string;
8
+ param?: string;
9
+ origin?: string;
10
+ retryable?: boolean;
11
+ retry_after_s?: number;
12
+ reset_at?: string;
13
+ request_id?: string;
14
+ run_id?: string;
15
+ question_id?: string;
16
+ scope?: string;
17
+ user_action?: string;
18
+ };
19
+ }
20
+ /** Thrown by `CrtrClient` on a non-2xx response (or a synthesized transport
21
+ * failure such as an unreachable daemon). Carries the HTTP status, the stable
22
+ * machine `code` from the `ErrorBody`, and optional structured `details`. */
23
+ export declare class APIError extends Error {
24
+ readonly status: number;
25
+ readonly code: string;
26
+ readonly details?: unknown;
27
+ readonly headers: Headers;
28
+ readonly type?: string;
29
+ readonly param?: string;
30
+ readonly origin?: string;
31
+ readonly retryable?: boolean;
32
+ readonly retryAfterS?: number;
33
+ readonly resetAt?: string;
34
+ readonly requestId?: string;
35
+ readonly runId?: string;
36
+ readonly questionId?: string;
37
+ readonly scope?: string;
38
+ readonly userAction?: string;
39
+ constructor(status: number, code: string, message: string, details?: unknown, headers?: HeadersInit, envelope?: Partial<ErrorBody['error']>);
40
+ }
41
+ /** @deprecated Use APIError. Kept as the in-repo compatibility alias. */
42
+ export { APIError as ApiError };
43
+ /** A local API transport failure has stable status/code identity, independent
44
+ * of message prose. */
45
+ export declare function isDaemonTransportApiError(error: unknown): error is APIError;
46
+ /** Type guard for an `ErrorBody`-shaped parsed payload. */
47
+ export declare function isErrorBody(value: unknown): value is ErrorBody;
@@ -0,0 +1,66 @@
1
+ // API error contract (spec §8). Uniform JSON error body on any non-2xx; the
2
+ // client parses it and throws `ApiError`.
3
+ //
4
+ // PURITY (spec §3.1): Node built-ins + `src/api/*` only.
5
+ /** Thrown by `CrtrClient` on a non-2xx response (or a synthesized transport
6
+ * failure such as an unreachable daemon). Carries the HTTP status, the stable
7
+ * machine `code` from the `ErrorBody`, and optional structured `details`. */
8
+ export class APIError extends Error {
9
+ status;
10
+ code;
11
+ details;
12
+ headers;
13
+ type;
14
+ param;
15
+ origin;
16
+ retryable;
17
+ retryAfterS;
18
+ resetAt;
19
+ requestId;
20
+ runId;
21
+ questionId;
22
+ scope;
23
+ userAction;
24
+ constructor(status, code, message, details, headers, envelope) {
25
+ super(message);
26
+ this.name = 'APIError';
27
+ this.status = status;
28
+ this.code = code;
29
+ this.headers = new Headers(headers);
30
+ if (details !== undefined)
31
+ this.details = details;
32
+ this.type = envelope?.type;
33
+ this.param = envelope?.param;
34
+ this.origin = envelope?.origin;
35
+ this.retryable = envelope?.retryable;
36
+ this.retryAfterS = envelope?.retry_after_s;
37
+ this.resetAt = envelope?.reset_at;
38
+ this.requestId = envelope?.request_id ?? this.headers.get('Request-Id') ?? undefined;
39
+ this.runId = envelope?.run_id;
40
+ this.questionId = envelope?.question_id;
41
+ this.scope = envelope?.scope;
42
+ this.userAction = envelope?.user_action;
43
+ }
44
+ }
45
+ /** @deprecated Use APIError. Kept as the in-repo compatibility alias. */
46
+ export { APIError as ApiError };
47
+ /** A local API transport failure has stable status/code identity, independent
48
+ * of message prose. */
49
+ export function isDaemonTransportApiError(error) {
50
+ if (!(error instanceof APIError))
51
+ return false;
52
+ return (error.status === 503 && (error.code === 'daemon_unavailable'
53
+ || error.code === 'transport_error'
54
+ || error.code === 'daemon_request_interrupted')) || (error.status === 504 && error.code === 'request_timeout')
55
+ || (error.status >= 500 && error.code === 'daemon_health_unavailable');
56
+ }
57
+ /** Type guard for an `ErrorBody`-shaped parsed payload. */
58
+ export function isErrorBody(value) {
59
+ if (typeof value !== 'object' || value === null)
60
+ return false;
61
+ const err = value.error;
62
+ if (typeof err !== 'object' || err === null)
63
+ return false;
64
+ const { code, message } = err;
65
+ return typeof code === 'string' && typeof message === 'string';
66
+ }
@@ -0,0 +1,42 @@
1
+ export { CrtrClient, waitForDaemonAvailability } from './client.js';
2
+ export type { CrtrClientOptions, CrtrRequestOptions } from './client.js';
3
+ export { APIError, ApiError, isErrorBody } from './errors.js';
4
+ export type { ErrorBody } from './errors.js';
5
+ export { errorCodes } from './error-codes.js';
6
+ export type { ErrorCode, ErrorEnvelope, ErrorOrigin, ErrorType } from './error-codes.js';
7
+ export { API_VERSION, routes } from './routes.js';
8
+ export * from '../shared/generated-context.js';
9
+ export * from './dto/common.js';
10
+ export * from './dto/health.js';
11
+ export * from './dto/grants.js';
12
+ export * from './dto/nodes.js';
13
+ export * from './dto/node-outcomes.js';
14
+ export * from './dto/node-events.js';
15
+ export * from './dto/run-events.js';
16
+ export * from './dto/broker-signals.js';
17
+ export * from './dto/bash-jobs.js';
18
+ export * from './dto/messages.js';
19
+ export * from './dto/reports.js';
20
+ export * from './dto/lifecycle.js';
21
+ export * from './dto/subscriptions.js';
22
+ export * from './dto/focus.js';
23
+ export * from './dto/crons.js';
24
+ export * from './dto/config.js';
25
+ export * from './dto/attach.js';
26
+ export * from './dto/broker.js';
27
+ export * from './dto/profiles.js';
28
+ export * from './dto/modelauth.js';
29
+ export * from './dto/model-config.js';
30
+ export * from './dto/canvas.js';
31
+ export * from './dto/worktree.js';
32
+ export * from './dto/human.js';
33
+ export * from './dto/files.js';
34
+ export * from './dto/bash.js';
35
+ export * from './dto/inbox.js';
36
+ export * from './dto/human-requests.js';
37
+ export * from './dto/reviews.js';
38
+ export * from './dto/review-comments.js';
39
+ export * from './dto/chat-inventory.js';
40
+ export * from './dto/analytics.js';
41
+ export * from './dto/custom-objects.js';
42
+ export type { WatchRequest, WatchResultDTO, UnwatchQuery, UnwatchResultDTO } from './dto/objects.js';
@@ -0,0 +1,41 @@
1
+ // `crouter/api` — the single source of truth for crtrd's API DTOs,
2
+ // route constants, error contract, and the typed `CrtrClient`. Dependency-light
3
+ // by design (spec §3.1): Node built-ins + `src/api/*` only.
4
+ export { CrtrClient, waitForDaemonAvailability } from './client.js';
5
+ export { APIError, ApiError, isErrorBody } from './errors.js';
6
+ export { errorCodes } from './error-codes.js';
7
+ export { API_VERSION, routes } from './routes.js';
8
+ export * from '../shared/generated-context.js';
9
+ export * from './dto/common.js';
10
+ export * from './dto/health.js';
11
+ export * from './dto/grants.js';
12
+ export * from './dto/nodes.js';
13
+ export * from './dto/node-outcomes.js';
14
+ export * from './dto/node-events.js';
15
+ export * from './dto/run-events.js';
16
+ export * from './dto/broker-signals.js';
17
+ export * from './dto/bash-jobs.js';
18
+ export * from './dto/messages.js';
19
+ export * from './dto/reports.js';
20
+ export * from './dto/lifecycle.js';
21
+ export * from './dto/subscriptions.js';
22
+ export * from './dto/focus.js';
23
+ export * from './dto/crons.js';
24
+ export * from './dto/config.js';
25
+ export * from './dto/attach.js';
26
+ export * from './dto/broker.js';
27
+ export * from './dto/profiles.js';
28
+ export * from './dto/modelauth.js';
29
+ export * from './dto/model-config.js';
30
+ export * from './dto/canvas.js';
31
+ export * from './dto/worktree.js';
32
+ export * from './dto/human.js';
33
+ export * from './dto/files.js';
34
+ export * from './dto/bash.js';
35
+ export * from './dto/inbox.js';
36
+ export * from './dto/human-requests.js';
37
+ export * from './dto/reviews.js';
38
+ export * from './dto/review-comments.js';
39
+ export * from './dto/chat-inventory.js';
40
+ export * from './dto/analytics.js';
41
+ export * from './dto/custom-objects.js';
@@ -0,0 +1,18 @@
1
+ import { CrtrClient, type CrtrClientOptions } from './client.js';
2
+ /** Resolve crtrd's default unix socket path the same way `apiSocketPath()` does,
3
+ * via Node built-ins only (no `core/canvas/paths.ts` import). */
4
+ export declare function defaultSocketPath(): string;
5
+ /** A standard `fetch` bound to one unix socket, built on `node:http` with
6
+ * `{ socketPath }`. The returned `Response`'s body is a live `ReadableStream`
7
+ * fed as bytes arrive — never buffered before the caller sees headers —
8
+ * which is what lets `CrtrClient` serve a streaming route (SSE) later without
9
+ * a second transport. Connection failures are wrapped as `TypeError('fetch
10
+ * failed', { cause })`, matching the shape native `fetch` throws, so
11
+ * `CrtrClient`'s cold-socket/interrupted-request classification (`err.cause.code`)
12
+ * reads identically off either transport. */
13
+ export declare function socketFetch(socketPath: string): typeof fetch;
14
+ /** Construct a client bound to the default local socket with autostart on.
15
+ * Without `onColdSocket`, a cold socket fails with `daemon_unavailable`. */
16
+ export declare function localClient(opts?: Omit<CrtrClientOptions, 'baseUrl' | 'fetch'> & {
17
+ socketPath?: string;
18
+ }): CrtrClient;
@@ -0,0 +1,105 @@
1
+ // The Node-only half of `@crouter/api`: crtrd's default unix
2
+ // socket path, a `fetch` implementation that speaks it, and `localClient()` —
3
+ // the one-line way to get a `CrtrClient` bound to the owner's own daemon.
4
+ //
5
+ // This is a SEPARATE package entry (`@crouter/api/node`) from the
6
+ // root so a browser bundle that imports the root never resolves `node:http`,
7
+ // `node:os`, or `node:path`. Import from here, never re-export it off the root.
8
+ import { request as httpRequest } from 'node:http';
9
+ import { homedir } from 'node:os';
10
+ import { join } from 'node:path';
11
+ import { CrtrClient } from './client.js';
12
+ /** Filesystem/scope constants mirrored from `core/types.ts` (`CRTR_DIR_NAME`)
13
+ * and `core/canvas/paths.ts` (`crtrHome`/`apiSocketPath`). Duplicated — not
14
+ * imported — to keep the exported `/api` contract dependency-light; the two
15
+ * MUST agree on the resolved socket path. */
16
+ const CRTR_DIR_NAME = '.crouter';
17
+ const SOCKET_BASENAME = 'api.sock';
18
+ const LOCAL_SOCKET_FETCH = Symbol.for('@crouter/api/local-socket-fetch');
19
+ /** Resolve crtrd's default unix socket path the same way `apiSocketPath()` does,
20
+ * via Node built-ins only (no `core/canvas/paths.ts` import). */
21
+ export function defaultSocketPath() {
22
+ const relay = process.env['CRTR_API_SOCKET'];
23
+ if (relay)
24
+ return relay;
25
+ // Read CRTR_HOME directly (as `envHomeOverride()` does): importing
26
+ // shared/env.ts would pull @crouter/identity into this
27
+ // zero-dependency package.
28
+ const override = process.env['CRTR_HOME'];
29
+ const root = override !== undefined && override !== '' ? override : join(homedir(), CRTR_DIR_NAME);
30
+ return join(process.platform === 'linux' ? '/run/crtr' : join(root, 'runtime'), SOCKET_BASENAME);
31
+ }
32
+ /** A standard `fetch` bound to one unix socket, built on `node:http` with
33
+ * `{ socketPath }`. The returned `Response`'s body is a live `ReadableStream`
34
+ * fed as bytes arrive — never buffered before the caller sees headers —
35
+ * which is what lets `CrtrClient` serve a streaming route (SSE) later without
36
+ * a second transport. Connection failures are wrapped as `TypeError('fetch
37
+ * failed', { cause })`, matching the shape native `fetch` throws, so
38
+ * `CrtrClient`'s cold-socket/interrupted-request classification (`err.cause.code`)
39
+ * reads identically off either transport. */
40
+ export function socketFetch(socketPath) {
41
+ const fetchOverSocket = function (input, init = {}) {
42
+ const url = input instanceof URL ? input : new URL(typeof input === 'string' ? input : input.url);
43
+ const method = init.method ?? 'GET';
44
+ const headers = {};
45
+ if (init.headers !== undefined) {
46
+ for (const [name, value] of new Headers(init.headers).entries())
47
+ headers[name] = value;
48
+ }
49
+ const payload = typeof init.body === 'string' ? init.body : undefined;
50
+ if (payload !== undefined)
51
+ headers['content-length'] = String(Buffer.byteLength(payload));
52
+ return new Promise((resolvePromise, reject) => {
53
+ const req = httpRequest({ socketPath, path: url.pathname + url.search, method, headers }, (res) => {
54
+ const body = new ReadableStream({
55
+ start(controller) {
56
+ res.on('data', (chunk) => controller.enqueue(new Uint8Array(chunk)));
57
+ res.on('end', () => controller.close());
58
+ res.on('error', (err) => controller.error(err));
59
+ },
60
+ cancel() {
61
+ res.destroy();
62
+ },
63
+ });
64
+ const responseHeaders = new Headers();
65
+ for (const [name, value] of Object.entries(res.headers)) {
66
+ if (value === undefined)
67
+ continue;
68
+ for (const one of Array.isArray(value) ? value : [value])
69
+ responseHeaders.append(name, one);
70
+ }
71
+ const status = res.statusCode ?? 0;
72
+ resolvePromise(new Response(status === 204 ? null : body, { status, statusText: res.statusMessage, headers: responseHeaders }));
73
+ });
74
+ req.on('error', (err) => reject(new TypeError('fetch failed', { cause: err })));
75
+ const signal = init.signal;
76
+ const abort = () => {
77
+ req.destroy();
78
+ reject(signal?.reason ?? new DOMException('The operation was aborted.', 'AbortError'));
79
+ };
80
+ if (signal !== null && signal !== undefined) {
81
+ if (signal.aborted) {
82
+ abort();
83
+ return;
84
+ }
85
+ signal.addEventListener('abort', abort, { once: true });
86
+ }
87
+ if (payload !== undefined)
88
+ req.write(payload);
89
+ req.end();
90
+ });
91
+ };
92
+ fetchOverSocket[LOCAL_SOCKET_FETCH] = true;
93
+ return fetchOverSocket;
94
+ }
95
+ /** Construct a client bound to the default local socket with autostart on.
96
+ * Without `onColdSocket`, a cold socket fails with `daemon_unavailable`. */
97
+ export function localClient(opts = {}) {
98
+ const { socketPath, ...rest } = opts;
99
+ return new CrtrClient({
100
+ baseUrl: 'http://localhost',
101
+ fetch: socketFetch(socketPath ?? defaultSocketPath()),
102
+ autostart: true,
103
+ ...rest,
104
+ });
105
+ }