@tangleai/models 0.21.1 → 0.24.1

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @tangleai/models
2
2
 
3
+ ## 0.24.1
4
+
5
+ No changes in this release.
6
+
7
+ ## 0.24.0
8
+
9
+ No changes in this release.
10
+
11
+ ## 0.23.0
12
+
13
+ No changes in this release.
14
+
15
+ ## 0.22.0
16
+
17
+ ### Patch Changes
18
+
19
+ - Convert the migrated source, tests, benchmarks and hosts to strict TypeScript,
20
+ with JavaScript and declarations emitted through one release build. Move the
21
+ program pen from `@tangleai/jaren/program` and the Jaren integration barrel to
22
+ `@tangleai/linq/program`, preserving its JSON format and phantom binding types.
23
+ The new `@tangleai/linq` root exposes the program namespace and shared build error.
24
+
25
+ Match the embedder declarations to unknown widths before the first response,
26
+ retain precise ledger result variants, and enforce the refinement-pressure
27
+ instrument's stated 60-second deadline through the chat client's abort signal.
28
+
3
29
  ## 0.21.1
4
30
 
5
31
  ### Patch Changes
package/README.md CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  Injected model clients, provider adapters, embeddings, replay, routing and structured generation.
4
4
 
5
- This package keeps its JS/JSDoc implementation and deterministic tests. Inject
5
+ The implementation and deterministic tests use strict TypeScript. Published
6
+ packages contain ESM JavaScript and declarations emitted from that source. Inject
6
7
  fetch, storage and compiler services at the existing seams. The public source
7
8
  exports and emitted npm JavaScript share one implementation.
8
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangleai/models",
3
- "version": "0.21.1",
3
+ "version": "0.24.1",
4
4
  "description": "Injected model clients, provider adapters, embeddings, replay, routing and structured generation.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -69,8 +69,8 @@
69
69
  },
70
70
  "sideEffects": false,
71
71
  "dependencies": {
72
- "@jarenjs/core": "0.84.3",
73
- "@jarenjs/validate": "0.84.3"
72
+ "@jarenjs/core": "0.86.0",
73
+ "@jarenjs/validate": "0.86.0"
74
74
  },
75
75
  "private": false,
