@falai/agent 0.4.0 → 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 +465 -275
- 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 -9
- 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 +465 -275
- 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 -9
- 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 +679 -332
- 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 -10
- 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 -105
- package/dist/cjs/core/PreparationEngine.d.ts.map +0 -1
- package/dist/cjs/core/PreparationEngine.js +0 -320
- 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 -105
- package/dist/core/PreparationEngine.d.ts.map +0 -1
- package/dist/core/PreparationEngine.js +0 -316
- 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 -500
- package/src/core/PromptBuilder.ts +0 -617
- package/src/types/observation.ts +0 -29
- package/src/types/prompt.ts +0 -49
package/dist/core/Agent.js
CHANGED
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Core Agent implementation
|
|
3
3
|
*/
|
|
4
|
+
import { createSession, enterRoute, enterState, mergeExtracted, } from "../types/session";
|
|
5
|
+
import { EventKind } from "../types/history";
|
|
6
|
+
import { PromptComposer } from "./PromptComposer";
|
|
4
7
|
import { Route } from "./Route";
|
|
5
8
|
import { DomainRegistry } from "./DomainRegistry";
|
|
6
|
-
import { PromptBuilder } from "./PromptBuilder";
|
|
7
|
-
import { Observation } from "./Observation";
|
|
8
9
|
import { PersistenceManager } from "./PersistenceManager";
|
|
9
|
-
import {
|
|
10
|
+
import { RoutingEngine } from "./RoutingEngine";
|
|
11
|
+
import { ResponseEngine } from "./ResponseEngine";
|
|
12
|
+
import { ToolExecutor } from "./ToolExecutor";
|
|
13
|
+
/**
|
|
14
|
+
* Helper to extract last message from history
|
|
15
|
+
*/
|
|
16
|
+
function getLastMessageFromHistory(history) {
|
|
17
|
+
for (let i = history.length - 1; i >= 0; i--) {
|
|
18
|
+
const event = history[i];
|
|
19
|
+
if (event.kind === EventKind.MESSAGE) {
|
|
20
|
+
return event.data.message;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return "";
|
|
24
|
+
}
|
|
10
25
|
/**
|
|
11
26
|
* Main Agent class with generic context support
|
|
12
27
|
*/
|
|
@@ -16,25 +31,26 @@ export class Agent {
|
|
|
16
31
|
this.terms = [];
|
|
17
32
|
this.guidelines = [];
|
|
18
33
|
this.capabilities = [];
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
35
|
this.routes = [];
|
|
20
|
-
this.observations = [];
|
|
21
36
|
this.domainRegistry = new DomainRegistry();
|
|
22
37
|
/**
|
|
23
38
|
* Dynamic domain property - populated via addDomain
|
|
24
39
|
*/
|
|
25
40
|
this.domain = {};
|
|
26
|
-
// Initialize with default values
|
|
27
|
-
if (!this.options.maxEngineIterations) {
|
|
28
|
-
this.options.maxEngineIterations = 1;
|
|
29
|
-
}
|
|
30
41
|
// Validate context configuration
|
|
31
42
|
if (options.context !== undefined && options.contextProvider) {
|
|
32
43
|
throw new Error("Cannot provide both 'context' and 'contextProvider'. Choose one.");
|
|
33
44
|
}
|
|
34
45
|
// Initialize context if provided
|
|
35
46
|
this.context = options.context;
|
|
36
|
-
// Initialize
|
|
37
|
-
this.
|
|
47
|
+
// Initialize routing and response engines
|
|
48
|
+
this.routingEngine = new RoutingEngine({
|
|
49
|
+
maxCandidates: 5,
|
|
50
|
+
allowRouteSwitch: true,
|
|
51
|
+
switchThreshold: 70,
|
|
52
|
+
});
|
|
53
|
+
this.responseEngine = new ResponseEngine();
|
|
38
54
|
// Initialize persistence if configured
|
|
39
55
|
if (options.persistence) {
|
|
40
56
|
this.persistenceManager = new PersistenceManager(options.persistence);
|
|
@@ -64,23 +80,6 @@ export class Agent {
|
|
|
64
80
|
this.createRoute(routeOptions);
|
|
65
81
|
});
|
|
66
82
|
}
|
|
67
|
-
if (options.observations) {
|
|
68
|
-
options.observations.forEach((obsOptions) => {
|
|
69
|
-
const obs = this.createObservation(obsOptions.description);
|
|
70
|
-
// If route refs were provided, resolve and disambiguate
|
|
71
|
-
if (obsOptions.routeRefs && obsOptions.routeRefs.length > 0) {
|
|
72
|
-
const resolvedRoutes = obsOptions.routeRefs
|
|
73
|
-
.map((ref) => {
|
|
74
|
-
// Try to find route by ID or title
|
|
75
|
-
return this.routes.find((r) => r.id === ref || r.title === ref);
|
|
76
|
-
})
|
|
77
|
-
.filter((r) => r !== undefined);
|
|
78
|
-
if (resolvedRoutes.length > 0) {
|
|
79
|
-
obs.disambiguate(resolvedRoutes);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
83
|
}
|
|
85
84
|
/**
|
|
86
85
|
* Get agent name
|
|
@@ -102,6 +101,7 @@ export class Agent {
|
|
|
102
101
|
}
|
|
103
102
|
/**
|
|
104
103
|
* Create a new route (journey)
|
|
104
|
+
* @template TExtracted - Type of data extracted throughout the route
|
|
105
105
|
*/
|
|
106
106
|
createRoute(options) {
|
|
107
107
|
const route = new Route(options);
|
|
@@ -138,21 +138,28 @@ export class Agent {
|
|
|
138
138
|
this.capabilities.push(capabilityWithId);
|
|
139
139
|
return this;
|
|
140
140
|
}
|
|
141
|
-
/**
|
|
142
|
-
* Create an observation for disambiguation
|
|
143
|
-
*/
|
|
144
|
-
createObservation(description) {
|
|
145
|
-
const observation = new Observation({ description });
|
|
146
|
-
this.observations.push(observation);
|
|
147
|
-
return observation;
|
|
148
|
-
}
|
|
149
141
|
/**
|
|
150
142
|
* Add a domain with its tools/methods
|
|
143
|
+
* Automatically tags all ToolRef objects with their domain name for security enforcement
|
|
151
144
|
*/
|
|
152
145
|
addDomain(name, domainObject) {
|
|
153
|
-
this
|
|
146
|
+
// Tag all tools in this domain with the domain name for security enforcement
|
|
147
|
+
const taggedDomain = { ...domainObject };
|
|
148
|
+
for (const key in taggedDomain) {
|
|
149
|
+
const value = taggedDomain[key];
|
|
150
|
+
// Check if value is a ToolRef (has handler, id, name properties)
|
|
151
|
+
if (value &&
|
|
152
|
+
typeof value === "object" &&
|
|
153
|
+
"handler" in value &&
|
|
154
|
+
"id" in value &&
|
|
155
|
+
"name" in value) {
|
|
156
|
+
// Tag the tool with its domain name
|
|
157
|
+
value.domainName = name;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
this.domainRegistry.register(name, taggedDomain);
|
|
154
161
|
// Attach to the domain property for easy access
|
|
155
|
-
this.domain[name] =
|
|
162
|
+
this.domain[name] = taggedDomain;
|
|
156
163
|
}
|
|
157
164
|
/**
|
|
158
165
|
* Update the agent's context
|
|
@@ -170,6 +177,26 @@ export class Agent {
|
|
|
170
177
|
await this.options.hooks.onContextUpdate(this.context, previousContext);
|
|
171
178
|
}
|
|
172
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* Update extracted data in session with lifecycle hook support
|
|
182
|
+
* Triggers the onExtractedUpdate lifecycle hook if configured
|
|
183
|
+
* @internal
|
|
184
|
+
*/
|
|
185
|
+
async updateExtracted(session, extractedUpdate) {
|
|
186
|
+
const previousExtracted = { ...session.extracted };
|
|
187
|
+
// Merge new extracted data
|
|
188
|
+
let newExtracted = {
|
|
189
|
+
...session.extracted,
|
|
190
|
+
...extractedUpdate,
|
|
191
|
+
};
|
|
192
|
+
// Trigger lifecycle hook if configured
|
|
193
|
+
if (this.options.hooks?.onExtractedUpdate) {
|
|
194
|
+
const updatedExtracted = (await this.options.hooks.onExtractedUpdate(newExtracted, previousExtracted));
|
|
195
|
+
newExtracted = updatedExtracted;
|
|
196
|
+
}
|
|
197
|
+
// Return updated session
|
|
198
|
+
return mergeExtracted(session, newExtracted);
|
|
199
|
+
}
|
|
173
200
|
/**
|
|
174
201
|
* Get current context (fetches from provider if configured)
|
|
175
202
|
* @internal
|
|
@@ -182,6 +209,46 @@ export class Agent {
|
|
|
182
209
|
// Otherwise return the stored context
|
|
183
210
|
return this.context;
|
|
184
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Determine the next state in a route based on extracted data
|
|
214
|
+
* @internal
|
|
215
|
+
*/
|
|
216
|
+
getNextState(route, currentState, extracted) {
|
|
217
|
+
// If no current state, start from initial state
|
|
218
|
+
if (!currentState) {
|
|
219
|
+
// Check if initial state should be skipped
|
|
220
|
+
if (route.initialState.shouldSkip(extracted)) {
|
|
221
|
+
return this.getNextState(route, route.initialState, extracted);
|
|
222
|
+
}
|
|
223
|
+
return route.initialState;
|
|
224
|
+
}
|
|
225
|
+
// Get transitions from current state
|
|
226
|
+
const transitions = currentState.getTransitions();
|
|
227
|
+
// If no transitions, stay in current state
|
|
228
|
+
if (transitions.length === 0) {
|
|
229
|
+
return currentState;
|
|
230
|
+
}
|
|
231
|
+
// Try to find the next state to transition to
|
|
232
|
+
for (const transition of transitions) {
|
|
233
|
+
const target = transition.getTarget();
|
|
234
|
+
if (!target)
|
|
235
|
+
continue;
|
|
236
|
+
// Check if target state should be skipped
|
|
237
|
+
if (target.shouldSkip(extracted)) {
|
|
238
|
+
// Recursively find next non-skipped state
|
|
239
|
+
return this.getNextState(route, target, extracted);
|
|
240
|
+
}
|
|
241
|
+
// Check if target state has required data
|
|
242
|
+
if (!target.hasRequiredData(extracted)) {
|
|
243
|
+
// Cannot enter this state yet, stay in current state
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
// Found valid next state
|
|
247
|
+
return target;
|
|
248
|
+
}
|
|
249
|
+
// No valid transition found, stay in current state
|
|
250
|
+
return currentState;
|
|
251
|
+
}
|
|
185
252
|
/**
|
|
186
253
|
* Generate a response based on history and context as a stream
|
|
187
254
|
*/
|
|
@@ -196,138 +263,208 @@ export class Agent {
|
|
|
196
263
|
this.context = currentContext;
|
|
197
264
|
}
|
|
198
265
|
// Merge context with override
|
|
199
|
-
|
|
266
|
+
const effectiveContext = {
|
|
200
267
|
...currentContext,
|
|
201
268
|
...contextOverride,
|
|
202
269
|
};
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
// 1
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
270
|
+
// Initialize or get session
|
|
271
|
+
let session = params.session || createSession();
|
|
272
|
+
// PHASE 1: TOOL EXECUTION - Execute tools if current state has toolState
|
|
273
|
+
if (session.currentRoute && session.currentState) {
|
|
274
|
+
const currentRoute = this.routes.find((r) => r.id === session.currentRoute?.id);
|
|
275
|
+
if (currentRoute) {
|
|
276
|
+
const currentState = currentRoute.getState(session.currentState.id);
|
|
277
|
+
if (currentState) {
|
|
278
|
+
const transitions = currentState.getTransitions();
|
|
279
|
+
const toolTransition = transitions.find((t) => t.spec.toolState);
|
|
280
|
+
if (toolTransition?.spec.toolState) {
|
|
281
|
+
const toolExecutor = new ToolExecutor();
|
|
282
|
+
// Get allowed domains from current route for security enforcement
|
|
283
|
+
const allowedDomains = currentRoute.getDomains();
|
|
284
|
+
const result = await toolExecutor.executeTool(toolTransition.spec.toolState, effectiveContext, this.updateContext.bind(this), history, session.extracted, allowedDomains);
|
|
285
|
+
// Update context with tool results
|
|
286
|
+
if (result.contextUpdate) {
|
|
287
|
+
await this.updateContext(result.contextUpdate);
|
|
288
|
+
}
|
|
289
|
+
// Update extracted data with tool results
|
|
290
|
+
if (result.extractedUpdate) {
|
|
291
|
+
session = await this.updateExtracted(session, result.extractedUpdate);
|
|
292
|
+
console.log(`[Agent] Tool updated extracted data:`, result.extractedUpdate);
|
|
293
|
+
}
|
|
294
|
+
console.log(`[Agent] Executed tool: ${result.toolName} (success: ${result.success})`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
222
298
|
}
|
|
223
|
-
//
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (this.
|
|
227
|
-
|
|
299
|
+
// PHASE 2: ROUTING - Determine which route to use
|
|
300
|
+
let selectedRoute;
|
|
301
|
+
let responseDirectives;
|
|
302
|
+
if (this.routes.length > 0) {
|
|
303
|
+
// Get last user message
|
|
304
|
+
const lastUserMessage = getLastMessageFromHistory(history);
|
|
305
|
+
// Build routing schema
|
|
306
|
+
const routingSchema = this.routingEngine.buildDynamicRoutingSchema(this.routes);
|
|
307
|
+
// Build routing prompt with session context
|
|
308
|
+
const routingPrompt = this.routingEngine.buildRoutingPrompt(history, this.routes, lastUserMessage, {
|
|
228
309
|
name: this.options.name,
|
|
310
|
+
goal: this.options.goal,
|
|
229
311
|
description: this.options.description,
|
|
312
|
+
personality: this.options.personality,
|
|
313
|
+
}, session // Pass session for context-aware routing
|
|
314
|
+
);
|
|
315
|
+
// Call AI to score routes (non-streaming for routing decision)
|
|
316
|
+
const routingResult = await this.options.ai.generateMessage({
|
|
317
|
+
prompt: routingPrompt,
|
|
318
|
+
history,
|
|
319
|
+
context: effectiveContext,
|
|
320
|
+
signal,
|
|
321
|
+
parameters: {
|
|
322
|
+
jsonSchema: routingSchema,
|
|
323
|
+
schemaName: "routing_output",
|
|
324
|
+
},
|
|
230
325
|
});
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
description: obs.description,
|
|
255
|
-
routes: obs.getRoutes().map((routeRef) => {
|
|
256
|
-
const route = this.routes.find((r) => r.id === routeRef.id);
|
|
257
|
-
return { title: route?.title || routeRef.id };
|
|
258
|
-
}),
|
|
259
|
-
}))
|
|
260
|
-
.filter((obs) => obs.routes.length > 0);
|
|
261
|
-
if (observationsWithRoutes.length > 0) {
|
|
262
|
-
promptBuilder.addObservations(observationsWithRoutes);
|
|
326
|
+
// Select best route from scores
|
|
327
|
+
if (routingResult.structured?.routes) {
|
|
328
|
+
const decision = this.routingEngine.decideRouteFromScores({
|
|
329
|
+
context: routingResult.structured.context,
|
|
330
|
+
routes: routingResult.structured.routes,
|
|
331
|
+
responseDirectives: routingResult.structured.responseDirectives,
|
|
332
|
+
});
|
|
333
|
+
selectedRoute = this.routes.find((r) => r.id === decision.routeId);
|
|
334
|
+
responseDirectives = routingResult.structured.responseDirectives;
|
|
335
|
+
if (selectedRoute) {
|
|
336
|
+
console.log(`[Agent] Selected route: ${selectedRoute.title} (score: ${decision.maxScore})`);
|
|
337
|
+
// Update session with selected route (if changed)
|
|
338
|
+
if (!session.currentRoute ||
|
|
339
|
+
session.currentRoute.id !== selectedRoute.id) {
|
|
340
|
+
session = enterRoute(session, selectedRoute.id, selectedRoute.title);
|
|
341
|
+
// Merge initial data if provided by the route
|
|
342
|
+
if (selectedRoute.initialData) {
|
|
343
|
+
session = mergeExtracted(session, selectedRoute.initialData);
|
|
344
|
+
console.log(`[Agent] Merged initial data:`, selectedRoute.initialData);
|
|
345
|
+
}
|
|
346
|
+
console.log(`[Agent] Entered route: ${selectedRoute.title}`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
263
349
|
}
|
|
264
350
|
}
|
|
265
|
-
//
|
|
266
|
-
if (
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
351
|
+
// PHASE 3: RESPONSE - Stream message using selected route
|
|
352
|
+
if (selectedRoute) {
|
|
353
|
+
// Determine next state based on current extracted data
|
|
354
|
+
const currentStateRef = session.currentState;
|
|
355
|
+
const currentState = currentStateRef
|
|
356
|
+
? selectedRoute.getState(currentStateRef.id)
|
|
357
|
+
: undefined;
|
|
358
|
+
const nextState = this.getNextState(selectedRoute, currentState, session.extracted);
|
|
359
|
+
// Update session with next state
|
|
360
|
+
session = enterState(session, nextState.id, nextState.description);
|
|
361
|
+
console.log(`[Agent] Entered state: ${nextState.id}`);
|
|
362
|
+
// Get last user message
|
|
363
|
+
const lastUserMessage = getLastMessageFromHistory(history);
|
|
364
|
+
// Build response schema for this route (with gather fields from state)
|
|
365
|
+
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, nextState);
|
|
366
|
+
// Build response prompt
|
|
367
|
+
const responsePrompt = this.responseEngine.buildResponsePrompt(selectedRoute, selectedRoute.getRules(), selectedRoute.getProhibitions(), responseDirectives, history, lastUserMessage, {
|
|
368
|
+
name: this.options.name,
|
|
369
|
+
goal: this.options.goal,
|
|
370
|
+
description: this.options.description,
|
|
371
|
+
personality: this.options.personality,
|
|
372
|
+
});
|
|
373
|
+
// Generate message stream using AI provider
|
|
374
|
+
const stream = this.options.ai.generateMessageStream({
|
|
375
|
+
prompt: responsePrompt,
|
|
376
|
+
history,
|
|
377
|
+
context: effectiveContext,
|
|
378
|
+
signal,
|
|
379
|
+
parameters: {
|
|
380
|
+
jsonSchema: responseSchema,
|
|
381
|
+
schemaName: "response_stream_output",
|
|
382
|
+
},
|
|
383
|
+
});
|
|
384
|
+
// Stream chunks to caller
|
|
385
|
+
for await (const chunk of stream) {
|
|
386
|
+
const toolCalls = undefined;
|
|
387
|
+
// Extract gathered data on final chunk
|
|
388
|
+
if (chunk.done && chunk.structured && nextState.gatherFields) {
|
|
389
|
+
const gatheredData = {};
|
|
390
|
+
// The structured response includes both base fields and gathered extraction fields
|
|
391
|
+
const structuredData = chunk.structured;
|
|
392
|
+
for (const field of nextState.gatherFields) {
|
|
393
|
+
if (field in structuredData) {
|
|
394
|
+
gatheredData[field] = structuredData[field];
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
// Merge gathered data into session
|
|
398
|
+
if (Object.keys(gatheredData).length > 0) {
|
|
399
|
+
session = await this.updateExtracted(session, gatheredData);
|
|
400
|
+
console.log(`[Agent] Extracted data:`, gatheredData);
|
|
308
401
|
}
|
|
309
402
|
}
|
|
310
|
-
//
|
|
311
|
-
if (chunk.
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
403
|
+
// Extract any additional data from structured response on final chunk
|
|
404
|
+
if (chunk.done &&
|
|
405
|
+
chunk.structured &&
|
|
406
|
+
typeof chunk.structured === "object" &&
|
|
407
|
+
"contextUpdate" in chunk.structured) {
|
|
408
|
+
await this.updateContext(chunk.structured
|
|
409
|
+
.contextUpdate);
|
|
316
410
|
}
|
|
317
|
-
//
|
|
318
|
-
if (chunk.
|
|
319
|
-
|
|
320
|
-
|
|
411
|
+
// Auto-save session state on final chunk
|
|
412
|
+
if (chunk.done &&
|
|
413
|
+
this.persistenceManager &&
|
|
414
|
+
session.metadata?.sessionId &&
|
|
415
|
+
this.options.persistence?.autoSave !== false) {
|
|
416
|
+
await this.persistenceManager.saveSessionState(session.metadata.sessionId, session);
|
|
417
|
+
console.log(`[Agent] Auto-saved session state to persistence: ${session.metadata.sessionId}`);
|
|
321
418
|
}
|
|
419
|
+
yield {
|
|
420
|
+
delta: chunk.delta,
|
|
421
|
+
accumulated: chunk.accumulated,
|
|
422
|
+
done: chunk.done,
|
|
423
|
+
session, // Return updated session
|
|
424
|
+
toolCalls,
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
// Fallback: No routes defined, stream a simple response
|
|
430
|
+
const fallbackPrompt = new PromptComposer()
|
|
431
|
+
.addAgentMeta({
|
|
432
|
+
name: this.options.name,
|
|
433
|
+
goal: this.options.goal,
|
|
434
|
+
description: this.options.description,
|
|
435
|
+
})
|
|
436
|
+
.addPersonality(this.options.personality)
|
|
437
|
+
.addInteractionHistory(history)
|
|
438
|
+
.addGlossary(this.terms)
|
|
439
|
+
.addGuidelines(this.guidelines)
|
|
440
|
+
.addCapabilities(this.capabilities)
|
|
441
|
+
.build();
|
|
442
|
+
const stream = this.options.ai.generateMessageStream({
|
|
443
|
+
prompt: fallbackPrompt,
|
|
444
|
+
history,
|
|
445
|
+
context: effectiveContext,
|
|
446
|
+
signal,
|
|
447
|
+
parameters: {
|
|
448
|
+
jsonSchema: {
|
|
449
|
+
type: "object",
|
|
450
|
+
properties: {
|
|
451
|
+
message: { type: "string" },
|
|
452
|
+
},
|
|
453
|
+
required: ["message"],
|
|
454
|
+
additionalProperties: false,
|
|
455
|
+
},
|
|
456
|
+
schemaName: "fallback_stream_response",
|
|
457
|
+
},
|
|
458
|
+
});
|
|
459
|
+
for await (const chunk of stream) {
|
|
460
|
+
yield {
|
|
461
|
+
delta: chunk.delta,
|
|
462
|
+
accumulated: chunk.accumulated,
|
|
463
|
+
done: chunk.done,
|
|
464
|
+
session, // Return updated session
|
|
465
|
+
toolCalls: undefined,
|
|
466
|
+
};
|
|
322
467
|
}
|
|
323
|
-
yield {
|
|
324
|
-
delta: chunk.delta,
|
|
325
|
-
accumulated: chunk.accumulated,
|
|
326
|
-
done: chunk.done,
|
|
327
|
-
route: route || undefined,
|
|
328
|
-
state: state || undefined,
|
|
329
|
-
toolCalls,
|
|
330
|
-
};
|
|
331
468
|
}
|
|
332
469
|
}
|
|
333
470
|
/**
|
|
@@ -344,135 +481,194 @@ export class Agent {
|
|
|
344
481
|
this.context = currentContext;
|
|
345
482
|
}
|
|
346
483
|
// Merge context with override
|
|
347
|
-
|
|
484
|
+
const effectiveContext = {
|
|
348
485
|
...currentContext,
|
|
349
486
|
...contextOverride,
|
|
350
487
|
};
|
|
351
|
-
//
|
|
352
|
-
|
|
353
|
-
// 1
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
488
|
+
// Initialize or get session
|
|
489
|
+
let session = params.session || createSession();
|
|
490
|
+
// PHASE 1: TOOL EXECUTION - Execute tools if current state has toolState
|
|
491
|
+
if (session.currentRoute && session.currentState) {
|
|
492
|
+
const currentRoute = this.routes.find((r) => r.id === session.currentRoute?.id);
|
|
493
|
+
if (currentRoute) {
|
|
494
|
+
const currentState = currentRoute.getState(session.currentState.id);
|
|
495
|
+
if (currentState) {
|
|
496
|
+
const transitions = currentState.getTransitions();
|
|
497
|
+
const toolTransition = transitions.find((t) => t.spec.toolState);
|
|
498
|
+
if (toolTransition?.spec.toolState) {
|
|
499
|
+
const toolExecutor = new ToolExecutor();
|
|
500
|
+
// Get allowed domains from current route for security enforcement
|
|
501
|
+
const allowedDomains = currentRoute.getDomains();
|
|
502
|
+
const result = await toolExecutor.executeTool(toolTransition.spec.toolState, effectiveContext, this.updateContext.bind(this), history, session.extracted, allowedDomains);
|
|
503
|
+
// Update context with tool results
|
|
504
|
+
if (result.contextUpdate) {
|
|
505
|
+
await this.updateContext(result.contextUpdate);
|
|
506
|
+
}
|
|
507
|
+
// Update extracted data with tool results
|
|
508
|
+
if (result.extractedUpdate) {
|
|
509
|
+
session = await this.updateExtracted(session, result.extractedUpdate);
|
|
510
|
+
console.log(`[Agent] Tool updated extracted data:`, result.extractedUpdate);
|
|
511
|
+
}
|
|
512
|
+
console.log(`[Agent] Executed tool: ${result.toolName} (success: ${result.success})`);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
370
516
|
}
|
|
371
|
-
//
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
if (this.
|
|
375
|
-
|
|
517
|
+
// PHASE 2: ROUTING - Determine which route to use
|
|
518
|
+
let selectedRoute;
|
|
519
|
+
let responseDirectives;
|
|
520
|
+
if (this.routes.length > 0) {
|
|
521
|
+
// Get last user message
|
|
522
|
+
const lastUserMessage = getLastMessageFromHistory(history);
|
|
523
|
+
// Build routing schema
|
|
524
|
+
const routingSchema = this.routingEngine.buildDynamicRoutingSchema(this.routes);
|
|
525
|
+
// Build routing prompt with session context
|
|
526
|
+
const routingPrompt = this.routingEngine.buildRoutingPrompt(history, this.routes, lastUserMessage, {
|
|
376
527
|
name: this.options.name,
|
|
528
|
+
goal: this.options.goal,
|
|
377
529
|
description: this.options.description,
|
|
530
|
+
personality: this.options.personality,
|
|
531
|
+
}, session // Pass session for context-aware routing
|
|
532
|
+
);
|
|
533
|
+
// Call AI to score routes
|
|
534
|
+
const routingResult = await this.options.ai.generateMessage({
|
|
535
|
+
prompt: routingPrompt,
|
|
536
|
+
history,
|
|
537
|
+
context: effectiveContext,
|
|
538
|
+
signal,
|
|
539
|
+
parameters: {
|
|
540
|
+
jsonSchema: routingSchema,
|
|
541
|
+
schemaName: "routing_output",
|
|
542
|
+
},
|
|
378
543
|
});
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
description: obs.description,
|
|
403
|
-
routes: obs.getRoutes().map((routeRef) => {
|
|
404
|
-
const route = this.routes.find((r) => r.id === routeRef.id);
|
|
405
|
-
return { title: route?.title || routeRef.id };
|
|
406
|
-
}),
|
|
407
|
-
}))
|
|
408
|
-
.filter((obs) => obs.routes.length > 0);
|
|
409
|
-
if (observationsWithRoutes.length > 0) {
|
|
410
|
-
promptBuilder.addObservations(observationsWithRoutes);
|
|
544
|
+
// Select best route from scores
|
|
545
|
+
if (routingResult.structured?.routes) {
|
|
546
|
+
const decision = this.routingEngine.decideRouteFromScores({
|
|
547
|
+
context: routingResult.structured.context,
|
|
548
|
+
routes: routingResult.structured.routes,
|
|
549
|
+
responseDirectives: routingResult.structured.responseDirectives,
|
|
550
|
+
});
|
|
551
|
+
selectedRoute = this.routes.find((r) => r.id === decision.routeId);
|
|
552
|
+
responseDirectives = routingResult.structured.responseDirectives;
|
|
553
|
+
if (selectedRoute) {
|
|
554
|
+
console.log(`[Agent] Selected route: ${selectedRoute.title} (score: ${decision.maxScore})`);
|
|
555
|
+
// Update session with selected route (if changed)
|
|
556
|
+
if (!session.currentRoute ||
|
|
557
|
+
session.currentRoute.id !== selectedRoute.id) {
|
|
558
|
+
session = enterRoute(session, selectedRoute.id, selectedRoute.title);
|
|
559
|
+
// Merge initial data if provided by the route
|
|
560
|
+
if (selectedRoute.initialData) {
|
|
561
|
+
session = mergeExtracted(session, selectedRoute.initialData);
|
|
562
|
+
console.log(`[Agent] Merged initial data:`, selectedRoute.initialData);
|
|
563
|
+
}
|
|
564
|
+
console.log(`[Agent] Entered route: ${selectedRoute.title}`);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
411
567
|
}
|
|
412
568
|
}
|
|
413
|
-
//
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
message = result.structured
|
|
449
|
-
//
|
|
450
|
-
if (result.structured.
|
|
451
|
-
const
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
569
|
+
// PHASE 3: RESPONSE - Generate message using selected route
|
|
570
|
+
let message;
|
|
571
|
+
const toolCalls = undefined;
|
|
572
|
+
if (selectedRoute) {
|
|
573
|
+
// Determine next state based on current extracted data
|
|
574
|
+
const currentStateRef = session.currentState;
|
|
575
|
+
const currentState = currentStateRef
|
|
576
|
+
? selectedRoute.getState(currentStateRef.id)
|
|
577
|
+
: undefined;
|
|
578
|
+
const nextState = this.getNextState(selectedRoute, currentState, session.extracted);
|
|
579
|
+
// Update session with next state
|
|
580
|
+
session = enterState(session, nextState.id, nextState.description);
|
|
581
|
+
console.log(`[Agent] Entered state: ${nextState.id}`);
|
|
582
|
+
// Get last user message
|
|
583
|
+
const lastUserMessage = getLastMessageFromHistory(history);
|
|
584
|
+
// Build response schema for this route (with gather fields from state)
|
|
585
|
+
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, nextState);
|
|
586
|
+
// Build response prompt
|
|
587
|
+
const responsePrompt = this.responseEngine.buildResponsePrompt(selectedRoute, selectedRoute.getRules(), selectedRoute.getProhibitions(), responseDirectives, history, lastUserMessage, {
|
|
588
|
+
name: this.options.name,
|
|
589
|
+
goal: this.options.goal,
|
|
590
|
+
description: this.options.description,
|
|
591
|
+
personality: this.options.personality,
|
|
592
|
+
});
|
|
593
|
+
// Generate message using AI provider
|
|
594
|
+
const result = await this.options.ai.generateMessage({
|
|
595
|
+
prompt: responsePrompt,
|
|
596
|
+
history,
|
|
597
|
+
context: effectiveContext,
|
|
598
|
+
signal,
|
|
599
|
+
parameters: {
|
|
600
|
+
jsonSchema: responseSchema,
|
|
601
|
+
schemaName: "response_output",
|
|
602
|
+
},
|
|
603
|
+
});
|
|
604
|
+
message = result.structured?.message || result.message;
|
|
605
|
+
// Extract gathered data from response
|
|
606
|
+
if (result.structured && nextState.gatherFields) {
|
|
607
|
+
const gatheredData = {};
|
|
608
|
+
// The structured response includes both base fields and gathered extraction fields
|
|
609
|
+
const structuredData = result.structured;
|
|
610
|
+
for (const field of nextState.gatherFields) {
|
|
611
|
+
if (field in structuredData) {
|
|
612
|
+
gatheredData[field] = structuredData[field];
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
// Merge gathered data into session
|
|
616
|
+
if (Object.keys(gatheredData).length > 0) {
|
|
617
|
+
session = mergeExtracted(session, gatheredData);
|
|
618
|
+
console.log(`[Agent] Extracted data:`, gatheredData);
|
|
457
619
|
}
|
|
458
620
|
}
|
|
459
|
-
//
|
|
460
|
-
if (result.structured
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
}
|
|
466
|
-
// Extract tool calls
|
|
467
|
-
if (result.structured.toolCalls &&
|
|
468
|
-
result.structured.toolCalls.length > 0) {
|
|
469
|
-
toolCalls = result.structured.toolCalls;
|
|
621
|
+
// Extract any additional data from structured response
|
|
622
|
+
if (result.structured &&
|
|
623
|
+
typeof result.structured === "object" &&
|
|
624
|
+
"contextUpdate" in result.structured) {
|
|
625
|
+
await this.updateContext(result.structured
|
|
626
|
+
.contextUpdate);
|
|
470
627
|
}
|
|
471
628
|
}
|
|
629
|
+
else {
|
|
630
|
+
// Fallback: No routes defined, generate a simple response
|
|
631
|
+
const fallbackPrompt = new PromptComposer()
|
|
632
|
+
.addAgentMeta({
|
|
633
|
+
name: this.options.name,
|
|
634
|
+
goal: this.options.goal,
|
|
635
|
+
description: this.options.description,
|
|
636
|
+
})
|
|
637
|
+
.addPersonality(this.options.personality)
|
|
638
|
+
.addInteractionHistory(history)
|
|
639
|
+
.addGlossary(this.terms)
|
|
640
|
+
.addGuidelines(this.guidelines)
|
|
641
|
+
.addCapabilities(this.capabilities)
|
|
642
|
+
.build();
|
|
643
|
+
const result = await this.options.ai.generateMessage({
|
|
644
|
+
prompt: fallbackPrompt,
|
|
645
|
+
history,
|
|
646
|
+
context: effectiveContext,
|
|
647
|
+
signal,
|
|
648
|
+
parameters: {
|
|
649
|
+
jsonSchema: {
|
|
650
|
+
type: "object",
|
|
651
|
+
properties: {
|
|
652
|
+
message: { type: "string" },
|
|
653
|
+
},
|
|
654
|
+
required: ["message"],
|
|
655
|
+
additionalProperties: false,
|
|
656
|
+
},
|
|
657
|
+
schemaName: "fallback_response",
|
|
658
|
+
},
|
|
659
|
+
});
|
|
660
|
+
message = result.structured?.message || result.message;
|
|
661
|
+
}
|
|
662
|
+
// Auto-save session state to persistence if configured
|
|
663
|
+
if (this.persistenceManager &&
|
|
664
|
+
session.metadata?.sessionId &&
|
|
665
|
+
this.options.persistence?.autoSave !== false) {
|
|
666
|
+
await this.persistenceManager.saveSessionState(session.metadata.sessionId, session);
|
|
667
|
+
console.log(`[Agent] Auto-saved session state to persistence: ${session.metadata.sessionId}`);
|
|
668
|
+
}
|
|
472
669
|
return {
|
|
473
670
|
message,
|
|
474
|
-
|
|
475
|
-
state: state || undefined,
|
|
671
|
+
session, // Return updated session with route/state info
|
|
476
672
|
toolCalls,
|
|
477
673
|
};
|
|
478
674
|
}
|
|
@@ -500,12 +696,6 @@ export class Agent {
|
|
|
500
696
|
getCapabilities() {
|
|
501
697
|
return [...this.capabilities];
|
|
502
698
|
}
|
|
503
|
-
/**
|
|
504
|
-
* Get all observations
|
|
505
|
-
*/
|
|
506
|
-
getObservations() {
|
|
507
|
-
return [...this.observations];
|
|
508
|
-
}
|
|
509
699
|
/**
|
|
510
700
|
* Get the domain registry
|
|
511
701
|
*/
|