octaflow 0.31.0 → 0.33.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 +7 -0
- package/dist/ai/index.d.ts +267 -27
- package/dist/ai/index.js +412 -3
- package/dist/ai/providers/index.d.ts +1 -1
- package/dist/{core-DBqxBk3R.js → core-COMWflJl.js} +2 -0
- package/dist/{dispatcher-ClQMXA9E.d.ts → dispatcher-BQErUGy_.d.ts} +1 -1
- package/dist/{hooks-mWaAKHqn.d.ts → hooks-DHomzpiq.d.ts} +1 -1
- package/dist/{index-Du05Lnwr.d.ts → index-DZUO24Rz.d.ts} +28 -10
- package/dist/index.d.ts +5 -5
- package/dist/index.js +15 -7
- package/dist/{observability-CkC4FRCp.d.ts → observability-BLUEjdto.d.ts} +1 -1
- package/dist/pg-boss/index.d.ts +2 -2
- package/dist/postgres/index.d.ts +49 -2
- package/dist/postgres/index.js +54 -2
- package/dist/{provider-probe-l2Jmpuhr.d.ts → provider-probe-BDg4c1Rk.d.ts} +1 -1
- package/package.json +2 -1
- package/skills/add-a-case-loop/SKILL.md +136 -0
package/README.md
CHANGED
|
@@ -202,6 +202,7 @@ next to what your steps actually do.
|
|
|
202
202
|
| 💤 | **Durable sleep** — hold a step in the queue for N ms (survives restarts) |
|
|
203
203
|
| 🔀 | **Conditional branching** — `when` guards skip a step and its branch; `join: 'any'` converges |
|
|
204
204
|
| 🎯 | **Decisions** — typed choices with a confidence from a swappable decider (a function, a model, your own); below a threshold a person settles it |
|
|
205
|
+
| 🧭 | **Case loops** — `defineCaseLoop` (`octaflow/ai`): a manager agent chooses every next move of a case, each move its own workflow ending in the same tail (result → decide → next); policy refuses a choice with its reason inside the exit's schema, a move with a step that could fail is refused at definition time, and a manager that cannot decide closes the case for a person |
|
|
205
206
|
| ⏳ | **Deadlines** — a budget on a suspended step (fail, or continue with a stand-in answer) and on a whole run |
|
|
206
207
|
| ♻️ | **Retry a failed run** — `retryWorkflow` resumes from the failure point; completed steps keep their output |
|
|
207
208
|
| 🧹 | **Delete the runs about a record** — `purgeWorkflows({ entityRef })` cancels and deletes them with their sub-workflow runs and steps, for an erasure or a deleted record; refuses only while a step is executing |
|
|
@@ -254,6 +255,12 @@ pnpm add ai @ai-sdk/provider
|
|
|
254
255
|
a `schema`, and is meant to be pasted into your own migration system; `applySchema(pool, ddl)`
|
|
255
256
|
is the dev and test shortcut.
|
|
256
257
|
|
|
258
|
+
The stores, the gate and the event sink reach the database only through the `SqlExecutor` seam
|
|
259
|
+
(`query` plus a same-connection `transaction`). Three executors ship with it: `poolExecutor(pool)`
|
|
260
|
+
for `pg`, `postgresJsExecutor(sql)` for a postgres.js host (`transaction` is `sql.begin`), and
|
|
261
|
+
`pgliteExecutor(pglite)` for PGlite in tests. Wrap any of them to set row-level-security GUCs
|
|
262
|
+
first.
|
|
263
|
+
|
|
257
264
|
#### The Drizzle columns
|
|
258
265
|
|
|
259
266
|
The rule for every table-owning capability on the platform: `./postgres` ships the store over
|
package/dist/ai/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { M as TypedStepContext, N as TypedWorkflow, O as DefineStepConfig, St as Result, U as RetryPolicy, f as Decider, gt as JoinRule, j as TypedStep, xt as FlowErrorShape } from "../index-DZUO24Rz.js";
|
|
2
2
|
import { n as Logger } from "../logger-BCus3AOa.js";
|
|
3
|
-
import { i as BuildStepContextArgs, o as WorkflowHooks } from "../hooks-
|
|
3
|
+
import { i as BuildStepContextArgs, o as WorkflowHooks } from "../hooks-DHomzpiq.js";
|
|
4
4
|
import { C as isSubprocessorResidency, S as embeddingDimensionsFor, _ as EmbeddingProviderMeta, a as AiProcessingRegion, b as OpenAiCompatibleProviderId, c as AiProviderModelOption, d as AiVendorResidency, f as DEFAULT_AI_PROVIDER, g as EmbeddingProviderId, h as EMBEDDING_PROVIDER_IDS, i as AiEndpointResidency, l as AiResidencyError, m as EMBEDDING_PROVIDERS, n as AI_PROVIDER_IDS, o as AiProviderId, p as DEFAULT_EMBEDDING_PROVIDER, r as AiEndpointRegion, s as AiProviderMeta, t as AI_PROVIDERS, u as AiResidencyResult, v as OPENAI_COMPATIBLE_PROVIDER, w as resolveEndpointResidency, x as OpenAiCompatibleProviderMeta, y as OPENAI_COMPATIBLE_PROVIDER_ID } from "../provider-registry-C_mOfdHH.js";
|
|
5
|
-
import { A as maskKeys, C as ProviderErrorExplanation, D as explainProviderError, E as ProviderErrorPreset, O as isFatalProviderError, S as ProviderError, T as ProviderErrorPhrase, _ as ExplainProviderErrorOptions, a as OllamaProbeReport, b as PROVIDER_ERROR_REDACTED, c as ProviderProbeOptions, d as testProvider, f as CircuitBreaker, g as DEFAULT_PROVIDER_ERROR_DETAIL_LENGTH, h as withCircuitBreaker, i as OllamaProbeOptions, k as isProviderError, l as ProviderProbeReport, m as createCircuitBreaker, n as DEFAULT_PROVIDER_PROBE_PROMPT, o as ProbeableProvider, p as CircuitBreakerOptions, r as DEFAULT_PROVIDER_PROBE_TIMEOUT_MS, s as ProviderProbeFailure, t as DEFAULT_OLLAMA_PROBE_TIMEOUT_MS, u as testOllamaModel, v as FATAL_PROVIDER_ERROR_KEYS, w as ProviderErrorKey, x as PROVIDER_ERROR_STATUS, y as PROVIDER_ERROR_PHRASES } from "../provider-probe-
|
|
5
|
+
import { A as maskKeys, C as ProviderErrorExplanation, D as explainProviderError, E as ProviderErrorPreset, O as isFatalProviderError, S as ProviderError, T as ProviderErrorPhrase, _ as ExplainProviderErrorOptions, a as OllamaProbeReport, b as PROVIDER_ERROR_REDACTED, c as ProviderProbeOptions, d as testProvider, f as CircuitBreaker, g as DEFAULT_PROVIDER_ERROR_DETAIL_LENGTH, h as withCircuitBreaker, i as OllamaProbeOptions, k as isProviderError, l as ProviderProbeReport, m as createCircuitBreaker, n as DEFAULT_PROVIDER_PROBE_PROMPT, o as ProbeableProvider, p as CircuitBreakerOptions, r as DEFAULT_PROVIDER_PROBE_TIMEOUT_MS, s as ProviderProbeFailure, t as DEFAULT_OLLAMA_PROBE_TIMEOUT_MS, u as testOllamaModel, v as FATAL_PROVIDER_ERROR_KEYS, w as ProviderErrorKey, x as PROVIDER_ERROR_STATUS, y as PROVIDER_ERROR_PHRASES } from "../provider-probe-BDg4c1Rk.js";
|
|
6
6
|
import { z } from "zod";
|
|
7
|
+
import { ToolSet } from "ai";
|
|
7
8
|
import { EmbeddingModelV4, LanguageModelV4, LanguageModelV4Usage, SharedV4ProviderMetadata } from "@ai-sdk/provider";
|
|
8
9
|
//#region src/ai/instrumented-model.d.ts
|
|
9
10
|
export interface AccumulatedUsage {
|
|
@@ -125,35 +126,18 @@ export interface AiContext<THost = unknown> {
|
|
|
125
126
|
//#region src/ai/define-ai-step.d.ts
|
|
126
127
|
/** An AI workflow step — a flow-core `TypedStep` whose context is an `AiContext`. */
|
|
127
128
|
export type AiTypedStep<TInput extends Record<string, unknown> = Record<string, unknown>, TOutput extends Record<string, unknown> = Record<string, unknown>, THost = unknown, TDeps extends Record<string, TypedStep<any, any, any, AiContext<THost>>> = {}> = TypedStep<TInput, TOutput, TDeps, AiContext<THost>>;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
/** Optional retry policy (max attempts, backoff) — e.g. for provider 429s. */
|
|
135
|
-
retry?: RetryPolicy;
|
|
136
|
-
/** Optional per-step wall-clock timeout in ms. */
|
|
137
|
-
timeoutMs?: number;
|
|
138
|
-
/** Optional durable start delay in ms — held in the queue once the step is ready. */
|
|
139
|
-
delayMs?: number;
|
|
140
|
-
/**
|
|
141
|
-
* What a terminal failure does — see `defineStep`'s `onFailure`. `{ output }`
|
|
142
|
-
* completes the step with a stand-in and the DAG carries on; the model's
|
|
143
|
-
* refusal or outage then costs one section of the result, not the run.
|
|
144
|
-
*/
|
|
145
|
-
onFailure?: 'fail' | {
|
|
146
|
-
output: TOutput;
|
|
147
|
-
};
|
|
148
|
-
/** Resources the step draws on (the model, a vendor), for the admission gate — see `defineStep`. */
|
|
149
|
-
resources?: readonly string[];
|
|
150
|
-
}
|
|
129
|
+
/**
|
|
130
|
+
* `defineStep`'s config with the handler context fixed to `AiContext<THost>` —
|
|
131
|
+
* every option a step has (`when`, `join`, heartbeats, `onFailure`, …), so an
|
|
132
|
+
* AI step branches and converges like any other.
|
|
133
|
+
*/
|
|
134
|
+
export type DefineAiStepConfig<TInput extends Record<string, unknown>, TOutput extends Record<string, unknown>, THost, TDeps extends Record<string, TypedStep<any, any, any, AiContext<THost>>>, TJoin extends JoinRule = 'all'> = DefineStepConfig<TInput, TOutput, TDeps, AiContext<THost>, TJoin>;
|
|
151
135
|
/**
|
|
152
136
|
* Define a type-safe AI workflow step. Identical to flow-core's `defineStep`
|
|
153
137
|
* except the handler context is fixed to `AiContext<THost>`, so handlers get a
|
|
154
138
|
* ready-to-use `ctx.context.model` (instrumented) and `ctx.context.host`.
|
|
155
139
|
*/
|
|
156
|
-
export declare function defineAiStep<TInput extends Record<string, unknown>, TOutput extends Record<string, unknown>, THost = unknown, TDeps extends Record<string, TypedStep<any, any, any, AiContext<THost>>> = {}>(config: DefineAiStepConfig<TInput, TOutput, THost, TDeps>): AiTypedStep<TInput, TOutput, THost, TDeps>;
|
|
140
|
+
export declare function defineAiStep<TInput extends Record<string, unknown>, TOutput extends Record<string, unknown>, THost = unknown, TDeps extends Record<string, TypedStep<any, any, any, AiContext<THost>>> = {}, TJoin extends JoinRule = 'all'>(config: DefineAiStepConfig<TInput, TOutput, THost, TDeps, TJoin>): AiTypedStep<TInput, TOutput, THost, TDeps>;
|
|
157
141
|
/** Build a typed AI workflow from `defineAiStep` definitions. */
|
|
158
142
|
export declare function buildAiWorkflow<TInput extends Record<string, unknown>, THost = unknown, TSteps extends Record<string, TypedStep<any, any, any, AiContext<THost>>> = {}>(config: {
|
|
159
143
|
type: string;
|
|
@@ -186,6 +170,114 @@ export interface ModelDeciderOptions {
|
|
|
186
170
|
*/
|
|
187
171
|
export declare function createModelDecider<THost = unknown>(options?: ModelDeciderOptions): Decider<AiContext<THost>>;
|
|
188
172
|
//#endregion
|
|
173
|
+
//#region src/ai/agent.d.ts
|
|
174
|
+
/** What one agent run did — persisted with the answer, never parsed. */
|
|
175
|
+
export interface AgentTrace {
|
|
176
|
+
/** Model calls the loop made. */
|
|
177
|
+
rounds: number;
|
|
178
|
+
/** Tool names in the order they were called, the exit last. */
|
|
179
|
+
toolCalls: string[];
|
|
180
|
+
/** Input + output tokens across all rounds. */
|
|
181
|
+
tokens: number;
|
|
182
|
+
}
|
|
183
|
+
/** One way out of an agent: the model ends the run by calling it, and its arguments are the value. */
|
|
184
|
+
export interface AgentExit<T = unknown> {
|
|
185
|
+
description: string;
|
|
186
|
+
schema: z.ZodType<T>;
|
|
187
|
+
}
|
|
188
|
+
export type AgentExits = Record<string, AgentExit<any>>;
|
|
189
|
+
/** The exit an agent took, typed by its name. */
|
|
190
|
+
export type AgentExitTaken<TExits extends AgentExits> = { [K in keyof TExits & string]: {
|
|
191
|
+
exit: K;
|
|
192
|
+
value: TExits[K] extends AgentExit<infer T> ? T : never;
|
|
193
|
+
}; }[keyof TExits & string];
|
|
194
|
+
interface AgentLimits {
|
|
195
|
+
/** The model — in a step, `ctx.context.model`, so usage lands on the step. */
|
|
196
|
+
model: LanguageModelV4;
|
|
197
|
+
system: string;
|
|
198
|
+
prompt: string;
|
|
199
|
+
/** The tools the agent works with. Their names must not collide with an exit's. */
|
|
200
|
+
tools?: ToolSet;
|
|
201
|
+
/** Most model calls before the run gives up. Default 8. */
|
|
202
|
+
maxRounds?: number;
|
|
203
|
+
/** Most input + output tokens before the run gives up. Default: no cap. */
|
|
204
|
+
maxTokens?: number;
|
|
205
|
+
/**
|
|
206
|
+
* Most output tokens per model call, passed to the AI SDK. Default: the
|
|
207
|
+
* provider's — which on a local server can be small enough to cut a
|
|
208
|
+
* thinking model off before it calls anything.
|
|
209
|
+
*/
|
|
210
|
+
maxOutputTokens?: number;
|
|
211
|
+
/** Called after every round; `false` stops the run — pass the step's `heartbeat`. */
|
|
212
|
+
heartbeat?: () => Promise<boolean>;
|
|
213
|
+
abortSignal?: AbortSignal;
|
|
214
|
+
/** Passed to the AI SDK. Default 0 — the step's retry policy owns retries. */
|
|
215
|
+
maxRetries?: number;
|
|
216
|
+
}
|
|
217
|
+
export interface RunAgentToExitOptions<TExits extends AgentExits> extends AgentLimits {
|
|
218
|
+
exits: TExits;
|
|
219
|
+
}
|
|
220
|
+
export interface RunAgentOptions<TOutput> extends AgentLimits {
|
|
221
|
+
/** The answer's shape — the arguments of the one exit, `answer`. */
|
|
222
|
+
output: z.ZodType<TOutput>;
|
|
223
|
+
}
|
|
224
|
+
export interface AgentRun<TOutput> {
|
|
225
|
+
output: TOutput;
|
|
226
|
+
trace: AgentTrace;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Run one agent until it takes one of `exits`, or fails. Stopping on a limit
|
|
230
|
+
* before an exit is not retryable — the same budget would stop the same way —
|
|
231
|
+
* so the step fails, or takes its `onFailure` stand-in.
|
|
232
|
+
*/
|
|
233
|
+
export declare function runAgentToExit<TExits extends AgentExits>(options: RunAgentToExitOptions<TExits>): Promise<AgentExitTaken<TExits> & {
|
|
234
|
+
trace: AgentTrace;
|
|
235
|
+
}>;
|
|
236
|
+
/** Run one agent to a typed answer: `runAgentToExit` with the single exit `answer`. */
|
|
237
|
+
export declare function runAgent<TOutput>(options: RunAgentOptions<TOutput>): Promise<AgentRun<TOutput>>;
|
|
238
|
+
/** The trace as a schema — for a step output that carries one. */
|
|
239
|
+
export declare const AGENT_TRACE_SCHEMA: z.ZodObject<{
|
|
240
|
+
rounds: z.ZodNumber;
|
|
241
|
+
toolCalls: z.ZodArray<z.ZodString>;
|
|
242
|
+
tokens: z.ZodNumber;
|
|
243
|
+
}, z.core.$strip>;
|
|
244
|
+
interface DefineAgentStepConfig<TInput extends Record<string, unknown>, TAnswer extends Record<string, unknown>, THost, TDeps extends Record<string, TypedStep<any, any, any, AiContext<THost>>>> {
|
|
245
|
+
type: string;
|
|
246
|
+
workflowInputSchema: z.ZodType<TInput>;
|
|
247
|
+
/** The answer's shape — the step outputs `{ answer, trace }`. */
|
|
248
|
+
answerSchema: z.ZodType<TAnswer>;
|
|
249
|
+
dependencies?: TDeps;
|
|
250
|
+
system: string;
|
|
251
|
+
/** The task, built from the workflow input and the dependencies' outputs. */
|
|
252
|
+
prompt: (ctx: TypedStepContext<TInput, TDeps, AiContext<THost>>) => string;
|
|
253
|
+
tools?: (ctx: TypedStepContext<TInput, TDeps, AiContext<THost>>) => ToolSet;
|
|
254
|
+
maxRounds?: number;
|
|
255
|
+
maxTokens?: number;
|
|
256
|
+
maxOutputTokens?: number;
|
|
257
|
+
retry?: RetryPolicy;
|
|
258
|
+
timeoutMs?: number;
|
|
259
|
+
/** See `defineStep`'s `heartbeatTimeoutMs` — every round beats. */
|
|
260
|
+
heartbeatTimeoutMs?: number;
|
|
261
|
+
/** See `defineStep`'s `onFailure`. */
|
|
262
|
+
onFailure?: 'fail' | {
|
|
263
|
+
output: {
|
|
264
|
+
answer: TAnswer;
|
|
265
|
+
trace: AgentTrace;
|
|
266
|
+
};
|
|
267
|
+
};
|
|
268
|
+
resources?: readonly string[];
|
|
269
|
+
when?: (ctx: TypedStepContext<TInput, TDeps, AiContext<THost>>) => boolean | Promise<boolean>;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* A step that runs one agent on the step's instrumented model. Its output is
|
|
273
|
+
* `{ answer, trace }`: dependents read `ctx.deps.<key>.answer`, and the trace
|
|
274
|
+
* stays on the run for whoever reads it back.
|
|
275
|
+
*/
|
|
276
|
+
export declare function defineAgentStep<TInput extends Record<string, unknown>, TAnswer extends Record<string, unknown>, THost = unknown, TDeps extends Record<string, TypedStep<any, any, any, AiContext<THost>>> = {}>(config: DefineAgentStepConfig<TInput, TAnswer, THost, TDeps>): TypedStep<TInput, {
|
|
277
|
+
answer: TAnswer;
|
|
278
|
+
trace: AgentTrace;
|
|
279
|
+
}, TDeps, AiContext<THost>>;
|
|
280
|
+
//#endregion
|
|
189
281
|
//#region src/ai/hooks.d.ts
|
|
190
282
|
export interface AiModelResolver<THost = unknown> {
|
|
191
283
|
/** Resolve the base (uninstrumented) model for a step. */
|
|
@@ -774,4 +866,152 @@ export declare function withJsonRepair(model: LanguageModelV4, options?: JsonRep
|
|
|
774
866
|
*/
|
|
775
867
|
export declare function addUsage(a: LanguageModelV4Usage, b: LanguageModelV4Usage): LanguageModelV4Usage;
|
|
776
868
|
//#endregion
|
|
869
|
+
//#region src/ai/case-loop.d.ts
|
|
870
|
+
/** What a move leaves for the manager: a summary, and an outcome when the move itself ends the case. */
|
|
871
|
+
export type CaseMoveResult<TOutcome extends string, TResult extends Record<string, unknown>> = TResult & {
|
|
872
|
+
summary: string;
|
|
873
|
+
closes?: TOutcome;
|
|
874
|
+
};
|
|
875
|
+
/** One finished move, as the next moves see it. */
|
|
876
|
+
export interface CaseMoveRecord<TMove extends string, TOutcome extends string, TResult extends Record<string, unknown>> {
|
|
877
|
+
no: number;
|
|
878
|
+
move: TMove;
|
|
879
|
+
/** The manager's reason for it — its exit's `why`, when the exit has one. */
|
|
880
|
+
why: string;
|
|
881
|
+
result: CaseMoveResult<TOutcome, TResult>;
|
|
882
|
+
}
|
|
883
|
+
/** A move's input: the case's own fields, plus where the case stands. */
|
|
884
|
+
export type CaseMoveInput<TMove extends string, TOutcome extends string, TCase extends Record<string, unknown>, TResult extends Record<string, unknown>> = TCase & {
|
|
885
|
+
caseId: string;
|
|
886
|
+
move: TMove;
|
|
887
|
+
/** 1 for the first move. */
|
|
888
|
+
moveNo: number;
|
|
889
|
+
/** The manager's arguments for this move — its exit's value. */
|
|
890
|
+
brief: Record<string, any>;
|
|
891
|
+
moves: CaseMoveRecord<TMove, TOutcome, TResult>[];
|
|
892
|
+
startedAt: string;
|
|
893
|
+
};
|
|
894
|
+
/** The manager's choice, as `decide` outputs it. `stuck` when it could not choose within its limits. */
|
|
895
|
+
export type CaseDecision<TExit extends string = string> = {
|
|
896
|
+
exit: TExit | 'stuck';
|
|
897
|
+
value: Record<string, any>;
|
|
898
|
+
/** Choices the policy refused on the way, each with its reason, de-duplicated. */
|
|
899
|
+
refusals: Array<{
|
|
900
|
+
choice: string;
|
|
901
|
+
reason: string;
|
|
902
|
+
}>;
|
|
903
|
+
trace: AgentTrace;
|
|
904
|
+
};
|
|
905
|
+
/** What `next` did: the case's outcome, or `continued` with the run it started. */
|
|
906
|
+
export type CaseNext<TOutcome extends string = string> = {
|
|
907
|
+
outcome: TOutcome | 'continued';
|
|
908
|
+
detail: string;
|
|
909
|
+
nextWorkflowId?: number;
|
|
910
|
+
};
|
|
911
|
+
type Ctx<THost> = AiContext<THost>;
|
|
912
|
+
type AnyStep<THost> = TypedStep<any, any, any, Ctx<THost>>;
|
|
913
|
+
export interface CaseLoopConfig<TMove extends string, TOutcome extends string, TCase extends Record<string, unknown>, TResult extends Record<string, unknown>, TDecisions extends AgentExits, TFacts, THost> {
|
|
914
|
+
/** Prefix of every workflow and step type: move `write` runs as `<name>:write`, its tail as `<name>:write:decide`. */
|
|
915
|
+
name: string;
|
|
916
|
+
moves: readonly [TMove, ...TMove[]];
|
|
917
|
+
/** The case's own fields, carried by every move. */
|
|
918
|
+
case: z.ZodType<TCase>;
|
|
919
|
+
/** The move result's own fields, beside `summary` and `closes`. */
|
|
920
|
+
result: z.ZodType<TResult>;
|
|
921
|
+
/** What a result step that failed stands in with — `summary` says it failed. */
|
|
922
|
+
failedResult: TResult;
|
|
923
|
+
outcomes: readonly [TOutcome, ...TOutcome[]];
|
|
924
|
+
/** The outcome of a case whose manager could not decide — a person takes it over. */
|
|
925
|
+
stuck: NoInfer<TOutcome>;
|
|
926
|
+
/** The exits the manager may take. An exit named after a move starts it; any other must be in `closers`. */
|
|
927
|
+
decisions: TDecisions;
|
|
928
|
+
/** The exits that close the case, each turning its value into the outcome. */
|
|
929
|
+
closers?: { [K in keyof TDecisions & string]?: (value: any) => {
|
|
930
|
+
outcome: NoInfer<TOutcome>;
|
|
931
|
+
detail: string;
|
|
932
|
+
}; };
|
|
933
|
+
/** The facts the policy is checked against, read once per decision — the move's own result included. */
|
|
934
|
+
facts: (ctx: TypedStepContext<CaseMoveInput<TMove, TOutcome, TCase, TResult>, any, Ctx<THost>>, result: CaseMoveResult<TOutcome, TResult>) => Promise<TFacts> | TFacts;
|
|
935
|
+
/** The policy on one choice: a reason refuses it. */
|
|
936
|
+
refuse?: (choice: keyof TDecisions & string, value: any, facts: TFacts, input: CaseMoveInput<TMove, TOutcome, TCase, TResult>) => string | null;
|
|
937
|
+
/** The most moves a case takes; from the last one on, only `atLimit` is allowed. */
|
|
938
|
+
maxMoves: number;
|
|
939
|
+
atLimit: ReadonlyArray<keyof TDecisions & string>;
|
|
940
|
+
manager: {
|
|
941
|
+
system: string;
|
|
942
|
+
/** The case file the manager decides on. */
|
|
943
|
+
prompt: (ctx: TypedStepContext<CaseMoveInput<TMove, TOutcome, TCase, TResult>, any, Ctx<THost>>, result: CaseMoveResult<TOutcome, TResult>, facts: TFacts) => string;
|
|
944
|
+
/** Read-only tools: the manager looks things up and chooses — the moves do the work. */
|
|
945
|
+
tools?: (ctx: TypedStepContext<CaseMoveInput<TMove, TOutcome, TCase, TResult>, any, Ctx<THost>>) => ToolSet;
|
|
946
|
+
maxRounds?: number;
|
|
947
|
+
maxTokens?: number;
|
|
948
|
+
maxOutputTokens?: number;
|
|
949
|
+
resources?: readonly string[];
|
|
950
|
+
retry?: RetryPolicy;
|
|
951
|
+
heartbeatTimeoutMs?: number;
|
|
952
|
+
/** The `detail` of a case closed as `stuck`. */
|
|
953
|
+
stuckDetail?: string;
|
|
954
|
+
};
|
|
955
|
+
startMove: (host: THost, input: CaseMoveInput<TMove, TOutcome, TCase, TResult>) => Promise<number>;
|
|
956
|
+
closeCase: (host: THost, closed: {
|
|
957
|
+
caseId: string;
|
|
958
|
+
outcome: TOutcome;
|
|
959
|
+
detail: string;
|
|
960
|
+
}) => Promise<void>;
|
|
961
|
+
}
|
|
962
|
+
export interface CaseMoveConfig<TMove extends string, TOutcome extends string, TCase extends Record<string, unknown>, TResult extends Record<string, unknown>, THost> {
|
|
963
|
+
/** The move's own steps, by key. `result`, `decide` and `next` are the tail's. */
|
|
964
|
+
steps: Record<string, AnyStep<THost>>;
|
|
965
|
+
/** The steps `result` reads — it runs once any of them completed and the others stopped. */
|
|
966
|
+
ends: Record<string, AnyStep<THost>>;
|
|
967
|
+
/** What the move achieved. `deps` holds the outputs of the `ends` that completed. */
|
|
968
|
+
summarize: (ctx: Omit<TypedStepContext<CaseMoveInput<TMove, TOutcome, TCase, TResult>, {}, Ctx<THost>>, 'deps'> & {
|
|
969
|
+
deps: Record<string, any>;
|
|
970
|
+
}) => Promise<CaseMoveResult<TOutcome, TResult>> | CaseMoveResult<TOutcome, TResult>;
|
|
971
|
+
}
|
|
972
|
+
export interface CaseLoop<TMove extends string, TOutcome extends string, TCase extends Record<string, unknown>, TResult extends Record<string, unknown>, TDecisions extends AgentExits, TFacts, THost> {
|
|
973
|
+
readonly name: string;
|
|
974
|
+
readonly inputSchema: z.ZodType<CaseMoveInput<TMove, TOutcome, TCase, TResult>>;
|
|
975
|
+
readonly resultSchema: z.ZodType<CaseMoveResult<TOutcome, TResult>>;
|
|
976
|
+
readonly decisionSchema: z.ZodType<CaseDecision<keyof TDecisions & string>>;
|
|
977
|
+
/** One move as its own workflow: its steps, then the tail. Throws on a step that can end in failure. */
|
|
978
|
+
move(name: TMove, config: CaseMoveConfig<TMove, TOutcome, TCase, TResult, THost>): TypedWorkflow<CaseMoveInput<TMove, TOutcome, TCase, TResult>, Ctx<THost>>;
|
|
979
|
+
/** The policy on one choice, with the move ceiling — what `decide` holds the manager to, for a page that shows it. */
|
|
980
|
+
refusal(choice: keyof TDecisions & string, value: unknown, facts: TFacts, input: CaseMoveInput<TMove, TOutcome, TCase, TResult>): string | null;
|
|
981
|
+
/** The input of a case's first move. */
|
|
982
|
+
first(fields: TCase & {
|
|
983
|
+
caseId: string;
|
|
984
|
+
move: TMove;
|
|
985
|
+
brief?: Record<string, any>;
|
|
986
|
+
startedAt?: string;
|
|
987
|
+
}): CaseMoveInput<TMove, TOutcome, TCase, TResult>;
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* Define a case loop: a manager agent that chooses every next move, each move
|
|
991
|
+
* its own workflow ending in the same tail — see the module comment.
|
|
992
|
+
*
|
|
993
|
+
* ```ts
|
|
994
|
+
* const loop = defineCaseLoop({
|
|
995
|
+
* name: 'move',
|
|
996
|
+
* moves: ['open', 'investigate', 'write', 'wait'],
|
|
997
|
+
* case: z.object({ invoice: z.string() }),
|
|
998
|
+
* result: z.object({ mailSent: z.boolean() }),
|
|
999
|
+
* failedResult: { mailSent: false },
|
|
1000
|
+
* outcomes: ['paid', 'unresolved'],
|
|
1001
|
+
* stuck: 'unresolved',
|
|
1002
|
+
* decisions: { investigate: …, write: …, wait: …, close: … },
|
|
1003
|
+
* closers: { close: (v) => ({ outcome: 'paid', detail: v.summary }) },
|
|
1004
|
+
* facts: async (ctx) => readBooks(ctx.workflowInput.caseId),
|
|
1005
|
+
* refuse: (choice, value, facts) => (choice === 'close' && facts.balance > 0 ? 'The balance is open.' : null),
|
|
1006
|
+
* maxMoves: 12,
|
|
1007
|
+
* atLimit: ['close'],
|
|
1008
|
+
* manager: { system: '…', prompt: (ctx, result) => caseFile(ctx.workflowInput, result) },
|
|
1009
|
+
* startMove: (host, input) => host.startMove(input),
|
|
1010
|
+
* closeCase: (host, c) => host.cases.close(c.caseId, c.outcome, c.detail),
|
|
1011
|
+
* });
|
|
1012
|
+
* const write = loop.move('write', { steps: { compose, approval, send }, ends: { approval, send }, summarize });
|
|
1013
|
+
* ```
|
|
1014
|
+
*/
|
|
1015
|
+
export declare function defineCaseLoop<const TMove extends string, const TOutcome extends string, TCase extends Record<string, unknown>, TResult extends Record<string, unknown>, TDecisions extends AgentExits, TFacts, THost = any>(config: CaseLoopConfig<TMove, TOutcome, TCase, TResult, TDecisions, TFacts, THost>): CaseLoop<TMove, TOutcome, TCase, TResult, TDecisions, TFacts, THost>;
|
|
1016
|
+
//#endregion
|
|
777
1017
|
export { AI_PROVIDERS, AI_PROVIDER_IDS, AiEndpointRegion, AiEndpointResidency, AiProcessingRegion, AiProviderId, AiProviderMeta, AiProviderModelOption, AiResidencyError, AiResidencyResult, AiVendorResidency, CircuitBreaker, CircuitBreakerOptions, DEFAULT_AI_PROVIDER, DEFAULT_EMBEDDING_PROVIDER, DEFAULT_OLLAMA_PROBE_TIMEOUT_MS, DEFAULT_PROVIDER_ERROR_DETAIL_LENGTH, DEFAULT_PROVIDER_PROBE_PROMPT, DEFAULT_PROVIDER_PROBE_TIMEOUT_MS, EMBEDDING_PROVIDERS, EMBEDDING_PROVIDER_IDS, EmbeddingProviderId, EmbeddingProviderMeta, ExplainProviderErrorOptions, FATAL_PROVIDER_ERROR_KEYS, OPENAI_COMPATIBLE_PROVIDER, OPENAI_COMPATIBLE_PROVIDER_ID, OllamaProbeOptions, OllamaProbeReport, OpenAiCompatibleProviderId, OpenAiCompatibleProviderMeta, PROVIDER_ERROR_PHRASES, PROVIDER_ERROR_REDACTED, PROVIDER_ERROR_STATUS, ProbeableProvider, ProviderError, ProviderErrorExplanation, ProviderErrorKey, ProviderErrorPhrase, ProviderErrorPreset, ProviderProbeFailure, ProviderProbeOptions, ProviderProbeReport, createCircuitBreaker, embeddingDimensionsFor, explainProviderError, isFatalProviderError, isProviderError, isSubprocessorResidency, maskKeys, resolveEndpointResidency, testOllamaModel, testProvider, withCircuitBreaker };
|