@demlik/tea 0.14.0 → 0.16.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.
- package/README.md +30 -7
- package/dist/agent/index.d.ts +49 -36
- package/dist/agent/index.js +12 -8
- package/dist/chunk-4LPY67E4.js +18 -0
- package/dist/chunk-4LPY67E4.js.map +1 -0
- package/dist/chunk-5XU6ZJO2.js +533 -0
- package/dist/chunk-5XU6ZJO2.js.map +1 -0
- package/dist/{chunk-AQ6ZIMEA.js → chunk-6NG4V5SB.js} +89 -115
- package/dist/chunk-6NG4V5SB.js.map +1 -0
- package/dist/{chunk-HYDWG35Q.js → chunk-7MGXQZPW.js} +11 -9
- package/dist/chunk-7MGXQZPW.js.map +1 -0
- package/dist/{chunk-BLJ2JQSH.js → chunk-BCTEOVOU.js} +3 -3
- package/dist/{chunk-BLJ2JQSH.js.map → chunk-BCTEOVOU.js.map} +1 -1
- package/dist/chunk-CH5KTOEZ.js +710 -0
- package/dist/chunk-CH5KTOEZ.js.map +1 -0
- package/dist/chunk-CIHSHLQX.js +64 -0
- package/dist/chunk-CIHSHLQX.js.map +1 -0
- package/dist/{chunk-Z2L3LSNV.js → chunk-EHUDXAKC.js} +246 -210
- package/dist/chunk-EHUDXAKC.js.map +1 -0
- package/dist/chunk-GOX2CYIM.js +380 -0
- package/dist/chunk-GOX2CYIM.js.map +1 -0
- package/dist/chunk-IVJP3GKJ.js +104 -0
- package/dist/chunk-IVJP3GKJ.js.map +1 -0
- package/dist/{chunk-F7FMAWLA.js → chunk-MVZS5FDM.js} +13 -6
- package/dist/chunk-MVZS5FDM.js.map +1 -0
- package/dist/{chunk-LYLTKJWM.js → chunk-MYNLY3HP.js} +9 -8
- package/dist/chunk-MYNLY3HP.js.map +1 -0
- package/dist/{chunk-I5MQMJDW.js → chunk-NSIAORRY.js} +20 -30
- package/dist/chunk-NSIAORRY.js.map +1 -0
- package/dist/{chunk-MYXFNWAJ.js → chunk-QNGYQMZB.js} +4 -4
- package/dist/chunk-QNGYQMZB.js.map +1 -0
- package/dist/chunk-WT5PBPLB.js +98 -0
- package/dist/chunk-WT5PBPLB.js.map +1 -0
- package/dist/{core-CTzMJ82M.d.ts → core-BbgtiXdg.d.ts} +231 -139
- package/dist/do/index.d.ts +37 -32
- package/dist/do/index.js +21 -14
- package/dist/do/index.js.map +1 -1
- package/dist/{durable-effects-B0-qGQDy.d.ts → durable-effects-7MTK_jnj.d.ts} +1 -1
- package/dist/effect/index.d.ts +151 -0
- package/dist/effect/index.js +98 -0
- package/dist/effect/index.js.map +1 -0
- package/dist/extension/index.d.ts +6 -7
- package/dist/extension/index.js +3 -2
- package/dist/extension/index.js.map +1 -1
- package/dist/flow/index.d.ts +68 -70
- package/dist/flow/index.js +32 -27
- package/dist/flow/index.js.map +1 -1
- package/dist/idempotency/index.d.ts +6 -7
- package/dist/idempotency/index.js +4 -2
- package/dist/{index-DJWIER_3.d.ts → index-7vV8xmsD.d.ts} +1 -1
- package/dist/{index-NjrT3fL2.d.ts → index-Bz5Rh9Ga.d.ts} +19 -96
- package/dist/index-CjFDUBeq.d.ts +207 -0
- package/dist/{index-6A7dB8f6.d.ts → index-CkFYA9Y6.d.ts} +14 -16
- package/dist/{index-B5BZ-_cT.d.ts → index-Cou86-GX.d.ts} +189 -108
- package/dist/{index-TvRb1KVf.d.ts → index-DU6JpQ8G.d.ts} +1 -1
- package/dist/{index-q0hXFeZ0.d.ts → index-Xufl55W8.d.ts} +286 -215
- package/dist/{index-4vZzljCD.d.ts → index-_dOR3xqA.d.ts} +57 -45
- package/dist/index.d.ts +181 -385
- package/dist/index.js +2 -1
- package/dist/jev/index.d.ts +147 -99
- package/dist/jev/index.js +329 -233
- package/dist/jev/index.js.map +1 -1
- package/dist/{machine-CdIcN2Xm.d.ts → machine-BQzTV8On.d.ts} +171 -280
- package/dist/machine-viz/index.d.ts +5 -5
- package/dist/machine-viz/index.js +8 -4
- package/dist/machine-viz/index.js.map +1 -1
- package/dist/mem/index.d.ts +3 -4
- package/dist/mem/index.js +2 -1
- package/dist/mem/index.js.map +1 -1
- package/dist/node/index.d.ts +119 -78
- package/dist/node/index.js +52 -38
- package/dist/node/index.js.map +1 -1
- package/dist/paginate/index.d.ts +27 -33
- package/dist/paginate/index.js +6 -4
- package/dist/parity/index.d.ts +4 -5
- package/dist/parity/index.js +3 -2
- package/dist/parity/index.js.map +1 -1
- package/dist/pbt/index.d.ts +2 -2
- package/dist/pbt/index.js +2 -1
- package/dist/pbt/index.js.map +1 -1
- package/dist/persistence/index.d.ts +6 -7
- package/dist/persistence/index.js +5 -3
- package/dist/promise/index.d.ts +186 -0
- package/dist/promise/index.js +5 -0
- package/dist/promise/index.js.map +1 -0
- package/dist/protocol-ClRZBhHQ.d.ts +53 -0
- package/dist/react/index.d.ts +36 -17
- package/dist/react/index.js +27 -4
- package/dist/react/index.js.map +1 -1
- package/dist/resilience/index.d.ts +63 -455
- package/dist/resilience/index.js +37 -483
- package/dist/resilience/index.js.map +1 -1
- package/dist/{runtime-types-LWDoi943.d.ts → runtime-types-CiVpC0HN.d.ts} +131 -388
- package/dist/testing/index.d.ts +165 -15
- package/dist/testing/index.js +104 -3
- package/dist/testing/index.js.map +1 -1
- package/dist/timing/index.d.ts +25 -22
- package/dist/timing/index.js +4 -3
- package/dist/timing/index.js.map +1 -1
- package/dist/{types-DP3f5NIl.d.ts → types-LxZxGYda.d.ts} +2 -2
- package/dist/work-queue/index.d.ts +5 -6
- package/package.json +18 -5
- package/dist/chunk-AQ6ZIMEA.js.map +0 -1
- package/dist/chunk-F2US5BW6.js +0 -72
- package/dist/chunk-F2US5BW6.js.map +0 -1
- package/dist/chunk-F7FMAWLA.js.map +0 -1
- package/dist/chunk-HUKZQX6U.js +0 -97
- package/dist/chunk-HUKZQX6U.js.map +0 -1
- package/dist/chunk-HYDWG35Q.js.map +0 -1
- package/dist/chunk-I5MQMJDW.js.map +0 -1
- package/dist/chunk-LYLTKJWM.js.map +0 -1
- package/dist/chunk-MYXFNWAJ.js.map +0 -1
- package/dist/chunk-RQULHGYH.js +0 -1804
- package/dist/chunk-RQULHGYH.js.map +0 -1
- package/dist/chunk-Z2L3LSNV.js.map +0 -1
- package/dist/index-DMCeMPMJ.d.ts +0 -272
|
@@ -1,133 +1,101 @@
|
|
|
1
|
-
import { C as Cmd,
|
|
2
|
-
import { a as MonitoredRunState, R as RunFailure, M as MonitoredRunCmd } from './index-
|
|
3
|
-
import { R as RunCmd, S as SucceedMsg, F as FailMsg, a as ResilientState,
|
|
4
|
-
import { D as DeadlineExceeded, a as DeadlineSub } from './index-
|
|
5
|
-
import {
|
|
1
|
+
import { C as Cmd, s as Tagged, p as Interpret, A as AnyCmdDef, c as CmdOf, b as CmdDef, j as Settled, t as OkOf, u as ErrOf, r as MalformedResult, l as Outcome, v as CmdValue, m as PortEmitter, g as TaggedError, M as Machine, d as Subscribe } from './core-BbgtiXdg.js';
|
|
2
|
+
import { a as MonitoredRunState, R as RunFailure, M as MonitoredRunCmd } from './index-Bz5Rh9Ga.js';
|
|
3
|
+
import { R as RunCmd, S as SucceedMsg, F as FailMsg, a as ResilientState, r as RunCmdDef } from './index-Cou86-GX.js';
|
|
4
|
+
import { D as DeadlineExceeded, a as DeadlineSub, b as DeadlinesSub } from './index-Xufl55W8.js';
|
|
5
|
+
import { M as MsgType, a as MsgTypeValue } from './protocol-ClRZBhHQ.js';
|
|
6
|
+
import { F as FanOutState } from './index-CkFYA9Y6.js';
|
|
6
7
|
import { RetryPolicy, AnyRetryPolicy } from './retry-backoff/index.js';
|
|
7
|
-
import {
|
|
8
|
-
import { z } from 'zod';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @packageDocumentation
|
|
12
|
-
* internal/llm-call — `resilient-call` + structured-output parse + a typed
|
|
13
|
-
* failure variant, around a purpose-discriminated LLM invocation. Internal
|
|
14
|
-
* since #49 — not published on any subpath; `@demlik/tea/agent` re-exports
|
|
15
|
-
* the types a consumer meets.
|
|
16
|
-
*
|
|
17
|
-
* This is the ~60-line `call_llm` handler from the audit-agent seed
|
|
18
|
-
* (`interpret.ts` / `effects.ts`) collapsed into the uniform L2 knob: a config
|
|
19
|
-
* object, the resilient-call slice it inherits, and one interpret handler that
|
|
20
|
-
* assembles messages, binds the structured-output schema for the call's
|
|
21
|
-
* `purpose`, invokes the model (retry composed from `../resilient-call`, NOT
|
|
22
|
-
* reinvented), parses the output, and RETURNS the enriched resilient settle Msg
|
|
23
|
-
* (`resilient_ok` / `resilient_err`) so it re-enters the host reducer and drives
|
|
24
|
-
* the inherited succeed/fail → backoff → onTimer loop.
|
|
25
|
-
*
|
|
26
|
-
* ## What it adds over `../resilient-call`
|
|
27
|
-
*
|
|
28
|
-
* - **Two DI ports** (the seed's two seams):
|
|
29
|
-
* 1. `model` — either `async (messages) => answer`, the plain-function
|
|
30
|
-
* port (#58), or `(modelId) => LLM`, the model factory that binds the
|
|
31
|
-
* structured-output schema itself. Tests pass a fake so the handler
|
|
32
|
-
* runs end-to-end without touching a real provider; the production
|
|
33
|
-
* worker wires `createChatModel(env, …)`.
|
|
34
|
-
* 2. `loadMessages: Loader` — the SDK / message loader. The seed lazy-
|
|
35
|
-
* imports `@langchain/core/messages` (a top-level `import type` blows
|
|
36
|
-
* up the workers test runner); the loader keeps that import lazy and
|
|
37
|
-
* stubbable. It produces the `BaseMessage[]` for a given call.
|
|
38
|
-
* - **Structured-output parse** — each `purpose` maps to a `Schema` in
|
|
39
|
-
* `config.schemas`. The handler binds `model.withStructuredOutput(schema)`
|
|
40
|
-
* so the invoke resolves to a typed object; a `Schema.parse` that throws
|
|
41
|
-
* becomes a `resilient_err` carrying an `LlmErr` (a parse failure is a
|
|
42
|
-
* failure, not a stall — "errors are data"). `withStructuredOutput` is the
|
|
43
|
-
* seed's brain-only path; the fake model in tests returns the typed object
|
|
44
|
-
* directly.
|
|
45
|
-
* - **A typed failure variant** — every failure (model throw, timeout-via-
|
|
46
|
-
* retry-exhaustion, schema parse) is surfaced as the `LlmErr` carried on the
|
|
47
|
-
* enriched `resilient_err` settle Msg, tagged with the `purpose` so the
|
|
48
|
-
* consumer's reducer routes per-stage. The seed dispatched
|
|
49
|
-
* `llm_failed{purpose}`; the consumer rebuilds that shape in its reducer arm
|
|
50
|
-
* from `m.error: LlmErr`.
|
|
51
|
-
*
|
|
52
|
-
* ## Inheriting resilient-call by composition (not reinvention)
|
|
53
|
-
*
|
|
54
|
-
* The retry / backoff lives in `../resilient-call`: `createLlmCall` builds a
|
|
55
|
-
* `createResilientCall` knob over the model-invoke port and DELEGATES `init`,
|
|
56
|
-
* `attempt`, `succeed`, `fail`, `onTimer`, `subs` to it verbatim — the slice is
|
|
57
|
-
* literally resilient-call's slice (the spec's "retry lives here"). There is no
|
|
58
|
-
* second backoff implementation here. The handler runs the invoke through the
|
|
59
|
-
* resilient-call handler so a transient model failure backs off exactly as a
|
|
60
|
-
* resilient HTTP call would; the `purpose`-branch + structured parse wrap the
|
|
61
|
-
* port the resilient handler drives.
|
|
62
|
-
*
|
|
63
|
-
* ## The two non-negotiables (canon, inherited)
|
|
64
|
-
*
|
|
65
|
-
* - **Durable** — the slice is resilient-call's plain-data slice (a Model
|
|
66
|
-
* field). Input carried on the `resilient_run` Cmd is the plain
|
|
67
|
-
* `LlmCall` request (purpose + modelId + payload) — no closures.
|
|
68
|
-
* - **Replayable** — every transition is a resilient-call verb; the handler
|
|
69
|
-
* is the only impurity, and the one clock read is `Date.now()` at the
|
|
70
|
-
* effect boundary (inside the handler), exactly as the seed stamped its
|
|
71
|
-
* `llm_responded` / `llm_failed` Msgs.
|
|
72
|
-
*
|
|
73
|
-
* ## Typical wiring
|
|
74
|
-
*
|
|
75
|
-
* const llm = createLlmCall<MyPurpose, MyOutputs>({
|
|
76
|
-
* model: (id) => createChatModel(env, id),
|
|
77
|
-
* schemas: { plan: planSchema, report: reportSchema },
|
|
78
|
-
* retry: defaultRetryPolicy,
|
|
79
|
-
* loadMessages: defaultMessagesLoader,
|
|
80
|
-
* });
|
|
81
|
-
*
|
|
82
|
-
* // in the machine:
|
|
83
|
-
* init: () => [{ resilience: llm.init() }, []],
|
|
84
|
-
* update: {
|
|
85
|
-
* call_llm: (s, m) => lift(s, llm.attempt(s.resilience, m.input, m.at)),
|
|
86
|
-
* // `resilient_ok` / `resilient_err` RE-ENTER from `handlers` (the settle
|
|
87
|
-
* // Msg the interpret handler returns). Run the inherited verb FIRST so the
|
|
88
|
-
* // succeed/fail → backoff → onTimer loop advances, THEN fold the enriched
|
|
89
|
-
* // payload (`m.result: LlmOk` / `m.error: LlmErr`) into the host's own
|
|
90
|
-
* // state — the enrichment lives in the reducer arm, not the handler.
|
|
91
|
-
* resilient_ok: (s, m) => {
|
|
92
|
-
* const [slice, cmds] = llm.succeed(s.resilience, m.key, m);
|
|
93
|
-
* return [{ ...s, resilience: slice, output: m.result.output }, cmds];
|
|
94
|
-
* },
|
|
95
|
-
* resilient_err: (s, m) => {
|
|
96
|
-
* const [slice, cmds] = llm.fail(s.resilience, m.key, m);
|
|
97
|
-
* return [{ ...s, resilience: slice, failure: m.error }, cmds];
|
|
98
|
-
* },
|
|
99
|
-
* deadline_exceeded: (s, m) => lift(s, llm.onTimer(s.resilience, m)),
|
|
100
|
-
* },
|
|
101
|
-
* subscriptions: (s) => llm.subs(s.resilience),
|
|
102
|
-
* subscribe: { deadline: subscribeDeadline },
|
|
103
|
-
* interpret: llm.handlers(),
|
|
104
|
-
*/
|
|
8
|
+
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
105
9
|
|
|
106
10
|
/**
|
|
107
11
|
* The minimal structured-output schema contract: `parse(unknown) => T`, the
|
|
108
|
-
* zod-style call
|
|
109
|
-
* settles `
|
|
110
|
-
* input)
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* it without an import.
|
|
12
|
+
* zod-style call `decode` uses to validate the model's output before it
|
|
13
|
+
* settles `resilient_run_ok`. A throwing `parse` (the zod contract on invalid
|
|
14
|
+
* input) becomes a `port_rejected` outcome — a parse failure is a failure,
|
|
15
|
+
* never a silent pass. Structural so a real `z.ZodType<T>` satisfies it
|
|
16
|
+
* without an import.
|
|
114
17
|
*/
|
|
115
18
|
interface Schema<T> {
|
|
116
19
|
/** Validate + narrow `value` to `T`, or throw on mismatch (the zod contract). */
|
|
117
20
|
parse(value: unknown): T;
|
|
118
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* One LLM call request — the resilient-call `input` for this module, carried on
|
|
24
|
+
* the `resilient_run` Cmd as plain data — no closures, so it survives
|
|
25
|
+
* persistence and replay. Purpose-discriminated: a `purpose` selecting the
|
|
26
|
+
* schema + prompt assembly, the `model` id, and the opaque per-purpose
|
|
27
|
+
* `payload` the handler's message loader consumes.
|
|
28
|
+
*
|
|
29
|
+
* `key` defaults to `purpose` when the consumer calls `attempt(s, input, at)`,
|
|
30
|
+
* so one in-flight call per purpose is tracked under the resilient-call slice —
|
|
31
|
+
* the common single-call-per-stage shape. A consumer that fans out many calls
|
|
32
|
+
* of one purpose passes a distinct `key`.
|
|
33
|
+
*/
|
|
34
|
+
interface LlmCall<P extends string> {
|
|
35
|
+
/** The stage / schema selector — drives both `schemas[purpose]` and message assembly. */
|
|
36
|
+
readonly purpose: P;
|
|
37
|
+
/** The model id to invoke; `null` = the host's default model. */
|
|
38
|
+
readonly model: string | null;
|
|
39
|
+
/** The per-purpose prompt payload the message loader consumes. Opaque to the knob. */
|
|
40
|
+
readonly payload: unknown;
|
|
41
|
+
}
|
|
42
|
+
/** The parsed, typed success carried on `resilient_run_ok`, tagged with its purpose. */
|
|
43
|
+
interface LlmOk<P extends string, O extends Record<P, unknown>> {
|
|
44
|
+
readonly key: string;
|
|
45
|
+
readonly purpose: P;
|
|
46
|
+
readonly output: O[P];
|
|
47
|
+
}
|
|
48
|
+
/** The typed failure variant — every failure path surfaces this, tagged by purpose. */
|
|
49
|
+
interface LlmErr<P extends string> {
|
|
50
|
+
readonly key: string;
|
|
51
|
+
readonly purpose: P;
|
|
52
|
+
/** A human-readable cause (model throw, retry-exhaustion, or schema parse). */
|
|
53
|
+
readonly reason: string;
|
|
54
|
+
/** The original error, carried untouched for the consumer to inspect. */
|
|
55
|
+
readonly error: unknown;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The effect Cmd this module emits: run the LLM call for `key` with `input`. It
|
|
59
|
+
* is `../resilient-call`'s `Cmd.define`d `RunCmd` specialized to the `LlmCall`
|
|
60
|
+
* input — NOT a re-declared shape — so the resilient verbs' return tuples
|
|
61
|
+
* thread through `attempt` / `succeed` / `fail` / `onTimer` with no cast.
|
|
62
|
+
*/
|
|
63
|
+
type LlmRunCmd<P extends string> = RunCmd<LlmCall<P>>;
|
|
64
|
+
/** The success Msg the engine mints — resilient-call's, with the parsed `LlmOk`. */
|
|
65
|
+
type LlmSucceedMsg<P extends string, O extends Record<P, unknown>> = SucceedMsg<LlmOk<P, O>, "resilient", LlmCall<P>>;
|
|
66
|
+
/**
|
|
67
|
+
* The failure Msg the engine mints — resilient-call's. Its `error` is the
|
|
68
|
+
* handler's `port_rejected` (an {@link LlmRejected} when the handler used
|
|
69
|
+
* `decode` / `rejected`); read it as the typed {@link LlmErr} with `errOf`.
|
|
70
|
+
*/
|
|
71
|
+
type LlmFailMsg<P extends string> = FailMsg<"resilient", LlmCall<P>>;
|
|
72
|
+
/** The retry / deadline timer Msg — `DeadlineExceeded`, inherited from resilient-call. */
|
|
73
|
+
type LlmTimerMsg = DeadlineExceeded;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @demlik/tea/agent — the model ports and the brain call's Promise handler.
|
|
77
|
+
*
|
|
78
|
+
* `../internal/llm-call` is pure: it owns the brain call's slice, its
|
|
79
|
+
* `Cmd.define`d run Cmd and the parse that turns a model's answer into that
|
|
80
|
+
* Cmd's outcome, and it ships no engine code (ADR 0021). The agent is a Promise
|
|
81
|
+
* host — `toMachine` hands its caller an `interpret` table and `defineAgent`
|
|
82
|
+
* runs itself — so the one handler that actually invokes the model lives here:
|
|
83
|
+
* the two DI ports (`model`, `loadMessages`) and {@link brainHandler}, which
|
|
84
|
+
* calls them and returns the outcome `llm.decode` builds.
|
|
85
|
+
*/
|
|
86
|
+
|
|
119
87
|
/**
|
|
120
88
|
* The minimal chat-model contract every model the handler talks to must
|
|
121
89
|
* satisfy — the seed's `InjectableChatModel`, trimmed to the one operation
|
|
122
|
-
*
|
|
90
|
+
* the brain call drives for brain-only stages:
|
|
123
91
|
*
|
|
124
92
|
* `withStructuredOutput(schema)` → a runnable whose `invoke(messages)`
|
|
125
93
|
* resolves to a typed object matching `schema`.
|
|
126
94
|
*
|
|
127
95
|
* `BaseChatModel` from `@langchain/core` is the runtime type; this surface
|
|
128
|
-
* names only what
|
|
96
|
+
* names only what the handler calls so a test fake can ignore the rest. Generic
|
|
129
97
|
* over the message shape `Msg` so a consumer's loader and model agree on it
|
|
130
|
-
* without
|
|
98
|
+
* without the agent inspecting messages.
|
|
131
99
|
*/
|
|
132
100
|
interface Llm<Msg> {
|
|
133
101
|
withStructuredOutput<T>(schema: Schema<T>): {
|
|
@@ -153,8 +121,8 @@ type ModelFactory<Msg> = (modelId: string | null) => Llm<Msg>;
|
|
|
153
121
|
* The plain-function model port — the common path. One async function
|
|
154
122
|
* from the assembled messages to the model's answer; the handler validates the
|
|
155
123
|
* answer through the purpose's `Schema` exactly as it re-validates the
|
|
156
|
-
* structured-output path, so a malformed answer is a `
|
|
157
|
-
* corrupt success. `ModelFactory` → `withStructuredOutput(schema).invoke(...)`
|
|
124
|
+
* structured-output path, so a malformed answer is a `resilient_run_err`, never
|
|
125
|
+
* a corrupt success. `ModelFactory` → `withStructuredOutput(schema).invoke(...)`
|
|
158
126
|
* stays the advanced form for a model that binds the schema itself.
|
|
159
127
|
*
|
|
160
128
|
* `T` is the answer type the schema narrows to — for the agent, an `AgentTurn`.
|
|
@@ -182,96 +150,6 @@ declare function plainModel<Msg, T>(fn: PlainModel<Msg, T>): ModelFactory<Msg>;
|
|
|
182
150
|
* passed as `model` bare — the one runtime shape neither port can own.
|
|
183
151
|
*/
|
|
184
152
|
declare const PLAIN_MODEL_MISROUTE_REASON: string;
|
|
185
|
-
/**
|
|
186
|
-
* One LLM call request — the resilient-call `input` for this module, carried on
|
|
187
|
-
* the `resilient_run` Cmd as plain data — no closures, so it survives
|
|
188
|
-
* persistence and replay. Purpose-discriminated: a `purpose` selecting the
|
|
189
|
-
* schema + prompt assembly, the `model` id, and the opaque per-purpose
|
|
190
|
-
* `payload` the loader consumes.
|
|
191
|
-
*
|
|
192
|
-
* `key` defaults to `purpose` when the consumer calls `attempt(s, purpose, …)`,
|
|
193
|
-
* so one in-flight call per purpose is tracked under the resilient-call slice —
|
|
194
|
-
* the common single-call-per-stage shape. A consumer that fans out many calls
|
|
195
|
-
* of one purpose passes a distinct `key`.
|
|
196
|
-
*/
|
|
197
|
-
interface LlmCall<P extends string> {
|
|
198
|
-
/** The stage / schema selector — drives both `schemas[purpose]` and message assembly. */
|
|
199
|
-
readonly purpose: P;
|
|
200
|
-
/** The model id to invoke; `null` = the host's default model. */
|
|
201
|
-
readonly model: string | null;
|
|
202
|
-
/** The per-purpose prompt payload the `MessageLoader` consumes. Opaque to the knob. */
|
|
203
|
-
readonly payload: unknown;
|
|
204
|
-
}
|
|
205
|
-
/** The parsed, typed success carried on the `resilient_ok` settle Msg, tagged with its purpose. */
|
|
206
|
-
interface LlmOk<P extends string, O extends Record<P, unknown>> {
|
|
207
|
-
readonly key: string;
|
|
208
|
-
readonly purpose: P;
|
|
209
|
-
readonly output: O[P];
|
|
210
|
-
}
|
|
211
|
-
/** The typed failure variant — every failure path surfaces this, tagged by purpose. */
|
|
212
|
-
interface LlmErr<P extends string> {
|
|
213
|
-
readonly key: string;
|
|
214
|
-
readonly purpose: P;
|
|
215
|
-
/** A human-readable cause (model throw, retry-exhaustion, or schema parse). */
|
|
216
|
-
readonly reason: string;
|
|
217
|
-
/** The original error, carried untouched for the consumer to inspect. */
|
|
218
|
-
readonly error: unknown;
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* The settle Msgs llm-call's handler RETURNS from `interpret` so the substrate
|
|
222
|
-
* enqueues them as follow-up Msgs (re-entry) into the host reducer — exactly as
|
|
223
|
-
* `../resilient-call` does. They are the resilient-call settle Msgs with the
|
|
224
|
-
* payloads ENRICHED to llm-call's typed variants: `result` is the parsed,
|
|
225
|
-
* purpose-tagged `LlmOk`; `error` is the typed `LlmErr` (purpose + reason +
|
|
226
|
-
* raw). The host wires `resilient_ok` → `succeed` and `resilient_err` → `fail`
|
|
227
|
-
* reducer arms (the doc-comment wiring), and folds the enriched payload into its
|
|
228
|
-
* own state there — llm-call never forces a Msg vocabulary on the host, and the
|
|
229
|
-
* settle Msg drives the inherited succeed/fail → backoff → onTimer loop instead
|
|
230
|
-
* of bypassing it.
|
|
231
|
-
*/
|
|
232
|
-
type LlmSucceedMsg<P extends string, O extends Record<P, unknown>> = SucceedMsg<LlmOk<P, O>>;
|
|
233
|
-
/**
|
|
234
|
-
* The FAILURE settle Msg (`resilient_err`) — resilient-call's `FailMsg` with its
|
|
235
|
-
* `error: unknown` narrowed to the typed `LlmErr`, so the host reducer reads the
|
|
236
|
-
* purpose, the reason and the raw payload without a cast.
|
|
237
|
-
*/
|
|
238
|
-
type LlmFailMsg<P extends string> = Omit<FailMsg, "error"> & {
|
|
239
|
-
readonly error: LlmErr<P>;
|
|
240
|
-
};
|
|
241
|
-
/** The retry / deadline timer Msg — `DeadlineExceeded`, inherited from resilient-call. */
|
|
242
|
-
type LlmTimerMsg = DeadlineExceeded;
|
|
243
|
-
/**
|
|
244
|
-
* The ports the LEGACY detached `handlers(ports)` form takes. Two outbound Msg
|
|
245
|
-
* builders the handler hands the typed Ok / Err; the consumer returns its own
|
|
246
|
-
* Msg (or `undefined`). KEPT only for `../agent`, which still inherits the
|
|
247
|
-
* detached shape; that path does NOT drive the retry loop (it dispatches the
|
|
248
|
-
* consumer's Msg directly and never re-enters the resilient settle Msg). New
|
|
249
|
-
* consumers use the no-arg `handlers()` form, which RETURNS the settle Msg for
|
|
250
|
-
* re-entry and drives the inherited succeed/fail → backoff → onTimer loop.
|
|
251
|
-
* `../agent` carries the same retry-loop gap and is fixed separately.
|
|
252
|
-
*
|
|
253
|
-
* The builders return `M | undefined` — `undefined` is the "dispatch nothing"
|
|
254
|
-
* sentinel the detached form checks (`!== undefined`), spelled as `undefined`
|
|
255
|
-
* rather than `void` so the union is unambiguous (a `void` member of a union is
|
|
256
|
-
* confusing and reads as "may return anything").
|
|
257
|
-
*/
|
|
258
|
-
interface LlmCallPorts<P extends string, O extends Record<P, unknown>, M> {
|
|
259
|
-
/** Build the Msg dispatched on a parsed success. Return `undefined` to dispatch nothing. */
|
|
260
|
-
readonly onOk: (ok: LlmOk<P, O>) => M | undefined;
|
|
261
|
-
/** Build the Msg dispatched on any failure (throw / retry-exhausted / parse). */
|
|
262
|
-
readonly onErr: (err: LlmErr<P>) => M | undefined;
|
|
263
|
-
}
|
|
264
|
-
/**
|
|
265
|
-
* The effect Cmd this module emits: run the LLM call for `key` with `input`. The
|
|
266
|
-
* `input` is the plain `LlmCall` request — the handler reads `purpose` /
|
|
267
|
-
* `model` / `payload` off it (invariant 3: Cmds are data).
|
|
268
|
-
*
|
|
269
|
-
* It is `../resilient-call`'s `RunCmd` specialized to the `LlmCall` input — NOT a
|
|
270
|
-
* re-declared shape — so the resilient verbs' return tuples (`[State, RunCmd[]]`)
|
|
271
|
-
* are this exact type and thread through `attempt` / `succeed` / `fail` /
|
|
272
|
-
* `onTimer` with no cast.
|
|
273
|
-
*/
|
|
274
|
-
type LlmRunCmd<P extends string> = RunCmd<LlmCall<P>>;
|
|
275
153
|
|
|
276
154
|
/**
|
|
277
155
|
* @demlik/tea/agent — the domain data model: the tool + turn shapes the consumer
|
|
@@ -1121,8 +999,8 @@ type CompactInterpret<M extends {
|
|
|
1121
999
|
*/
|
|
1122
1000
|
|
|
1123
1001
|
/**
|
|
1124
|
-
* The prefix a protocol discriminant was minted from: `
|
|
1125
|
-
* `
|
|
1002
|
+
* The prefix a protocol discriminant was minted from: `resilient_run_ok` →
|
|
1003
|
+
* `resilient_run`, `compact_run` → `compact`. A tool named by that prefix would
|
|
1126
1004
|
* mint the same `<name>_ok` / `<name>_err` the agent's reducer already owns.
|
|
1127
1005
|
*/
|
|
1128
1006
|
type SettlePrefixOf<T extends string> = T extends `${infer P}_ok` | `${infer P}_err` | `${infer P}_run` ? P : never;
|
|
@@ -1132,10 +1010,13 @@ declare const SNAPSHOT_WRITE_TYPE = "snapshot_write";
|
|
|
1132
1010
|
* A tool name `tool()` refuses. A tool's name is its Cmd `type` — so
|
|
1133
1011
|
* its interpret key — and the prefix of its settle Msgs, so every string
|
|
1134
1012
|
* already spoken by the protocol is taken twice over: the settle prefixes
|
|
1135
|
-
* (`
|
|
1013
|
+
* (`resilient_run`, `agent_tool`, `compact`) would overwrite the agent's own
|
|
1136
1014
|
* reducer handlers through `toMachine`'s last-wins spread, and the discriminants
|
|
1137
1015
|
* themselves (`compact_run`, `resilient_run`, …) would shadow the interpret
|
|
1138
|
-
* handler of that name.
|
|
1016
|
+
* handler of that name. `resilient` is reserved as a Cmd prefix — the part
|
|
1017
|
+
* before `_run` in the brain Cmd `resilient_run` — not as a settle prefix: its
|
|
1018
|
+
* `resilient_ok` / `resilient_err` name nothing the agent settles. Both halves
|
|
1019
|
+
* derive from `MsgType`: a new entry there
|
|
1139
1020
|
* reserves its name and its prefix with no second edit. The two names outside
|
|
1140
1021
|
* the protocol are the router's own `tool_rejected` and the checkpoint handler
|
|
1141
1022
|
* `snapshot_write`, which `toMachine` merges under the consumer's key.
|
|
@@ -1173,60 +1054,67 @@ type ToolThrown = {
|
|
|
1173
1054
|
* fixed to what the `ok` schema parses, so a value of the wrong shape is
|
|
1174
1055
|
* refused where it is written.
|
|
1175
1056
|
*/
|
|
1176
|
-
type ToolOk<Ok, E extends Tagged> = (value: Ok) =>
|
|
1057
|
+
type ToolOk<Ok, E extends Tagged> = (value: Ok) => Outcome<Ok, E>;
|
|
1177
1058
|
/**
|
|
1178
1059
|
* The typed failure constructor a handler receives: `fail({ _tag })` with `E`
|
|
1179
1060
|
* fixed to the declared tags, so the literal is checked against them where it
|
|
1180
1061
|
* is written. (A bare `{ _tag: "x" }` built elsewhere infers `_tag: string`
|
|
1181
1062
|
* and cannot be — the parameter type is what keeps it literal.)
|
|
1182
1063
|
*/
|
|
1183
|
-
type ToolFail<Ok, E extends Tagged> = (error: E) =>
|
|
1064
|
+
type ToolFail<Ok, E extends Tagged> = (error: E) => Outcome<Ok, E>;
|
|
1184
1065
|
/**
|
|
1185
1066
|
* The two constructors a handler is handed, one per channel — `ok` for the
|
|
1186
|
-
* value the `ok` schema parses, `fail` for a declared `{ _tag }`. Both
|
|
1187
|
-
*
|
|
1188
|
-
* underneath.
|
|
1067
|
+
* value the `ok` schema parses, `fail` for a declared `{ _tag }`. Both build
|
|
1068
|
+
* the core's `Outcome` record (ADR 0021).
|
|
1189
1069
|
*/
|
|
1190
1070
|
type ToolConstructors<Ok, E extends Tagged> = {
|
|
1191
1071
|
readonly ok: ToolOk<Ok, E>;
|
|
1192
1072
|
readonly fail: ToolFail<Ok, E>;
|
|
1193
1073
|
};
|
|
1194
1074
|
/**
|
|
1195
|
-
* A tool's handler: the parsed `args`, the
|
|
1196
|
-
* typed `{ ok, fail }`, to
|
|
1197
|
-
* the `ok` schema parses, `E` the declared `_tag` union. An undeclared
|
|
1198
|
-
* does not compile.
|
|
1075
|
+
* A tool's handler: the parsed `args`, the plain `ctx` the host handed `run`,
|
|
1076
|
+
* and the typed `{ ok, fail }`, to an outcome over the declared channels — `Ok`
|
|
1077
|
+
* is what the `ok` schema parses, `E` the declared `_tag` union. An undeclared
|
|
1078
|
+
* tag does not compile. `Ctx` is whatever the handler annotates its `ctx`
|
|
1079
|
+
* parameter with; tea does no dependency injection (ADR 0020).
|
|
1199
1080
|
*/
|
|
1200
|
-
type ToolHandler<Args, Ok, E extends Tagged,
|
|
1081
|
+
type ToolHandler<Args, Ok, E extends Tagged, Ctx> = (args: Args, ctx: Ctx & PortEmitter, settle: ToolConstructors<Ok, E>) => Promise<Outcome<Ok, E>>;
|
|
1201
1082
|
/**
|
|
1202
1083
|
* What `tool()` returns: the `Cmd.define`d constructor (so `Settled<typeof t>`
|
|
1203
1084
|
* / `CmdOf<typeof t>` read it like any def) plus the colocated `interpret` handler,
|
|
1204
1085
|
* the bare `args` schema the router parses a call against, and the
|
|
1205
1086
|
* `description` a provider adapter declares to the model beside that schema.
|
|
1206
1087
|
* `E` is the full failure union the Cmd settles with — the declared tags plus
|
|
1207
|
-
* `thrown`.
|
|
1088
|
+
* `thrown`. `Ctx` is the ctx the colocated handler reads — a fact about the
|
|
1089
|
+
* handler, never about the Cmd it builds (ADR 0020).
|
|
1208
1090
|
*/
|
|
1209
|
-
type ToolDef<Name extends string, Args, Ok, E extends Tagged,
|
|
1091
|
+
type ToolDef<Name extends string, Args, Ok, E extends Tagged, Ctx> = CmdDef<Name, ToolInput<Args>, Ok, E> & {
|
|
1210
1092
|
readonly description: string;
|
|
1211
|
-
readonly args:
|
|
1093
|
+
readonly args: StandardSchemaV1<unknown, Args>;
|
|
1212
1094
|
/**
|
|
1213
1095
|
* The timeout / retry knob this tool declared, or `null` when it declared
|
|
1214
1096
|
* neither. `toolRouter` serves it to the agent as `resilienceOf`.
|
|
1215
1097
|
*/
|
|
1216
1098
|
readonly resilience: ToolResilience | null;
|
|
1217
|
-
|
|
1099
|
+
/**
|
|
1100
|
+
* The colocated handler, as an interpret cell: it returns the tool's
|
|
1101
|
+
* outcome, and the engine mints `<name>_ok` / `<name>_err` from it.
|
|
1102
|
+
*/
|
|
1103
|
+
readonly interpret: (cmd: CmdValue<Name, ToolInput<Args>, Ok, E>, ctx: Ctx & PortEmitter) => Promise<Outcome<Ok, E>>;
|
|
1104
|
+
/** Phantom — the ctx the handler reads. Never assigned. */
|
|
1105
|
+
readonly __ctx?: Ctx;
|
|
1218
1106
|
};
|
|
1219
1107
|
/** The declaration-erased view the router reads. */
|
|
1220
1108
|
type AnyToolDef = AnyCmdDef & {
|
|
1221
1109
|
readonly description: string;
|
|
1222
|
-
readonly args:
|
|
1110
|
+
readonly args: StandardSchemaV1;
|
|
1223
1111
|
readonly resilience: ToolResilience | null;
|
|
1224
1112
|
readonly interpret: (cmd: never, ctx: never) => Promise<unknown>;
|
|
1225
1113
|
};
|
|
1226
1114
|
/**
|
|
1227
1115
|
* Declare one tool the model may call — its name, the schemas for its arguments
|
|
1228
1116
|
* and result, the failures it may return and the handler that runs it — and get
|
|
1229
|
-
* back a `Cmd<T,
|
|
1117
|
+
* back a `Cmd<T, Ok, E>` definition, whose `Ok` is what `ok` parses and whose `E`
|
|
1230
1118
|
* is the `err` tag union, that you pass to `toolRouter` or `defineAgent`.
|
|
1231
1119
|
*
|
|
1232
1120
|
* So a tool's two declared channels ARE the kernel's two typed effect channels
|
|
@@ -1240,9 +1128,10 @@ type AnyToolDef = AnyCmdDef & {
|
|
|
1240
1128
|
* `description`, OpenAI `function.description`) so the model can tell when to
|
|
1241
1129
|
* call the tool, read off `def.description`, never off the `input` schema;
|
|
1242
1130
|
* `input` parses the model's `args`; `ok` parses the handler's value at the
|
|
1243
|
-
* edge; `err` is the `_tag` list the handler may fail with
|
|
1244
|
-
*
|
|
1245
|
-
*
|
|
1131
|
+
* edge; `err` is the `_tag` list the handler may fail with. The handler reads
|
|
1132
|
+
* its services off the plain `ctx` `run` was handed — annotate its `ctx`
|
|
1133
|
+
* parameter and `defineAgent` asks for that ctx at `run`. The handler returns
|
|
1134
|
+
* one of the two constructors it is handed — `ok(value)` or the typed `fail({ _tag })`; a
|
|
1246
1135
|
* throw settles `<name>_err` — with the thrown `_tag` when it is a declared
|
|
1247
1136
|
* one, else as `{ _tag: "thrown", message }`.
|
|
1248
1137
|
*
|
|
@@ -1250,12 +1139,11 @@ type AnyToolDef = AnyCmdDef & {
|
|
|
1250
1139
|
* as a widened `string` throws — the same declaration-bug refusal
|
|
1251
1140
|
* `toolRouter` gives a name declared twice.
|
|
1252
1141
|
*/
|
|
1253
|
-
declare function tool<const Name extends string, Args, Ok, const Tags extends readonly string[],
|
|
1142
|
+
declare function tool<const Name extends string, Args, Ok, const Tags extends readonly string[], Ctx = unknown>(name: Name & NotReserved<Name>, spec: {
|
|
1254
1143
|
readonly description: string;
|
|
1255
|
-
readonly input:
|
|
1256
|
-
readonly ok:
|
|
1144
|
+
readonly input: StandardSchemaV1<unknown, Args>;
|
|
1145
|
+
readonly ok: StandardSchemaV1<unknown, Ok>;
|
|
1257
1146
|
readonly err: Tags;
|
|
1258
|
-
readonly requirements?: Requirements<R>;
|
|
1259
1147
|
/**
|
|
1260
1148
|
* The budget one call of this tool gets, in ms — the overall cap, measured
|
|
1261
1149
|
* from the first attempt and not restarted by a retry. When it elapses the
|
|
@@ -1275,7 +1163,7 @@ declare function tool<const Name extends string, Args, Ok, const Tags extends re
|
|
|
1275
1163
|
* Omit → the first failure is the outcome.
|
|
1276
1164
|
*/
|
|
1277
1165
|
readonly retry?: ToolResilience["retry"];
|
|
1278
|
-
}, handler: ToolHandler<Args, Ok, TaggedError<Tags[number]>,
|
|
1166
|
+
}, handler: ToolHandler<Args, Ok, TaggedError<Tags[number]>, Ctx>): ToolDef<Name, Args, Ok, TaggedError<Tags[number] | "thrown">, Ctx>;
|
|
1279
1167
|
/**
|
|
1280
1168
|
* A call the router could not hand to a tool: the model named a tool nobody
|
|
1281
1169
|
* declared, or its `args` failed the tool's `input` schema. `toolOf` is total —
|
|
@@ -1302,11 +1190,24 @@ declare const rejected: CmdDef<"tool_rejected", {
|
|
|
1302
1190
|
} | {
|
|
1303
1191
|
readonly [detail: string]: unknown;
|
|
1304
1192
|
readonly _tag: "malformed_args";
|
|
1305
|
-
}
|
|
1193
|
+
}>;
|
|
1306
1194
|
/** The Cmd `tool_rejected` builds — the router-owned variant of `ToolCmd`. */
|
|
1307
1195
|
type ToolRejectedCmd = CmdOf<typeof rejected>;
|
|
1308
1196
|
/** The Cmd union a router's `toolOf` produces — `TC` for `createAgent`. */
|
|
1309
1197
|
type ToolCmd<T extends AnyToolDef> = CmdOf<T> | ToolRejectedCmd;
|
|
1198
|
+
/** The ctx one tool's handler reads; `unknown` for a handler that reads none. */
|
|
1199
|
+
type ToolCtxOf<T> = T extends {
|
|
1200
|
+
readonly __ctx?: infer Ctx;
|
|
1201
|
+
} ? Ctx : unknown;
|
|
1202
|
+
type UnionToIntersection<U> = (U extends unknown ? (u: U) => void : never) extends (u: infer I) => void ? I : never;
|
|
1203
|
+
type ToolCtxBoxed<T> = T extends unknown ? [ToolCtxOf<T>] : never;
|
|
1204
|
+
type KnownToolCtx<B> = B extends [infer Ctx] ? unknown extends Ctx ? never : Ctx : never;
|
|
1205
|
+
/**
|
|
1206
|
+
* The ctx a tool set's handlers read, intersected — what `run` asks the host
|
|
1207
|
+
* for once the tools are wired into a machine. A tool whose handler reads
|
|
1208
|
+
* nothing leaves its siblings' demand intact.
|
|
1209
|
+
*/
|
|
1210
|
+
type ToolsCtx<T extends AnyToolDef> = UnionToIntersection<KnownToolCtx<ToolCtxBoxed<T>>>;
|
|
1310
1211
|
/** The settled Msg union a router's handlers return — folded by `toMachine`. */
|
|
1311
1212
|
type ToolMsg<T extends AnyToolDef> = Settled<T> | Settled<typeof rejected>;
|
|
1312
1213
|
/**
|
|
@@ -1355,7 +1256,7 @@ interface ToolRouter<T extends AnyToolDef> {
|
|
|
1355
1256
|
/** The `toolOf` for `createAgent`: total, pure, parses `args` at the edge. */
|
|
1356
1257
|
readonly toolOf: (call: ToolCall) => ToolCmd<T>;
|
|
1357
1258
|
/** One interpret handler per tool plus the `tool_rejected` handler. */
|
|
1358
|
-
readonly interpret: Interpret<ToolMsg<T>, ToolCmd<T>,
|
|
1259
|
+
readonly interpret: Interpret<ToolMsg<T>, ToolCmd<T>, ToolsCtx<T>>;
|
|
1359
1260
|
/**
|
|
1360
1261
|
* The timeout / retry knob the called tool declared — `AgentConfigCore`'s
|
|
1361
1262
|
* `toolResilienceOf` seam, filled from the `tool()` specs. `null` for a tool
|
|
@@ -1419,7 +1320,7 @@ declare function toolRouter<T extends AnyToolDef>(tools: readonly T[]): ToolRout
|
|
|
1419
1320
|
* the bare cells at the serial default, and a tool that never overlaps is the
|
|
1420
1321
|
* exact function `toolRouter` built.
|
|
1421
1322
|
*/
|
|
1422
|
-
declare function fanOutInterpret<T extends AnyToolDef>(interpret: Interpret<ToolMsg<T>, ToolCmd<T>,
|
|
1323
|
+
declare function fanOutInterpret<T extends AnyToolDef>(interpret: Interpret<ToolMsg<T>, ToolCmd<T>, ToolsCtx<T>>): Interpret<ToolMsg<T>, ToolCmd<T>, ToolsCtx<T>>;
|
|
1423
1324
|
/**
|
|
1424
1325
|
* Turn a tool failure into the human-readable reason string the conversation
|
|
1425
1326
|
* carries — pass the `{ _tag, ...detail }` a tool failed with, get the tag
|
|
@@ -1487,7 +1388,10 @@ type SnapshotInterpret<M extends {
|
|
|
1487
1388
|
readonly snapshot_write?: never;
|
|
1488
1389
|
};
|
|
1489
1390
|
/**
|
|
1490
|
-
* The `toMachine` signature
|
|
1391
|
+
* The `toMachine` signature. It returns a `Wired`: the machine and, beside it,
|
|
1392
|
+
* the merged `interpret` table and the `deadline` runner its one Sub needs — a
|
|
1393
|
+
* machine carries no handlers (#278, #279), so it is run as
|
|
1394
|
+
* `run(wired.machine, { ...wired, ctx })`. Parametrized on the `Snap` + `Compact` discriminants
|
|
1491
1395
|
* so the snapshotting / compaction overloads of `createAgent` hand back the right
|
|
1492
1396
|
* obligations. The `toolInterpret` requires (ON) or forbids (OFF) the
|
|
1493
1397
|
* `snapshot_write` handler via {@link SnapshotInterpret} and the `compact_run` handler
|
|
@@ -1503,11 +1407,16 @@ type SnapshotInterpret<M extends {
|
|
|
1503
1407
|
type AgentToMachine<Stage, P extends string, O extends Record<P, AgentTurn>, R, TC extends Cmd, Snap extends boolean, Compact extends boolean> = <Ctx = object, T extends AnyToolDef = never>(opts?: {
|
|
1504
1408
|
readonly tools?: ToolRouter<T>;
|
|
1505
1409
|
readonly toolInterpret?: Interpret<AgentMachineMsg<P, O, R> | WiredToolMsg<T>, Exclude<TC, WiredToolCmd<T>>, Ctx> & SnapshotInterpret<AgentMachineMsg<P, O, R> | WiredToolMsg<T>, Snap, Ctx> & CompactInterpret<AgentMachineMsg<P, O, R> | WiredToolMsg<T>, Compact, Ctx>;
|
|
1506
|
-
}) =>
|
|
1410
|
+
}) => {
|
|
1411
|
+
readonly machine: Machine<AgentState<Stage, P, O, R>, AgentMachineMsg<P, O, R> | WiredToolMsg<T>, AgentCmd<P, TC, Snap, Compact>, DeadlinesSub, Ctx & ToolsCtx<T>>;
|
|
1412
|
+
readonly interpret: Interpret<AgentMachineMsg<P, O, R> | WiredToolMsg<T>, AgentCmd<P, TC, Snap, Compact>, Ctx & ToolsCtx<T>>;
|
|
1413
|
+
readonly subscribe: Subscribe<AgentMachineMsg<P, O, R> | WiredToolMsg<T>, DeadlinesSub, Ctx & ToolsCtx<T>>;
|
|
1414
|
+
};
|
|
1507
1415
|
/**
|
|
1508
1416
|
* The agent handle `createAgent` returns — the uniform verb contract every tea
|
|
1509
|
-
* composition exposes, plus the wired `toMachine` and the
|
|
1510
|
-
*
|
|
1417
|
+
* composition exposes, plus the wired `toMachine` and `brainInterpret`, the
|
|
1418
|
+
* brain call's handler for a consumer wiring the verbs by hand. `Snap` flows
|
|
1419
|
+
* ONLY into `toMachine`'s `toolInterpret` obligation
|
|
1511
1420
|
* (the snapshot derivation); every verb is snapshot-agnostic. The model
|
|
1512
1421
|
* message shape `Msg` does not appear on the handle's surface (it is internal to the
|
|
1513
1422
|
* brain call's loader), so it is not a type parameter here — only `createAgent`
|
|
@@ -1537,12 +1446,10 @@ interface AgentKnob<Stage, P extends string, O extends Record<P, AgentTurn>, R,
|
|
|
1537
1446
|
at: number
|
|
1538
1447
|
]>;
|
|
1539
1448
|
readonly succeed: AgentVerb1<Stage, P, O, R, TC, [
|
|
1540
|
-
key: string,
|
|
1541
1449
|
msg: AgentLlmOkMsg<P, O>,
|
|
1542
1450
|
at: number
|
|
1543
1451
|
]>;
|
|
1544
1452
|
readonly fail: AgentVerb1<Stage, P, O, R, TC, [
|
|
1545
|
-
key: string,
|
|
1546
1453
|
msg: AgentLlmErrMsg<P>,
|
|
1547
1454
|
at: number
|
|
1548
1455
|
]>;
|
|
@@ -1563,15 +1470,23 @@ interface AgentKnob<Stage, P extends string, O extends Record<P, AgentTurn>, R,
|
|
|
1563
1470
|
readonly brainCall: (s: AgentState<Stage, P, O, R>) => LlmCall<P>;
|
|
1564
1471
|
readonly subs: (s: AgentState<Stage, P, O, R>) => readonly DeadlineSub[];
|
|
1565
1472
|
readonly toMachine: AgentToMachine<Stage, P, O, R, TC, Snap, Compact>;
|
|
1566
|
-
|
|
1473
|
+
/**
|
|
1474
|
+
* The brain call's `resilient_run` handler — the one `toMachine` wires. Its
|
|
1475
|
+
* Cmd is `Cmd.define`d, so it returns an outcome and the engine mints the
|
|
1476
|
+
* `resilient_run_ok` / `resilient_run_err` Msg that `succeed` / `fail` fold
|
|
1477
|
+
* (ADR 0021). List `AgentKnob`'s brain Cmd def in `cmds` when you hand-wire.
|
|
1478
|
+
*/
|
|
1479
|
+
readonly brainInterpret: () => Interpret<AgentLlmOkMsg<P, O> | AgentLlmErrMsg<P>, AgentLlmRunCmd<P>, unknown>;
|
|
1480
|
+
/** The brain call's `Cmd.define`d run Cmd def — list it in `cmds` when you hand-wire. */
|
|
1481
|
+
readonly brain: RunCmdDef<LlmCall<P>, LlmOk<P, O>>;
|
|
1567
1482
|
}
|
|
1568
1483
|
/** A verb taking the state + `Args`, returning the agent's `[State, Cmd[]]` tuple. */
|
|
1569
1484
|
type AgentVerb1<Stage, P extends string, O extends Record<P, AgentTurn>, R, TC extends Cmd, Args extends readonly unknown[]> = (s: AgentState<Stage, P, O, R>, ...args: Args) => readonly [AgentState<Stage, P, O, R>, readonly AgentCmd<P, TC>[]];
|
|
1570
1485
|
/** The brain-call SUCCESS settle Msg, inherited from `../llm-call`. */
|
|
1571
1486
|
type AgentLlmOkMsg<P extends string, O extends Record<P, unknown>> = LlmSucceedMsg<P, O>;
|
|
1572
1487
|
/**
|
|
1573
|
-
* The brain-call FAILURE settle Msg, inherited from `../llm-call` —
|
|
1574
|
-
* the agent's `fail` verb, which backs off via the retry ladder rather than
|
|
1488
|
+
* The brain-call FAILURE settle Msg, inherited from `../llm-call` — the engine
|
|
1489
|
+
* mints it from the brain handler's outcome and it drives the agent's `fail` verb, which backs off via the retry ladder rather than
|
|
1575
1490
|
* ending the run.
|
|
1576
1491
|
*/
|
|
1577
1492
|
type AgentLlmErrMsg<P extends string> = LlmFailMsg<P>;
|
|
@@ -1579,35 +1494,11 @@ type AgentLlmErrMsg<P extends string> = LlmFailMsg<P>;
|
|
|
1579
1494
|
* The timer Msg (retry + safety deadline) — `DeadlineExceeded`, the shared
|
|
1580
1495
|
* shape of both composed wrappers' timer Msgs (`LlmTimerMsg` and `MonitoredRunTimerMsg`
|
|
1581
1496
|
* are both `DeadlineExceeded`). One Msg variant covers both timers; `onTimer`
|
|
1582
|
-
* disambiguates by
|
|
1583
|
-
*
|
|
1497
|
+
* disambiguates by deadline id. This is also the machine Msg the
|
|
1498
|
+
* `subscribeDeadline` runner dispatches directly (no wrapping), matching the
|
|
1499
|
+
* sibling gold standard.
|
|
1584
1500
|
*/
|
|
1585
1501
|
type AgentTimerMsg = LlmTimerMsg;
|
|
1586
|
-
/** Ports the consumer supplies to the llm-call handler — re-exported shape. */
|
|
1587
|
-
type AgentPorts<P extends string, O extends Record<P, unknown>, M> = LlmCallPorts<P, O, M>;
|
|
1588
|
-
/**
|
|
1589
|
-
* The LEGACY detached brain-call handler dictionary `handlers(ports)` returns,
|
|
1590
|
-
* superseded by the `Interpret` table `AgentKnob.toMachine()` wires — reach for
|
|
1591
|
-
* `toMachine()` unless you are hand-wiring the verbs yourself.
|
|
1592
|
-
*
|
|
1593
|
-
* It is the inherited `../llm-call` detached form's exact shape, NOT an
|
|
1594
|
-
* `Interpret`.
|
|
1595
|
-
* The `resilient_run` handler runs the invoke inside `ctx.waitUntil` and dispatches
|
|
1596
|
-
* the consumer's `onOk` / `onErr` Msg directly (returning `void`), so it is a
|
|
1597
|
-
* fire-and-forget handler with a structural `{ waitUntil, dispatch }` ctx — it
|
|
1598
|
-
* does not re-enter the resilient settle Msg and so does not drive the retry
|
|
1599
|
-
* loop. Naming the type precisely (rather than laundering it through
|
|
1600
|
-
* `as unknown as Interpret<...>`) keeps `agent.unsafeDetachedHandlers(ports)` honest: the
|
|
1601
|
-
* consumer that wires the verbs by hand gets the real detached shape, and its
|
|
1602
|
-
* `resilient_run` is callable with a plain Cmd + a `{ waitUntil, dispatch }` ctx
|
|
1603
|
-
* with no `as never` at the call site.
|
|
1604
|
-
*/
|
|
1605
|
-
type AgentDetachedHandlers<P extends string, M> = {
|
|
1606
|
-
readonly resilient_run: (cmd: AgentLlmRunCmd<P>, ctx: {
|
|
1607
|
-
waitUntil(p: Promise<unknown>): void;
|
|
1608
|
-
dispatch(msg: M): unknown;
|
|
1609
|
-
}) => void;
|
|
1610
|
-
};
|
|
1611
1502
|
/** The Msg `do/host`'s `autoBoot` fires to re-enter the agent's `boot` verb on rehydrate. */
|
|
1612
1503
|
type AgentBootMsg = {
|
|
1613
1504
|
readonly type: typeof MsgType.AgentBoot;
|
|
@@ -1637,16 +1528,16 @@ declare function agentCancelMsg(at: number): AgentCancelMsg;
|
|
|
1637
1528
|
* The agent machine's Msg union — one variant per reducer entry point. A
|
|
1638
1529
|
* consumer using `toMachine` dispatches `agent_start` to begin and `agent_tool_ok`
|
|
1639
1530
|
* / `agent_tool_err` to route settled tools back; the brain-call settle Msgs
|
|
1640
|
-
* (`
|
|
1641
|
-
*
|
|
1642
|
-
*
|
|
1531
|
+
* (`resilient_run_ok` / `resilient_run_err`) are minted by the engine from the
|
|
1532
|
+
* outcome the FIXED `brainHandlers` returns (ADR 0021), driving `succeed` /
|
|
1533
|
+
* `fail`. Time enters via `at` on every variant — the
|
|
1643
1534
|
* reducer never reads the clock.
|
|
1644
1535
|
*
|
|
1645
1536
|
* There is deliberately NO `agent_turn` variant here. The wired loop folds a
|
|
1646
|
-
* model turn INSIDE `succeed` from the
|
|
1537
|
+
* model turn INSIDE `succeed` from the minted `resilient_run_ok` — a single
|
|
1647
1538
|
* settle Msg advances both the retry slice and the conversation (the L3 fix).
|
|
1648
1539
|
* Exposing `agent_turn` as a dispatchable Msg re-opened the stuck-`running` bug:
|
|
1649
|
-
* a hand-fed turn folds the conversation without ever
|
|
1540
|
+
* a hand-fed turn folds the conversation without ever settling `resilient_run_ok`,
|
|
1650
1541
|
* so `succeed` never runs and the resilient slice stays `running`. The
|
|
1651
1542
|
* `turn` verb remains on the handle for the consumer that wires the verbs by hand
|
|
1652
1543
|
* (manual wiring), but it is not part of the one wired machine's Msg surface.
|
|
@@ -1678,7 +1569,7 @@ type AgentMachineMsg<P extends string, O extends Record<P, unknown>, R> = {
|
|
|
1678
1569
|
* the retry plumbing is renamed.
|
|
1679
1570
|
*
|
|
1680
1571
|
* - `TurnSettled` — a brain turn settled (the model produced an `AgentTurn`).
|
|
1681
|
-
* Projected off the private `
|
|
1572
|
+
* Projected off the private `resilient_run_ok` settle Msg; carries the parsed
|
|
1682
1573
|
* `turn` (the narration + tool calls the model asked for).
|
|
1683
1574
|
* - `ToolSettled` — a tool call settled OK. Projected off the private
|
|
1684
1575
|
* `agent_tool_ok` Msg; carries the `callId` and the tool `result`.
|
|
@@ -1704,7 +1595,7 @@ type AgentEvent<R> = {
|
|
|
1704
1595
|
* `run(machine, { events: agentEvents() })` to light up `runtime.on(...)`.
|
|
1705
1596
|
*
|
|
1706
1597
|
* This is the ONE place the agent's PRIVATE Msg names are read: it maps
|
|
1707
|
-
* `
|
|
1598
|
+
* `resilient_run_ok` → `TurnSettled` and `agent_tool_ok` → `ToolSettled`, and reads
|
|
1708
1599
|
* the post-transition `run.phase` for `RunDone`. The mapping is total over the
|
|
1709
1600
|
* Msg union (a `default`-free switch on the discriminant) and returns `[]` for
|
|
1710
1601
|
* the transitions that carry no public event (start / boot / timer / the error
|
|
@@ -1712,7 +1603,7 @@ type AgentEvent<R> = {
|
|
|
1712
1603
|
*
|
|
1713
1604
|
* A single transition may emit more than one event: the brain turn that retires
|
|
1714
1605
|
* the final stage settles a turn (`TurnSettled`) AND finishes the run
|
|
1715
|
-
* (`RunDone`) — both are projected from that one `
|
|
1606
|
+
* (`RunDone`) — both are projected from that one `resilient_run_ok` transition.
|
|
1716
1607
|
* `RunDone` is gated on `run.phase === "done"`, which the wired loop reaches
|
|
1717
1608
|
* exactly once (the agent is terminal there and dispatches no further
|
|
1718
1609
|
* transition), so the event fires once per run.
|
|
@@ -1770,4 +1661,4 @@ declare function liftAgent<S extends {
|
|
|
1770
1661
|
agent: AgentState<Stage, P, O, R>;
|
|
1771
1662
|
}, Stage, P extends string, O extends Record<P, unknown>, R, C extends Cmd>(state: S, [slice, cmds]: readonly [AgentState<Stage, P, O, R>, readonly C[]]): readonly [S, readonly C[]];
|
|
1772
1663
|
|
|
1773
|
-
export { PLAIN_MODEL_MISROUTE_REASON as $, type AnyToolDef as A, type
|
|
1664
|
+
export { PLAIN_MODEL_MISROUTE_REASON as $, type AnyToolDef as A, type AgentStatus as B, type Conversation as C, type AgentTerminalFailure as D, type AgentTimerMsg as E, type AgentToMachine as F, type Awaiting as G, COMPACTION_PURPOSE as H, type CompactInterpret as I, type CompactionOutputs as J, type CompactionPurpose as K, type CompactionSummary as L, type Llm as M, type LlmCall as N, type LlmErr as O, type PlainModel as P, type LlmFailMsg as Q, type LlmOk as R, type StreamingModel as S, type ToolCall as T, type LlmRunCmd as U, type LlmSucceedMsg as V, type WiredToolMsg as W, type MessageLoader as X, type ModelFactory as Y, type ModelPort as Z, type ModelStream as _, type ToolOutcome as a, type ReservedToolName as a0, type Schema as a1, type SnapshotInterpret as a2, TOOL_RETRY_EXHAUSTED_TAG as a3, TOOL_TIMEOUT_TAG as a4, type TaggedFailure as a5, type ToolConstructors as a6, type ToolDef as a7, type ToolError as a8, type ToolFail as a9, liftAgent as aA, mergeInterpret as aB, plainModel as aC, status as aD, tool as aE, toolErrorReason as aF, toolRouter as aG, type ToolFailure as aa, type ToolHandler as ab, type ToolInput as ac, type ToolMsg as ad, type ToolOk as ae, type ToolRecord as af, type ToolRejectedCmd as ag, type ToolRejection as ah, type ToolResilience as ai, type ToolResilienceError as aj, type ToolRetryExhausted as ak, type ToolRouter as al, type ToolSettlement as am, type ToolThrown as an, type ToolTimedOut as ao, type WiredToolCmd as ap, agentBootMsg as aq, agentCancelMsg as ar, agentEvents as as, agentTurnSchema as at, compactionSummarySchema as au, fanOutInterpret as av, isAgentTurn as aw, isCompactionSummary as ax, isReservedToolName as ay, isStreamingModel as az, type AgentTurn as b, type AgentState as c, type ToolResult as d, type ToolFailureOf as e, type ToolsCtx as f, type AgentEvent as g, type TurnChunk as h, type AgentMachineMsg as i, type AgentCmd as j, type ToolCmd as k, type AgentConfigCore as l, type CompactionPolicy as m, type AgentKnob as n, type AgentBootMsg as o, type AgentCancelMsg as p, type AgentCompactErrMsg as q, type AgentCompactOkMsg as r, type AgentCompactRunCmd as s, type AgentCompactionConfig as t, type AgentConfig as u, type AgentFailure as v, type AgentLlmErrMsg as w, type AgentLlmOkMsg as x, type AgentLlmRunCmd as y, type AgentSnapshotConfig as z };
|