@falai/agent 0.4.1 → 0.5.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 +21 -74
- package/dist/cjs/core/Agent.d.ts +22 -29
- package/dist/cjs/core/Agent.d.ts.map +1 -1
- package/dist/cjs/core/Agent.js +464 -291
- package/dist/cjs/core/Agent.js.map +1 -1
- package/dist/cjs/core/Events.d.ts +10 -1
- package/dist/cjs/core/Events.d.ts.map +1 -1
- package/dist/cjs/core/Events.js +3 -2
- package/dist/cjs/core/Events.js.map +1 -1
- package/dist/cjs/core/PersistenceManager.d.ts +19 -0
- package/dist/cjs/core/PersistenceManager.d.ts.map +1 -1
- package/dist/cjs/core/PersistenceManager.js +57 -0
- package/dist/cjs/core/PersistenceManager.js.map +1 -1
- package/dist/cjs/core/PromptComposer.d.ts +24 -0
- package/dist/cjs/core/PromptComposer.d.ts.map +1 -0
- package/dist/cjs/core/PromptComposer.js +127 -0
- package/dist/cjs/core/PromptComposer.js.map +1 -0
- package/dist/cjs/core/ResponseEngine.d.ts +19 -0
- package/dist/cjs/core/ResponseEngine.d.ts.map +1 -0
- package/dist/cjs/core/ResponseEngine.js +51 -0
- package/dist/cjs/core/ResponseEngine.js.map +1 -0
- package/dist/cjs/core/Route.d.ts +18 -12
- package/dist/cjs/core/Route.d.ts.map +1 -1
- package/dist/cjs/core/Route.js +15 -9
- package/dist/cjs/core/Route.js.map +1 -1
- package/dist/cjs/core/RoutingEngine.d.ts +38 -0
- package/dist/cjs/core/RoutingEngine.d.ts.map +1 -0
- package/dist/cjs/core/RoutingEngine.js +110 -0
- package/dist/cjs/core/RoutingEngine.js.map +1 -0
- package/dist/cjs/core/State.d.ts +15 -4
- package/dist/cjs/core/State.d.ts.map +1 -1
- package/dist/cjs/core/State.js +21 -2
- package/dist/cjs/core/State.js.map +1 -1
- package/dist/cjs/core/ToolExecutor.d.ts +29 -0
- package/dist/cjs/core/ToolExecutor.d.ts.map +1 -0
- package/dist/cjs/core/ToolExecutor.js +73 -0
- package/dist/cjs/core/ToolExecutor.js.map +1 -0
- package/dist/cjs/core/Transition.d.ts +5 -5
- package/dist/cjs/core/Transition.d.ts.map +1 -1
- package/dist/cjs/core/Transition.js.map +1 -1
- package/dist/cjs/index.d.ts +6 -8
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +8 -10
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/providers/AnthropicProvider.d.ts.map +1 -1
- package/dist/cjs/providers/AnthropicProvider.js +10 -13
- package/dist/cjs/providers/AnthropicProvider.js.map +1 -1
- package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/cjs/providers/GeminiProvider.js +12 -8
- package/dist/cjs/providers/GeminiProvider.js.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.js +10 -53
- package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
- package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenRouterProvider.js +10 -53
- package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
- package/dist/cjs/types/agent.d.ts +13 -12
- package/dist/cjs/types/agent.d.ts.map +1 -1
- package/dist/cjs/types/ai.d.ts +8 -2
- package/dist/cjs/types/ai.d.ts.map +1 -1
- package/dist/cjs/types/history.d.ts +8 -0
- package/dist/cjs/types/history.d.ts.map +1 -1
- package/dist/cjs/types/index.d.ts +0 -3
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/types/index.js +1 -3
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/types/route.d.ts +39 -4
- package/dist/cjs/types/route.d.ts.map +1 -1
- package/dist/cjs/types/routing.d.ts +16 -0
- package/dist/cjs/types/routing.d.ts.map +1 -0
- package/dist/cjs/types/routing.js +3 -0
- package/dist/cjs/types/routing.js.map +1 -0
- package/dist/cjs/types/schema.d.ts +22 -0
- package/dist/cjs/types/schema.d.ts.map +1 -0
- package/dist/cjs/types/schema.js +3 -0
- package/dist/cjs/types/schema.js.map +1 -0
- package/dist/cjs/types/session.d.ts +72 -0
- package/dist/cjs/types/session.d.ts.map +1 -0
- package/dist/cjs/types/session.js +140 -0
- package/dist/cjs/types/session.js.map +1 -0
- package/dist/cjs/types/tool.d.ts +11 -5
- package/dist/cjs/types/tool.d.ts.map +1 -1
- package/dist/cjs/utils/id.d.ts +0 -5
- package/dist/cjs/utils/id.d.ts.map +1 -1
- package/dist/cjs/utils/id.js +0 -10
- package/dist/cjs/utils/id.js.map +1 -1
- package/dist/cjs/utils/schema.d.ts +17 -0
- package/dist/cjs/utils/schema.d.ts.map +1 -0
- package/dist/cjs/utils/schema.js +32 -0
- package/dist/cjs/utils/schema.js.map +1 -0
- package/dist/core/Agent.d.ts +22 -29
- package/dist/core/Agent.d.ts.map +1 -1
- package/dist/core/Agent.js +464 -291
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/Events.d.ts +10 -1
- package/dist/core/Events.d.ts.map +1 -1
- package/dist/core/Events.js +3 -2
- package/dist/core/Events.js.map +1 -1
- package/dist/core/PersistenceManager.d.ts +19 -0
- package/dist/core/PersistenceManager.d.ts.map +1 -1
- package/dist/core/PersistenceManager.js +57 -0
- package/dist/core/PersistenceManager.js.map +1 -1
- package/dist/core/PromptComposer.d.ts +24 -0
- package/dist/core/PromptComposer.d.ts.map +1 -0
- package/dist/core/PromptComposer.js +123 -0
- package/dist/core/PromptComposer.js.map +1 -0
- package/dist/core/ResponseEngine.d.ts +19 -0
- package/dist/core/ResponseEngine.d.ts.map +1 -0
- package/dist/core/ResponseEngine.js +47 -0
- package/dist/core/ResponseEngine.js.map +1 -0
- package/dist/core/Route.d.ts +18 -12
- package/dist/core/Route.d.ts.map +1 -1
- package/dist/core/Route.js +15 -9
- package/dist/core/Route.js.map +1 -1
- package/dist/core/RoutingEngine.d.ts +38 -0
- package/dist/core/RoutingEngine.d.ts.map +1 -0
- package/dist/core/RoutingEngine.js +106 -0
- package/dist/core/RoutingEngine.js.map +1 -0
- package/dist/core/State.d.ts +15 -4
- package/dist/core/State.d.ts.map +1 -1
- package/dist/core/State.js +21 -2
- package/dist/core/State.js.map +1 -1
- package/dist/core/ToolExecutor.d.ts +29 -0
- package/dist/core/ToolExecutor.d.ts.map +1 -0
- package/dist/core/ToolExecutor.js +69 -0
- package/dist/core/ToolExecutor.js.map +1 -0
- package/dist/core/Transition.d.ts +5 -5
- package/dist/core/Transition.d.ts.map +1 -1
- package/dist/core/Transition.js.map +1 -1
- package/dist/index.d.ts +6 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -5
- package/dist/index.js.map +1 -1
- package/dist/providers/AnthropicProvider.d.ts.map +1 -1
- package/dist/providers/AnthropicProvider.js +10 -13
- package/dist/providers/AnthropicProvider.js.map +1 -1
- package/dist/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/providers/GeminiProvider.js +12 -8
- package/dist/providers/GeminiProvider.js.map +1 -1
- package/dist/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/providers/OpenAIProvider.js +10 -53
- package/dist/providers/OpenAIProvider.js.map +1 -1
- package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
- package/dist/providers/OpenRouterProvider.js +10 -53
- package/dist/providers/OpenRouterProvider.js.map +1 -1
- package/dist/types/agent.d.ts +13 -12
- package/dist/types/agent.d.ts.map +1 -1
- package/dist/types/ai.d.ts +8 -2
- package/dist/types/ai.d.ts.map +1 -1
- package/dist/types/history.d.ts +8 -0
- package/dist/types/history.d.ts.map +1 -1
- package/dist/types/index.d.ts +0 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +0 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/route.d.ts +39 -4
- package/dist/types/route.d.ts.map +1 -1
- package/dist/types/routing.d.ts +16 -0
- package/dist/types/routing.d.ts.map +1 -0
- package/dist/types/routing.js +2 -0
- package/dist/types/routing.js.map +1 -0
- package/dist/types/schema.d.ts +22 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +2 -0
- package/dist/types/schema.js.map +1 -0
- package/dist/types/session.d.ts +72 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +132 -0
- package/dist/types/session.js.map +1 -0
- package/dist/types/tool.d.ts +11 -5
- package/dist/types/tool.d.ts.map +1 -1
- package/dist/utils/id.d.ts +0 -5
- package/dist/utils/id.d.ts.map +1 -1
- package/dist/utils/id.js +0 -9
- package/dist/utils/id.js.map +1 -1
- package/dist/utils/schema.d.ts +17 -0
- package/dist/utils/schema.d.ts.map +1 -0
- package/dist/utils/schema.js +27 -0
- package/dist/utils/schema.js.map +1 -0
- package/docs/ADAPTERS.md +83 -3
- package/docs/API_REFERENCE.md +95 -104
- package/docs/ARCHITECTURE.md +284 -286
- package/docs/CONSTRUCTOR_OPTIONS.md +192 -135
- package/docs/CONTEXT_MANAGEMENT.md +311 -28
- package/docs/CONTRIBUTING.md +1 -1
- package/docs/DOMAINS.md +61 -0
- package/docs/GETTING_STARTED.md +177 -88
- package/docs/PERSISTENCE.md +170 -23
- package/docs/README.md +7 -10
- package/examples/business-onboarding.ts +21 -9
- package/examples/company-qna-agent.ts +508 -0
- package/examples/declarative-agent.ts +143 -26
- package/examples/domain-scoping.ts +31 -10
- package/examples/extracted-data-modification.ts +415 -0
- package/examples/healthcare-agent.ts +194 -90
- package/examples/openai-agent.ts +67 -25
- package/examples/opensearch-persistence.ts +455 -151
- package/examples/persistent-onboarding.ts +162 -96
- package/examples/prisma-persistence.ts +371 -125
- package/examples/redis-persistence.ts +393 -23
- package/examples/rules-prohibitions.ts +32 -11
- package/examples/streaming-agent.ts +61 -13
- package/examples/travel-agent.ts +266 -133
- package/package.json +1 -1
- package/src/core/Agent.ts +674 -356
- package/src/core/Events.ts +12 -2
- package/src/core/PersistenceManager.ts +83 -0
- package/src/core/PromptComposer.ts +143 -0
- package/src/core/ResponseEngine.ts +82 -0
- package/src/core/Route.ts +32 -17
- package/src/core/RoutingEngine.ts +165 -0
- package/src/core/State.ts +55 -15
- package/src/core/ToolExecutor.ts +117 -0
- package/src/core/Transition.ts +5 -5
- package/src/index.ts +12 -21
- package/src/providers/AnthropicProvider.ts +10 -13
- package/src/providers/GeminiProvider.ts +12 -8
- package/src/providers/OpenAIProvider.ts +10 -56
- package/src/providers/OpenRouterProvider.ts +10 -56
- package/src/types/agent.ts +16 -13
- package/src/types/ai.ts +6 -2
- package/src/types/history.ts +8 -0
- package/src/types/index.ts +0 -11
- package/src/types/route.ts +41 -5
- package/src/types/routing.ts +18 -0
- package/src/types/schema.ts +23 -0
- package/src/types/session.ts +207 -0
- package/src/types/tool.ts +29 -7
- package/src/utils/id.ts +0 -10
- package/src/utils/schema.ts +32 -0
- package/dist/cjs/core/ConditionEvaluator.d.ts +0 -72
- package/dist/cjs/core/ConditionEvaluator.d.ts.map +0 -1
- package/dist/cjs/core/ConditionEvaluator.js +0 -272
- package/dist/cjs/core/ConditionEvaluator.js.map +0 -1
- package/dist/cjs/core/Observation.d.ts +0 -24
- package/dist/cjs/core/Observation.d.ts.map +0 -1
- package/dist/cjs/core/Observation.js +0 -39
- package/dist/cjs/core/Observation.js.map +0 -1
- package/dist/cjs/core/PreparationEngine.d.ts +0 -116
- package/dist/cjs/core/PreparationEngine.d.ts.map +0 -1
- package/dist/cjs/core/PreparationEngine.js +0 -353
- package/dist/cjs/core/PreparationEngine.js.map +0 -1
- package/dist/cjs/core/PromptBuilder.d.ts +0 -136
- package/dist/cjs/core/PromptBuilder.d.ts.map +0 -1
- package/dist/cjs/core/PromptBuilder.js +0 -421
- package/dist/cjs/core/PromptBuilder.js.map +0 -1
- package/dist/cjs/types/observation.d.ts +0 -27
- package/dist/cjs/types/observation.d.ts.map +0 -1
- package/dist/cjs/types/observation.js +0 -6
- package/dist/cjs/types/observation.js.map +0 -1
- package/dist/cjs/types/prompt.d.ts +0 -46
- package/dist/cjs/types/prompt.d.ts.map +0 -1
- package/dist/cjs/types/prompt.js +0 -19
- package/dist/cjs/types/prompt.js.map +0 -1
- package/dist/core/ConditionEvaluator.d.ts +0 -72
- package/dist/core/ConditionEvaluator.d.ts.map +0 -1
- package/dist/core/ConditionEvaluator.js +0 -268
- package/dist/core/ConditionEvaluator.js.map +0 -1
- package/dist/core/Observation.d.ts +0 -24
- package/dist/core/Observation.d.ts.map +0 -1
- package/dist/core/Observation.js +0 -35
- package/dist/core/Observation.js.map +0 -1
- package/dist/core/PreparationEngine.d.ts +0 -116
- package/dist/core/PreparationEngine.d.ts.map +0 -1
- package/dist/core/PreparationEngine.js +0 -349
- package/dist/core/PreparationEngine.js.map +0 -1
- package/dist/core/PromptBuilder.d.ts +0 -136
- package/dist/core/PromptBuilder.d.ts.map +0 -1
- package/dist/core/PromptBuilder.js +0 -417
- package/dist/core/PromptBuilder.js.map +0 -1
- package/dist/types/observation.d.ts +0 -27
- package/dist/types/observation.d.ts.map +0 -1
- package/dist/types/observation.js +0 -5
- package/dist/types/observation.js.map +0 -1
- package/dist/types/prompt.d.ts +0 -46
- package/dist/types/prompt.d.ts.map +0 -1
- package/dist/types/prompt.js +0 -16
- package/dist/types/prompt.js.map +0 -1
- package/docs/STRUCTURE.md +0 -58
- package/src/core/ConditionEvaluator.ts +0 -381
- package/src/core/Observation.ts +0 -47
- package/src/core/PreparationEngine.ts +0 -561
- package/src/core/PromptBuilder.ts +0 -617
- package/src/types/observation.ts +0 -29
- package/src/types/prompt.ts +0 -49
package/src/core/State.ts
CHANGED
|
@@ -16,18 +16,27 @@ import { generateStateId } from "../utils/id";
|
|
|
16
16
|
/**
|
|
17
17
|
* Represents a state within a route
|
|
18
18
|
*/
|
|
19
|
-
export class State<TContext = unknown> {
|
|
19
|
+
export class State<TContext = unknown, TExtracted = unknown> {
|
|
20
20
|
public readonly id: string;
|
|
21
|
-
private transitions: Transition<TContext>[] = [];
|
|
21
|
+
private transitions: Transition<TContext, TExtracted>[] = [];
|
|
22
22
|
private guidelines: Guideline[] = [];
|
|
23
|
+
public readonly gatherFields?: string[];
|
|
24
|
+
public readonly skipIf?: (extracted: Partial<TExtracted>) => boolean;
|
|
25
|
+
public readonly requiredData?: string[];
|
|
23
26
|
|
|
24
27
|
constructor(
|
|
25
28
|
public readonly routeId: string,
|
|
26
29
|
public readonly description?: string,
|
|
27
|
-
customId?: string
|
|
30
|
+
customId?: string,
|
|
31
|
+
gatherFields?: string[],
|
|
32
|
+
skipIf?: (extracted: Partial<TExtracted>) => boolean,
|
|
33
|
+
requiredData?: string[]
|
|
28
34
|
) {
|
|
29
35
|
// Use provided ID or generate a deterministic one
|
|
30
36
|
this.id = customId || generateStateId(routeId, description);
|
|
37
|
+
this.gatherFields = gatherFields;
|
|
38
|
+
this.skipIf = skipIf;
|
|
39
|
+
this.requiredData = requiredData;
|
|
31
40
|
}
|
|
32
41
|
|
|
33
42
|
/**
|
|
@@ -38,16 +47,16 @@ export class State<TContext = unknown> {
|
|
|
38
47
|
* @returns TransitionResult that supports chaining
|
|
39
48
|
*/
|
|
40
49
|
transitionTo(
|
|
41
|
-
spec: TransitionSpec<TContext>,
|
|
50
|
+
spec: TransitionSpec<TContext, TExtracted>,
|
|
42
51
|
condition?: string
|
|
43
|
-
): TransitionResult<TContext> {
|
|
52
|
+
): TransitionResult<TContext, TExtracted> {
|
|
44
53
|
// Handle END_ROUTE
|
|
45
54
|
if (
|
|
46
55
|
spec.state &&
|
|
47
56
|
typeof spec.state === "symbol" &&
|
|
48
57
|
spec.state === END_ROUTE
|
|
49
58
|
) {
|
|
50
|
-
const endTransition = new Transition<TContext>(
|
|
59
|
+
const endTransition = new Transition<TContext, TExtracted>(
|
|
51
60
|
this.getRef(),
|
|
52
61
|
{ state: END_ROUTE },
|
|
53
62
|
condition
|
|
@@ -60,7 +69,7 @@ export class State<TContext = unknown> {
|
|
|
60
69
|
|
|
61
70
|
// Handle direct state reference
|
|
62
71
|
if (spec.state && typeof spec.state !== "symbol") {
|
|
63
|
-
const transition = new Transition<TContext>(
|
|
72
|
+
const transition = new Transition<TContext, TExtracted>(
|
|
64
73
|
this.getRef(),
|
|
65
74
|
spec,
|
|
66
75
|
condition
|
|
@@ -71,8 +80,19 @@ export class State<TContext = unknown> {
|
|
|
71
80
|
}
|
|
72
81
|
|
|
73
82
|
// Create new target state for chatState or toolState
|
|
74
|
-
const targetState = new State<TContext>(
|
|
75
|
-
|
|
83
|
+
const targetState = new State<TContext, TExtracted>(
|
|
84
|
+
this.routeId,
|
|
85
|
+
spec.chatState,
|
|
86
|
+
undefined,
|
|
87
|
+
spec.gather,
|
|
88
|
+
spec.skipIf,
|
|
89
|
+
spec.requiredData
|
|
90
|
+
);
|
|
91
|
+
const transition = new Transition<TContext, TExtracted>(
|
|
92
|
+
this.getRef(),
|
|
93
|
+
spec,
|
|
94
|
+
condition
|
|
95
|
+
);
|
|
76
96
|
transition.setTarget(targetState);
|
|
77
97
|
|
|
78
98
|
this.transitions.push(transition);
|
|
@@ -97,10 +117,28 @@ export class State<TContext = unknown> {
|
|
|
97
117
|
/**
|
|
98
118
|
* Get all transitions from this state
|
|
99
119
|
*/
|
|
100
|
-
getTransitions(): Transition<TContext>[] {
|
|
120
|
+
getTransitions(): Transition<TContext, TExtracted>[] {
|
|
101
121
|
return [...this.transitions];
|
|
102
122
|
}
|
|
103
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Check if this state should be skipped based on extracted data
|
|
126
|
+
*/
|
|
127
|
+
shouldSkip(extracted: Partial<TExtracted>): boolean {
|
|
128
|
+
if (!this.skipIf) return false;
|
|
129
|
+
return this.skipIf(extracted);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Check if this state has all required data to proceed
|
|
134
|
+
*/
|
|
135
|
+
hasRequiredData(extracted: Partial<TExtracted>): boolean {
|
|
136
|
+
if (!this.requiredData || this.requiredData.length === 0) return true;
|
|
137
|
+
return this.requiredData.every(
|
|
138
|
+
(key) => extracted[key as keyof TExtracted] !== undefined
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
104
142
|
/**
|
|
105
143
|
* Get state reference
|
|
106
144
|
*/
|
|
@@ -116,21 +154,23 @@ export class State<TContext = unknown> {
|
|
|
116
154
|
*/
|
|
117
155
|
private createStateRefWithTransition(
|
|
118
156
|
ref: StateRef,
|
|
119
|
-
state?: State<TContext>
|
|
120
|
-
): TransitionResult<TContext> {
|
|
157
|
+
state?: State<TContext, TExtracted>
|
|
158
|
+
): TransitionResult<TContext, TExtracted> {
|
|
121
159
|
const stateInstance = state || this;
|
|
122
160
|
|
|
123
161
|
return {
|
|
124
162
|
...ref,
|
|
125
|
-
transitionTo: (
|
|
126
|
-
|
|
163
|
+
transitionTo: (
|
|
164
|
+
spec: TransitionSpec<TContext, TExtracted>,
|
|
165
|
+
condition?: string
|
|
166
|
+
) => stateInstance.transitionTo(spec, condition),
|
|
127
167
|
};
|
|
128
168
|
}
|
|
129
169
|
|
|
130
170
|
/**
|
|
131
171
|
* Create a terminal state reference (for END_ROUTE)
|
|
132
172
|
*/
|
|
133
|
-
private createTerminalRef(): TransitionResult<TContext> {
|
|
173
|
+
private createTerminalRef(): TransitionResult<TContext, TExtracted> {
|
|
134
174
|
const terminalRef: StateRef = {
|
|
135
175
|
id: "END",
|
|
136
176
|
routeId: this.routeId,
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ToolExecutor - Simple utility for executing tools with context
|
|
3
|
+
*
|
|
4
|
+
* Tools execute BEFORE message generation to enrich context with data.
|
|
5
|
+
* The LLM sees the enriched context when generating responses.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Event } from "../types/history";
|
|
9
|
+
import type { ToolRef, ToolContext } from "../types/tool";
|
|
10
|
+
|
|
11
|
+
export interface ToolExecutionResult {
|
|
12
|
+
toolName: string;
|
|
13
|
+
success: boolean;
|
|
14
|
+
data?: unknown;
|
|
15
|
+
contextUpdate?: Record<string, unknown>;
|
|
16
|
+
extractedUpdate?: Record<string, unknown>;
|
|
17
|
+
error?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class ToolExecutor<TContext = unknown, TExtracted = unknown> {
|
|
21
|
+
/**
|
|
22
|
+
* Execute a single tool with context and extracted data
|
|
23
|
+
* @param allowedDomains - Array of domain names allowed for this execution context (undefined = all domains allowed)
|
|
24
|
+
*/
|
|
25
|
+
async executeTool(
|
|
26
|
+
tool: ToolRef<TContext, unknown[], unknown>,
|
|
27
|
+
context: TContext,
|
|
28
|
+
updateContext: (updates: Partial<TContext>) => Promise<void>,
|
|
29
|
+
history: Event[],
|
|
30
|
+
extracted?: Partial<TExtracted>,
|
|
31
|
+
allowedDomains?: string[]
|
|
32
|
+
): Promise<ToolExecutionResult> {
|
|
33
|
+
try {
|
|
34
|
+
// Domain enforcement: Check if tool's domain is allowed
|
|
35
|
+
if (allowedDomains !== undefined && tool.domainName) {
|
|
36
|
+
// allowedDomains is explicitly set (could be empty array)
|
|
37
|
+
if (!allowedDomains.includes(tool.domainName)) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`Domain security violation: Tool "${
|
|
40
|
+
tool.name
|
|
41
|
+
}" belongs to domain "${
|
|
42
|
+
tool.domainName
|
|
43
|
+
}" which is not allowed in this route. Allowed domains: [${allowedDomains.join(
|
|
44
|
+
", "
|
|
45
|
+
)}]`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Build tool context with extracted data
|
|
51
|
+
const toolContext: ToolContext<TContext, TExtracted> = {
|
|
52
|
+
context,
|
|
53
|
+
updateContext,
|
|
54
|
+
history,
|
|
55
|
+
extracted,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Execute tool (no arguments - tools read from context/extracted)
|
|
59
|
+
const result = await tool.handler(toolContext);
|
|
60
|
+
|
|
61
|
+
// Return execution result
|
|
62
|
+
return {
|
|
63
|
+
toolName: tool.name,
|
|
64
|
+
success: true,
|
|
65
|
+
data: result.data,
|
|
66
|
+
contextUpdate: result.contextUpdate,
|
|
67
|
+
extractedUpdate: result.extractedUpdate,
|
|
68
|
+
};
|
|
69
|
+
} catch (error) {
|
|
70
|
+
return {
|
|
71
|
+
toolName: tool.name,
|
|
72
|
+
success: false,
|
|
73
|
+
error: error instanceof Error ? error.message : String(error),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Execute multiple tools in sequence
|
|
80
|
+
* @param allowedDomains - Array of domain names allowed for this execution context (undefined = all domains allowed)
|
|
81
|
+
*/
|
|
82
|
+
async executeTools(
|
|
83
|
+
tools: Array<ToolRef<TContext, unknown[], unknown>>,
|
|
84
|
+
context: TContext,
|
|
85
|
+
updateContext: (updates: Partial<TContext>) => Promise<void>,
|
|
86
|
+
history: Event[],
|
|
87
|
+
extracted?: Partial<TExtracted>,
|
|
88
|
+
allowedDomains?: string[]
|
|
89
|
+
): Promise<ToolExecutionResult[]> {
|
|
90
|
+
const results: ToolExecutionResult[] = [];
|
|
91
|
+
|
|
92
|
+
for (const tool of tools) {
|
|
93
|
+
const result = await this.executeTool(
|
|
94
|
+
tool,
|
|
95
|
+
context,
|
|
96
|
+
updateContext,
|
|
97
|
+
history,
|
|
98
|
+
extracted,
|
|
99
|
+
allowedDomains
|
|
100
|
+
);
|
|
101
|
+
results.push(result);
|
|
102
|
+
|
|
103
|
+
// If tool failed, stop execution chain
|
|
104
|
+
if (!result.success) {
|
|
105
|
+
console.error(`[ToolExecutor] Tool ${tool.name} failed:`, result.error);
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Apply context updates from tool result
|
|
110
|
+
if (result.contextUpdate) {
|
|
111
|
+
await updateContext(result.contextUpdate as Partial<TContext>);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return results;
|
|
116
|
+
}
|
|
117
|
+
}
|
package/src/core/Transition.ts
CHANGED
|
@@ -8,26 +8,26 @@ import type { State } from "./State";
|
|
|
8
8
|
/**
|
|
9
9
|
* Represents a transition from one state to another
|
|
10
10
|
*/
|
|
11
|
-
export class Transition<TContext = unknown> {
|
|
12
|
-
private target?: State<TContext>;
|
|
11
|
+
export class Transition<TContext = unknown, TExtracted = unknown> {
|
|
12
|
+
private target?: State<TContext, TExtracted>;
|
|
13
13
|
|
|
14
14
|
constructor(
|
|
15
15
|
public readonly source: StateRef,
|
|
16
|
-
public readonly spec: TransitionSpec<TContext>,
|
|
16
|
+
public readonly spec: TransitionSpec<TContext, TExtracted>,
|
|
17
17
|
public readonly condition?: string
|
|
18
18
|
) {}
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Set the target state for this transition
|
|
22
22
|
*/
|
|
23
|
-
setTarget(state: State<TContext>): void {
|
|
23
|
+
setTarget(state: State<TContext, TExtracted>): void {
|
|
24
24
|
this.target = state;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Get the target state
|
|
29
29
|
*/
|
|
30
|
-
getTarget(): State<TContext> | undefined {
|
|
30
|
+
getTarget(): State<TContext, TExtracted> | undefined {
|
|
31
31
|
return this.target;
|
|
32
32
|
}
|
|
33
33
|
|
package/src/index.ts
CHANGED
|
@@ -9,14 +9,12 @@ export { Agent } from "./core/Agent";
|
|
|
9
9
|
export { Route } from "./core/Route";
|
|
10
10
|
export { State } from "./core/State";
|
|
11
11
|
export { Transition } from "./core/Transition";
|
|
12
|
-
export { Observation } from "./core/Observation";
|
|
13
12
|
export { defineTool } from "./core/Tool";
|
|
14
13
|
export { DomainRegistry } from "./core/DomainRegistry";
|
|
15
14
|
export { adaptEvent, createMessageEvent, createToolEvent } from "./core/Events";
|
|
16
|
-
export { PromptBuilder } from "./core/PromptBuilder";
|
|
17
|
-
export type { Customer, AgentInfo } from "./core/PromptBuilder";
|
|
18
|
-
export { BuiltInSection } from "./core/PromptBuilder";
|
|
19
15
|
export { PersistenceManager } from "./core/PersistenceManager";
|
|
16
|
+
export { ToolExecutor } from "./core/ToolExecutor";
|
|
17
|
+
export type { ToolExecutionResult } from "./core/ToolExecutor";
|
|
20
18
|
|
|
21
19
|
// Providers
|
|
22
20
|
export { GeminiProvider } from "./providers/GeminiProvider";
|
|
@@ -67,12 +65,7 @@ export type {
|
|
|
67
65
|
export { END_ROUTE } from "./constants";
|
|
68
66
|
|
|
69
67
|
// Utils
|
|
70
|
-
export {
|
|
71
|
-
generateRouteId,
|
|
72
|
-
generateStateId,
|
|
73
|
-
generateObservationId,
|
|
74
|
-
generateToolId,
|
|
75
|
-
} from "./utils/id";
|
|
68
|
+
export { generateRouteId, generateStateId, generateToolId } from "./utils/id";
|
|
76
69
|
|
|
77
70
|
// Types
|
|
78
71
|
export type {
|
|
@@ -104,6 +97,14 @@ export type {
|
|
|
104
97
|
TransitionResult,
|
|
105
98
|
} from "./types/route";
|
|
106
99
|
|
|
100
|
+
export type { SessionState } from "./types/session";
|
|
101
|
+
export {
|
|
102
|
+
createSession,
|
|
103
|
+
enterRoute,
|
|
104
|
+
enterState,
|
|
105
|
+
mergeExtracted,
|
|
106
|
+
} from "./types/session";
|
|
107
|
+
|
|
107
108
|
export type {
|
|
108
109
|
ToolContext,
|
|
109
110
|
ToolResult,
|
|
@@ -119,17 +120,7 @@ export type {
|
|
|
119
120
|
ReasoningConfig,
|
|
120
121
|
} from "./types/ai";
|
|
121
122
|
|
|
122
|
-
export type {
|
|
123
|
-
PromptSection,
|
|
124
|
-
ContextVariable,
|
|
125
|
-
ContextVariableValue,
|
|
126
|
-
} from "./types/prompt";
|
|
127
|
-
export { SectionStatus } from "./types/prompt";
|
|
128
|
-
|
|
129
|
-
export type {
|
|
130
|
-
Observation as IObservation,
|
|
131
|
-
ObservationOptions,
|
|
132
|
-
} from "./types/observation";
|
|
123
|
+
export type { StructuredSchema } from "./types/schema";
|
|
133
124
|
|
|
134
125
|
export type {
|
|
135
126
|
SessionData,
|
|
@@ -258,13 +258,10 @@ export class AnthropicProvider implements AiProvider {
|
|
|
258
258
|
...this.config,
|
|
259
259
|
};
|
|
260
260
|
|
|
261
|
-
// Handle
|
|
262
|
-
|
|
263
|
-
// but we can add it to the system prompt
|
|
264
|
-
if (input.parameters?.jsonMode) {
|
|
265
|
-
// Add system message requesting JSON output
|
|
261
|
+
// Handle schema: Anthropic doesn't have a native schema mode, so embed constraints
|
|
262
|
+
if (input.parameters?.jsonSchema) {
|
|
266
263
|
const systemPrompt =
|
|
267
|
-
"You must respond with valid JSON only
|
|
264
|
+
"You must respond with valid JSON only and it MUST match the provided schema.";
|
|
268
265
|
|
|
269
266
|
// Merge with existing system if present
|
|
270
267
|
if (typeof this.config?.system === "string") {
|
|
@@ -294,9 +291,9 @@ export class AnthropicProvider implements AiProvider {
|
|
|
294
291
|
throw new Error("No response from Anthropic");
|
|
295
292
|
}
|
|
296
293
|
|
|
297
|
-
// Parse JSON response if
|
|
294
|
+
// Parse JSON response if schema was provided
|
|
298
295
|
let structured: AgentStructuredResponse | undefined;
|
|
299
|
-
if (input.parameters?.
|
|
296
|
+
if (input.parameters?.jsonSchema) {
|
|
300
297
|
try {
|
|
301
298
|
structured = JSON.parse(message) as AgentStructuredResponse;
|
|
302
299
|
} catch (error) {
|
|
@@ -418,10 +415,10 @@ export class AnthropicProvider implements AiProvider {
|
|
|
418
415
|
...this.config,
|
|
419
416
|
};
|
|
420
417
|
|
|
421
|
-
// Handle
|
|
422
|
-
if (input.parameters?.
|
|
418
|
+
// Handle schema in streaming: embed constraint
|
|
419
|
+
if (input.parameters?.jsonSchema) {
|
|
423
420
|
const systemPrompt =
|
|
424
|
-
"You must respond with valid JSON only
|
|
421
|
+
"You must respond with valid JSON only and it MUST match the provided schema.";
|
|
425
422
|
|
|
426
423
|
if (typeof this.config?.system === "string") {
|
|
427
424
|
params.system = `${this.config.system}\n\n${systemPrompt}`;
|
|
@@ -466,9 +463,9 @@ export class AnthropicProvider implements AiProvider {
|
|
|
466
463
|
}
|
|
467
464
|
}
|
|
468
465
|
|
|
469
|
-
// Parse JSON response if
|
|
466
|
+
// Parse JSON response if schema was provided
|
|
470
467
|
let structured: AgentStructuredResponse | undefined;
|
|
471
|
-
if (input.parameters?.
|
|
468
|
+
if (input.parameters?.jsonSchema && accumulated) {
|
|
472
469
|
try {
|
|
473
470
|
structured = JSON.parse(accumulated) as AgentStructuredResponse;
|
|
474
471
|
} catch (error) {
|
|
@@ -235,10 +235,13 @@ export class GeminiProvider implements AiProvider {
|
|
|
235
235
|
input: GenerateMessageInput<TContext>
|
|
236
236
|
): Promise<GenerateMessageOutput<TStructured>> {
|
|
237
237
|
const operation = async (): Promise<GenerateMessageOutput> => {
|
|
238
|
-
//
|
|
238
|
+
// Schema-required: configure response schema
|
|
239
239
|
const configOverride: Partial<GenerateContentConfig> = { ...this.config };
|
|
240
|
-
if (input.parameters?.
|
|
240
|
+
if (input.parameters?.jsonSchema) {
|
|
241
241
|
configOverride.responseMimeType = "application/json";
|
|
242
|
+
// Gemini expects responseSchema. We pass through our schema as-is.
|
|
243
|
+
// A deeper mapping can be added via utils if needed.
|
|
244
|
+
configOverride.responseSchema = input.parameters.jsonSchema;
|
|
242
245
|
}
|
|
243
246
|
|
|
244
247
|
const response: GenerateContentResponse =
|
|
@@ -253,9 +256,9 @@ export class GeminiProvider implements AiProvider {
|
|
|
253
256
|
throw new Error("No response from Gemini");
|
|
254
257
|
}
|
|
255
258
|
|
|
256
|
-
// Parse JSON response if
|
|
259
|
+
// Parse JSON response if schema was provided
|
|
257
260
|
let structured: AgentStructuredResponse | undefined;
|
|
258
|
-
if (input.parameters?.
|
|
261
|
+
if (input.parameters?.jsonSchema) {
|
|
259
262
|
try {
|
|
260
263
|
structured = JSON.parse(message) as AgentStructuredResponse;
|
|
261
264
|
} catch (error) {
|
|
@@ -353,10 +356,11 @@ export class GeminiProvider implements AiProvider {
|
|
|
353
356
|
model: string,
|
|
354
357
|
input: GenerateMessageInput<TContext>
|
|
355
358
|
): AsyncGenerator<GenerateMessageStreamChunk<TStructured>> {
|
|
356
|
-
//
|
|
359
|
+
// Streaming: request JSON if schema provided
|
|
357
360
|
const configOverride: Partial<GenerateContentConfig> = { ...this.config };
|
|
358
|
-
if (input.parameters?.
|
|
361
|
+
if (input.parameters?.jsonSchema) {
|
|
359
362
|
configOverride.responseMimeType = "application/json";
|
|
363
|
+
configOverride.responseSchema = input.parameters.jsonSchema;
|
|
360
364
|
}
|
|
361
365
|
|
|
362
366
|
const stream = await this.genAI.models.generateContentStream({
|
|
@@ -390,9 +394,9 @@ export class GeminiProvider implements AiProvider {
|
|
|
390
394
|
}
|
|
391
395
|
}
|
|
392
396
|
|
|
393
|
-
// Parse JSON response if
|
|
397
|
+
// Parse JSON response if schema was provided
|
|
394
398
|
let structured: AgentStructuredResponse | undefined;
|
|
395
|
-
if (input.parameters?.
|
|
399
|
+
if (input.parameters?.jsonSchema && accumulated) {
|
|
396
400
|
try {
|
|
397
401
|
structured = JSON.parse(accumulated) as AgentStructuredResponse;
|
|
398
402
|
} catch (error) {
|
|
@@ -266,53 +266,8 @@ export class OpenAIProvider implements AiProvider {
|
|
|
266
266
|
params.max_tokens = input.parameters.maxOutputTokens;
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
-
// Use structured output API if JSON
|
|
270
|
-
if (input.parameters?.
|
|
271
|
-
// Define the JSON schema for agent response
|
|
272
|
-
const agentResponseSchema = {
|
|
273
|
-
type: "object",
|
|
274
|
-
properties: {
|
|
275
|
-
message: {
|
|
276
|
-
type: "string",
|
|
277
|
-
description: "The actual message to send to the user",
|
|
278
|
-
},
|
|
279
|
-
route: {
|
|
280
|
-
type: ["string", "null"],
|
|
281
|
-
description:
|
|
282
|
-
"The title of the route chosen (or null if no specific route)",
|
|
283
|
-
},
|
|
284
|
-
state: {
|
|
285
|
-
type: ["string", "null"],
|
|
286
|
-
description:
|
|
287
|
-
"The current state within the route (or null if not in a route)",
|
|
288
|
-
},
|
|
289
|
-
toolCalls: {
|
|
290
|
-
type: "array",
|
|
291
|
-
items: {
|
|
292
|
-
type: "object",
|
|
293
|
-
properties: {
|
|
294
|
-
toolName: {
|
|
295
|
-
type: "string",
|
|
296
|
-
description: "Name of the tool to call",
|
|
297
|
-
},
|
|
298
|
-
arguments: {
|
|
299
|
-
type: "object",
|
|
300
|
-
description: "Arguments to pass to the tool",
|
|
301
|
-
},
|
|
302
|
-
},
|
|
303
|
-
required: ["toolName", "arguments"],
|
|
304
|
-
},
|
|
305
|
-
description: "Tool calls the agent wants to execute",
|
|
306
|
-
},
|
|
307
|
-
reasoning: {
|
|
308
|
-
type: "string",
|
|
309
|
-
description: "Optional: Internal reasoning for this response",
|
|
310
|
-
},
|
|
311
|
-
},
|
|
312
|
-
required: ["message"],
|
|
313
|
-
additionalProperties: false,
|
|
314
|
-
};
|
|
315
|
-
|
|
269
|
+
// Use structured output API if JSON schema is provided
|
|
270
|
+
if (input.parameters?.jsonSchema) {
|
|
316
271
|
const response = await this.client.responses.parse({
|
|
317
272
|
model,
|
|
318
273
|
instructions: input.prompt,
|
|
@@ -323,8 +278,8 @@ export class OpenAIProvider implements AiProvider {
|
|
|
323
278
|
text: {
|
|
324
279
|
format: {
|
|
325
280
|
type: "json_schema",
|
|
326
|
-
name: "
|
|
327
|
-
schema:
|
|
281
|
+
name: input.parameters?.schemaName || "structured_output",
|
|
282
|
+
schema: input.parameters.jsonSchema,
|
|
328
283
|
},
|
|
329
284
|
},
|
|
330
285
|
});
|
|
@@ -348,7 +303,7 @@ export class OpenAIProvider implements AiProvider {
|
|
|
348
303
|
};
|
|
349
304
|
}
|
|
350
305
|
|
|
351
|
-
// Fall back to regular chat completions API if
|
|
306
|
+
// Fall back to regular chat completions API if no schema provided
|
|
352
307
|
const response = await this.client.chat.completions.create(params);
|
|
353
308
|
|
|
354
309
|
const message = response.choices[0]?.message?.content;
|
|
@@ -468,10 +423,9 @@ export class OpenAIProvider implements AiProvider {
|
|
|
468
423
|
params.max_tokens = input.parameters.maxOutputTokens;
|
|
469
424
|
}
|
|
470
425
|
|
|
471
|
-
//
|
|
472
|
-
//
|
|
473
|
-
|
|
474
|
-
if (input.parameters?.jsonMode) {
|
|
426
|
+
// Streaming path does not support responses.parse; if schema present,
|
|
427
|
+
// request JSON object and parse at the end.
|
|
428
|
+
if (input.parameters?.jsonSchema) {
|
|
475
429
|
params.response_format = { type: "json_object" };
|
|
476
430
|
}
|
|
477
431
|
|
|
@@ -509,9 +463,9 @@ export class OpenAIProvider implements AiProvider {
|
|
|
509
463
|
}
|
|
510
464
|
}
|
|
511
465
|
|
|
512
|
-
// Parse JSON response if
|
|
466
|
+
// Parse JSON response if schema was provided
|
|
513
467
|
let structured: TStructured | undefined;
|
|
514
|
-
if (input.parameters?.
|
|
468
|
+
if (input.parameters?.jsonSchema && accumulated) {
|
|
515
469
|
try {
|
|
516
470
|
structured = JSON.parse(accumulated) as TStructured;
|
|
517
471
|
} catch (error) {
|
|
@@ -273,53 +273,8 @@ export class OpenRouterProvider implements AiProvider {
|
|
|
273
273
|
params.max_tokens = input.parameters.maxOutputTokens;
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
-
// Use structured output API if JSON
|
|
277
|
-
if (input.parameters?.
|
|
278
|
-
// Define the JSON schema for agent response
|
|
279
|
-
const agentResponseSchema = {
|
|
280
|
-
type: "object",
|
|
281
|
-
properties: {
|
|
282
|
-
message: {
|
|
283
|
-
type: "string",
|
|
284
|
-
description: "The actual message to send to the user",
|
|
285
|
-
},
|
|
286
|
-
route: {
|
|
287
|
-
type: ["string", "null"],
|
|
288
|
-
description:
|
|
289
|
-
"The title of the route chosen (or null if no specific route)",
|
|
290
|
-
},
|
|
291
|
-
state: {
|
|
292
|
-
type: ["string", "null"],
|
|
293
|
-
description:
|
|
294
|
-
"The current state within the route (or null if not in a route)",
|
|
295
|
-
},
|
|
296
|
-
toolCalls: {
|
|
297
|
-
type: "array",
|
|
298
|
-
items: {
|
|
299
|
-
type: "object",
|
|
300
|
-
properties: {
|
|
301
|
-
toolName: {
|
|
302
|
-
type: "string",
|
|
303
|
-
description: "Name of the tool to call",
|
|
304
|
-
},
|
|
305
|
-
arguments: {
|
|
306
|
-
type: "object",
|
|
307
|
-
description: "Arguments to pass to the tool",
|
|
308
|
-
},
|
|
309
|
-
},
|
|
310
|
-
required: ["toolName", "arguments"],
|
|
311
|
-
},
|
|
312
|
-
description: "Tool calls the agent wants to execute",
|
|
313
|
-
},
|
|
314
|
-
reasoning: {
|
|
315
|
-
type: "string",
|
|
316
|
-
description: "Optional: Internal reasoning for this response",
|
|
317
|
-
},
|
|
318
|
-
},
|
|
319
|
-
required: ["message"],
|
|
320
|
-
additionalProperties: false,
|
|
321
|
-
};
|
|
322
|
-
|
|
276
|
+
// Use structured output API if JSON schema is provided
|
|
277
|
+
if (input.parameters?.jsonSchema) {
|
|
323
278
|
const response = await this.client.responses.parse({
|
|
324
279
|
model,
|
|
325
280
|
instructions: input.prompt,
|
|
@@ -330,8 +285,8 @@ export class OpenRouterProvider implements AiProvider {
|
|
|
330
285
|
text: {
|
|
331
286
|
format: {
|
|
332
287
|
type: "json_schema",
|
|
333
|
-
name: "
|
|
334
|
-
schema:
|
|
288
|
+
name: input.parameters?.schemaName || "structured_output",
|
|
289
|
+
schema: input.parameters.jsonSchema,
|
|
335
290
|
},
|
|
336
291
|
},
|
|
337
292
|
});
|
|
@@ -355,7 +310,7 @@ export class OpenRouterProvider implements AiProvider {
|
|
|
355
310
|
};
|
|
356
311
|
}
|
|
357
312
|
|
|
358
|
-
// Fall back to regular chat completions API if
|
|
313
|
+
// Fall back to regular chat completions API if no schema provided
|
|
359
314
|
const response = await this.client.chat.completions.create(params);
|
|
360
315
|
|
|
361
316
|
const message = response.choices[0]?.message?.content;
|
|
@@ -469,10 +424,9 @@ export class OpenRouterProvider implements AiProvider {
|
|
|
469
424
|
params.max_tokens = input.parameters.maxOutputTokens;
|
|
470
425
|
}
|
|
471
426
|
|
|
472
|
-
//
|
|
473
|
-
//
|
|
474
|
-
|
|
475
|
-
if (input.parameters?.jsonMode) {
|
|
427
|
+
// Streaming path does not support responses.parse; if schema present,
|
|
428
|
+
// request JSON object and parse at the end.
|
|
429
|
+
if (input.parameters?.jsonSchema) {
|
|
476
430
|
params.response_format = { type: "json_object" };
|
|
477
431
|
}
|
|
478
432
|
|
|
@@ -510,9 +464,9 @@ export class OpenRouterProvider implements AiProvider {
|
|
|
510
464
|
}
|
|
511
465
|
}
|
|
512
466
|
|
|
513
|
-
// Parse JSON response if
|
|
467
|
+
// Parse JSON response if schema was provided
|
|
514
468
|
let structured: TStructured | undefined;
|
|
515
|
-
if (input.parameters?.
|
|
469
|
+
if (input.parameters?.jsonSchema && accumulated) {
|
|
516
470
|
try {
|
|
517
471
|
structured = JSON.parse(accumulated) as TStructured;
|
|
518
472
|
} catch (error) {
|