76
76
  "files": [
package/src/check.d.ts CHANGED
@@ -1,3 +1,7 @@
1
+ /** Model-facing validation feedback over the shared strict check contract. */
2
+ /** Validation errors reported back per rejected write — enough to fix
3
+ * from, few enough to stay readable in a model's context. */
4
+ export declare const MAX_INPUT_ERRORS = 8;
1
5
  /**
2
6
  * The one rejection shape every schema-guarded boundary in this package
3
7
  * answers with: `{ error, errors, inputSchema }`, never a throw. The
@@ -10,20 +14,15 @@
10
14
  * (the toolbox's `hint`), then `inputSchema` last, because the schema is
11
15
  * the biggest member and a reader scans the message first.
12
16
  *
13
- * @param {string} what - what was being validated (`add`, `memory`, …)
14
- * @param {{ errors: any[] }} outcome - a normalized {@link checkOutcome}
15
- * @param {any} inputSchema - the schema to re-read
16
- * @param {Record<string, any>} [extra] - boundary-specific members
17
- * @returns {{ error: string, errors: any[], inputSchema: any }}
17
+ * @param what - what was being validated (`add`, `memory`, …)
18
+ * @param outcome - a normalized {@link checkOutcome}
19
+ * @param inputSchema - the schema to re-read
20
+ * @param [extra] - boundary-specific members
18
21
  */
19
- export function invalidInput(what: string, outcome: {
22
+ export declare function invalidInput(what: string, outcome: {
20
23
  errors: any[];
21
24
  }, inputSchema: any, extra?: Record<string, any>): {
22
25
  error: string;
23
26
  errors: any[];
24
27
  inputSchema: any;
25
28
  };
26
- /** Model-facing validation feedback over the shared strict check contract. */
27
- /** Validation errors reported back per rejected write — enough to fix
28
- * from, few enough to stay readable in a model's context. */
29
- export const MAX_INPUT_ERRORS: 8;
package/src/check.js CHANGED
@@ -1,10 +1,7 @@
1
- //@ts-check
2
1
  /** Model-facing validation feedback over the shared strict check contract. */
3
-
4
2
  /** Validation errors reported back per rejected write — enough to fix
5
3
  * from, few enough to stay readable in a model's context. */
6
4
  export const MAX_INPUT_ERRORS = 8;
7
-
8
5
  /**
9
6
  * The one rejection shape every schema-guarded boundary in this package
10
7
  * answers with: `{ error, errors, inputSchema }`, never a throw. The
@@ -17,21 +14,20 @@ export const MAX_INPUT_ERRORS = 8;
17
14
  * (the toolbox's `hint`), then `inputSchema` last, because the schema is
18
15
  * the biggest member and a reader scans the message first.
19
16
  *
20
- * @param {string} what - what was being validated (`add`, `memory`, …)
21
- * @param {{ errors: any[] }} outcome - a normalized {@link checkOutcome}
22
- * @param {any} inputSchema - the schema to re-read
23
- * @param {Record<string, any>} [extra] - boundary-specific members
24
- * @returns {{ error: string, errors: any[], inputSchema: any }}
17
+ * @param what - what was being validated (`add`, `memory`, …)
18
+ * @param outcome - a normalized {@link checkOutcome}
19
+ * @param inputSchema - the schema to re-read
20
+ * @param [extra] - boundary-specific members
25
21
  */
26
22
  export function invalidInput(what, outcome, inputSchema, extra = {}) {
27
- return {
28
- error: `invalid input for ${what}`,
29
- errors: outcome.errors.slice(0, MAX_INPUT_ERRORS).map((e) => ({
30
- instancePath: e.instancePath ?? '',
31
- keyword: e.keyword ?? '',
32
- message: e.message ?? 'invalid',
33
- })),
34
- ...extra,
35
- inputSchema,
36
- };
23
+ return {
24
+ error: `invalid input for ${what}`,
25
+ errors: outcome.errors.slice(0, MAX_INPUT_ERRORS).map((e) => ({
26
+ instancePath: e.instancePath ?? '',
27
+ keyword: e.keyword ?? '',
28
+ message: e.message ?? 'invalid',
29
+ })),
30
+ ...extra,
31
+ inputSchema,
32
+ };
37
33
  }
package/src/client.d.ts CHANGED
@@ -1,63 +1,35 @@
1
+ /**
2
+ * The chat client: one `complete()` call against any OpenAI-compatible
3
+ * `/chat/completions` endpoint, streaming by default. The host injects
4
+ * `fetch` exactly like every other jarenjs boundary injects its
5
+ * environment, so the client runs identically in the browser, in Node
6
+ * and in tests against a scripted stub.
7
+ *
8
+ * The reply is normalized to `{ message: { role, content, toolCalls },
9
+ * finishReason, usage, model }` whether the server streamed deltas or
10
+ * answered in one JSON document.
11
+ */
1
12
  /**
2
13
  * The reasoning text one streamed chunk carries: the OpenRouter/`o`-
3
14
  * family `delta.reasoning` string, or the `reasoning_details` text
4
15
  * entries some providers emit instead.
5
- * @param {any} delta
6
- * @returns {string}
7
16
  */
8
- export function reasoningOf(delta: any): string;
17
+ export declare function reasoningOf(delta: any): string;
9
18
  /**
10
19
  * Accumulates OpenAI streaming chunks (`choices[0].delta`) into one
11
20
  * normalized assistant message. Tool-call fragments merge by `index`;
12
21
  * argument strings concatenate across chunks; reasoning deltas
13
22
  * accumulate into `message.reasoning` (absent when the model emitted
14
23
  * none) so a reasoning-only turn is distinguishable from an empty one.
15
- * @returns {{ push: (chunk: any) => string, result: () => any }}
24
+ * @returns
16
25
  * `push` returns the text delta this chunk contributed (may be '').
17
26
  */
18
- export function createStreamAccumulator(): {
27
+ export declare function createStreamAccumulator(): {
19
28
  push: (chunk: any) => string;
20
29
  result: () => any;
21
30
  };
22
31
  /**
23
- * @typedef {Object} ChatRequest
24
- * @property {any[]} messages - OpenAI wire-shape messages
25
- * @property {any[]} [tools] - OpenAI function-tool definitions
26
- * @property {any} [toolChoice] - `tool_choice` passthrough
27
- * @property {string} [model] - overrides the client's configured model
28
- * @property {number} [temperature]
29
- * @property {number} [maxTokens] - token ceiling for this reply, sent under
30
- * the client's `maxTokensField`. Overrides the client default; when
31
- * both are unset, the provider chooses the limit. With
32
- * `max_completion_tokens`, reasoning tokens share this budget with
33
- * visible output tokens.
34
- * @property {boolean} [stream] - default true
35
- * @property {{ name?: string, schema?: any, strict?: boolean, type?: 'json' }} [responseFormat]
36
- * - structured output: `{ name, schema, strict? }` emits the OpenAI
37
- * `response_format: { type: "json_schema", … }` wire shape (strict
38
- * defaults to true); `{ type: 'json' }` emits `json_object` mode
39
- * @property {{ effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high',
40
- * enabled?: boolean, exclude?: boolean, max_tokens?: number }} [reasoning]
41
- * - the provider-normalized thinking control, forwarded verbatim.
42
- * `{ effort: 'none' }` (or `{ enabled: false }`) turns a hybrid
43
- * thinking model OFF: it answers directly, which on a short task is
44
- * dramatically cheaper and faster. `{ exclude: true }` only HIDES the
45
- * thinking — the model still thinks and you still pay for it.
46
- * Overrides the client-level default.
47
- * @property {AbortSignal} [signal]
48
- * @property {(text: string) => void} [onDelta] - streamed text callback
49
- * @property {(text: string) => void} [onReasoning] - streamed reasoning
50
- * callback (reasoning models emit thinking before/instead of content)
51
- */
52
- /**
53
- * @param {{ provider?: string, baseUrl?: string, apiKey?: string,
54
- * model?: string, headers?: Record<string, string>,
55
- * fetch?: typeof fetch, maxTokens?: number,
56
- * maxTokensField?: 'max_tokens' | 'max_completion_tokens',
57
- * reasoning?: { effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high',
58
- * enabled?: boolean, exclude?: boolean, max_tokens?: number },
59
- * retry?: import('./retry.js').RetryOptions,
60
- * cache?: import('./replay.js').ReplayCache }} [options]
32
+ * @param [options]
61
33
  * - `maxTokensField` selects the wire field for client and request
62
34
  * `maxTokens` budgets (default `'max_tokens'`). Select
63
35
  * `'max_completion_tokens'` for OpenAI Chat Completions, including
@@ -86,11 +58,8 @@ export function createStreamAccumulator(): {
86
58
  * value it asked for rides the final error as `retryAfterMs` for
87
59
  * the caller to honour. `random` and `sleep` exist for deterministic
88
60
  * tests.
89
- * @returns {{ endpoint: { provider: string, base: string, url: string,
90
- * headers: Record<string, string>, model: string },
91
- * complete: (request: ChatRequest) => Promise<any> }}
92
61
  */
93
- export function createChatClient(options?: {
62
+ export declare function createChatClient(options?: {
94
63
  provider?: string;
95
64
  baseUrl?: string;
96
65
  apiKey?: string;
@@ -98,15 +67,15 @@ export function createChatClient(options?: {
98
67
  headers?: Record<string, string>;
99
68
  fetch?: typeof fetch;
100
69
  maxTokens?: number;
101
- maxTokensField?: "max_tokens" | "max_completion_tokens";
70
+ maxTokensField?: 'max_tokens' | 'max_completion_tokens';
102
71
  reasoning?: {
103
- effort?: "none" | "minimal" | "low" | "medium" | "high";
72
+ effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high';
104
73
  enabled?: boolean;
105
74
  exclude?: boolean;
106
75
  max_tokens?: number;
107
76
  };
108
- retry?: import("./retry.js").RetryOptions;
109
- cache?: import("./replay.js").ReplayCache;
77
+ retry?: import('./retry.ts').RetryOptions;
78
+ cache?: import('./replay.ts').ReplayCache;
110
79
  }): {
111
80
  endpoint: {
112
81
  provider: string;
@@ -118,68 +87,56 @@ export function createChatClient(options?: {
118
87
  complete: (request: ChatRequest) => Promise<any>;
119
88
  };
120
89
  export type ChatRequest = {
121
- /**
122
- * - OpenAI wire-shape messages
123
- */
124
- messages: any[];
125
- /**
126
- * - OpenAI function-tool definitions
127
- */
128
- tools?: any[];
129
- /**
130
- * - `tool_choice` passthrough
131
- */
132
- toolChoice?: any;
133
- /**
134
- * - overrides the client's configured model
135
- */
90
+ messages: any[]; /**
91
+ * - OpenAI function-tool definitions
92
+ */
93
+ tools?: any[]; /**
94
+ * - `tool_choice` passthrough
95
+ */
96
+ toolChoice?: any; /**
97
+ * - overrides the client's configured model
98
+ */
136
99
  model?: string;
137
- temperature?: number;
138
- /**
139
- * - token ceiling for this reply, sent under
140
- * the client's `maxTokensField`. Overrides the client default; when
141
- * both are unset, the provider chooses the limit. With
142
- * `max_completion_tokens`, reasoning tokens share this budget with
143
- * visible output tokens.
144
- */
145
- maxTokens?: number;
146
- /**
147
- * - default true
148
- */
149
- stream?: boolean;
150
- /**
151
- * - structured output: `{ name, schema, strict? }` emits the OpenAI
152
- * `response_format: { type: "json_schema", … }` wire shape (strict
153
- * defaults to true); `{ type: 'json' }` emits `json_object` mode
154
- */
100
+ temperature?: number; /**
101
+ * - token ceiling for this reply, sent under
102
+ * the client's `maxTokensField`. Overrides the client default; when
103
+ * both are unset, the provider chooses the limit. With
104
+ * `max_completion_tokens`, reasoning tokens share this budget with
105
+ * visible output tokens.
106
+ */
107
+ maxTokens?: number; /**
108
+ * - default true
109
+ */
110
+ stream?: boolean; /**
111
+ * - structured output: `{ name, schema, strict? }` emits the OpenAI
112
+ * `response_format: { type: "json_schema", … }` wire shape (strict
113
+ * defaults to true); `{ type: 'json' }` emits `json_object` mode
114
+ */
155
115
  responseFormat?: {
156
116
  name?: string;
157
117
  schema?: any;
158
118
  strict?: boolean;
159
119
  type?: "json";
160
- };
161
- /**
162
- * - the provider-normalized thinking control, forwarded verbatim.
163
- * `{ effort: 'none' }` (or `{ enabled: false }`) turns a hybrid
164
- * thinking model OFF: it answers directly, which on a short task is
165
- * dramatically cheaper and faster. `{ exclude: true }` only HIDES the
166
- * thinking the model still thinks and you still pay for it.
167
- * Overrides the client-level default.
168
- */
120
+ }; /**
121
+ * - the provider-normalized thinking control, forwarded verbatim.
122
+ * `{ effort: 'none' }` (or `{ enabled: false }`) turns a hybrid
123
+ * thinking model OFF: it answers directly, which on a short task is
124
+ * dramatically cheaper and faster. `{ exclude: true }` only HIDES the
125
+ * thinking the model still thinks and you still pay for it.
126
+ * Overrides the client-level default.
127
+ */
169
128
  reasoning?: {
170
129
  effort?: "none" | "minimal" | "low" | "medium" | "high";
171
130
  enabled?: boolean;
172
131
  exclude?: boolean;
173
132
  max_tokens?: number;
174
133
  };
175
- signal?: AbortSignal;
176
- /**
177
- * - streamed text callback
178
- */
179
- onDelta?: (text: string) => void;
180
- /**
181
- * - streamed reasoning
182
- * callback (reasoning models emit thinking before/instead of content)
183
- */
134
+ signal?: AbortSignal; /**
135
+ * - streamed text callback
136
+ */
137
+ onDelta?: (text: string) => void; /**
138
+ * - streamed reasoning
139
+ * callback (reasoning models emit thinking before/instead of content)
140
+ */
184
141
  onReasoning?: (text: string) => void;
185
142
  };