agentnet 0.0.2 → 0.0.4
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 +69 -1
- package/examples/simple/simple.js +2 -2
- package/jest.config.js +1 -0
- package/package.json +5 -2
- package/src/agent/agent-loader.js +75 -12
- package/src/agent/agent.js +4 -2
- package/src/agent/runtime.js +7 -4
- package/src/llm/base.js +131 -0
- package/src/llm/gemini.js +137 -122
- package/src/llm/gpt.js +131 -109
- package/src/tests/agent.test.js +350 -0
- package/src/tools/migrate-version.js +250 -0
- package/src/transport/README.md +123 -0
- package/src/transport/base.js +237 -0
- package/src/transport/index.js +89 -0
- package/src/transport/kafka.js +474 -0
- package/src/transport/nats.js +521 -0
- package/src/transport/rabbitmq.js +722 -0
- package/src/transport/redis.js +532 -0
- package/src/utils/version.js +212 -0
- package/src/agent/runtimes/nats.js +0 -506
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
- [Introduction](#introduction)
|
|
6
6
|
- [Installation](#installation)
|
|
7
|
+
- [API Keys Configuration](#api-keys-configuration)
|
|
7
8
|
- [Super Simple Example (Quick Start)](#super-simple-example-quick-start)
|
|
8
9
|
- [Declarative Agent Definitions (YAML & JavaScript)](#declarative-agent-definitions-yaml--javascript)
|
|
9
10
|
- [State Management](#state-management)
|
|
@@ -41,6 +42,32 @@ Key aspects include:
|
|
|
41
42
|
npm install agentnet
|
|
42
43
|
```
|
|
43
44
|
|
|
45
|
+
## API Keys Configuration
|
|
46
|
+
|
|
47
|
+
Agentnet requires API keys for accessing the LLM providers you plan to use. The keys should be set as environment variables:
|
|
48
|
+
|
|
49
|
+
- **Gemini**: Set `GEMINI_API_KEY` for using Google's Gemini models
|
|
50
|
+
- **OpenAI**: Set `OPENAI_API_KEY` for using OpenAI's GPT models
|
|
51
|
+
|
|
52
|
+
You can set these environment variables in your deployment environment or use a `.env` file with a package like `dotenv`:
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
// In your main file, before importing agentnet
|
|
56
|
+
import dotenv from 'dotenv';
|
|
57
|
+
dotenv.config();
|
|
58
|
+
|
|
59
|
+
// Now the API keys are available to agentnet
|
|
60
|
+
import { Agent, Gemini } from "agentnet";
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Example `.env` file:
|
|
64
|
+
```
|
|
65
|
+
GEMINI_API_KEY=your_gemini_api_key_here
|
|
66
|
+
OPENAI_API_KEY=your_openai_api_key_here
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
> Note: If you try to use an LLM provider without setting the corresponding API key, Agentnet will throw an error indicating which environment variable is missing.
|
|
70
|
+
|
|
44
71
|
## Super Simple Example (Quick Start)
|
|
45
72
|
|
|
46
73
|
Here's how you can quickly get an agent up and running:
|
|
@@ -88,7 +115,7 @@ Define agent metadata, LLM configurations, transport, tools, and discovery schem
|
|
|
88
115
|
|
|
89
116
|
```yaml
|
|
90
117
|
---
|
|
91
|
-
apiVersion: agentnet
|
|
118
|
+
apiVersion: agentnet/v1alpha1
|
|
92
119
|
kind: AgentDefinition
|
|
93
120
|
metadata:
|
|
94
121
|
name: bookingAgent
|
|
@@ -131,6 +158,47 @@ spec:
|
|
|
131
158
|
# parameters schema for the discovery...
|
|
132
159
|
```
|
|
133
160
|
|
|
161
|
+
### API Versioning
|
|
162
|
+
|
|
163
|
+
Agentnet supports API versioning to maintain backwards compatibility while evolving the platform:
|
|
164
|
+
|
|
165
|
+
```yaml
|
|
166
|
+
apiVersion: agentnet/v1alpha1 # Specify which API version this definition uses
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Currently supported API versions:
|
|
170
|
+
|
|
171
|
+
- `agentnet/v1alpha1`: Current API version
|
|
172
|
+
|
|
173
|
+
When creating agent definitions, you should specify which API version you're targeting. This allows Agentnet to:
|
|
174
|
+
|
|
175
|
+
1. Apply the correct validation rules
|
|
176
|
+
2. Handle differences in configuration format
|
|
177
|
+
3. Maintain backward compatibility with older definitions
|
|
178
|
+
4. Enable new features only available in newer versions
|
|
179
|
+
|
|
180
|
+
If you don't specify an `apiVersion`, Agentnet will default to `agentnet/v1alpha1` but will log a warning.
|
|
181
|
+
|
|
182
|
+
#### Version Migration Tool
|
|
183
|
+
|
|
184
|
+
Agentnet includes a command-line tool to help migrate your agent definitions to newer API versions:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Migrate a YAML file to the latest version
|
|
188
|
+
node src/tools/migrate-version.js ./agents.yaml
|
|
189
|
+
|
|
190
|
+
# Specify a target version
|
|
191
|
+
node src/tools/migrate-version.js ./agents.yaml --version agentnet.io/v1alpha1
|
|
192
|
+
|
|
193
|
+
# Write to a specific output file
|
|
194
|
+
node src/tools/migrate-version.js ./agents.yaml --output ./agents-new.yaml
|
|
195
|
+
|
|
196
|
+
# Just check if migration is needed without modifying
|
|
197
|
+
node src/tools/migrate-version.js ./agents.yaml --check
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
This tool helps you keep your agent definitions up-to-date with the latest features while maintaining compatibility with the Agentnet platform.
|
|
201
|
+
|
|
134
202
|
### Dynamic Implementation (JavaScript)
|
|
135
203
|
|
|
136
204
|
Load YAML definitions and bind tool implementations dynamically:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { AgentLoaderJSON, Message, Bindings, PostgresStore } from "
|
|
1
|
+
import { AgentLoaderJSON, Message, Bindings, PostgresStore } from "../../src/index.js"
|
|
2
2
|
|
|
3
3
|
const agentDefinition = {
|
|
4
|
-
"apiVersion": "
|
|
4
|
+
"apiVersion": "agentnet/v1alpha1",
|
|
5
5
|
"kind": "AgentDefinition",
|
|
6
6
|
"metadata": {
|
|
7
7
|
"name": "accomodationAgent",
|
package/jest.config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default { transform: {} }
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentnet",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent library used by Smartness",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "
|
|
8
|
+
"test": "node --experimental-vm-modules ./node_modules/.bin/jest --rootDir=src/tests"
|
|
9
9
|
},
|
|
10
10
|
"author": "",
|
|
11
11
|
"license": "ISC",
|
|
@@ -19,5 +19,8 @@
|
|
|
19
19
|
"redis": "^5.0.1",
|
|
20
20
|
"uuid": "^11.1.0",
|
|
21
21
|
"yaml": "^2.7.1"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"jest": "^29.7.0"
|
|
22
25
|
}
|
|
23
26
|
}
|
|
@@ -2,6 +2,18 @@ import fs from 'fs'
|
|
|
2
2
|
import { parse } from 'yaml'
|
|
3
3
|
import { Gemini } from "../index.js"
|
|
4
4
|
import { Agent } from "./agent.js"
|
|
5
|
+
import { logger } from "../utils/logger.js"
|
|
6
|
+
import { ConfigurationError } from "../errors/index.js"
|
|
7
|
+
import { validateApiVersion, DEFAULT_API_VERSION, API_VERSIONS } from '../utils/version.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Version handlers for different API versions
|
|
11
|
+
*/
|
|
12
|
+
const VERSION_HANDLERS = {
|
|
13
|
+
'smartagent.io/v1alpha1': processV1Alpha1Definition,
|
|
14
|
+
'agentnet.io/v1alpha1': processV1Alpha1Definition
|
|
15
|
+
// Additional version handlers can be added here as the API evolves
|
|
16
|
+
};
|
|
5
17
|
|
|
6
18
|
/**
|
|
7
19
|
* Loads agent definitions from a YAML file
|
|
@@ -47,10 +59,10 @@ function parseAgentDefinitionsFromYaml(yamlContent) {
|
|
|
47
59
|
if (isValidAgentDefinition(definition)) {
|
|
48
60
|
agentDefinitions.push(definition);
|
|
49
61
|
} else {
|
|
50
|
-
|
|
62
|
+
logger.warn("Skipping invalid or non-AgentDefinition document in YAML.");
|
|
51
63
|
}
|
|
52
64
|
} catch (error) {
|
|
53
|
-
|
|
65
|
+
logger.warn(`Failed to parse YAML document: ${error.message}`);
|
|
54
66
|
}
|
|
55
67
|
}
|
|
56
68
|
|
|
@@ -66,6 +78,58 @@ function isValidAgentDefinition(definition) {
|
|
|
66
78
|
return definition && definition.kind === 'AgentDefinition' && definition.spec;
|
|
67
79
|
}
|
|
68
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Gets the appropriate version handler for a definition
|
|
83
|
+
* @param {object} definition - Agent definition
|
|
84
|
+
* @returns {Function} Version handler function
|
|
85
|
+
* @throws {ConfigurationError} If version is unsupported
|
|
86
|
+
*/
|
|
87
|
+
function getVersionHandler(definition) {
|
|
88
|
+
// Validate the API version using our utility
|
|
89
|
+
const versionData = validateApiVersion(definition);
|
|
90
|
+
const apiVersion = versionData.version;
|
|
91
|
+
|
|
92
|
+
// Get the appropriate handler for this version
|
|
93
|
+
const handler = VERSION_HANDLERS[apiVersion];
|
|
94
|
+
|
|
95
|
+
if (!handler) {
|
|
96
|
+
throw new ConfigurationError(
|
|
97
|
+
`No implementation handler for apiVersion '${apiVersion}'`,
|
|
98
|
+
{ apiVersion, supportedHandlers: Object.keys(VERSION_HANDLERS) }
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return handler;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Process a v1alpha1 agent definition
|
|
107
|
+
* @param {object} definition - Agent definition
|
|
108
|
+
* @param {object} agentBuilder - Agent builder
|
|
109
|
+
* @param {object} bindings - IO and store bindings
|
|
110
|
+
* @returns {object} Processed agent interface and tool map
|
|
111
|
+
*/
|
|
112
|
+
async function processV1Alpha1Definition(definition, agentBuilder, bindings) {
|
|
113
|
+
const spec = definition.spec;
|
|
114
|
+
|
|
115
|
+
// Add apiVersion to agent metadata
|
|
116
|
+
agentBuilder.setMetadata({
|
|
117
|
+
...agentBuilder._config.metadata,
|
|
118
|
+
apiVersion: definition.apiVersion || DEFAULT_API_VERSION
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Configure different aspects of the agent
|
|
122
|
+
agentBuilder = configureIO(agentBuilder, spec.io, bindings);
|
|
123
|
+
agentBuilder = configureStore(agentBuilder, spec.store, bindings);
|
|
124
|
+
agentBuilder = await configureLLM(agentBuilder, spec.llm);
|
|
125
|
+
agentBuilder = configureDiscoverySchemas(agentBuilder, spec.discoverySchemas);
|
|
126
|
+
|
|
127
|
+
// Set up tools
|
|
128
|
+
const toolMap = configureTools(agentBuilder, spec.tools);
|
|
129
|
+
|
|
130
|
+
return { agentBuilder, toolMap };
|
|
131
|
+
}
|
|
132
|
+
|
|
69
133
|
/**
|
|
70
134
|
* Loads an LLM provider instance
|
|
71
135
|
* @param {string} providerName - Name of the provider
|
|
@@ -237,7 +301,6 @@ async function AgentLoader(agentsDefinitions, config = {}) {
|
|
|
237
301
|
throw new Error(`Invalid agent definition: missing spec`);
|
|
238
302
|
}
|
|
239
303
|
|
|
240
|
-
const spec = definition.spec;
|
|
241
304
|
const metadata = definition.metadata || {
|
|
242
305
|
name: "default",
|
|
243
306
|
description: "Agent from definition"
|
|
@@ -250,21 +313,21 @@ async function AgentLoader(agentsDefinitions, config = {}) {
|
|
|
250
313
|
// Initialize agent builder with metadata
|
|
251
314
|
let agentBuilder = Agent().setMetadata(metadata);
|
|
252
315
|
|
|
253
|
-
//
|
|
254
|
-
|
|
255
|
-
agentBuilder = configureStore(agentBuilder, spec.store, bindings);
|
|
256
|
-
agentBuilder = await configureLLM(agentBuilder, spec.llm);
|
|
257
|
-
agentBuilder = configureDiscoverySchemas(agentBuilder, spec.discoverySchemas);
|
|
316
|
+
// Get the appropriate version handler
|
|
317
|
+
const versionHandler = getVersionHandler(definition);
|
|
258
318
|
|
|
259
|
-
//
|
|
260
|
-
const toolMap =
|
|
319
|
+
// Process according to API version
|
|
320
|
+
const { agentBuilder: updatedBuilder, toolMap } =
|
|
321
|
+
await versionHandler(definition, agentBuilder, bindings);
|
|
261
322
|
|
|
262
323
|
// Create the agent interface
|
|
263
|
-
loadedAgents[metadata.name] = createAgentInterface(
|
|
324
|
+
loadedAgents[metadata.name] = createAgentInterface(updatedBuilder, toolMap);
|
|
325
|
+
|
|
326
|
+
logger.info(`Agent '${metadata.name}' loaded successfully with apiVersion: ${definition.apiVersion || DEFAULT_API_VERSION}`);
|
|
264
327
|
|
|
265
328
|
} catch (error) {
|
|
266
329
|
const agentName = definition.metadata?.name || 'Unnamed Agent';
|
|
267
|
-
|
|
330
|
+
logger.error(`Failed to load agent "${agentName}": ${error.message}`, { error });
|
|
268
331
|
// Optional: decide whether to throw or just log and continue
|
|
269
332
|
// throw error;
|
|
270
333
|
}
|
package/src/agent/agent.js
CHANGED
|
@@ -23,7 +23,8 @@ const DEFAULT_CONFIG = {
|
|
|
23
23
|
metadata: {
|
|
24
24
|
name: "default",
|
|
25
25
|
namespace: "default",
|
|
26
|
-
description: "A default agent"
|
|
26
|
+
description: "A default agent",
|
|
27
|
+
apiVersion: "agentnet/v1alpha1" // Default API version
|
|
27
28
|
},
|
|
28
29
|
runner: {
|
|
29
30
|
maxRuns: 10
|
|
@@ -41,7 +42,8 @@ const AGENT_CONFIG_SCHEMA = {
|
|
|
41
42
|
properties: {
|
|
42
43
|
name: { type: 'string' },
|
|
43
44
|
namespace: { type: 'string' },
|
|
44
|
-
description: { type: 'string' }
|
|
45
|
+
description: { type: 'string' },
|
|
46
|
+
apiVersion: { type: 'string' }
|
|
45
47
|
},
|
|
46
48
|
required: ['name', 'namespace']
|
|
47
49
|
},
|
package/src/agent/runtime.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { build, makeToolsAndHandoffsMap } from "./executor.js"
|
|
2
|
-
import { NatsIOAgentRuntime } from "./runtimes/nats.js"
|
|
3
2
|
import { logger } from "../utils/logger.js"
|
|
4
3
|
import { Response, SessionStore } from "../index.js"
|
|
4
|
+
import { createAgentRuntime } from "../transport/index.js"
|
|
5
5
|
|
|
6
6
|
export async function AgentRuntime(agentConfig) {
|
|
7
7
|
const {
|
|
@@ -19,11 +19,14 @@ export async function AgentRuntime(agentConfig) {
|
|
|
19
19
|
} = agentConfig
|
|
20
20
|
|
|
21
21
|
// Initialize IO runtime
|
|
22
|
-
const
|
|
23
|
-
|
|
22
|
+
const transportType = ioInterfaces.length > 0 ? ioInterfaces[0].type.replace('IO', '').toLowerCase() : 'nats';
|
|
23
|
+
logger.info(`Creating agent runtime with transport type: ${transportType}`);
|
|
24
|
+
|
|
25
|
+
const { handleTask, discoveredAgents } = await createAgentRuntime(
|
|
26
|
+
transportType,
|
|
24
27
|
namespace,
|
|
25
28
|
agentName,
|
|
26
|
-
|
|
29
|
+
ioInterfaces,
|
|
27
30
|
discoverySchemas
|
|
28
31
|
)
|
|
29
32
|
|
package/src/llm/base.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { logger } from '../utils/logger.js'
|
|
2
|
+
import { LLMError } from '../errors/index.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Base class for LLM implementations
|
|
6
|
+
* Provides common functionality and defines required interface
|
|
7
|
+
*/
|
|
8
|
+
export class BaseLLM {
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} providerType - The LLM provider type (e.g., 'gemini', 'openai')
|
|
11
|
+
*/
|
|
12
|
+
constructor(providerType) {
|
|
13
|
+
this.type = providerType;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Initialize and get the LLM client
|
|
18
|
+
* @returns {Promise<any>} Initialized LLM client
|
|
19
|
+
* @throws {LLMError} If initialization fails
|
|
20
|
+
*/
|
|
21
|
+
async getClient() {
|
|
22
|
+
throw new Error('getClient() must be implemented by subclasses');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Call the LLM model with the provided configuration and context
|
|
27
|
+
* @param {Object} config - LLM-specific configuration
|
|
28
|
+
* @param {Object} context - Context containing client, tools map and conversation
|
|
29
|
+
* @returns {Promise<Object>} The model response
|
|
30
|
+
* @throws {LLMError} If the API call fails
|
|
31
|
+
*/
|
|
32
|
+
async callModel(config, context) {
|
|
33
|
+
throw new Error('callModel() must be implemented by subclasses');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Process the model response, handling text responses and function calls
|
|
38
|
+
* @param {Object} state - Current application state
|
|
39
|
+
* @param {Array} conversation - The conversation history
|
|
40
|
+
* @param {Object} toolsAndHandoffsMap - Map of available tools
|
|
41
|
+
* @param {Object} response - The model response to process
|
|
42
|
+
* @returns {Promise<string|null>} Text response or null if processing tool calls
|
|
43
|
+
*/
|
|
44
|
+
async onResponse(state, conversation, toolsAndHandoffsMap, response) {
|
|
45
|
+
throw new Error('onResponse() must be implemented by subclasses');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Add a user prompt to the conversation
|
|
50
|
+
* @param {Array} conversation - The conversation history
|
|
51
|
+
* @param {string} formattedPrompt - The formatted user prompt
|
|
52
|
+
* @returns {Promise<void>}
|
|
53
|
+
*/
|
|
54
|
+
async prompt(conversation, formattedPrompt) {
|
|
55
|
+
logger.debug('Adding user prompt to conversation', {
|
|
56
|
+
promptPreview: formattedPrompt.substring(0, 100)
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Subclasses must implement appropriate conversation format
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Check if required API key is set in environment variables
|
|
64
|
+
* @param {string} keyName - Environment variable name for the API key
|
|
65
|
+
* @returns {void}
|
|
66
|
+
* @throws {LLMError} If API key is not set
|
|
67
|
+
*/
|
|
68
|
+
checkApiKey(keyName) {
|
|
69
|
+
if (!process.env[keyName]) {
|
|
70
|
+
throw new LLMError(
|
|
71
|
+
`${keyName} environment variable is not set`,
|
|
72
|
+
this.type
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Execute a tool call from the model response
|
|
79
|
+
* @param {Object} toolCall - The tool call to execute
|
|
80
|
+
* @param {Object} state - Current application state
|
|
81
|
+
* @param {Array} conversation - The conversation history
|
|
82
|
+
* @param {Object} toolsAndHandoffsMap - Map of available tools
|
|
83
|
+
* @returns {Promise<any>} Result of the tool execution
|
|
84
|
+
*/
|
|
85
|
+
async executeToolCall(toolCall, name, args, state, conversation, toolsAndHandoffsMap) {
|
|
86
|
+
logger.debug(`Executing tool from ${this.type}`, {
|
|
87
|
+
toolName: name,
|
|
88
|
+
argsPreview: JSON.stringify(args).substring(0, 100)
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
if (!toolsAndHandoffsMap[name] || !toolsAndHandoffsMap[name].function) {
|
|
93
|
+
throw new Error(`Tool "${name}" not found or has no function implementation`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let result = null;
|
|
97
|
+
if (toolsAndHandoffsMap[name].type === 'handoff') {
|
|
98
|
+
result = await toolsAndHandoffsMap[name].function(conversation, state, args);
|
|
99
|
+
// Process handoff results if needed
|
|
100
|
+
this.processHandoffResult(result, state);
|
|
101
|
+
} else {
|
|
102
|
+
result = await toolsAndHandoffsMap[name].function(state, args);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
logger.debug('Tool execution successful', { toolName: name });
|
|
106
|
+
return result;
|
|
107
|
+
|
|
108
|
+
} catch (error) {
|
|
109
|
+
logger.error(`Error executing tool "${name}"`, { error });
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Process the result of a handoff operation
|
|
116
|
+
* @param {string} result - The JSON string result from handoff
|
|
117
|
+
* @param {Object} state - The state to update
|
|
118
|
+
*/
|
|
119
|
+
processHandoffResult(result, state) {
|
|
120
|
+
try {
|
|
121
|
+
const resultParsed = JSON.parse(result);
|
|
122
|
+
if (resultParsed.session) {
|
|
123
|
+
Object.entries(resultParsed.session).forEach(([key, value]) => {
|
|
124
|
+
state[key] = value;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
} catch (error) {
|
|
128
|
+
logger.error('Failed to process handoff result', { error });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|