@niscorp/signal 0.1.0 → 0.1.3
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 +48 -0
- package/DESIGN.md +1 -2
- package/DOCS.md +89 -36
- package/README.md +3 -1
- package/dist/index.cjs +5 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# @niscorp/signal
|
|
2
|
+
|
|
3
|
+
## 0.1.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 63445cb: `complete()` and `stream()` on a decision provider say their own name.
|
|
8
|
+
|
|
9
|
+
Both run through `stepStream`, and the refusal a decision provider gives a chat verb named that instead: `signal.complete('…')` failed with `stepStream() is not available on a decision provider…` and `context.verb: "stepStream"`, for a call the caller never made.
|
|
10
|
+
|
|
11
|
+
The error now names the verb that was called — `complete() is not available on a decision provider — it answers decide() and generates no text`, `context.verb: "complete"`, and the same for `stream`. `step`, `stepStream` and `embed` already named themselves.
|
|
12
|
+
|
|
13
|
+
Only those two strings change. The code is `E_VERB_NOT_SUPPORTED` as before, it is raised at the same moment (for `stream()`, when the stream is first read), and no request is sent.
|
|
14
|
+
|
|
15
|
+
**What to change:** nothing.
|
|
16
|
+
|
|
17
|
+
- 8973c15: DOCS.md says what `embed()` and `meta.provider.raw` do. `embed()` does not check `supportsEmbedding`: the flag is what `describe()` reports, and the request is sent either way; a refused request is `E_PROVIDER_ERROR` with the provider's own error under `context.raw`. `meta.provider.raw` is `null` after `complete()` and `stream()`, which read the reply as a stream and keep no body (`step()` returns the body), and it is the provider's error for a call Signal recovered from a rejection. No code changed.
|
|
18
|
+
|
|
19
|
+
**What to change:** nothing.
|
|
20
|
+
|
|
21
|
+
- ce21cf7: DOCS.md says what a tool's `input` schema may be. The model is sent its JSON Schema, taken from the schema's output side, and the arguments are parsed with it once. So an `input` schema validates and does not convert:
|
|
22
|
+
- One with no JSON Schema (a `.transform()`, a `z.date()`) rejects the call before any request is made, with Zod's own error rather than a `SignalError`.
|
|
23
|
+
- One whose output is another kind than its input (`z.stringbool()`) is described to the model by its output: told `boolean`, a model that sends one gets `input_invalid` back, and it is the string that is accepted.
|
|
24
|
+
|
|
25
|
+
Convert inside `execute`. DOCS.md says this under "Defining Tools", and a test holds the first. No code changed.
|
|
26
|
+
|
|
27
|
+
**What to change:** nothing.
|
|
28
|
+
|
|
29
|
+
## 0.1.2
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- fe30458: Every package exports its `package.json`, so an app can say which version of a package it runs by reading it from the package:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import prism from '@niscorp/prism/package.json' with { type: 'json' };
|
|
37
|
+
prism.version; // the version that is installed, not the range that asked for it
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Until now the `exports` map hid it, and the only way to the version was a path into `node_modules`. `check:packages` installs the tarballs and reads every package's version this way.
|
|
41
|
+
|
|
42
|
+
**What to change:** nothing. An app that read a version by path can read it by name.
|
|
43
|
+
|
|
44
|
+
## 0.1.1
|
|
45
|
+
|
|
46
|
+
### Patch Changes
|
|
47
|
+
|
|
48
|
+
- b67a125: Documentation only: each package's README, reference and design docs checked against its source and corrected — install lines and peers, signatures, defaults, status codes, licenses (loom, signal: Apache-2.0), and API that existed but was not documented.
|
package/DESIGN.md
CHANGED
|
@@ -62,8 +62,7 @@ sides is two changes.
|
|
|
62
62
|
- **The router owns classification.** A response is `tool_calls`
|
|
63
63
|
(declared tool), `output` (anything whose repaired value passes the
|
|
64
64
|
acceptance gate — exit-tool args and pseudo-tool args included), or
|
|
65
|
-
`failed` with evidence (+ `
|
|
66
|
-
but failed the gate; + `truncated` when bytes end mid-structure).
|
|
65
|
+
`failed` with evidence (+ `truncated` when bytes end mid-structure).
|
|
67
66
|
Callers switch on the outcome; they never parse strings.
|
|
68
67
|
- **Rejections are arrivals.** A provider 400 that carries the model's
|
|
69
68
|
attempt is recovered by an error-hook strategy and routed
|
package/DOCS.md
CHANGED
|
@@ -8,7 +8,7 @@ Complete reference for `@niscorp/signal`.
|
|
|
8
8
|
|
|
9
9
|
### Stateless Immutable Builder
|
|
10
10
|
|
|
11
|
-
Signal uses an immutable builder pattern. Every configuration method returns a **new instance** — the original is never modified. `complete()`
|
|
11
|
+
Signal uses an immutable builder pattern. Every configuration method returns a **new instance** — the original is never modified. Nothing is sent until an execution method (`complete()`, `stream()`, `step()`, `stepStream()`, `embed()`, `decide()`) is called.
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
14
|
const base = createSignal('groq').systemPrompt('You are helpful.');
|
|
@@ -35,6 +35,9 @@ Each provider has a capability profile that Signal uses to pick the right strate
|
|
|
35
35
|
- **`nativeTools`** — Can the provider do tool calling natively?
|
|
36
36
|
- **`nativeJsonSchema`** — Can it enforce a JSON Schema on the response?
|
|
37
37
|
- **`nativeJsonMode`** — Can it guarantee JSON output?
|
|
38
|
+
- **`toolsWithStructuredOutput`** — Is `response_format` accepted together with `tools` in one request?
|
|
39
|
+
- **`validatesToolArgs`** — Does the endpoint validate tool-call arguments server-side and reject the request on a mismatch?
|
|
40
|
+
- **`manglesNestedToolArgs`** — Does the model corrupt nested tool-call arguments?
|
|
38
41
|
- **`multimodal`** — Does it accept image content?
|
|
39
42
|
- **`supportsEmbedding`** — Can it convert text to vectors?
|
|
40
43
|
|
|
@@ -50,7 +53,18 @@ You don't need to think about this unless you're overriding defaults.
|
|
|
50
53
|
const signal = createSignal('groq');
|
|
51
54
|
```
|
|
52
55
|
|
|
53
|
-
Reads `GROQ_API_KEY` from environment automatically. Known providers: `'groq'`, `'openai'`, `'openrouter'`, `'anthropic'`, `'google'`.
|
|
56
|
+
Reads `GROQ_API_KEY` from environment automatically. Known providers: `'groq'`, `'openai'`, `'openrouter'`, `'anthropic'`, `'google'`, `'typesafe'`.
|
|
57
|
+
|
|
58
|
+
| Provider | Env var | Default model |
|
|
59
|
+
|----------|---------|---------------|
|
|
60
|
+
| `'groq'` | `GROQ_API_KEY` | `qwen/qwen3.8-27b` |
|
|
61
|
+
| `'openai'` | `OPENAI_API_KEY` | `gpt-4o` |
|
|
62
|
+
| `'openrouter'` | `OPENROUTER_API_KEY` | `openai/gpt-4o` |
|
|
63
|
+
| `'anthropic'` | `ANTHROPIC_API_KEY` | `claude-sonnet-4-20250514` |
|
|
64
|
+
| `'google'` | `GOOGLE_API_KEY` | `gemini-2.0-flash` |
|
|
65
|
+
| `'typesafe'` | `TYPESAFE_API_KEY` | `jev-latest` |
|
|
66
|
+
|
|
67
|
+
`'anthropic'` and `'google'` are registry rows whose adapters are not implemented yet: the client builds and `describe()` answers, but every execution method throws `E_PROVIDER_ERROR` (`E_MISSING_API_KEY` first when no key is set; `count()`, which never reaches the adapter, still works). Reach those models through `'openrouter'`.
|
|
54
68
|
|
|
55
69
|
### Known Provider with Options
|
|
56
70
|
|
|
@@ -73,7 +87,7 @@ const signal = createSignal({
|
|
|
73
87
|
});
|
|
74
88
|
```
|
|
75
89
|
|
|
76
|
-
Any OpenAI-compatible API works.
|
|
90
|
+
Any OpenAI-compatible API works. A custom provider is outside the registry, so it states what it does itself — `capabilities` (a `Partial<Capabilities>`; unstated fields are `false`) and, optionally, `wire` strategy ids. `adapter` defaults to `'openai-compatible'`.
|
|
77
91
|
|
|
78
92
|
---
|
|
79
93
|
|
|
@@ -115,7 +129,7 @@ signal.history(previousMessages)
|
|
|
115
129
|
```
|
|
116
130
|
|
|
117
131
|
### `.retries(count)`
|
|
118
|
-
Set max validation retries (default: 2). When a response fails Zod validation, Signal feeds the error back to the model and tries again
|
|
132
|
+
Set max validation retries (default: 2). When a response fails Zod validation, Signal feeds the error back to the model and tries again; once the retries are spent the call fails with `E_VALIDATION_FAILED`.
|
|
119
133
|
```typescript
|
|
120
134
|
signal.retries(3)
|
|
121
135
|
```
|
|
@@ -127,7 +141,7 @@ signal.apiKey('gsk_...')
|
|
|
127
141
|
```
|
|
128
142
|
|
|
129
143
|
### `.options(opts)`
|
|
130
|
-
Set LLM options
|
|
144
|
+
Set LLM options: `temperature`, `maxTokens`, `topP`, `stopSequences`, `seed`, `signal` (an `AbortSignal`), `reasoningEffort`. Merged over any options already set. These are rarely needed.
|
|
131
145
|
```typescript
|
|
132
146
|
signal.options({ temperature: 0 })
|
|
133
147
|
```
|
|
@@ -144,10 +158,11 @@ createSignal('groq').describe()
|
|
|
144
158
|
// { provider: 'groq', model: 'qwen/qwen3.8-27b', kind: 'chat', modelKnown: true, capabilities: {…} }
|
|
145
159
|
```
|
|
146
160
|
A `reasoningEffort` the model's row does not list is refused when the
|
|
147
|
-
client is built (`SignalError`), not by a provider 400
|
|
161
|
+
client is built (`SignalError`, `E_VALIDATION_FAILED`), not by a provider 400
|
|
162
|
+
mid-run. An unmeasured model is not checked.
|
|
148
163
|
|
|
149
164
|
### `.onRetry(handler)`
|
|
150
|
-
Hook called on each validation
|
|
165
|
+
Hook called on each validation failure, including the last one that exhausts the retries.
|
|
151
166
|
```typescript
|
|
152
167
|
signal.onRetry((error, attempt) => console.log(`Retry ${attempt}:`, error.message))
|
|
153
168
|
```
|
|
@@ -179,9 +194,39 @@ await signal.complete([
|
|
|
179
194
|
]);
|
|
180
195
|
```
|
|
181
196
|
|
|
182
|
-
### `.stream(input)`
|
|
197
|
+
### `.stream(input, options?)`
|
|
198
|
+
|
|
199
|
+
The same run as `complete()`, delivered as it happens. Returns `AsyncIterable<StreamEvent<T>>`; `options.signal` (an `AbortSignal`) aborts it.
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
for await (const event of signal.stream('Tell me a story')) {
|
|
203
|
+
if (event.type === 'text') process.stdout.write(event.text);
|
|
204
|
+
if (event.type === 'done') console.log(event.meta.usage);
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
type StreamEvent<T> =
|
|
210
|
+
| { type: 'text'; text: string }
|
|
211
|
+
| { type: 'tool_start'; name: string; args: unknown }
|
|
212
|
+
| { type: 'tool_end'; name: string; result: unknown }
|
|
213
|
+
| { type: 'retry'; reason: string; attempt: number }
|
|
214
|
+
| { type: 'error'; error: Error; recovered: boolean }
|
|
215
|
+
| { type: 'done'; response: T; history: Message[]; meta: SignalMeta };
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Schema validation happens at the end of the stream; when the retries are spent the stream ends with an `error` event (which `complete()` throws).
|
|
219
|
+
|
|
220
|
+
### `.step(request)` / `.stepStream(request, options?)`
|
|
221
|
+
|
|
222
|
+
The low-level primitives `complete()` and `stream()` are built on: one model call, no tool execution, no schema retries. The caller owns the loop. `step()` takes a `StepRequest` (`messages`, `tools`, `toolChoice`, `output`, `responseFormat`, `options`) and returns a `StepResult` (`content`, `toolCalls`, `usage`, `finishReason`, `raw`, and — when the request carried `output.accept` — the routed `outcome` and `wire` report). `stepStream()` yields `text`, `reasoning` and `tool_call_delta` events and a final `done` carrying the `StepResult`.
|
|
183
223
|
|
|
184
|
-
|
|
224
|
+
### `.count(input)`
|
|
225
|
+
|
|
226
|
+
Rough token count for a string or a message list. A heuristic (about 4 characters per token), not a tokenizer.
|
|
227
|
+
```typescript
|
|
228
|
+
const tokens = await signal.count('How long is this?');
|
|
229
|
+
```
|
|
185
230
|
|
|
186
231
|
---
|
|
187
232
|
|
|
@@ -209,12 +254,14 @@ type SignalMeta = {
|
|
|
209
254
|
retries: number; // validation retries that occurred
|
|
210
255
|
toolCalls: ToolCallRecord[]; // tools called, args, results, timing
|
|
211
256
|
provider: {
|
|
212
|
-
raw: unknown; //
|
|
213
|
-
errors: ProviderError[]; //
|
|
257
|
+
raw: unknown; // null: these calls read the reply as a stream, which leaves no body to keep (an array, one entry per call, when the run took several)
|
|
258
|
+
errors: ProviderError[]; // currently always empty
|
|
214
259
|
};
|
|
215
260
|
};
|
|
216
261
|
```
|
|
217
262
|
|
|
263
|
+
`step()` returns the provider's response body as its `raw`. Where a provider rejected a call and Signal recovered the attempt from the rejection, that call's `raw` is the provider's error.
|
|
264
|
+
|
|
218
265
|
---
|
|
219
266
|
|
|
220
267
|
## Structured Output
|
|
@@ -237,15 +284,15 @@ const { response } = await createSignal('groq')
|
|
|
237
284
|
|
|
238
285
|
### How It Works
|
|
239
286
|
|
|
240
|
-
1. Zod schema is converted to JSON Schema
|
|
241
|
-
2. Based on
|
|
242
|
-
- `nativeJsonSchema` → sends JSON Schema as `response_format`
|
|
243
|
-
- `nativeJsonMode` → sends `response_format: json_object` + schema in system
|
|
244
|
-
-
|
|
245
|
-
3.
|
|
287
|
+
1. Zod schema is converted to JSON Schema (draft-07)
|
|
288
|
+
2. Based on capabilities:
|
|
289
|
+
- `nativeJsonSchema` (and, when tools are set, `toolsWithStructuredOutput`) → sends JSON Schema as `response_format`
|
|
290
|
+
- otherwise `nativeJsonMode` and no tools → sends `response_format: json_object` + schema in a system message
|
|
291
|
+
- otherwise → schema in a system message only
|
|
292
|
+
3. The response is normalized by the wire layer (JSON extraction and repairs, each counted only if the result passes the schema)
|
|
246
293
|
4. Validated with `schema.safeParse()`
|
|
247
|
-
5. On failure:
|
|
248
|
-
6. Retries up to `retries` times (default: 2)
|
|
294
|
+
5. On failure: the evidence is sent back to the model as a correction message
|
|
295
|
+
6. Retries up to `retries` times (default: 2), then fails with `E_VALIDATION_FAILED`
|
|
249
296
|
7. Returns typed, validated result
|
|
250
297
|
|
|
251
298
|
---
|
|
@@ -271,7 +318,9 @@ const searchTool = defineTool({
|
|
|
271
318
|
});
|
|
272
319
|
```
|
|
273
320
|
|
|
274
|
-
The Zod `input` schema validates the model's arguments before `execute` runs. The return value is stringified and sent back to the model.
|
|
321
|
+
The Zod `input` schema validates the model's arguments before `execute` runs. The return value is stringified and sent back to the model. A call to an unknown tool, arguments that fail the schema, and an `execute` that throws do not fail the run: each goes back to the model as an `error: …` tool result (and is recorded in `meta.toolCalls`).
|
|
322
|
+
|
|
323
|
+
The model is sent the `input` schema as JSON Schema, taken from the schema's output side, so an `input` schema validates and does not convert. One with no JSON Schema (a `.transform()`, a `z.date()`) rejects the call before any request is made, with Zod's own error (`Transforms cannot be represented in JSON Schema`) rather than a `SignalError`. One whose output is another kind than its input (`z.stringbool()`) is described to the model by its output: told `boolean`, a model that sends one gets `input_invalid` back, and it is the string (`"true"`) that is accepted. Convert inside `execute`.
|
|
275
324
|
|
|
276
325
|
### Using Tools
|
|
277
326
|
|
|
@@ -287,17 +336,15 @@ const { response, meta } = await createSignal('groq')
|
|
|
287
336
|
|
|
288
337
|
### How Tool Calling Works
|
|
289
338
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
**Native tools** (OpenAI) — Uses the provider's native `tools` parameter and `tool_calls` response. The model decides when to call tools.
|
|
293
|
-
|
|
294
|
-
**Unified schema** (Groq, others) — Tool descriptions are injected into the system prompt. The response format includes a discriminator field (`_action: "call" | "respond"`). Signal handles the loop:
|
|
339
|
+
Tools use the provider's native `tools` parameter and `tool_calls` response; the model decides when to call them. A provider without `nativeTools` cannot take tools — the call throws `E_PROVIDER_ERROR`. Signal handles the loop:
|
|
295
340
|
|
|
296
|
-
1. Model responds with
|
|
341
|
+
1. Model responds with tool calls
|
|
297
342
|
2. Signal validates args with Zod, executes the tool
|
|
298
343
|
3. Tool result is sent back to the model
|
|
299
|
-
4. Model responds with
|
|
300
|
-
5.
|
|
344
|
+
4. Model responds with the final answer
|
|
345
|
+
5. With a schema set, the final answer is validated against it
|
|
346
|
+
|
|
347
|
+
Where the model cannot combine `response_format` with tools (`toolsWithStructuredOutput: false`, e.g. Groq), the schema rides a system message instead and is validated client-side. A run that is still calling tools after 10 tool turns (plus the retry budget) fails with `E_MAX_ITERATIONS`.
|
|
301
348
|
|
|
302
349
|
---
|
|
303
350
|
|
|
@@ -348,6 +395,14 @@ const small = await embedder.embed('text', { dimensions: 256 });
|
|
|
348
395
|
// small: number[256]
|
|
349
396
|
```
|
|
350
397
|
|
|
398
|
+
### Usage
|
|
399
|
+
|
|
400
|
+
`embed()` returns vectors only. To read what the call cost, pass `onUsage` — called after a successful call with the provider's usage and the model that resolved:
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
await embedder.embed('text', { onUsage: (usage, model) => meter(model, usage.totalTokens) });
|
|
404
|
+
```
|
|
405
|
+
|
|
351
406
|
### Similarity
|
|
352
407
|
|
|
353
408
|
Cosine similarity between embedding vectors measures semantic relatedness:
|
|
@@ -369,7 +424,7 @@ const similarity = cosine(a, b);
|
|
|
369
424
|
|
|
370
425
|
### Provider Support
|
|
371
426
|
|
|
372
|
-
|
|
427
|
+
`embed()` does not check `supportsEmbedding`: the flag is what `describe()` reports, and the request goes to the provider's embeddings endpoint either way. Of the known providers only **OpenAI** is marked as having one (`text-embedding-3-small`, `text-embedding-3-large`). An endpoint that refuses the request surfaces as `E_PROVIDER_ERROR` (`Embedding error: …`, the provider's own error under `context.raw`). A decision provider and the two adapters that are not implemented fail before any request is made.
|
|
373
428
|
|
|
374
429
|
Use a separate Signal client for embedding — embedding models are different from chat models:
|
|
375
430
|
|
|
@@ -468,12 +523,10 @@ All errors are `SignalError` instances with a `.code` and optional `.context`:
|
|
|
468
523
|
| `E_MISSING_API_KEY` | No API key found (env or explicit) |
|
|
469
524
|
| `E_MISSING_MODEL` | No model specified for custom provider |
|
|
470
525
|
| `E_MISSING_SDK` | Provider SDK not installed |
|
|
471
|
-
| `E_VALIDATION_FAILED` | Response failed Zod validation after all retries |
|
|
472
|
-
| `
|
|
473
|
-
| `E_PROVIDER_ERROR` | Provider API error (rate limit, server error, etc.) |
|
|
474
|
-
| `E_TOOL_NOT_FOUND` |
|
|
475
|
-
| `E_TOOL_EXECUTION` | Tool execute() threw |
|
|
476
|
-
| `E_TOOL_VALIDATION` | Tool args failed Zod validation |
|
|
526
|
+
| `E_VALIDATION_FAILED` | Response failed Zod validation after all retries; a `decide()` answer failed its gate; a `reasoningEffort` the model does not take |
|
|
527
|
+
| `E_MAX_ITERATIONS` | The tool loop did not finish within its turn limit |
|
|
528
|
+
| `E_PROVIDER_ERROR` | Provider API error (rate limit, server error, a refused `embed()`, etc.); tools on a provider without `nativeTools`; an adapter that is not implemented |
|
|
529
|
+
| `E_MAX_RETRIES`, `E_TOOL_NOT_FOUND`, `E_TOOL_EXECUTION`, `E_TOOL_VALIDATION` | Declared in `ErrorCode`, not currently thrown — tool failures go back to the model as tool results, and exhausted retries are `E_VALIDATION_FAILED` |
|
|
477
530
|
| `E_VERB_NOT_SUPPORTED` | A chat verb was called on a decision provider |
|
|
478
531
|
|
|
479
532
|
```typescript
|
|
@@ -494,7 +547,7 @@ try {
|
|
|
494
547
|
|
|
495
548
|
Groq is fast and cheap but has quirks:
|
|
496
549
|
|
|
497
|
-
- **No native tools + structured output together.** Signal
|
|
550
|
+
- **No native tools + structured output together.** With tools set, Signal sends no `response_format` there; the schema rides a system message and is validated client-side.
|
|
498
551
|
- **`json_validate_failed` errors.** Groq sometimes returns the model's failed output in the error. Signal extracts and recovers from this.
|
|
499
552
|
- **Model-dependent capabilities.** What each Groq model does (json_schema, nested tool args, reasoning efforts) is its own row in the model registry, measured by the probe.
|
|
500
553
|
- **Tool args are validated server-side.** So `respond` params would enforce nothing on Groq, and `auto` resolves every agent there to `emit`.
|
package/README.md
CHANGED
|
@@ -53,6 +53,8 @@ signal.schema(zodSchema) // typed structured output
|
|
|
53
53
|
signal.tools([myTool]) // tool calling
|
|
54
54
|
signal.history(messages) // multi-turn
|
|
55
55
|
signal.retries(3) // validation retries
|
|
56
|
+
signal.options({ temperature: 0 }) // sampling / generation options
|
|
57
|
+
signal.apiKey(key) // override the env key
|
|
56
58
|
signal.describe() // provider, model, capabilities — from the registry
|
|
57
59
|
signal.onRetry(handler) // retry hook
|
|
58
60
|
signal.onToolCall(handler) // tool call hook
|
|
@@ -114,4 +116,4 @@ API keys are read from environment variables (`GROQ_API_KEY`, `OPENAI_API_KEY`,
|
|
|
114
116
|
|
|
115
117
|
## License
|
|
116
118
|
|
|
117
|
-
|
|
119
|
+
Apache-2.0
|
package/dist/index.cjs
CHANGED
|
@@ -1502,9 +1502,9 @@ var createSignalFromConfig = (config) => {
|
|
|
1502
1502
|
});
|
|
1503
1503
|
return { ...result, outcome: routed.outcome, wire: routed.wire };
|
|
1504
1504
|
};
|
|
1505
|
-
const
|
|
1505
|
+
const stepStreamAs = (verb) => (request, streamOptions) => {
|
|
1506
1506
|
const run = async function* () {
|
|
1507
|
-
const adapter = await getChatAdapter(
|
|
1507
|
+
const adapter = await getChatAdapter(verb);
|
|
1508
1508
|
const resolved = resolveProvider(config);
|
|
1509
1509
|
const declared = new Set((request.tools ?? []).map((tool) => tool.name));
|
|
1510
1510
|
const merged = config.options !== void 0 || request.options !== void 0 ? { ...request, options: { ...config.options, ...request.options } } : request;
|
|
@@ -1544,6 +1544,7 @@ var createSignalFromConfig = (config) => {
|
|
|
1544
1544
|
};
|
|
1545
1545
|
return run();
|
|
1546
1546
|
};
|
|
1547
|
+
const stepStream = stepStreamAs("stepStream");
|
|
1547
1548
|
const decideCalibrated = async (adapter, model, request, started) => {
|
|
1548
1549
|
const response = await adapter.decide(
|
|
1549
1550
|
{ model, state: request.state, questions: request.questions },
|
|
@@ -1631,7 +1632,7 @@ var createSignalFromConfig = (config) => {
|
|
|
1631
1632
|
onRetry: config.onRetry,
|
|
1632
1633
|
onToolCall: config.onToolCall
|
|
1633
1634
|
},
|
|
1634
|
-
{ stepStream, model: resolveProvider(config).model, capabilities: resolveCapabilities(config) }
|
|
1635
|
+
{ stepStream: stepStreamAs("complete"), model: resolveProvider(config).model, capabilities: resolveCapabilities(config) }
|
|
1635
1636
|
),
|
|
1636
1637
|
stream: (input, streamOptions) => runStream(
|
|
1637
1638
|
{
|
|
@@ -1644,7 +1645,7 @@ var createSignalFromConfig = (config) => {
|
|
|
1644
1645
|
onRetry: config.onRetry,
|
|
1645
1646
|
onToolCall: config.onToolCall
|
|
1646
1647
|
},
|
|
1647
|
-
{ stepStream, model: resolveProvider(config).model, capabilities: resolveCapabilities(config) }
|
|
1648
|
+
{ stepStream: stepStreamAs("stream"), model: resolveProvider(config).model, capabilities: resolveCapabilities(config) }
|
|
1648
1649
|
),
|
|
1649
1650
|
// ─── Low-level primitives — the execution core itself ────
|
|
1650
1651
|
step,
|