@cloudraker/milliseconds 0.1.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.
@@ -0,0 +1,330 @@
1
+ //#region src/types.d.ts
2
+ /**
3
+ * Every public type of the SDK.
4
+ *
5
+ * Wire names never change. A field that crosses the wire keeps its exact name from
6
+ * `decide.schema.ts`, `snake_case` included. Only SDK-invented names are camelCase.
7
+ */
8
+ interface ClientOptions {
9
+ /** Your key. Falls back to MS_API_KEY in the environment. */
10
+ apiKey?: string;
11
+ /** Default 'https://api.milliseconds.ai'. A trailing slash is trimmed. */
12
+ baseUrl?: string;
13
+ /** Per attempt, in milliseconds. Default 60_000. */
14
+ timeout?: number;
15
+ /** Retries after the first attempt. Default 2. */
16
+ maxRetries?: number;
17
+ /** Merged into every request. It cannot override `authorization`. */
18
+ headers?: Record<string, string>;
19
+ /** For tests, proxies, or a Workers service binding. Default globalThis.fetch. */
20
+ fetch?: typeof globalThis.fetch;
21
+ /** The key is a secret. Set true only when the bundle never reaches a user. */
22
+ dangerouslyAllowBrowser?: boolean;
23
+ }
24
+ interface CallOptions {
25
+ timeout?: number;
26
+ maxRetries?: number;
27
+ signal?: AbortSignal;
28
+ headers?: Record<string, string>;
29
+ }
30
+ /** A Promise of the result. `withUsage()` reaches the headers. */
31
+ type Decision<T> = Promise<T> & {
32
+ withUsage(): Promise<{
33
+ result: T;
34
+ usage: Usage;
35
+ response: Response;
36
+ }>;
37
+ };
38
+ interface Usage {
39
+ /** x-input-chars */
40
+ inputChars: number;
41
+ /** x-input-tokens — what this call bills. */
42
+ inputTokens: number;
43
+ /** x-inference-ms — model time, summed over the calls this request made. */
44
+ inferenceMs: number;
45
+ /** Null when the response carried no x-ratelimit-* headers. */
46
+ rateLimit: RateLimit | null;
47
+ /** Every response header. Read a new x-* value with no SDK release. */
48
+ headers: Headers;
49
+ }
50
+ /**
51
+ * The numbers come from the previous request at that Cloudflare colo. The middleware
52
+ * accounts after the response. Read them as a trailing gauge, never as admission control.
53
+ */
54
+ interface RateLimit {
55
+ limitRequests: number;
56
+ remainingRequests: number;
57
+ /** OpenAI style, for example '5m0s'. */
58
+ resetRequests: string;
59
+ limitTokens: number;
60
+ remainingTokens: number;
61
+ resetTokens: string;
62
+ }
63
+ type ErrorCode = 'invalid_request' | 'invalid_schema' | 'missing_api_key' | 'invalid_api_key' | 'rate_limit_exceeded' | 'insufficient_quota' | 'runner_error' | 'overloaded' | 'http_error' | 'internal_error' | 'connection_error' | 'timeout' | 'client_error' | (string & {});
64
+ type Input = string | readonly string[];
65
+ /** One text gives one result. A tuple of texts gives a tuple of results, same length. */
66
+ type Fan<T extends Input, R> = T extends readonly string[] ? { -readonly [K in keyof T]: R; } : R;
67
+ /** Label names, or name -> description. */
68
+ type Labels = readonly string[] | Readonly<Record<string, string>>;
69
+ type LabelOf<L extends Labels> = L extends readonly (infer S extends string)[] ? S : Extract<keyof L, string>;
70
+ /** 0 | 1 | ... | n-1 for a tuple. `number` for a plain array. */
71
+ type IndexOf<S extends readonly unknown[]> = number extends S['length'] ? number : Exclude<keyof S, keyof unknown[]> extends (infer K) ? K extends `${infer N extends number}` ? N : never : never;
72
+ interface TreeNode {
73
+ readonly description?: string;
74
+ readonly labels?: Tree;
75
+ }
76
+ type Tree = {
77
+ readonly [label: string]: string | TreeNode;
78
+ };
79
+ /** Every label at every level. What `path` can hold. */
80
+ type TreeLabels<T> = Extract<keyof T, string> | { [K in keyof T]: T[K] extends {
81
+ labels: infer C extends object;
82
+ } ? TreeLabels<C> : never; }[keyof T];
83
+ /**
84
+ * Only the labels a walk can stop on. What `label` is.
85
+ *
86
+ * An empty `labels` object is a leaf: `decide.service.ts` stops the walk when the child
87
+ * level holds no key, and `decide.schema.ts` recurses into a non-empty child only.
88
+ */
89
+ type LeafLabels<T> = Extract<{ [K in keyof T]: T[K] extends {
90
+ labels: infer C extends object;
91
+ } ? [keyof C] extends [never] ? K : LeafLabels<C> : K; }[keyof T], string>;
92
+ interface YesNoResult<S extends string = string> {
93
+ statement: S;
94
+ answer: boolean;
95
+ probability: number;
96
+ }
97
+ interface ClassifyResult<L extends string = string> {
98
+ label: L;
99
+ probability: number;
100
+ /** 1 = one clear winner. 0 = flat. */
101
+ confidence: number;
102
+ scores: Record<L, number>;
103
+ }
104
+ interface ClassifyTreeLevel {
105
+ label: string;
106
+ probability: number;
107
+ confidence: number;
108
+ /** Only this level's siblings. The keys are narrower than the tree. */
109
+ scores: Record<string, number>;
110
+ input_chars: number;
111
+ input_tokens: number;
112
+ inference_ms: number;
113
+ }
114
+ interface ClassifyTreeResult<L extends string = string, Leaf extends L = L> {
115
+ /** The winning label per level, top to bottom. */
116
+ path: L[];
117
+ /** The deepest label, the last of `path`. */
118
+ label: Leaf;
119
+ /** The product over the levels. */
120
+ probability: number;
121
+ confidence: number;
122
+ /**
123
+ * One entry per level. The per-level `input_chars` and `input_tokens` do not sum to
124
+ * `Usage.inputChars`: the header counts one pass over the body, each level re-sends the
125
+ * text.
126
+ */
127
+ levels: ClassifyTreeLevel[];
128
+ }
129
+ interface RateResult<S extends readonly string[] = readonly string[]> {
130
+ /** The probability-weighted position, 0 to scale.length - 1. Route on this, not `level`. */
131
+ score: number;
132
+ level: IndexOf<S>;
133
+ label: S[number];
134
+ confidence: number;
135
+ /** One probability per level, in scale order. */
136
+ scores: { -readonly [K in keyof S]: number; };
137
+ }
138
+ /** The service sets answer, start and end together, or nulls all three. */
139
+ type AnswerResult<Q extends string = string> = {
140
+ question: Q;
141
+ answer: string;
142
+ probability: number;
143
+ start: number;
144
+ end: number;
145
+ } | {
146
+ question: Q;
147
+ answer: null;
148
+ probability: number;
149
+ start: null;
150
+ end: null;
151
+ };
152
+ interface Entity<T extends string = string> {
153
+ type: T;
154
+ text: string;
155
+ probability: number;
156
+ start: number;
157
+ end: number;
158
+ }
159
+ interface VerifyResult {
160
+ matches: boolean;
161
+ probability: number;
162
+ /** What the text actually says for that field. */
163
+ found: string[];
164
+ }
165
+ type JsonSchema = {
166
+ readonly type?: string | readonly string[];
167
+ readonly [k: string]: unknown;
168
+ };
169
+ /** A Standard Schema object: zod 4, valibot 1.1+, arktype. */
170
+ interface StandardSchemaV1<Output = unknown> {
171
+ readonly '~standard': {
172
+ readonly version: 1;
173
+ readonly vendor: string;
174
+ readonly types?: {
175
+ readonly input: unknown;
176
+ readonly output: Output;
177
+ };
178
+ };
179
+ }
180
+ /** A JSON Schema branded with the type it produces. */
181
+ type Typed<T> = JsonSchema & {
182
+ readonly '~milliseconds.output'?: T;
183
+ };
184
+ type ExtractSchema = JsonSchema | StandardSchemaV1 | Typed<unknown>;
185
+ type SchemaOutput<S> = S extends StandardSchemaV1<infer O> ? O : S extends {
186
+ '~milliseconds.output'?: infer T;
187
+ } ? [unknown] extends [T] ? FromJsonSchema<S> : T : FromJsonSchema<S>;
188
+ /** Reads a JSON Schema object literal at the type level, exactly as `kindOf` reads it. */
189
+ type FromJsonSchema<S> = S extends {
190
+ enum: readonly (infer E)[];
191
+ } ? E extends string ? E : string : S extends {
192
+ type: readonly (infer T extends string)[];
193
+ } ? FromJsonSchema<Omit<S, 'type'> & {
194
+ type: Exclude<T, 'null'>;
195
+ }> : S extends {
196
+ type: 'object';
197
+ } ? S extends {
198
+ properties: infer P;
199
+ } ? { -readonly [K in keyof P]: FromJsonSchema<P[K]>; } : Record<string, never> : S extends {
200
+ type: 'array';
201
+ } ? S extends {
202
+ items: infer I;
203
+ } ? I extends {
204
+ type: 'object';
205
+ } ? object[] : string[] : string[] : S extends {
206
+ type: 'string';
207
+ } ? string : S extends {
208
+ type: 'number' | 'integer';
209
+ } ? number : S extends {
210
+ type: 'boolean';
211
+ } ? boolean : S extends {
212
+ type: string;
213
+ } ? undefined : string;
214
+ /**
215
+ * What the runner really sends. A missing value is null. An array of objects is always [].
216
+ * An array of scalars arrives as strings. An enum is not checked server side. A nested
217
+ * object is not nullable, because `setPath` materialises it.
218
+ */
219
+ type Extracted<T> = [T] extends [undefined] ? undefined : [T] extends [readonly unknown[]] ? T extends readonly (infer E)[] ? [E] extends [object] ? never[] : string[] | null : never : [T] extends [object] ? { -readonly [K in keyof T]-?: Extracted<Exclude<T[K], null | undefined>>; } : [T] extends [string] ? string extends T ? string | null : T | (string & {}) | null : T | null;
220
+ //#endregion
221
+ //#region src/client.d.ts
222
+ /** Transport: fetch, retries, errors and usage. Every capability is two lines on top. */
223
+ declare class Client {
224
+ #private;
225
+ readonly baseUrl: string;
226
+ constructor(options?: ClientOptions);
227
+ /** Escape hatch. Your path, your body, your type, the SDK's auth, retries and errors. */
228
+ post<R>(path: string, body: unknown, options?: CallOptions): Decision<R>;
229
+ /** `unwrap` maps the parsed body to the result. It follows the request, never the response. */
230
+ protected call<R>(path: string, body: unknown, options: CallOptions | undefined, unwrap: (raw: unknown) => R): Decision<R>;
231
+ private send;
232
+ private attempt;
233
+ }
234
+ //#endregion
235
+ //#region src/decision-machine.d.ts
236
+ /**
237
+ * `decision-machine-1` at api.milliseconds.ai. Every capability is a pure function, so
238
+ * every retry is safe.
239
+ */
240
+ export declare class DecisionMachine extends Client {
241
+ /** Paths are `${baseUrl}/v1/${model}/<capability>`. */
242
+ static readonly model = "decision-machine-1";
243
+ /**
244
+ * Answers each statement with yes or no and a probability. The statements share one
245
+ * inference call, so extra statements are nearly free.
246
+ */
247
+ yesNo<const T extends Input, const S extends string | readonly string[]>(input: T, statements: S, options?: CallOptions & {
248
+ when_true?: string;
249
+ when_false?: string;
250
+ }): Decision<Fan<T, S extends readonly string[] ? { -readonly [K in keyof S]: YesNoResult<S[K] & string>; } : YesNoResult<S & string>>>;
251
+ /** Picks one label and returns the full distribution. Describe each label. */
252
+ classify<const T extends Input, const L extends Labels>(input: T, labels: L, options?: CallOptions): Decision<Fan<T, ClassifyResult<LabelOf<L>>>>;
253
+ /**
254
+ * Runs classify once per level of a nested tree, descending into the winner.
255
+ *
256
+ * The per-level `input_chars` and `input_tokens` do not sum to `Usage.inputChars`: the
257
+ * header counts one pass over the body, and each level re-sends the text.
258
+ */
259
+ classifyTree<const T extends Input, const N extends Tree>(input: T, tree: N, options?: CallOptions): Decision<Fan<T, ClassifyTreeResult<TreeLabels<N>, LeafLabels<N>>>>;
260
+ /** Places the text on an ordered scale of described levels, low to high. */
261
+ rate<const T extends Input, const S extends readonly string[]>(input: T, scale: S, options?: CallOptions): Decision<Fan<T, RateResult<S>>>;
262
+ /** Quotes the answer out of the text, with its offsets. `answer` is null when nothing fits. */
263
+ answer<const T extends Input, const Q extends string | readonly string[]>(input: T, questions: Q, options?: CallOptions): Decision<Fan<T, Q extends readonly string[] ? { -readonly [K in keyof Q]: AnswerResult<Q[K] & string>; } : AnswerResult<Q & string>>>;
264
+ /**
265
+ * Fills a JSON Schema from the text. Missing values are null, arrays of objects come back
266
+ * empty, arrays of scalars come back as strings, and enums are not checked server side.
267
+ */
268
+ extract<const T extends Input, const S extends ExtractSchema>(input: T, schema: S, options?: CallOptions): Decision<Fan<T, Extracted<SchemaOutput<S>>>>;
269
+ /** Finds every span matching each type, with offsets, sorted by start. */
270
+ entities<const T extends Input, const E extends Labels>(input: T, types: E, options?: CallOptions): Decision<Fan<T, Entity<LabelOf<E>>[]>>;
271
+ /** Checks whether the text says `value` for `field`. */
272
+ verify<const T extends Input>(input: T, field: string | {
273
+ name: string;
274
+ description?: string;
275
+ }, value: string | number, options?: CallOptions): Decision<Fan<T, VerifyResult>>;
276
+ /** `{ results }` is unwrapped for a batch, and the per-text envelope for one text. */
277
+ private capability;
278
+ }
279
+ //#endregion
280
+ //#region src/errors.d.ts
281
+ /** A brand property, so a duplicated copy of the package in a bundle still matches. */
282
+ declare const BRAND = "~milliseconds.error";
283
+ interface ErrorInit {
284
+ code: ErrorCode;
285
+ /** 0 when the call never reached the API. */
286
+ status?: number;
287
+ /** The API's own message, unchanged. */
288
+ apiMessage: string;
289
+ /** The thrown `message`: the API message plus one hint line. */
290
+ message?: string;
291
+ retryAfter?: number | null;
292
+ rateLimit?: RateLimit | null;
293
+ response?: Response | null;
294
+ attempts?: number;
295
+ retryable?: boolean;
296
+ cause?: unknown;
297
+ }
298
+ /**
299
+ * One error class. Switch on `code`: the union narrows exhaustively and never goes stale
300
+ * when the API adds a code.
301
+ */
302
+ export declare class MillisecondsError extends Error {
303
+ readonly name = "MillisecondsError";
304
+ readonly [BRAND] = true;
305
+ readonly code: ErrorCode;
306
+ /** 0 when the call never reached the API. */
307
+ readonly status: number;
308
+ /** The API's own message, unchanged. `message` adds one hint line. */
309
+ readonly apiMessage: string;
310
+ /** Seconds from the retry-after header. Only 429 rate_limit_exceeded carries it. */
311
+ readonly retryAfter: number | null;
312
+ readonly rateLimit: RateLimit | null;
313
+ readonly response: Response | null;
314
+ /** Attempts this call made, including the first. */
315
+ readonly attempts: number;
316
+ /** True for the codes the SDK retries. */
317
+ readonly retryable: boolean;
318
+ constructor(init: ErrorInit);
319
+ }
320
+ export declare function isMillisecondsError(e: unknown): e is MillisecondsError;
321
+ //#endregion
322
+ //#region src/schema.d.ts
323
+ /**
324
+ * Brands a JSON Schema with the type it produces. One cast, no runtime cost.
325
+ *
326
+ * `dm.extract(text, typed<z.infer<typeof S>>(z.toJSONSchema(S)))`
327
+ */
328
+ export declare const typed: <T>(schema: object) => Typed<T>;
329
+ //#endregion
330
+ export type { AnswerResult, CallOptions, ClassifyResult, ClassifyTreeLevel, ClassifyTreeResult, ClientOptions, Decision, Entity, ErrorCode, ExtractSchema, Extracted, Fan, FromJsonSchema, IndexOf, Input, JsonSchema, LabelOf, Labels, LeafLabels, RateLimit, RateResult, SchemaOutput, StandardSchemaV1, Tree, TreeLabels, TreeNode, Typed, Usage, VerifyResult, YesNoResult };
@@ -0,0 +1,330 @@
1
+ //#region src/types.d.ts
2
+ /**
3
+ * Every public type of the SDK.
4
+ *
5
+ * Wire names never change. A field that crosses the wire keeps its exact name from
6
+ * `decide.schema.ts`, `snake_case` included. Only SDK-invented names are camelCase.
7
+ */
8
+ interface ClientOptions {
9
+ /** Your key. Falls back to MS_API_KEY in the environment. */
10
+ apiKey?: string;
11
+ /** Default 'https://api.milliseconds.ai'. A trailing slash is trimmed. */
12
+ baseUrl?: string;
13
+ /** Per attempt, in milliseconds. Default 60_000. */
14
+ timeout?: number;
15
+ /** Retries after the first attempt. Default 2. */
16
+ maxRetries?: number;
17
+ /** Merged into every request. It cannot override `authorization`. */
18
+ headers?: Record<string, string>;
19
+ /** For tests, proxies, or a Workers service binding. Default globalThis.fetch. */
20
+ fetch?: typeof globalThis.fetch;
21
+ /** The key is a secret. Set true only when the bundle never reaches a user. */
22
+ dangerouslyAllowBrowser?: boolean;
23
+ }
24
+ interface CallOptions {
25
+ timeout?: number;
26
+ maxRetries?: number;
27
+ signal?: AbortSignal;
28
+ headers?: Record<string, string>;
29
+ }
30
+ /** A Promise of the result. `withUsage()` reaches the headers. */
31
+ type Decision<T> = Promise<T> & {
32
+ withUsage(): Promise<{
33
+ result: T;
34
+ usage: Usage;
35
+ response: Response;
36
+ }>;
37
+ };
38
+ interface Usage {
39
+ /** x-input-chars */
40
+ inputChars: number;
41
+ /** x-input-tokens — what this call bills. */
42
+ inputTokens: number;
43
+ /** x-inference-ms — model time, summed over the calls this request made. */
44
+ inferenceMs: number;
45
+ /** Null when the response carried no x-ratelimit-* headers. */
46
+ rateLimit: RateLimit | null;
47
+ /** Every response header. Read a new x-* value with no SDK release. */
48
+ headers: Headers;
49
+ }
50
+ /**
51
+ * The numbers come from the previous request at that Cloudflare colo. The middleware
52
+ * accounts after the response. Read them as a trailing gauge, never as admission control.
53
+ */
54
+ interface RateLimit {
55
+ limitRequests: number;
56
+ remainingRequests: number;
57
+ /** OpenAI style, for example '5m0s'. */
58
+ resetRequests: string;
59
+ limitTokens: number;
60
+ remainingTokens: number;
61
+ resetTokens: string;
62
+ }
63
+ type ErrorCode = 'invalid_request' | 'invalid_schema' | 'missing_api_key' | 'invalid_api_key' | 'rate_limit_exceeded' | 'insufficient_quota' | 'runner_error' | 'overloaded' | 'http_error' | 'internal_error' | 'connection_error' | 'timeout' | 'client_error' | (string & {});
64
+ type Input = string | readonly string[];
65
+ /** One text gives one result. A tuple of texts gives a tuple of results, same length. */
66
+ type Fan<T extends Input, R> = T extends readonly string[] ? { -readonly [K in keyof T]: R; } : R;
67
+ /** Label names, or name -> description. */
68
+ type Labels = readonly string[] | Readonly<Record<string, string>>;
69
+ type LabelOf<L extends Labels> = L extends readonly (infer S extends string)[] ? S : Extract<keyof L, string>;
70
+ /** 0 | 1 | ... | n-1 for a tuple. `number` for a plain array. */
71
+ type IndexOf<S extends readonly unknown[]> = number extends S['length'] ? number : Exclude<keyof S, keyof unknown[]> extends (infer K) ? K extends `${infer N extends number}` ? N : never : never;
72
+ interface TreeNode {
73
+ readonly description?: string;
74
+ readonly labels?: Tree;
75
+ }
76
+ type Tree = {
77
+ readonly [label: string]: string | TreeNode;
78
+ };
79
+ /** Every label at every level. What `path` can hold. */
80
+ type TreeLabels<T> = Extract<keyof T, string> | { [K in keyof T]: T[K] extends {
81
+ labels: infer C extends object;
82
+ } ? TreeLabels<C> : never; }[keyof T];
83
+ /**
84
+ * Only the labels a walk can stop on. What `label` is.
85
+ *
86
+ * An empty `labels` object is a leaf: `decide.service.ts` stops the walk when the child
87
+ * level holds no key, and `decide.schema.ts` recurses into a non-empty child only.
88
+ */
89
+ type LeafLabels<T> = Extract<{ [K in keyof T]: T[K] extends {
90
+ labels: infer C extends object;
91
+ } ? [keyof C] extends [never] ? K : LeafLabels<C> : K; }[keyof T], string>;
92
+ interface YesNoResult<S extends string = string> {
93
+ statement: S;
94
+ answer: boolean;
95
+ probability: number;
96
+ }
97
+ interface ClassifyResult<L extends string = string> {
98
+ label: L;
99
+ probability: number;
100
+ /** 1 = one clear winner. 0 = flat. */
101
+ confidence: number;
102
+ scores: Record<L, number>;
103
+ }
104
+ interface ClassifyTreeLevel {
105
+ label: string;
106
+ probability: number;
107
+ confidence: number;
108
+ /** Only this level's siblings. The keys are narrower than the tree. */
109
+ scores: Record<string, number>;
110
+ input_chars: number;
111
+ input_tokens: number;
112
+ inference_ms: number;
113
+ }
114
+ interface ClassifyTreeResult<L extends string = string, Leaf extends L = L> {
115
+ /** The winning label per level, top to bottom. */
116
+ path: L[];
117
+ /** The deepest label, the last of `path`. */
118
+ label: Leaf;
119
+ /** The product over the levels. */
120
+ probability: number;
121
+ confidence: number;
122
+ /**
123
+ * One entry per level. The per-level `input_chars` and `input_tokens` do not sum to
124
+ * `Usage.inputChars`: the header counts one pass over the body, each level re-sends the
125
+ * text.
126
+ */
127
+ levels: ClassifyTreeLevel[];
128
+ }
129
+ interface RateResult<S extends readonly string[] = readonly string[]> {
130
+ /** The probability-weighted position, 0 to scale.length - 1. Route on this, not `level`. */
131
+ score: number;
132
+ level: IndexOf<S>;
133
+ label: S[number];
134
+ confidence: number;
135
+ /** One probability per level, in scale order. */
136
+ scores: { -readonly [K in keyof S]: number; };
137
+ }
138
+ /** The service sets answer, start and end together, or nulls all three. */
139
+ type AnswerResult<Q extends string = string> = {
140
+ question: Q;
141
+ answer: string;
142
+ probability: number;
143
+ start: number;
144
+ end: number;
145
+ } | {
146
+ question: Q;
147
+ answer: null;
148
+ probability: number;
149
+ start: null;
150
+ end: null;
151
+ };
152
+ interface Entity<T extends string = string> {
153
+ type: T;
154
+ text: string;
155
+ probability: number;
156
+ start: number;
157
+ end: number;
158
+ }
159
+ interface VerifyResult {
160
+ matches: boolean;
161
+ probability: number;
162
+ /** What the text actually says for that field. */
163
+ found: string[];
164
+ }
165
+ type JsonSchema = {
166
+ readonly type?: string | readonly string[];
167
+ readonly [k: string]: unknown;
168
+ };
169
+ /** A Standard Schema object: zod 4, valibot 1.1+, arktype. */
170
+ interface StandardSchemaV1<Output = unknown> {
171
+ readonly '~standard': {
172
+ readonly version: 1;
173
+ readonly vendor: string;
174
+ readonly types?: {
175
+ readonly input: unknown;
176
+ readonly output: Output;
177
+ };
178
+ };
179
+ }
180
+ /** A JSON Schema branded with the type it produces. */
181
+ type Typed<T> = JsonSchema & {
182
+ readonly '~milliseconds.output'?: T;
183
+ };
184
+ type ExtractSchema = JsonSchema | StandardSchemaV1 | Typed<unknown>;
185
+ type SchemaOutput<S> = S extends StandardSchemaV1<infer O> ? O : S extends {
186
+ '~milliseconds.output'?: infer T;
187
+ } ? [unknown] extends [T] ? FromJsonSchema<S> : T : FromJsonSchema<S>;
188
+ /** Reads a JSON Schema object literal at the type level, exactly as `kindOf` reads it. */
189
+ type FromJsonSchema<S> = S extends {
190
+ enum: readonly (infer E)[];
191
+ } ? E extends string ? E : string : S extends {
192
+ type: readonly (infer T extends string)[];
193
+ } ? FromJsonSchema<Omit<S, 'type'> & {
194
+ type: Exclude<T, 'null'>;
195
+ }> : S extends {
196
+ type: 'object';
197
+ } ? S extends {
198
+ properties: infer P;
199
+ } ? { -readonly [K in keyof P]: FromJsonSchema<P[K]>; } : Record<string, never> : S extends {
200
+ type: 'array';
201
+ } ? S extends {
202
+ items: infer I;
203
+ } ? I extends {
204
+ type: 'object';
205
+ } ? object[] : string[] : string[] : S extends {
206
+ type: 'string';
207
+ } ? string : S extends {
208
+ type: 'number' | 'integer';
209
+ } ? number : S extends {
210
+ type: 'boolean';
211
+ } ? boolean : S extends {
212
+ type: string;
213
+ } ? undefined : string;
214
+ /**
215
+ * What the runner really sends. A missing value is null. An array of objects is always [].
216
+ * An array of scalars arrives as strings. An enum is not checked server side. A nested
217
+ * object is not nullable, because `setPath` materialises it.
218
+ */
219
+ type Extracted<T> = [T] extends [undefined] ? undefined : [T] extends [readonly unknown[]] ? T extends readonly (infer E)[] ? [E] extends [object] ? never[] : string[] | null : never : [T] extends [object] ? { -readonly [K in keyof T]-?: Extracted<Exclude<T[K], null | undefined>>; } : [T] extends [string] ? string extends T ? string | null : T | (string & {}) | null : T | null;
220
+ //#endregion
221
+ //#region src/client.d.ts
222
+ /** Transport: fetch, retries, errors and usage. Every capability is two lines on top. */
223
+ declare class Client {
224
+ #private;
225
+ readonly baseUrl: string;
226
+ constructor(options?: ClientOptions);
227
+ /** Escape hatch. Your path, your body, your type, the SDK's auth, retries and errors. */
228
+ post<R>(path: string, body: unknown, options?: CallOptions): Decision<R>;
229
+ /** `unwrap` maps the parsed body to the result. It follows the request, never the response. */
230
+ protected call<R>(path: string, body: unknown, options: CallOptions | undefined, unwrap: (raw: unknown) => R): Decision<R>;
231
+ private send;
232
+ private attempt;
233
+ }
234
+ //#endregion
235
+ //#region src/decision-machine.d.ts
236
+ /**
237
+ * `decision-machine-1` at api.milliseconds.ai. Every capability is a pure function, so
238
+ * every retry is safe.
239
+ */
240
+ export declare class DecisionMachine extends Client {
241
+ /** Paths are `${baseUrl}/v1/${model}/<capability>`. */
242
+ static readonly model = "decision-machine-1";
243
+ /**
244
+ * Answers each statement with yes or no and a probability. The statements share one
245
+ * inference call, so extra statements are nearly free.
246
+ */
247
+ yesNo<const T extends Input, const S extends string | readonly string[]>(input: T, statements: S, options?: CallOptions & {
248
+ when_true?: string;
249
+ when_false?: string;
250
+ }): Decision<Fan<T, S extends readonly string[] ? { -readonly [K in keyof S]: YesNoResult<S[K] & string>; } : YesNoResult<S & string>>>;
251
+ /** Picks one label and returns the full distribution. Describe each label. */
252
+ classify<const T extends Input, const L extends Labels>(input: T, labels: L, options?: CallOptions): Decision<Fan<T, ClassifyResult<LabelOf<L>>>>;
253
+ /**
254
+ * Runs classify once per level of a nested tree, descending into the winner.
255
+ *
256
+ * The per-level `input_chars` and `input_tokens` do not sum to `Usage.inputChars`: the
257
+ * header counts one pass over the body, and each level re-sends the text.
258
+ */
259
+ classifyTree<const T extends Input, const N extends Tree>(input: T, tree: N, options?: CallOptions): Decision<Fan<T, ClassifyTreeResult<TreeLabels<N>, LeafLabels<N>>>>;
260
+ /** Places the text on an ordered scale of described levels, low to high. */
261
+ rate<const T extends Input, const S extends readonly string[]>(input: T, scale: S, options?: CallOptions): Decision<Fan<T, RateResult<S>>>;
262
+ /** Quotes the answer out of the text, with its offsets. `answer` is null when nothing fits. */
263
+ answer<const T extends Input, const Q extends string | readonly string[]>(input: T, questions: Q, options?: CallOptions): Decision<Fan<T, Q extends readonly string[] ? { -readonly [K in keyof Q]: AnswerResult<Q[K] & string>; } : AnswerResult<Q & string>>>;
264
+ /**
265
+ * Fills a JSON Schema from the text. Missing values are null, arrays of objects come back
266
+ * empty, arrays of scalars come back as strings, and enums are not checked server side.
267
+ */
268
+ extract<const T extends Input, const S extends ExtractSchema>(input: T, schema: S, options?: CallOptions): Decision<Fan<T, Extracted<SchemaOutput<S>>>>;
269
+ /** Finds every span matching each type, with offsets, sorted by start. */
270
+ entities<const T extends Input, const E extends Labels>(input: T, types: E, options?: CallOptions): Decision<Fan<T, Entity<LabelOf<E>>[]>>;
271
+ /** Checks whether the text says `value` for `field`. */
272
+ verify<const T extends Input>(input: T, field: string | {
273
+ name: string;
274
+ description?: string;
275
+ }, value: string | number, options?: CallOptions): Decision<Fan<T, VerifyResult>>;
276
+ /** `{ results }` is unwrapped for a batch, and the per-text envelope for one text. */
277
+ private capability;
278
+ }
279
+ //#endregion
280
+ //#region src/errors.d.ts
281
+ /** A brand property, so a duplicated copy of the package in a bundle still matches. */
282
+ declare const BRAND = "~milliseconds.error";
283
+ interface ErrorInit {
284
+ code: ErrorCode;
285
+ /** 0 when the call never reached the API. */
286
+ status?: number;
287
+ /** The API's own message, unchanged. */
288
+ apiMessage: string;
289
+ /** The thrown `message`: the API message plus one hint line. */
290
+ message?: string;
291
+ retryAfter?: number | null;
292
+ rateLimit?: RateLimit | null;
293
+ response?: Response | null;
294
+ attempts?: number;
295
+ retryable?: boolean;
296
+ cause?: unknown;
297
+ }
298
+ /**
299
+ * One error class. Switch on `code`: the union narrows exhaustively and never goes stale
300
+ * when the API adds a code.
301
+ */
302
+ export declare class MillisecondsError extends Error {
303
+ readonly name = "MillisecondsError";
304
+ readonly [BRAND] = true;
305
+ readonly code: ErrorCode;
306
+ /** 0 when the call never reached the API. */
307
+ readonly status: number;
308
+ /** The API's own message, unchanged. `message` adds one hint line. */
309
+ readonly apiMessage: string;
310
+ /** Seconds from the retry-after header. Only 429 rate_limit_exceeded carries it. */
311
+ readonly retryAfter: number | null;
312
+ readonly rateLimit: RateLimit | null;
313
+ readonly response: Response | null;
314
+ /** Attempts this call made, including the first. */
315
+ readonly attempts: number;
316
+ /** True for the codes the SDK retries. */
317
+ readonly retryable: boolean;
318
+ constructor(init: ErrorInit);
319
+ }
320
+ export declare function isMillisecondsError(e: unknown): e is MillisecondsError;
321
+ //#endregion
322
+ //#region src/schema.d.ts
323
+ /**
324
+ * Brands a JSON Schema with the type it produces. One cast, no runtime cost.
325
+ *
326
+ * `dm.extract(text, typed<z.infer<typeof S>>(z.toJSONSchema(S)))`
327
+ */
328
+ export declare const typed: <T>(schema: object) => Typed<T>;
329
+ //#endregion
330
+ export type { AnswerResult, CallOptions, ClassifyResult, ClassifyTreeLevel, ClassifyTreeResult, ClientOptions, Decision, Entity, ErrorCode, ExtractSchema, Extracted, Fan, FromJsonSchema, IndexOf, Input, JsonSchema, LabelOf, Labels, LeafLabels, RateLimit, RateResult, SchemaOutput, StandardSchemaV1, Tree, TreeLabels, TreeNode, Typed, Usage, VerifyResult, YesNoResult };