@argentic/chest-sdk 0.1.1 → 0.3.0

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 (57) hide show
  1. package/README.md +573 -37
  2. package/client/index.ts +12 -5
  3. package/client/src/ai.ts +374 -0
  4. package/client/src/api.ts +85 -0
  5. package/client/src/chest.ts +80 -0
  6. package/client/src/errors.ts +58 -3
  7. package/client/src/events.ts +228 -0
  8. package/client/src/files.ts +93 -88
  9. package/client/src/member.ts +61 -17
  10. package/client/src/members.ts +167 -0
  11. package/client/src/notifications.ts +148 -0
  12. package/client/src/testing.ts +564 -0
  13. package/dist/index.d.ts +5 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +12 -5
  16. package/dist/index.js.map +1 -1
  17. package/dist/src/ai.d.ts +131 -0
  18. package/dist/src/ai.d.ts.map +1 -0
  19. package/dist/src/ai.js +290 -0
  20. package/dist/src/ai.js.map +1 -0
  21. package/dist/src/api.d.ts +11 -0
  22. package/dist/src/api.d.ts.map +1 -0
  23. package/dist/src/api.js +93 -0
  24. package/dist/src/api.js.map +1 -0
  25. package/dist/src/chest.d.ts +10 -0
  26. package/dist/src/chest.d.ts.map +1 -0
  27. package/dist/src/chest.js +49 -0
  28. package/dist/src/chest.js.map +1 -0
  29. package/dist/src/errors.d.ts +19 -0
  30. package/dist/src/errors.d.ts.map +1 -1
  31. package/dist/src/errors.js +49 -3
  32. package/dist/src/errors.js.map +1 -1
  33. package/dist/src/events.d.ts +56 -0
  34. package/dist/src/events.d.ts.map +1 -0
  35. package/dist/src/events.js +193 -0
  36. package/dist/src/events.js.map +1 -0
  37. package/dist/src/files.d.ts +17 -1
  38. package/dist/src/files.d.ts.map +1 -1
  39. package/dist/src/files.js +95 -92
  40. package/dist/src/files.js.map +1 -1
  41. package/dist/src/member.d.ts +10 -3
  42. package/dist/src/member.d.ts.map +1 -1
  43. package/dist/src/member.js +34 -11
  44. package/dist/src/member.js.map +1 -1
  45. package/dist/src/members.d.ts +34 -0
  46. package/dist/src/members.d.ts.map +1 -0
  47. package/dist/src/members.js +146 -0
  48. package/dist/src/members.js.map +1 -0
  49. package/dist/src/notifications.d.ts +25 -0
  50. package/dist/src/notifications.d.ts.map +1 -0
  51. package/dist/src/notifications.js +121 -0
  52. package/dist/src/notifications.js.map +1 -0
  53. package/dist/src/testing.d.ts +101 -0
  54. package/dist/src/testing.d.ts.map +1 -0
  55. package/dist/src/testing.js +552 -0
  56. package/dist/src/testing.js.map +1 -0
  57. package/package.json +40 -4
