@falai/agent 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/core/Agent.d.ts +1 -1
- package/dist/cjs/core/Agent.js +3 -3
- package/dist/cjs/core/Agent.js.map +1 -1
- package/dist/cjs/core/AutoChainExecutor.d.ts +2 -2
- package/dist/cjs/core/AutoChainExecutor.js +2 -2
- package/dist/cjs/core/AutoChainExecutor.js.map +1 -1
- package/dist/cjs/core/PromptComposer.d.ts +1 -1
- package/dist/cjs/core/PromptComposer.js +2 -2
- package/dist/cjs/core/PromptComposer.js.map +1 -1
- package/dist/cjs/core/ResponseEngine.d.ts +1 -1
- package/dist/cjs/core/ResponseModal.js +6 -6
- package/dist/cjs/core/ResponseModal.js.map +1 -1
- package/dist/cjs/core/ResponsePipeline.d.ts +2 -2
- package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/cjs/core/ResponsePipeline.js.map +1 -1
- package/dist/cjs/core/SignalProcessor.d.ts +3 -3
- package/dist/cjs/core/SignalProcessor.d.ts.map +1 -1
- package/dist/cjs/core/SignalProcessor.js +1 -1
- package/dist/cjs/core/SignalProcessor.js.map +1 -1
- package/dist/cjs/core/Step.d.ts +1 -1
- package/dist/cjs/core/Step.js +1 -1
- package/dist/cjs/core/ToolManager.d.ts +1 -1
- package/dist/cjs/core/ToolManager.js +1 -1
- package/dist/cjs/core/flow-namespace.d.ts +4 -4
- package/dist/cjs/core/flow-namespace.d.ts.map +1 -1
- package/dist/cjs/core/flow-namespace.js +14 -25
- package/dist/cjs/core/flow-namespace.js.map +1 -1
- package/dist/cjs/index.d.ts +3 -3
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/providers/AnthropicProvider.d.ts +1 -1
- package/dist/cjs/providers/AnthropicProvider.js +1 -1
- package/dist/cjs/providers/GeminiProvider.d.ts +1 -1
- package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/cjs/providers/GeminiProvider.js +1 -1
- package/dist/cjs/providers/GeminiProvider.js.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.d.ts +1 -1
- package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.js +1 -1
- package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
- package/dist/cjs/types/agent.d.ts +1 -1
- package/dist/cjs/types/agent.d.ts.map +1 -1
- package/dist/cjs/types/ai.d.ts +1 -1
- package/dist/cjs/types/ai.js +1 -1
- package/dist/cjs/types/flow.d.ts +33 -25
- package/dist/cjs/types/flow.d.ts.map +1 -1
- package/dist/cjs/types/index.d.ts +1 -1
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/types/signals.d.ts +4 -5
- package/dist/cjs/types/signals.d.ts.map +1 -1
- package/dist/cjs/utils/session.d.ts +1 -1
- package/dist/cjs/utils/session.js +4 -4
- package/dist/cjs/utils/session.js.map +1 -1
- package/dist/core/Agent.d.ts +1 -1
- package/dist/core/Agent.js +3 -3
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/AutoChainExecutor.d.ts +2 -2
- package/dist/core/AutoChainExecutor.js +2 -2
- package/dist/core/AutoChainExecutor.js.map +1 -1
- package/dist/core/PromptComposer.d.ts +1 -1
- package/dist/core/PromptComposer.js +2 -2
- package/dist/core/PromptComposer.js.map +1 -1
- package/dist/core/ResponseEngine.d.ts +1 -1
- package/dist/core/ResponseModal.js +6 -6
- package/dist/core/ResponseModal.js.map +1 -1
- package/dist/core/ResponsePipeline.d.ts +2 -2
- package/dist/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/core/ResponsePipeline.js.map +1 -1
- package/dist/core/SignalProcessor.d.ts +3 -3
- package/dist/core/SignalProcessor.d.ts.map +1 -1
- package/dist/core/SignalProcessor.js +1 -1
- package/dist/core/SignalProcessor.js.map +1 -1
- package/dist/core/Step.d.ts +1 -1
- package/dist/core/Step.js +1 -1
- package/dist/core/ToolManager.d.ts +1 -1
- package/dist/core/ToolManager.js +1 -1
- package/dist/core/flow-namespace.d.ts +4 -4
- package/dist/core/flow-namespace.d.ts.map +1 -1
- package/dist/core/flow-namespace.js +14 -25
- package/dist/core/flow-namespace.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/providers/AnthropicProvider.d.ts +1 -1
- package/dist/providers/AnthropicProvider.js +1 -1
- package/dist/providers/GeminiProvider.d.ts +1 -1
- package/dist/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/providers/GeminiProvider.js +1 -1
- package/dist/providers/GeminiProvider.js.map +1 -1
- package/dist/providers/OpenAIProvider.d.ts +1 -1
- package/dist/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/providers/OpenAIProvider.js +1 -1
- package/dist/providers/OpenAIProvider.js.map +1 -1
- package/dist/types/agent.d.ts +1 -1
- package/dist/types/agent.d.ts.map +1 -1
- package/dist/types/ai.d.ts +1 -1
- package/dist/types/ai.js +1 -1
- package/dist/types/flow.d.ts +33 -25
- package/dist/types/flow.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/signals.d.ts +4 -5
- package/dist/types/signals.d.ts.map +1 -1
- package/dist/utils/session.d.ts +1 -1
- package/dist/utils/session.js +4 -4
- package/dist/utils/session.js.map +1 -1
- package/docs/README.md +12 -3
- package/docs/concepts/architecture.md +19 -26
- package/docs/concepts/directives.md +53 -84
- package/docs/concepts/pipeline.md +4 -4
- package/docs/guides/flow-control.md +12 -13
- package/docs/guides/streaming.md +1 -1
- package/docs/migration/README.md +9 -10
- package/docs/migration/v1-to-v2.md +508 -6
- package/docs/reference/adapters.md +1 -1
- package/docs/reference/directive.md +9 -10
- package/docs/reference/flow.md +3 -3
- package/docs/reference/instruction.md +1 -1
- package/docs/reference/providers.md +14 -14
- package/docs/reference/signals.md +3 -4
- package/docs/reference/step.md +9 -10
- package/docs/reference/tool.md +1 -1
- package/docs/start/01-install.md +1 -1
- package/docs/start/02-first-agent.md +2 -3
- package/examples/01-quickstart.ts +1 -1
- package/examples/02-data-extraction.ts +1 -1
- package/examples/03-tools.ts +1 -1
- package/examples/04-instructions.ts +1 -1
- package/examples/05-branching.ts +1 -1
- package/examples/06-flow-control.ts +1 -1
- package/examples/07-streaming.ts +1 -1
- package/examples/08-persistence.ts +1 -1
- package/examples/09-signals.ts +1 -1
- package/examples/tsconfig.json +1 -3
- package/package.json +9 -5
- package/src/core/Agent.ts +4 -4
- package/src/core/AutoChainExecutor.ts +3 -3
- package/src/core/PromptComposer.ts +2 -2
- package/src/core/ResponseEngine.ts +1 -1
- package/src/core/ResponseModal.ts +18 -18
- package/src/core/ResponsePipeline.ts +1 -2
- package/src/core/SignalProcessor.ts +7 -7
- package/src/core/Step.ts +1 -1
- package/src/core/ToolManager.ts +1 -1
- package/src/core/flow-namespace.ts +32 -53
- package/src/index.ts +2 -3
- package/src/providers/AnthropicProvider.ts +2 -2
- package/src/providers/GeminiProvider.ts +2 -2
- package/src/providers/OpenAIProvider.ts +2 -2
- package/src/types/agent.ts +1 -1
- package/src/types/ai.ts +1 -1
- package/src/types/flow.ts +41 -26
- package/src/types/index.ts +0 -1
- package/src/types/signals.ts +4 -5
- package/src/utils/session.ts +5 -5
- package/docs/migration/route-to-flow.md +0 -560
- package/docs/reference/pre-directive.md +0 -131
|
@@ -35,12 +35,12 @@ import {
|
|
|
35
35
|
|
|
36
36
|
const provider =
|
|
37
37
|
process.env.PROVIDER === "openai"
|
|
38
|
-
? new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY!, model: "gpt-5
|
|
38
|
+
? new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY!, model: "gpt-5.5" })
|
|
39
39
|
: process.env.PROVIDER === "anthropic"
|
|
40
|
-
? new AnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY!, model: "claude-sonnet-4-
|
|
40
|
+
? new AnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY!, model: "claude-sonnet-4-6" })
|
|
41
41
|
: process.env.PROVIDER === "openrouter"
|
|
42
|
-
? new OpenRouterProvider({ apiKey: process.env.OPENROUTER_API_KEY!, model: "anthropic/claude-sonnet-4.
|
|
43
|
-
: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY!, model: "
|
|
42
|
+
? new OpenRouterProvider({ apiKey: process.env.OPENROUTER_API_KEY!, model: "anthropic/claude-sonnet-4.6" })
|
|
43
|
+
: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY!, model: "gemini-3.1-pro-preview" });
|
|
44
44
|
|
|
45
45
|
const agent = createAgent({ provider, schema, flows });
|
|
46
46
|
```
|
|
@@ -66,7 +66,7 @@ interface GeminiProviderOptions {
|
|
|
66
66
|
| Field | Type | Required | Default | Notes |
|
|
67
67
|
|-------|------|----------|---------|-------|
|
|
68
68
|
| `apiKey` | `string` | yes | — | Throws if empty. |
|
|
69
|
-
| `model` | `string` | yes | — | Use the
|
|
69
|
+
| `model` | `string` | yes | — | Use the model id, e.g. `"gemini-3.1-pro-preview"`. |
|
|
70
70
|
| `backupModels` | `string[]` | no | `[]` | Tried in order on 429/500/503/overload errors. |
|
|
71
71
|
| `config` | `Partial<GenerateContentConfig>` | no | — | Vendor-typed defaults (e.g. `temperature`, `systemInstruction`). |
|
|
72
72
|
| `retryConfig.timeout` | `number` | no | `60000` | Per-attempt timeout in ms. |
|
|
@@ -77,8 +77,8 @@ interface GeminiProviderOptions {
|
|
|
77
77
|
```typescript
|
|
78
78
|
const gemini = new GeminiProvider({
|
|
79
79
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
80
|
-
model: "
|
|
81
|
-
backupModels: ["
|
|
80
|
+
model: "gemini-3.1-pro-preview",
|
|
81
|
+
backupModels: ["gemini-3.1-flash-lite"],
|
|
82
82
|
config: { temperature: 0.3 },
|
|
83
83
|
});
|
|
84
84
|
```
|
|
@@ -106,7 +106,7 @@ interface OpenAIProviderOptions {
|
|
|
106
106
|
|-------|------|----------|---------|-------|
|
|
107
107
|
| `apiKey` | `string` | yes | — | Throws if empty. |
|
|
108
108
|
| `organization` | `string` | no | — | Forwarded as `OpenAI-Organization`. |
|
|
109
|
-
| `model` | `string` | yes | — | e.g. `"gpt-5"`, `"gpt-5
|
|
109
|
+
| `model` | `string` | yes | — | e.g. `"gpt-5.5"`, `"gpt-5.4"`. |
|
|
110
110
|
| `backupModels` | `string[]` | no | `[]` | Tried in order on overload/rate-limit errors. |
|
|
111
111
|
| `config` | OpenAI params | no | — | Defaults for `temperature`, `top_p`, etc. |
|
|
112
112
|
| `retryConfig.timeout` | `number` | no | `60000` | Per-attempt timeout in ms. |
|
|
@@ -117,7 +117,7 @@ interface OpenAIProviderOptions {
|
|
|
117
117
|
```typescript
|
|
118
118
|
const openai = new OpenAIProvider({
|
|
119
119
|
apiKey: process.env.OPENAI_API_KEY!,
|
|
120
|
-
model: "gpt-5
|
|
120
|
+
model: "gpt-5.5",
|
|
121
121
|
organization: "org_abc",
|
|
122
122
|
config: { temperature: 0.2 },
|
|
123
123
|
});
|
|
@@ -144,7 +144,7 @@ interface AnthropicProviderOptions {
|
|
|
144
144
|
| Field | Type | Required | Default | Notes |
|
|
145
145
|
|-------|------|----------|---------|-------|
|
|
146
146
|
| `apiKey` | `string` | yes | — | Throws if empty. |
|
|
147
|
-
| `model` | `string` | yes | — | e.g. `"claude-sonnet-4-
|
|
147
|
+
| `model` | `string` | yes | — | e.g. `"claude-sonnet-4-6"`, `"claude-opus-4-7"`. |
|
|
148
148
|
| `backupModels` | `string[]` | no | `[]` | Tried in order on 429/500/503/529/overload. |
|
|
149
149
|
| `config` | Anthropic params | no | — | Defaults for `max_tokens`, `system`, etc. The provider sets `max_tokens=4096` if neither `config.max_tokens` nor `parameters.maxOutputTokens` is set. |
|
|
150
150
|
| `retryConfig.timeout` | `number` | no | `60000` | Per-attempt timeout in ms. |
|
|
@@ -155,7 +155,7 @@ interface AnthropicProviderOptions {
|
|
|
155
155
|
```typescript
|
|
156
156
|
const anthropic = new AnthropicProvider({
|
|
157
157
|
apiKey: process.env.ANTHROPIC_API_KEY!,
|
|
158
|
-
model: "claude-sonnet-4-
|
|
158
|
+
model: "claude-sonnet-4-6",
|
|
159
159
|
config: { max_tokens: 8192 },
|
|
160
160
|
});
|
|
161
161
|
```
|
|
@@ -185,7 +185,7 @@ interface OpenRouterProviderOptions {
|
|
|
185
185
|
| Field | Type | Required | Default | Notes |
|
|
186
186
|
|-------|------|----------|---------|-------|
|
|
187
187
|
| `apiKey` | `string` | yes | — | Throws if empty. |
|
|
188
|
-
| `model` | `string` | yes | — | OpenRouter model id, e.g. `"anthropic/claude-sonnet-4.
|
|
188
|
+
| `model` | `string` | yes | — | OpenRouter model id, e.g. `"anthropic/claude-sonnet-4.6"`. See [openrouter.ai/models](https://openrouter.ai/models). |
|
|
189
189
|
| `backupModels` | `string[]` | no | `[]` | Tried in order on overload/capacity errors. |
|
|
190
190
|
| `siteUrl` | `string` | no | `""` | Sent as `HTTP-Referer` for OpenRouter rankings. |
|
|
191
191
|
| `siteName` | `string` | no | `""` | Sent as `X-Title` for OpenRouter rankings. |
|
|
@@ -198,8 +198,8 @@ interface OpenRouterProviderOptions {
|
|
|
198
198
|
```typescript
|
|
199
199
|
const openrouter = new OpenRouterProvider({
|
|
200
200
|
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
201
|
-
model: "anthropic/claude-sonnet-4.
|
|
202
|
-
backupModels: ["openai/gpt-5
|
|
201
|
+
model: "anthropic/claude-sonnet-4.6",
|
|
202
|
+
backupModels: ["openai/gpt-5.5", "google/gemini-3.1-pro-preview"],
|
|
203
203
|
siteName: "My App",
|
|
204
204
|
});
|
|
205
205
|
```
|
|
@@ -83,7 +83,7 @@ interface SignalContext<TContext = unknown, TData = unknown, TExtract = void> {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
interface SignalDirective<TContext = unknown, TData = unknown>
|
|
86
|
-
extends
|
|
86
|
+
extends Directive<TContext, TData> {
|
|
87
87
|
stopOtherSignals?: boolean;
|
|
88
88
|
replyWith?: string | ((ctx: SignalContext<TContext, TData>) => string);
|
|
89
89
|
}
|
|
@@ -176,7 +176,7 @@ Passed to handlers when a signal fires. Symmetric with `ToolContext`.
|
|
|
176
176
|
|
|
177
177
|
### `SignalDirective`
|
|
178
178
|
|
|
179
|
-
Extends [`
|
|
179
|
+
Extends [`Directive`](./directive.md). All position fields (`goTo`, `goToStep`, `complete`, `abort`, `reset`), state writes (`dataUpdate`, `contextUpdate`), `reply`, and pre-LLM fields (`appendPrompt`, `injectTools`, `halt`) are inherited unchanged.
|
|
180
180
|
|
|
181
181
|
| Added field | Type | Notes |
|
|
182
182
|
|-------------|------|-------|
|
|
@@ -349,8 +349,7 @@ Soft failures handled in-band (no thrown error, turn continues):
|
|
|
349
349
|
## Related
|
|
350
350
|
|
|
351
351
|
- [Turn pipeline](../concepts/pipeline.md) — where signal phases sit in the turn lifecycle.
|
|
352
|
-
- [Directives](../concepts/directives.md) — the
|
|
352
|
+
- [Directives](../concepts/directives.md) — the Directive shape and SignalDirective extension.
|
|
353
353
|
- [Directive](./directive.md) — base shape for all position and state fields.
|
|
354
|
-
- [PreDirective](./pre-directive.md) — pre-LLM extras inherited by `SignalDirective`.
|
|
355
354
|
- [createAgent](./create-agent.md) — `signals` and `signalBatchSize` options.
|
|
356
355
|
- [Errors](./errors.md) — `FlowConfigurationError` format contract.
|
package/docs/reference/step.md
CHANGED
|
@@ -66,7 +66,7 @@ interface StepOptions<TContext = unknown, TData = unknown> {
|
|
|
66
66
|
| ((ctx: TContext, data?: Partial<TData>) =>
|
|
67
67
|
void | PrepareResult | Promise<void | PrepareResult>);
|
|
68
68
|
|
|
69
|
-
// Lifecycle (full — receives HookContext, returns
|
|
69
|
+
// Lifecycle (full — receives HookContext, returns Directive)
|
|
70
70
|
hooks?: StepLifecycleHooks<TContext, TData>;
|
|
71
71
|
|
|
72
72
|
// Routing
|
|
@@ -75,9 +75,9 @@ interface StepOptions<TContext = unknown, TData = unknown> {
|
|
|
75
75
|
|
|
76
76
|
interface StepLifecycleHooks<TContext = unknown, TData = unknown> {
|
|
77
77
|
onEnter?: (ctx: HookContext<TContext, TData>) =>
|
|
78
|
-
void |
|
|
78
|
+
void | Directive<TContext, TData> | Promise<void | Directive<TContext, TData>>;
|
|
79
79
|
prepare?: (ctx: HookContext<TContext, TData>) =>
|
|
80
|
-
void |
|
|
80
|
+
void | Directive<TContext, TData> | Promise<void | Directive<TContext, TData>>;
|
|
81
81
|
finalize?: (ctx: HookContext<TContext, TData>) =>
|
|
82
82
|
void | Directive<TContext, TData> | Promise<void | Directive<TContext, TData>>;
|
|
83
83
|
onExit?: (ctx: HookContext<TContext, TData>, reason: ExitReason) =>
|
|
@@ -114,8 +114,8 @@ fields, with a smaller return type.
|
|
|
114
114
|
|
|
115
115
|
| Hook | When it fires | `hooks.<name>` returns | Top-level shorthand returns | Use it for |
|
|
116
116
|
|------|---------------|------------------------|------------------------------|------------|
|
|
117
|
-
| `onEnter` | Before any other work the first time the step becomes current. | `void \|
|
|
118
|
-
| `prepare` | Right before the LLM call, after `onEnter`. | `void \|
|
|
117
|
+
| `onEnter` | Before any other work the first time the step becomes current. | `void \| Directive` | n/a (no shorthand) | Append per-turn prompt context, inject one-turn tools, or short-circuit with `halt + reply`. |
|
|
118
|
+
| `prepare` | Right before the LLM call, after `onEnter`. | `void \| Directive` | `void \| PrepareResult` | Mutate session data, fetch external context, halt the LLM call. |
|
|
119
119
|
| `finalize` | After the LLM call and tool loop complete. | `void \| Directive` | `void \| PrepareResult` | Validate collected data, redirect with `goTo` / `goToStep`, complete the flow. |
|
|
120
120
|
| `onExit` | When the step is left (next step entered, flow completed, aborted). | `void` | n/a | Emit telemetry. Cannot influence flow control. |
|
|
121
121
|
|
|
@@ -123,7 +123,7 @@ fields, with a smaller return type.
|
|
|
123
123
|
common Directive fields (`dataUpdate`, `contextUpdate`, `goTo`,
|
|
124
124
|
`goToStep`, `complete`, `halt`, `reply`). Use `hooks.<name>` when you
|
|
125
125
|
need the full `HookContext` (with `session`, `history`, `dispatch`)
|
|
126
|
-
or the full `Directive`
|
|
126
|
+
or the full `Directive` surface (`appendPrompt`,
|
|
127
127
|
`injectTools`, `abort`, `reset`).
|
|
128
128
|
|
|
129
129
|
### Resolution within a step
|
|
@@ -133,7 +133,7 @@ For one step, the engine walks this sequence per turn:
|
|
|
133
133
|
1. Evaluate `if` (code, AND) and `when` (AI, AND) — fails skip the step entirely.
|
|
134
134
|
2. Evaluate `skip` (code, OR) — true means bypass and fall through.
|
|
135
135
|
3. Check `requires` — refuse entry if any required field is missing.
|
|
136
|
-
4. Run `onEnter`, then `prepare` / `hooks.prepare`. May emit a `
|
|
136
|
+
4. Run `onEnter`, then `prepare` / `hooks.prepare`. May emit a `Directive` (pre-LLM fields honored).
|
|
137
137
|
5. **LLM step**: call the LLM with the step's prompt, tools, and instructions; tool loop runs until completion. **Auto step**: skip the LLM call. **Reply step**: render `reply` as the verbatim assistant message.
|
|
138
138
|
6. Run `finalize` / `hooks.finalize`. May emit a `Directive`.
|
|
139
139
|
7. Evaluate `branches`. The first entry whose `if`/`when` passes wins; its `then` resolves to a step id, a flow id, or a full `Directive`. If no entry matches, fall through.
|
|
@@ -282,7 +282,7 @@ const agent = createAgent({
|
|
|
282
282
|
}),
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
// Full hook — receives HookContext, returns
|
|
285
|
+
// Full hook — receives HookContext, returns Directive.
|
|
286
286
|
{
|
|
287
287
|
id: 'enrich',
|
|
288
288
|
auto: true,
|
|
@@ -326,14 +326,13 @@ Runtime errors that surface from a step's hook execution include
|
|
|
326
326
|
|
|
327
327
|
## Related
|
|
328
328
|
|
|
329
|
-
- [Architecture](../concepts/architecture.md) — where Step fits among the
|
|
329
|
+
- [Architecture](../concepts/architecture.md) — where Step fits among the six primitives
|
|
330
330
|
- [Turn pipeline](../concepts/pipeline.md) — when each step phase fires inside a turn
|
|
331
331
|
- [Flow](./flow.md) — the parent type that contains a step's `steps[]` entry
|
|
332
332
|
- [Tool](./tool.md) — the shape consumed by `tools[]`
|
|
333
333
|
- [Instruction](./instruction.md) — the shape consumed by `instructions[]`
|
|
334
334
|
- [Branches](./branches.md) — the full `BranchEntry` / `BranchMap` contract
|
|
335
335
|
- [Directive](./directive.md) — the post-LLM return type for `hooks.finalize`
|
|
336
|
-
- [PreDirective](./pre-directive.md) — the pre-LLM return type for `hooks.onEnter` and `hooks.prepare`
|
|
337
336
|
- [When and if](../guides/conditions.md) — picking between AI and code conditions
|
|
338
337
|
- [Branching](../guides/branching.md) — adding source-local forks
|
|
339
338
|
- [Flow control](../guides/flow-control.md) — redirecting from a hook
|
package/docs/reference/tool.md
CHANGED
|
@@ -262,7 +262,7 @@ Permission denials (`checkPermissions` returning `allowed: false`) are surfaced
|
|
|
262
262
|
## Related
|
|
263
263
|
|
|
264
264
|
- [Add tools](../start/04-add-tools.md) — tutorial that introduces this type.
|
|
265
|
-
- [Architecture](../concepts/architecture.md) — where Tool fits among the
|
|
265
|
+
- [Architecture](../concepts/architecture.md) — where Tool fits among the six primitives.
|
|
266
266
|
- [Directives](../concepts/directives.md) — what `dispatch` and `directive` emit.
|
|
267
267
|
- [Directive](./directive.md) — the flat shape used by both forms above.
|
|
268
268
|
- [Flow control](../guides/flow-control.md) — recipes for redirecting from tools and hooks.
|
package/docs/start/01-install.md
CHANGED
|
@@ -67,7 +67,7 @@ import { GeminiProvider } from "@falai/agent";
|
|
|
67
67
|
|
|
68
68
|
const provider = new GeminiProvider({
|
|
69
69
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
70
|
-
model: "
|
|
70
|
+
model: "gemini-3.1-pro-preview",
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
console.log("Provider ready:", provider.constructor.name);
|
|
@@ -36,7 +36,7 @@ const response = await agent.respond("Hi, I'm Alice");
|
|
|
36
36
|
console.log(response.message);
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
That is the whole program. No persistence config, no tools, no branches, no signals. Three primitives appear by name (`Agent`, `Flow`, `Step`) and
|
|
39
|
+
That is the whole program. No persistence config, no tools, no branches, no signals. Three primitives appear by name (`Agent`, `Flow`, `Step`) and three more sit one decision away (`Tool`, `Instruction`, `Directive`). The next sections walk through every line.
|
|
40
40
|
|
|
41
41
|
## Walk it line by line
|
|
42
42
|
|
|
@@ -139,7 +139,6 @@ Three primitives appear by name in the code above: [`Agent`](../concepts/archite
|
|
|
139
139
|
- [`Tool`](../concepts/architecture.md#tool) — a typed function the AI can call. May redirect the conversation by emitting a directive. Added on page [04](./04-add-tools.md).
|
|
140
140
|
- [`Instruction`](../concepts/architecture.md#instruction) — a `must` / `never` / `should` behavioral statement at agent, flow, or step scope.
|
|
141
141
|
- [`Directive`](../concepts/architecture.md#directive) — a flat object any tool, hook, or branch returns to write state, change position, or speak verbatim.
|
|
142
|
-
- [`PreDirective`](../concepts/architecture.md#predirective) — a `Directive` plus per-turn shaping (`appendPrompt`, `injectTools`, `halt`) returned from `onEnter` and `prepare` hooks.
|
|
143
142
|
|
|
144
143
|
Read [Architecture](../concepts/architecture.md) end to end when you want the full mental model — what each primitive owns, how they reference each other, and why the set is exactly seven.
|
|
145
144
|
|
|
@@ -185,7 +184,7 @@ A few common failure modes and where to look:
|
|
|
185
184
|
- **`Missing API key`** or a 401 from Gemini — `GEMINI_API_KEY` is unset or your `.env` did not load. Bun loads `.env` automatically; Node needs `--env-file=.env`.
|
|
186
185
|
- **`FlowConfigurationError: collect references unknown key 'foo'`** — the schema does not declare `foo` as a property. Add it to `schema.properties` or fix the `collect` array.
|
|
187
186
|
- **`FlowConfigurationError: duplicate flow id` / `duplicate step id`** — two flows or two steps share the same auto-derived id. Set explicit `id` values to disambiguate.
|
|
188
|
-
- **The LLM call hangs** — check the `model` (Gemini's free tier expects `"
|
|
187
|
+
- **The LLM call hangs** — check the `model` (Gemini's free tier expects `"gemini-3.1-pro-preview"` or `"gemini-3.1-flash-lite"`) and your network. Provider errors surface as `ResponseGenerationError`.
|
|
189
188
|
|
|
190
189
|
The full set of typed errors and the `[<ErrorClass>] <what>: <why>. <how to fix>.` format contract live in the [Errors reference](../reference/errors.md).
|
|
191
190
|
|
|
@@ -7,7 +7,7 @@ if (!process.env.GEMINI_API_KEY) throw new Error("Set GEMINI_API_KEY");
|
|
|
7
7
|
|
|
8
8
|
const agent = createAgent({
|
|
9
9
|
name: "Greeter",
|
|
10
|
-
provider: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY, model: "
|
|
10
|
+
provider: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY, model: "gemini-3.1-flash-lite" }),
|
|
11
11
|
schema: { type: "object", properties: { name: { type: "string" } } },
|
|
12
12
|
flows: [{
|
|
13
13
|
title: "Greet",
|
|
@@ -40,7 +40,7 @@ const agent = createAgent<Record<string, never>, BookingData>({
|
|
|
40
40
|
name: "Booking Agent",
|
|
41
41
|
provider: new GeminiProvider({
|
|
42
42
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
43
|
-
model: "
|
|
43
|
+
model: "gemini-3.1-flash-lite",
|
|
44
44
|
}),
|
|
45
45
|
schema,
|
|
46
46
|
flows: [
|
package/examples/03-tools.ts
CHANGED
|
@@ -99,7 +99,7 @@ const agent = createAgent<AppContext, AppData>({
|
|
|
99
99
|
name: "BookingAgent",
|
|
100
100
|
provider: new GeminiProvider({
|
|
101
101
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
102
|
-
model: "
|
|
102
|
+
model: "gemini-3.1-flash-lite",
|
|
103
103
|
}),
|
|
104
104
|
schema: {
|
|
105
105
|
type: "object",
|
package/examples/05-branching.ts
CHANGED
|
@@ -13,7 +13,7 @@ interface Data { intent: string; query: string; answer: string }
|
|
|
13
13
|
|
|
14
14
|
const provider = new GeminiProvider({
|
|
15
15
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
16
|
-
model: "
|
|
16
|
+
model: "gemini-3.1-flash-lite",
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
// ─── Steps with branches ─────────────────────────────────────────────────────
|
package/examples/07-streaming.ts
CHANGED
package/examples/09-signals.ts
CHANGED
|
@@ -100,7 +100,7 @@ const agent = createAgent<AppContext, AppData>({
|
|
|
100
100
|
name: "SupportAgent",
|
|
101
101
|
provider: new GeminiProvider({
|
|
102
102
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
103
|
-
model: "
|
|
103
|
+
model: "gemini-3.1-flash-lite",
|
|
104
104
|
}),
|
|
105
105
|
context: { supportTier: "free" },
|
|
106
106
|
schema: {
|
package/examples/tsconfig.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@falai/agent",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "Conversational state engine for TypeScript where the AI understands, but the code is in control",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"bugs": {
|
|
37
37
|
"url": "https://github.com/falai-dev/agent/issues"
|
|
38
38
|
},
|
|
39
|
-
"homepage": "https://
|
|
39
|
+
"homepage": "https://falai.dev",
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "npm run build:esm && npm run build:cjs && npm run fix:cjs",
|
|
42
42
|
"build:esm": "tsc",
|
|
@@ -65,11 +65,15 @@
|
|
|
65
65
|
"typescript",
|
|
66
66
|
"conversational",
|
|
67
67
|
"gemini",
|
|
68
|
+
"openai",
|
|
69
|
+
"anthropic",
|
|
68
70
|
"llm",
|
|
69
71
|
"chatbot",
|
|
70
72
|
"framework",
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
+
"flows",
|
|
74
|
+
"schema",
|
|
75
|
+
"directives",
|
|
76
|
+
"signals"
|
|
73
77
|
],
|
|
74
78
|
"author": "Gustavo Salomé <gusnips>",
|
|
75
79
|
"license": "MIT",
|
package/src/core/Agent.ts
CHANGED
|
@@ -1225,7 +1225,7 @@ export class Agent<TContext = any, TData = any> {
|
|
|
1225
1225
|
}
|
|
1226
1226
|
}
|
|
1227
1227
|
|
|
1228
|
-
// Strip
|
|
1228
|
+
// Strip pre-LLM-only fields before storing
|
|
1229
1229
|
const stripped = this.stripPreDirectiveFields(directive);
|
|
1230
1230
|
|
|
1231
1231
|
// Set pendingDirective on the session without applying it
|
|
@@ -1439,7 +1439,7 @@ export class Agent<TContext = any, TData = any> {
|
|
|
1439
1439
|
}
|
|
1440
1440
|
|
|
1441
1441
|
/**
|
|
1442
|
-
* Strip
|
|
1442
|
+
* Strip pre-LLM-only fields (appendPrompt, injectTools, halt) from a directive.
|
|
1443
1443
|
* These fields are transient (one-turn lifetime) and must not be persisted.
|
|
1444
1444
|
* @private
|
|
1445
1445
|
*/
|
|
@@ -1452,8 +1452,8 @@ export class Agent<TContext = any, TData = any> {
|
|
|
1452
1452
|
const { appendPrompt, injectTools, halt, ...rest } = raw;
|
|
1453
1453
|
|
|
1454
1454
|
if (appendPrompt || injectTools || halt !== undefined) {
|
|
1455
|
-
logger.
|
|
1456
|
-
`[Agent]
|
|
1455
|
+
logger.warn(
|
|
1456
|
+
`[Agent] Ignoring pre-LLM-only fields on pendingDirective (these only take effect in onEnter/prepare hooks): ` +
|
|
1457
1457
|
`${[appendPrompt && 'appendPrompt', injectTools && 'injectTools', halt !== undefined && 'halt'].filter(Boolean).join(', ')}`
|
|
1458
1458
|
);
|
|
1459
1459
|
}
|
|
@@ -25,7 +25,7 @@ import type { StoppedReason } from "../types/flow";
|
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* The directive-like object that `prepare` may return on auto-steps.
|
|
28
|
-
* This is a structural subset of
|
|
28
|
+
* This is a structural subset of Directive (pre-LLM fields).
|
|
29
29
|
*/
|
|
30
30
|
export interface AutoStepPrepareResult {
|
|
31
31
|
dataUpdate?: Record<string, unknown>;
|
|
@@ -292,7 +292,7 @@ export class AutoChainExecutor<TContext = unknown, TData = unknown> {
|
|
|
292
292
|
|
|
293
293
|
/**
|
|
294
294
|
* Run onEnter and prepare hooks for an auto-step, collecting any
|
|
295
|
-
*
|
|
295
|
+
* Directive return values (pre-LLM fields honored).
|
|
296
296
|
*/
|
|
297
297
|
private async runStepHooks(
|
|
298
298
|
step: Step<TContext, TData>,
|
|
@@ -310,7 +310,7 @@ export class AutoChainExecutor<TContext = unknown, TData = unknown> {
|
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
-
// prepare hook — for auto-steps, prepare may return a
|
|
313
|
+
// prepare hook — for auto-steps, prepare may return a Directive with pre-LLM fields
|
|
314
314
|
if (step.prepare) {
|
|
315
315
|
if (typeof step.prepare === 'function') {
|
|
316
316
|
const prepareResult = await (step.prepare as (
|
|
@@ -419,7 +419,7 @@ export class PromptComposer<TContext = unknown, TData = unknown> {
|
|
|
419
419
|
* Build the final prompt string.
|
|
420
420
|
*
|
|
421
421
|
* @param options.transientAppendage - Per-turn sentences from merged
|
|
422
|
-
*
|
|
422
|
+
* Directive.appendPrompt arrays (outer-to-inner: agent.onEnter →
|
|
423
423
|
* flow.onEnter → step.onEnter → step.prepare). Appended after all
|
|
424
424
|
* other sections. Fresh every turn, never cached, never persisted.
|
|
425
425
|
* **Validates: Requirements 2.2, 2.8, 2.11, 27.1, 27.2, 27.4**
|
|
@@ -434,7 +434,7 @@ export class PromptComposer<TContext = unknown, TData = unknown> {
|
|
|
434
434
|
sections = this.parts.filter(Boolean);
|
|
435
435
|
}
|
|
436
436
|
|
|
437
|
-
// Append transient per-turn sentences (from
|
|
437
|
+
// Append transient per-turn sentences (from Directive.appendPrompt).
|
|
438
438
|
// These are never cached — they are a fresh slot built per turn.
|
|
439
439
|
if (options?.transientAppendage && options.transientAppendage.length > 0) {
|
|
440
440
|
const appendageBlock = options.transientAppendage.join("\n");
|
|
@@ -33,7 +33,7 @@ export interface BuildResponsePromptParams<
|
|
|
33
33
|
// NEW: Agent-level schema for data validation
|
|
34
34
|
agentSchema?: StructuredSchema;
|
|
35
35
|
/**
|
|
36
|
-
* Per-turn transient appendage from merged
|
|
36
|
+
* Per-turn transient appendage from merged Directive.appendPrompt arrays.
|
|
37
37
|
* Appended to the system prompt after all other sections.
|
|
38
38
|
* Fresh every turn, never cached, never persisted.
|
|
39
39
|
*/
|
|
@@ -18,7 +18,7 @@ import type {
|
|
|
18
18
|
ScopedInstructions,
|
|
19
19
|
AppliedInstruction,
|
|
20
20
|
PrepareResult,
|
|
21
|
-
|
|
21
|
+
Directive,
|
|
22
22
|
} from "../types";
|
|
23
23
|
import type { SignalFiring } from "../types/signals";
|
|
24
24
|
import type { Agent } from "./Agent";
|
|
@@ -140,7 +140,7 @@ interface ResponseContext<TContext = unknown, TData = unknown> {
|
|
|
140
140
|
/** Signal firings accumulated across both phases (pre + post) for the response surface. */
|
|
141
141
|
signalFirings?: SignalFiring<TContext, TData>[];
|
|
142
142
|
/** Pre-phase merged directive from signals (non-position fields like appendPrompt, injectTools). */
|
|
143
|
-
signalPreDirective?:
|
|
143
|
+
signalPreDirective?: Directive<TContext, TData>;
|
|
144
144
|
/** Whether the pre-signal phase emitted a halt directive. */
|
|
145
145
|
signalHalted?: boolean;
|
|
146
146
|
/** Reply from a halt directive. */
|
|
@@ -477,7 +477,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
477
477
|
session: SessionState<TData>;
|
|
478
478
|
isFlowComplete: boolean;
|
|
479
479
|
signalFirings?: SignalFiring<TContext, TData>[];
|
|
480
|
-
signalPreDirective?:
|
|
480
|
+
signalPreDirective?: Directive<TContext, TData>;
|
|
481
481
|
signalHalted?: boolean;
|
|
482
482
|
signalHaltReply?: string;
|
|
483
483
|
};
|
|
@@ -533,7 +533,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
533
533
|
/** Signal firings from the pre-phase (threaded through for response surface). */
|
|
534
534
|
signalFirings?: SignalFiring<TContext, TData>[];
|
|
535
535
|
/** Non-position signal directive for pre-LLM augmentation (appendPrompt, injectTools, etc). */
|
|
536
|
-
signalPreDirective?:
|
|
536
|
+
signalPreDirective?: Directive<TContext, TData>;
|
|
537
537
|
/** Pre-signal phase halted the turn. */
|
|
538
538
|
signalHalted?: boolean;
|
|
539
539
|
/** Reply text from the halt directive. */
|
|
@@ -752,7 +752,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
752
752
|
signalResult: {
|
|
753
753
|
firings: SignalFiring<TContext, TData>[];
|
|
754
754
|
updatedSession: SessionState<TData>;
|
|
755
|
-
mergedDirective:
|
|
755
|
+
mergedDirective: Directive<TContext, TData> | undefined;
|
|
756
756
|
},
|
|
757
757
|
_params: { session: SessionState<TData>; history: Event[]; context: TContext },
|
|
758
758
|
): {
|
|
@@ -762,7 +762,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
762
762
|
session: SessionState<TData>;
|
|
763
763
|
isFlowComplete: boolean;
|
|
764
764
|
signalFirings?: SignalFiring<TContext, TData>[];
|
|
765
|
-
signalPreDirective?:
|
|
765
|
+
signalPreDirective?: Directive<TContext, TData>;
|
|
766
766
|
signalHalted?: boolean;
|
|
767
767
|
signalHaltReply?: string;
|
|
768
768
|
} {
|
|
@@ -1381,15 +1381,15 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1381
1381
|
historyEvents: Event[];
|
|
1382
1382
|
signal?: AbortSignal;
|
|
1383
1383
|
/**
|
|
1384
|
-
* Per-turn transient appendage from merged
|
|
1384
|
+
* Per-turn transient appendage from merged directive.appendPrompt.
|
|
1385
1385
|
* Fresh every turn, never cached, never persisted.
|
|
1386
1386
|
*/
|
|
1387
1387
|
transientAppendage?: string[];
|
|
1388
1388
|
/**
|
|
1389
|
-
* Merged
|
|
1389
|
+
* Merged directive from the directive bus's pre-LLM phase drain.
|
|
1390
1390
|
* When `halt: true`, the LLM call is skipped entirely.
|
|
1391
1391
|
*/
|
|
1392
|
-
mergedPreDirective?:
|
|
1392
|
+
mergedPreDirective?: Directive<TContext, TData>;
|
|
1393
1393
|
}): Promise<{
|
|
1394
1394
|
message: string;
|
|
1395
1395
|
toolCalls?: Array<{ toolName: string; arguments: Record<string, unknown> }>;
|
|
@@ -1503,7 +1503,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1503
1503
|
// ── STEP.REPLY SHORT-CIRCUIT (Requirement 25.1–25.7, 17.9) ──────────────
|
|
1504
1504
|
// A step with `reply` set emits a verbatim template response without LLM.
|
|
1505
1505
|
// onEnter and prepare have already fired normally at this point.
|
|
1506
|
-
// If prepare returned a
|
|
1506
|
+
// If prepare returned a Directive with `reply`, that overrides
|
|
1507
1507
|
// the step-declared reply (last-emission-wins per Algorithm 4).
|
|
1508
1508
|
if (nextStep.reply != null) {
|
|
1509
1509
|
// Determine the effective reply: prepare-emitted reply wins over step-declared
|
|
@@ -1515,7 +1515,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1515
1515
|
return { message: effectiveReply, session, stoppedReason: 'reply' };
|
|
1516
1516
|
}
|
|
1517
1517
|
|
|
1518
|
-
// Transient appendage: per-turn slot from
|
|
1518
|
+
// Transient appendage: per-turn slot from Directive.appendPrompt.
|
|
1519
1519
|
// Fresh each turn, never cached, never persisted.
|
|
1520
1520
|
// Wrapped in try/finally to ensure cleanup even on abnormal termination.
|
|
1521
1521
|
let turnTransientAppendage: string[] | undefined = transientAppendage;
|
|
@@ -1592,7 +1592,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1592
1592
|
return { message, toolCalls, session, appliedInstructions };
|
|
1593
1593
|
} finally {
|
|
1594
1594
|
// Drain the transient appendage at end of turn.
|
|
1595
|
-
// This ensures
|
|
1595
|
+
// This ensures Directive.appendPrompt does not leak to subsequent
|
|
1596
1596
|
// turns even when the turn terminates abnormally (error, abort, reject).
|
|
1597
1597
|
turnTransientAppendage = undefined;
|
|
1598
1598
|
}
|
|
@@ -1799,15 +1799,15 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1799
1799
|
historyEvents: Event[];
|
|
1800
1800
|
signal?: AbortSignal;
|
|
1801
1801
|
/**
|
|
1802
|
-
* Per-turn transient appendage from merged
|
|
1802
|
+
* Per-turn transient appendage from merged directive.appendPrompt.
|
|
1803
1803
|
* Fresh every turn, never cached, never persisted.
|
|
1804
1804
|
*/
|
|
1805
1805
|
transientAppendage?: string[];
|
|
1806
1806
|
/**
|
|
1807
|
-
* Merged
|
|
1807
|
+
* Merged directive from the directive bus's pre-LLM phase drain.
|
|
1808
1808
|
* When `halt: true`, the LLM call is skipped entirely.
|
|
1809
1809
|
*/
|
|
1810
|
-
mergedPreDirective?:
|
|
1810
|
+
mergedPreDirective?: Directive<TContext, TData>;
|
|
1811
1811
|
}): AsyncGenerator<AgentResponseStreamChunk<TData>> {
|
|
1812
1812
|
const { selectedFlow, selectedStep, responseDirectives, history, context, historyEvents, signal, transientAppendage, mergedPreDirective } = params;
|
|
1813
1813
|
let session = params.session;
|
|
@@ -1918,7 +1918,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1918
1918
|
// ── STEP.REPLY SHORT-CIRCUIT (Requirement 25.1–25.7, 17.9) ──────────────
|
|
1919
1919
|
// A step with `reply` set emits a verbatim template response without LLM.
|
|
1920
1920
|
// onEnter and prepare have already fired normally. If prepare returned
|
|
1921
|
-
// a
|
|
1921
|
+
// a Directive with `reply`, that overrides the step-declared reply.
|
|
1922
1922
|
if (nextStep.reply != null) {
|
|
1923
1923
|
const effectiveReply = mergedPreDirective?.reply ?? await render(
|
|
1924
1924
|
nextStep.reply,
|
|
@@ -1937,7 +1937,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1937
1937
|
return;
|
|
1938
1938
|
}
|
|
1939
1939
|
|
|
1940
|
-
// Transient appendage: per-turn slot from
|
|
1940
|
+
// Transient appendage: per-turn slot from Directive.appendPrompt.
|
|
1941
1941
|
// Fresh each turn, never cached, never persisted.
|
|
1942
1942
|
// Wrapped in try/finally to ensure cleanup even on abnormal termination.
|
|
1943
1943
|
let turnTransientAppendage: string[] | undefined = transientAppendage;
|
|
@@ -2092,7 +2092,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
2092
2092
|
}
|
|
2093
2093
|
} finally {
|
|
2094
2094
|
// Drain the transient appendage at end of turn.
|
|
2095
|
-
// This ensures
|
|
2095
|
+
// This ensures Directive.appendPrompt does not leak to subsequent
|
|
2096
2096
|
// turns even when the turn terminates abnormally (error, abort, reject).
|
|
2097
2097
|
turnTransientAppendage = undefined;
|
|
2098
2098
|
}
|
|
@@ -9,7 +9,6 @@ import type {
|
|
|
9
9
|
AgentStructuredResponse,
|
|
10
10
|
Tool,
|
|
11
11
|
Directive,
|
|
12
|
-
PreDirective,
|
|
13
12
|
} from "../types";
|
|
14
13
|
import type { SignalFiring } from "../types/signals";
|
|
15
14
|
import type { SignalProcessor } from "./SignalProcessor";
|
|
@@ -162,7 +161,7 @@ export class ResponsePipeline<TContext = unknown, TData = unknown> {
|
|
|
162
161
|
): Promise<{
|
|
163
162
|
firings: SignalFiring<TContext, TData>[];
|
|
164
163
|
updatedSession: SessionState<TData>;
|
|
165
|
-
mergedDirective:
|
|
164
|
+
mergedDirective: Directive<TContext, TData> | undefined;
|
|
166
165
|
}> {
|
|
167
166
|
if (!this.signalProcessor) {
|
|
168
167
|
return { firings: [], updatedSession: session, mergedDirective: undefined };
|