@@ -0,0 +1,131 @@
1
+ export type Alias = "default" | "fast" | "smart" | "embedding";
2
+ export type Provider = "openrouter";
3
+ export type ChatMessage = {
4
+ role: "system" | "developer" | "user" | "assistant" | "tool";
5
+ content?: string | unknown[] | null;
6
+ name?: string;
7
+ tool_calls?: {
8
+ id: string;
9
+ type: "function";
10
+ function: {
11
+ name: string;
12
+ arguments: string;
13
+ };
14
+ }[];
15
+ tool_call_id?: string;
16
+ };
17
+ export type ChatTool = {
18
+ type: "function";
19
+ function: {
20
+ name: string;
21
+ description?: string;
22
+ parameters?: Record<string, unknown>;
23
+ strict?: boolean;
24
+ };
25
+ };
26
+ export type ToolChoice = "auto" | "none" | "required" | {
27
+ type: "function";
28
+ function: {
29
+ name: string;
30
+ };
31
+ };
32
+ export type ResponseFormat = {
33
+ type: "text";
34
+ } | {
35
+ type: "json_object";
36
+ } | {
37
+ type: "json_schema";
38
+ json_schema: {
39
+ name: string;
40
+ schema: Record<string, unknown>;
41
+ strict?: boolean;
42
+ description?: string;
43
+ };
44
+ };
45
+ export type ChatOptions = {
46
+ model: Alias;
47
+ messages: ChatMessage[];
48
+ maxTokens?: number;
49
+ temperature?: number;
50
+ topP?: number;
51
+ stop?: string | string[];
52
+ tools?: ChatTool[];
53
+ toolChoice?: ToolChoice;
54
+ responseFormat?: ResponseFormat;
55
+ parallelToolCalls?: boolean;
56
+ seed?: number;
57
+ reasoningEffort?: string;
58
+ member?: string;
59
+ signal?: AbortSignal;
60
+ };
61
+ export type ToolCall = {
62
+ id: string;
63
+ name: string;
64
+ arguments: string;
65
+ };
66
+ export type ToolCallDelta = {
67
+ index: number;
68
+ id?: string;
69
+ name?: string;
70
+ arguments?: string;
71
+ };
72
+ export type Usage = {
73
+ input: number;
74
+ output: number;
75
+ cached: number;
76
+ cost: number;
77
+ };
78
+ export type ChatResult = {
79
+ text: string;
80
+ message: ChatMessage;
81
+ toolCalls: ToolCall[];
82
+ finishReason: string;
83
+ model: string;
84
+ usage: Usage;
85
+ };
86
+ export type ChatChunk = {
87
+ text: string;
88
+ toolCalls?: ToolCallDelta[];
89
+ finishReason?: string;
90
+ usage?: Usage;
91
+ };
92
+ export type EmbedOptions = {
93
+ model: Alias;
94
+ input: string | string[];
95
+ dimensions?: number;
96
+ member?: string;
97
+ };
98
+ export type Embeddings = {
99
+ embeddings: number[][];
100
+ model: string;
101
+ usage: {
102
+ input: number;
103
+ cost: number;
104
+ };
105
+ };
106
+ export type AiModel = {
107
+ alias: Alias;
108
+ model: string;
109
+ provider: Provider;
110
+ input: number;
111
+ output: number;
112
+ };
113
+ export type AiUsage = {
114
+ month: string;
115
+ spent: number;
116
+ cap: number;
117
+ resetsAt: Date;
118
+ };
119
+ export declare function chat(options: ChatOptions & {
120
+ stream: true;
121
+ }): AsyncIterable<ChatChunk>;
122
+ export declare function chat(options: ChatOptions & {
123
+ stream?: false;
124
+ }): Promise<ChatResult>;
125
+ export declare function chat(options: ChatOptions & {
126
+ stream?: boolean;
127
+ }): Promise<ChatResult> | AsyncIterable<ChatChunk>;
128
+ export declare function embed(options: EmbedOptions): Promise<Embeddings>;
129
+ export declare function models(): Promise<AiModel[]>;
130
+ export declare function usage(): Promise<AiUsage>;
131
+ //# sourceMappingURL=ai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../client/src/ai.ts"],"names":[],"mappings":"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"}
package/dist/src/ai.js ADDED
@@ -0,0 +1,290 @@
1
+ import { ask, json, read } from "./api.js";
2
+ import { AiCapReached, AiModelNotAllowed, AiRefused, AiUnavailable, CapabilityNotGranted, ChestError, RateLimited, TooLarge, Unavailable } from "./errors.js";
3
+ import { memberIdPattern } from "./member.js";
4
+ const aliases = ["default", "fast", "smart", "embedding"];
5
+ const providers = ["openrouter"];
6
+ const reasons = ["no_connector", "provider_key_invalid", "provider_unavailable"];
7
+ // The bounds of the Chest's gateway, and of what the SDK reads of it.
8
+ const maxBody = 10 << 20, maxAnswer = 16 << 20, maxLine = 1 << 20, maxOutput = 128000, maxInputs = 256;
9
+ const chatDeadline = 600_000;
10
+ // The HTTP status of each code the gateway sends, to map one that comes in a
11
+ // stream.
12
+ const statuses = { capability_not_granted: 403, model_not_allowed: 403, cap_reached: 402, rate_limited: 429, no_connector: 503, provider_key_invalid: 502, provider_unavailable: 503, content_refused: 422, too_large: 413, invalid_body: 400, invalid_request: 400 };
13
+ const rfc3339 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,9})?(Z|[+-]\d{2}:\d{2})$/u;
14
+ const invalid = (message) => new ChestError("invalid_body", 400, message);
15
+ const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
16
+ const tokens = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
17
+ const amount = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0;
18
+ function time(value) {
19
+ if (typeof value !== "string" || !rfc3339.test(value))
20
+ return null;
21
+ const date = new Date(value);
22
+ return Number.isNaN(date.getTime()) ? null : date;
23
+ }
24
+ function checkModel(model) {
25
+ if (typeof model !== "string" || !aliases.includes(model))
26
+ throw new AiModelNotAllowed();
27
+ }
28
+ function checkMember(member) {
29
+ if (typeof member !== "string" || !memberIdPattern.test(member))
30
+ throw invalid("member is a member identifier (mbr_…)");
31
+ return member;
32
+ }
33
+ // request is the wire body of a chat, checked as the Chest checks it.
34
+ function request(options, stream) {
35
+ const o = options;
36
+ if (!o)
37
+ throw invalid("chat takes options");
38
+ checkModel(o.model);
39
+ if (!Array.isArray(o.messages) || o.messages.length < 1 || !o.messages.every(m => typeof record(m)?.["role"] === "string"))
40
+ throw invalid("messages are 1 or more {role, content}");
41
+ if (o.maxTokens !== undefined && (!Number.isInteger(o.maxTokens) || o.maxTokens < 1 || o.maxTokens > maxOutput))
42
+ throw invalid("maxTokens is 1 to 128000");
43
+ const pairs = [["max_tokens", o.maxTokens], ["temperature", o.temperature], ["top_p", o.topP], ["stop", o.stop], ["tools", o.tools], ["tool_choice", o.toolChoice], ["response_format", o.responseFormat], ["parallel_tool_calls", o.parallelToolCalls], ["seed", o.seed], ["reasoning_effort", o.reasoningEffort], ["member", o.member === undefined ? undefined : checkMember(o.member)]];
44
+ return { model: o.model, messages: o.messages, ...Object.fromEntries(pairs.filter(([, v]) => v !== undefined)), ...(stream ? { stream: true } : {}) };
45
+ }
46
+ // send posts a body of JSON to the gateway, 10 MiB at most.
47
+ async function send(path, body, signal, deadline) {
48
+ const raw = JSON.stringify(body);
49
+ if (Buffer.byteLength(raw) > maxBody)
50
+ throw new TooLarge();
51
+ return ask("ai", "POST", path, { body: raw, type: "application/json", ...(deadline !== undefined ? { deadline } : {}), ...(signal !== undefined ? { signal } : {}) });
52
+ }
53
+ // answer reads a success of 16 MiB at most as JSON; anything else is not the
54
+ // Chest's.
55
+ async function answer(response, signal) {
56
+ try {
57
+ return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await read(response, maxAnswer)));
58
+ }
59
+ catch {
60
+ if (signal?.aborted)
61
+ throw signal.reason;
62
+ throw new Unavailable();
63
+ }
64
+ }
65
+ // mapped turns a refusal of the gateway, with the status it came with, into
66
+ // what the tool tests.
67
+ function mapped(status, error) {
68
+ const code = error?.["error"];
69
+ const resets = time(error?.["resets"]), scope = error?.["scope"];
70
+ if (status === 402 && code === "cap_reached" && resets && (scope === "tool" || scope === "chest"))
71
+ return new AiCapReached(scope, resets);
72
+ if (status === 403)
73
+ return code === "model_not_allowed" ? new AiModelNotAllowed() : new CapabilityNotGranted("ai");
74
+ if (status === 429)
75
+ return new RateLimited();
76
+ if (status === 413)
77
+ return new TooLarge();
78
+ if (status === 422 && code === "content_refused")
79
+ return new AiRefused();
80
+ if (typeof code === "string" && reasons.includes(code) && statuses[code] === status)
81
+ return new AiUnavailable(code);
82
+ if (status === 400 && typeof code === "string" && /^[a-z_]{1,40}$/u.test(code)) {
83
+ const message = error?.["message"];
84
+ return new ChestError(code, 400, code === "invalid_request" && typeof message === "string" && message.length <= 300 ? `the AI provider rejected the request: ${message}` : `the Chest refused: ${code}`);
85
+ }
86
+ return new Unavailable();
87
+ }
88
+ async function refused(response) {
89
+ if (response.status < 400) {
90
+ await response.body?.cancel();
91
+ return new Unavailable();
92
+ }
93
+ let error = null;
94
+ try {
95
+ error = record(await json(response));
96
+ }
97
+ catch {
98
+ // Not the gateway's refusal: mapped by its status alone.
99
+ }
100
+ return mapped(response.status, error);
101
+ }
102
+ function usageOf(value) {
103
+ const u = record(value), cached = record(u?.["prompt_tokens_details"])?.["cached_tokens"];
104
+ if (!u || !tokens(u["prompt_tokens"]) || !tokens(u["completion_tokens"]) || !tokens(u["total_tokens"]) || !tokens(cached) || !amount(u["cost"]))
105
+ throw new Unavailable();
106
+ return { input: u["prompt_tokens"], output: u["completion_tokens"], cached, cost: u["cost"] };
107
+ }
108
+ // result reads a chat completion; anything else is not the Chest's.
109
+ function result(value) {
110
+ const c = record(value), choices = c?.["choices"];
111
+ if (!c || c["object"] !== "chat.completion" || typeof c["model"] !== "string" || !Array.isArray(choices) || choices.length !== 1)
112
+ throw new Unavailable();
113
+ const choice = record(choices[0]), m = record(choice?.["message"]);
114
+ const content = m?.["content"], calls = m?.["tool_calls"];
115
+ if (!choice || choice["index"] !== 0 || typeof choice["finish_reason"] !== "string" || !m || m["role"] !== "assistant" || !(content === null || typeof content === "string") || !(calls === undefined || Array.isArray(calls)))
116
+ throw new Unavailable();
117
+ const toolCalls = (calls ?? []).map((value) => {
118
+ const call = record(value), f = record(call?.["function"]);
119
+ if (!call || typeof call["id"] !== "string" || call["type"] !== "function" || !f || typeof f["name"] !== "string" || typeof f["arguments"] !== "string")
120
+ throw new Unavailable();
121
+ return { id: call["id"], name: f["name"], arguments: f["arguments"] };
122
+ });
123
+ const message = { role: "assistant", content, ...(toolCalls.length ? { tool_calls: toolCalls.map(t => ({ id: t.id, type: "function", function: { name: t.name, arguments: t.arguments } })) } : {}) };
124
+ return { text: content ?? "", message, toolCalls, finishReason: choice["finish_reason"], model: c["model"], usage: usageOf(c["usage"]) };
125
+ }
126
+ // chunk reads a chunk of a stream: an error of the gateway is thrown, a
127
+ // chunk is read as the tool gets it; anything else is not the Chest's.
128
+ function chunk(value) {
129
+ const c = record(value);
130
+ if (c && "error" in c) {
131
+ const code = c["error"];
132
+ throw mapped(typeof code === "string" ? statuses[code] ?? 503 : 503, c);
133
+ }
134
+ const choices = c?.["choices"], usage = c?.["usage"];
135
+ if (!c || c["object"] !== "chat.completion.chunk" || !Array.isArray(choices) || choices.length > 1)
136
+ throw new Unavailable();
137
+ const piece = { text: "" };
138
+ if (choices.length === 1) {
139
+ const choice = record(choices[0]), delta = record(choice?.["delta"]);
140
+ const content = delta?.["content"], calls = delta?.["tool_calls"], finish = choice?.["finish_reason"];
141
+ if (!choice || choice["index"] !== 0 || !delta || !(content === undefined || content === null || typeof content === "string") || !(calls === undefined || Array.isArray(calls)) || !(finish === undefined || finish === null || typeof finish === "string"))
142
+ throw new Unavailable();
143
+ piece.text = content ?? "";
144
+ if (calls?.length) {
145
+ piece.toolCalls = calls.map((value) => {
146
+ const call = record(value), f = call?.["function"] === undefined ? {} : record(call["function"]);
147
+ const index = call?.["index"], id = call?.["id"], name = f?.["name"], args = f?.["arguments"];
148
+ if (!call || !f || !tokens(index) || !(id === undefined || typeof id === "string") || !(call["type"] === undefined || call["type"] === "function") || !(name === undefined || typeof name === "string") || !(args === undefined || typeof args === "string"))
149
+ throw new Unavailable();
150
+ return { index, ...(id !== undefined ? { id } : {}), ...(name !== undefined ? { name } : {}), ...(args !== undefined ? { arguments: args } : {}) };
151
+ });
152
+ }
153
+ if (typeof finish === "string")
154
+ piece.finishReason = finish;
155
+ }
156
+ if (usage !== undefined && usage !== null)
157
+ piece.usage = usageOf(usage);
158
+ else if (choices.length === 0)
159
+ throw new Unavailable();
160
+ return piece;
161
+ }
162
+ // lines reads the lines of an event stream, each 1 MiB at most; a line cut
163
+ // by the end of the stream is not read.
164
+ async function* lines(body) {
165
+ const decoder = new TextDecoder("utf-8", { fatal: true });
166
+ let pending = "";
167
+ for await (const bytes of body) {
168
+ pending += decoder.decode(bytes, { stream: true });
169
+ for (let at = pending.indexOf("\n"); at >= 0; at = pending.indexOf("\n")) {
170
+ const line = pending.slice(0, at);
171
+ pending = pending.slice(at + 1);
172
+ if (Buffer.byteLength(line) > maxLine + 1)
173
+ throw new Unavailable();
174
+ yield line.endsWith("\r") ? line.slice(0, -1) : line;
175
+ }
176
+ if (Buffer.byteLength(pending) > maxLine)
177
+ throw new Unavailable();
178
+ }
179
+ }
180
+ async function completed(options) {
181
+ const response = await send("/ai/chat", request(options, false), options.signal, chatDeadline);
182
+ if (response.status !== 200)
183
+ throw await refused(response);
184
+ return result(await answer(response, options.signal));
185
+ }
186
+ async function* streamed(options) {
187
+ const response = await send("/ai/chat", request(options, true), options.signal, chatDeadline);
188
+ if (response.status !== 200)
189
+ throw await refused(response);
190
+ if (!/^text\/event-stream(;|$)/iu.test(response.headers.get("content-type") ?? "") || !response.body) {
191
+ await response.body?.cancel();
192
+ throw new Unavailable();
193
+ }
194
+ // The stream ends with the usage, then [DONE]; a stream cut before is not
195
+ // the Chest's.
196
+ let usage = false, done = false;
197
+ try {
198
+ for await (const line of lines(response.body)) {
199
+ options.signal?.throwIfAborted();
200
+ if (line === "" || line.startsWith(":"))
201
+ continue;
202
+ if (!line.startsWith("data:"))
203
+ throw new Unavailable();
204
+ const data = line.slice(line.startsWith("data: ") ? 6 : 5);
205
+ if (data === "[DONE]") {
206
+ done = true;
207
+ break;
208
+ }
209
+ let value;
210
+ try {
211
+ value = JSON.parse(data);
212
+ }
213
+ catch {
214
+ throw new Unavailable();
215
+ }
216
+ const piece = chunk(value);
217
+ if (piece.usage)
218
+ usage = true;
219
+ yield piece;
220
+ }
221
+ }
222
+ catch (error) {
223
+ if (options.signal?.aborted)
224
+ throw options.signal.reason;
225
+ throw error instanceof ChestError ? error : new Unavailable();
226
+ }
227
+ if (!done || !usage)
228
+ throw new Unavailable();
229
+ }
230
+ export function chat(options) {
231
+ return options?.stream === true ? streamed(options) : completed(options);
232
+ }
233
+ // embed turns 1 to 256 texts into vectors, one per text in the order given.
234
+ export async function embed(options) {
235
+ const o = options;
236
+ if (!o)
237
+ throw invalid("embed takes options");
238
+ checkModel(o.model);
239
+ const inputs = typeof o.input === "string" ? [o.input] : o.input;
240
+ if (!Array.isArray(inputs) || inputs.length < 1 || inputs.length > maxInputs || !inputs.every(i => typeof i === "string"))
241
+ throw invalid("input is 1 to 256 texts");
242
+ if (o.dimensions !== undefined && (!Number.isSafeInteger(o.dimensions) || o.dimensions < 1))
243
+ throw invalid("dimensions is a positive integer");
244
+ const body = { model: o.model, input: o.input, ...(o.dimensions !== undefined ? { dimensions: o.dimensions } : {}), ...(o.member !== undefined ? { member: checkMember(o.member) } : {}) };
245
+ const response = await send("/ai/embeddings", body);
246
+ if (response.status !== 200)
247
+ throw await refused(response);
248
+ const a = record(await answer(response)), data = a?.["data"], u = record(a?.["usage"]);
249
+ if (!a || a["object"] !== "list" || typeof a["model"] !== "string" || !Array.isArray(data) || data.length !== inputs.length || !u || !tokens(u["prompt_tokens"]) || !tokens(u["total_tokens"]) || !amount(u["cost"]))
250
+ throw new Unavailable();
251
+ const embeddings = [];
252
+ for (const value of data) {
253
+ const e = record(value), index = e?.["index"], vector = e?.["embedding"];
254
+ if (!e || e["object"] !== "embedding" || !tokens(index) || index >= inputs.length || embeddings[index] !== undefined || !Array.isArray(vector) || vector.length < 1 || !vector.every(x => typeof x === "number" && Number.isFinite(x)))
255
+ throw new Unavailable();
256
+ embeddings[index] = [...vector];
257
+ }
258
+ if (!embeddings.every(v => v.length === embeddings[0].length))
259
+ throw new Unavailable();
260
+ return { embeddings, model: a["model"], usage: { input: u["prompt_tokens"], cost: u["cost"] } };
261
+ }
262
+ // models are the aliases the tool declared that the owner mapped, in alias
263
+ // order: each one's model, provider and prices.
264
+ export async function models() {
265
+ const response = await ask("ai", "GET", "/ai/models");
266
+ if (response.status !== 200)
267
+ throw await refused(response);
268
+ const list = record(await json(response))?.["models"];
269
+ if (!Array.isArray(list) || list.length > aliases.length)
270
+ throw new Unavailable();
271
+ const seen = [];
272
+ return list.map((value) => {
273
+ const m = record(value), alias = m?.["alias"], model = m?.["model"], provider = m?.["provider"], input = m?.["input"], output = m?.["output"];
274
+ if (typeof alias !== "string" || !aliases.includes(alias) || aliases.indexOf(alias) <= aliases.indexOf(seen.at(-1) ?? "") || typeof model !== "string" || model.length < 1 || model.length > 200 || typeof provider !== "string" || !providers.includes(provider) || !amount(input) || !amount(output))
275
+ throw new Unavailable();
276
+ seen.push(alias);
277
+ return { alias: alias, model, provider: provider, input, output };
278
+ });
279
+ }
280
+ // usage is this tool's month: what it spent, its cap, when both reset.
281
+ export async function usage() {
282
+ const response = await ask("ai", "GET", "/ai/usage");
283
+ if (response.status !== 200)
284
+ throw await refused(response);
285
+ const u = record(await json(response)), month = u?.["month"], spent = u?.["spent"], cap = u?.["cap"], resetsAt = time(u?.["resets"]);
286
+ if (typeof month !== "string" || !/^\d{4}-(0[1-9]|1[0-2])$/u.test(month) || !amount(spent) || !tokens(cap) || !resetsAt)
287
+ throw new Unavailable();
288
+ return { month, spent, cap, resetsAt };
289
+ }
290
+ //# sourceMappingURL=ai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.js","sourceRoot":"","sources":["../../client/src/ai.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { ChestError } from "./errors.js";
2
+ export declare function ask(capability: string, method: string, path: string, init?: {
3
+ body?: Uint8Array<ArrayBuffer> | string;
4
+ type?: string;
5
+ deadline?: number;
6
+ signal?: AbortSignal;
7
+ }): Promise<Response>;
8
+ export declare function read(response: Response, limit: number): Promise<Uint8Array>;
9
+ export declare function json(response: Response): Promise<unknown>;
10
+ export declare function refusal(response: Response, capability: string): Promise<ChestError>;
11
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../client/src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,UAAU,EAAqD,MAAM,aAAa,CAAC;AAuBlH,wBAAsB,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAW7M;AAID,wBAAsB,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAqBjF;AAGD,wBAAsB,IAAI,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAM/D;AAGD,wBAAsB,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAazF"}
@@ -0,0 +1,93 @@
1
+ import { CapabilityNotGranted, ChestError, QuotaExceeded, RateLimited, TooLarge, Unavailable } from "./errors.js";
2
+ // The Chest's API as a server tool reaches it, shared by the modules that
3
+ // call it (files, members): CHEST_API is http://127.0.0.1:<port>, the tool's
4
+ // launcher, which relays each request to the Chest — the container has no
5
+ // network. A call reaches what is the tool's only: its instance is its
6
+ // identity. Not a published module.
7
+ const maxAnswer = 4 << 20;
8
+ const deadline = 120000;
9
+ // base is the Chest's API as the launcher gives it; without, the version holds
10
+ // none of the capabilities that use it.
11
+ function base(capability) {
12
+ const value = process.env["CHEST_API"];
13
+ if (typeof value !== "string" || !/^http:\/\/127\.0\.0\.1:[1-9][0-9]{0,4}$/u.test(value) || Number(value.slice(17)) > 65535)
14
+ throw new CapabilityNotGranted(capability);
15
+ return value;
16
+ }
17
+ // ask sends one request of a capability to the Chest; a failure to reach it
18
+ // is Unavailable. The request and the reading of its answer end after
19
+ // deadline milliseconds (120 seconds unless said), or when the caller's
20
+ // signal aborts: its reason is then thrown.
21
+ export async function ask(capability, method, path, init = {}) {
22
+ const headers = {};
23
+ if (init.type !== undefined)
24
+ headers["Content-Type"] = init.type;
25
+ const url = base(capability) + path;
26
+ const timeout = AbortSignal.timeout(init.deadline ?? deadline);
27
+ try {
28
+ return await fetch(url, { method, headers, ...(init.body !== undefined ? { body: init.body } : {}), redirect: "error", signal: init.signal ? AbortSignal.any([timeout, init.signal]) : timeout });
29
+ }
30
+ catch {
31
+ if (init.signal?.aborted)
32
+ throw init.signal.reason;
33
+ throw new Unavailable();
34
+ }
35
+ }
36
+ // read takes a body of limit bytes at most; beyond, or cut, the answer is not
37
+ // the Chest's.
38
+ export async function read(response, limit) {
39
+ const declared = Number(response.headers.get("content-length") ?? "0");
40
+ if (declared > limit)
41
+ throw new Unavailable();
42
+ const chunks = [];
43
+ let size = 0;
44
+ try {
45
+ for await (const chunk of response.body ?? []) {
46
+ size += chunk.byteLength;
47
+ if (size > limit)
48
+ throw new Unavailable();
49
+ chunks.push(chunk);
50
+ }
51
+ }
52
+ catch {
53
+ throw new Unavailable();
54
+ }
55
+ const all = new Uint8Array(size);
56
+ let at = 0;
57
+ for (const chunk of chunks) {
58
+ all.set(chunk, at);
59
+ at += chunk.byteLength;
60
+ }
61
+ return all;
62
+ }
63
+ // json reads an answer of the Chest as JSON; anything else is Unavailable.
64
+ export async function json(response) {
65
+ try {
66
+ return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await read(response, maxAnswer)));
67
+ }
68
+ catch {
69
+ throw new Unavailable();
70
+ }
71
+ }
72
+ // refusal turns an answer that is not a success into what the tool tests.
73
+ export async function refusal(response, capability) {
74
+ let code = "refused";
75
+ try {
76
+ const given = (await json(response))?.error;
77
+ if (typeof given === "string" && /^[a-z_]{1,40}$/u.test(given))
78
+ code = given;
79
+ }
80
+ catch {
81
+ // The code stays "refused".
82
+ }
83
+ if (response.status === 403)
84
+ return new CapabilityNotGranted(capability);
85
+ if (response.status === 413)
86
+ return new TooLarge();
87
+ if (response.status === 429)
88
+ return code === "rate_limited" ? new RateLimited() : new QuotaExceeded();
89
+ if (response.status >= 500)
90
+ return new Unavailable();
91
+ return new ChestError(code, response.status, `the Chest refused: ${code}`);
92
+ }
93
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../client/src/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export type Chest = {
2
+ readonly organization: {
3
+ readonly name: string;
4
+ };
5
+ readonly timeZone: string;
6
+ readonly language: string;
7
+ today(at?: Date | number): string;
8
+ };
9
+ export declare const chest: Chest;
10
+ //# sourceMappingURL=chest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chest.d.ts","sourceRoot":"","sources":["../../client/src/chest.ts"],"names":[],"mappings":"AA0BA,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,CAAC,YAAY,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;CACnC,CAAC;AAiCF,eAAO,MAAM,KAAK,EAAE,KAenB,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { ChestError } from "./errors.js";
2
+ import { languagePattern, timeZonePattern } from "./member.js";
3
+ // The shapes the Chest gives: the organization's (2 to 80 characters,
4
+ // counted as code points, without control characters), a zone's
5
+ // (timeZonePattern, and one this runtime knows), a language's.
6
+ const organizationPattern = /^[^\u0000-\u001f\u007f-\u009f]{2,80}$/u;
7
+ function read(name, valid) {
8
+ const value = process.env[name];
9
+ if (typeof value !== "string" || !valid(value))
10
+ throw new ChestError("not_in_chest", 500, `not running in a Chest: ${name} is missing or invalid`);
11
+ return value;
12
+ }
13
+ function knownZone(zone) {
14
+ if (!timeZonePattern.test(zone))
15
+ return false;
16
+ try {
17
+ new Intl.DateTimeFormat("en-US", { timeZone: zone });
18
+ return true;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ const zone = () => read("CHEST_TIME_ZONE", knownZone);
25
+ // dateIn is the date at that instant in a zone, as YYYY-MM-DD.
26
+ function dateIn(at, zone) {
27
+ const parts = Object.fromEntries(new Intl.DateTimeFormat("en-US", { timeZone: zone, year: "numeric", month: "2-digit", day: "2-digit" }).formatToParts(at).map(p => [p.type, p.value]));
28
+ return `${parts["year"]}-${parts["month"]}-${parts["day"]}`;
29
+ }
30
+ // chest reads the environment at each access: what a test's fakeChest sets
31
+ // is what it answers.
32
+ export const chest = {
33
+ get organization() {
34
+ return { name: read("CHEST_ORGANIZATION", value => organizationPattern.test(value)) };
35
+ },
36
+ get timeZone() {
37
+ return zone();
38
+ },
39
+ get language() {
40
+ return read("CHEST_LANGUAGE", value => languagePattern.test(value));
41
+ },
42
+ today(at = Date.now()) {
43
+ const instant = typeof at === "number" ? new Date(at) : at;
44
+ if (Number.isNaN(instant.getTime()))
45
+ throw new RangeError("today() needs a valid date");
46
+ return dateIn(instant, zone());
47
+ },
48
+ };
49
+ //# sourceMappingURL=chest.js.map