agentnet 0.0.3 → 0.0.5
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/examples/simple/simple.js +12 -18
- package/examples/smartness/agents-smartness.yaml +20 -25
- package/examples/smartness/index.js +11 -3
- package/package.json +2 -2
- package/src/agent/agent-loader.js +13 -7
- package/src/agent/executor.js +6 -7
- package/src/agent/runtime.js +1 -0
- package/src/llm/base.js +4 -4
- package/src/llm/gemini.js +2 -2
- package/src/llm/gpt.js +3 -4
- package/src/store/store.js +2 -0
- package/src/transport/nats.js +3 -4
- package/src/utils/logger.js +1 -1
- package/src/utils/version.js +9 -17
- package/src/tools/migrate-version.js +0 -250
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AgentLoaderJSON, Message, Bindings,
|
|
1
|
+
import { AgentLoaderJSON, Message, Bindings, MemoryStore } from "../../src/index.js"
|
|
2
2
|
|
|
3
3
|
const agentDefinition = {
|
|
4
4
|
"apiVersion": "agentnet/v1alpha1",
|
|
@@ -9,25 +9,18 @@ const agentDefinition = {
|
|
|
9
9
|
},
|
|
10
10
|
"spec": {
|
|
11
11
|
"store": {
|
|
12
|
-
"type": "
|
|
12
|
+
"type": "Memory",
|
|
13
13
|
},
|
|
14
14
|
"llm": {
|
|
15
|
-
"provider": "
|
|
16
|
-
"model": "
|
|
17
|
-
"
|
|
18
|
-
"config": {
|
|
19
|
-
"temperature": 0.5,
|
|
20
|
-
"toolConfig": {
|
|
21
|
-
"functionCallingConfig": {
|
|
22
|
-
"mode": "auto"
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
15
|
+
"provider": "GPT",
|
|
16
|
+
"model": "gpt-4o-mini",
|
|
17
|
+
"instructions": "You are a highly advanced accomodation manager agent. \nPrioritize clarity and helpfulness.\nUse tools effectively to gather information."
|
|
26
18
|
},
|
|
27
19
|
"tools": [
|
|
28
20
|
{
|
|
29
|
-
"name": "
|
|
21
|
+
"name": "get_rooms_list_tool",
|
|
30
22
|
"description": "Retrieves a list of available rooms based on criteria.",
|
|
23
|
+
"type": "function",
|
|
31
24
|
"parameters": {
|
|
32
25
|
"type": "object",
|
|
33
26
|
"properties": {
|
|
@@ -51,8 +44,9 @@ const agentDefinition = {
|
|
|
51
44
|
}
|
|
52
45
|
},
|
|
53
46
|
{
|
|
54
|
-
"name": "
|
|
47
|
+
"name": "get_room_detail_tool",
|
|
55
48
|
"description": "Retrieves detailed information about a specific room.",
|
|
49
|
+
"type": "function",
|
|
56
50
|
"parameters": {
|
|
57
51
|
"type": "object",
|
|
58
52
|
"properties": {
|
|
@@ -73,15 +67,15 @@ const agentDefinition = {
|
|
|
73
67
|
// Load the agent definition
|
|
74
68
|
const agents = await AgentLoaderJSON(agentDefinition, {
|
|
75
69
|
bindings: {
|
|
76
|
-
[Bindings.
|
|
70
|
+
[Bindings.Memory]: MemoryStore()
|
|
77
71
|
}
|
|
78
72
|
})
|
|
79
73
|
|
|
80
74
|
// Add the binding tools to the agent
|
|
81
|
-
agents.accomodationAgent.tools.
|
|
75
|
+
agents.accomodationAgent.tools.get_rooms_list_tool.bind(async (state, input) => {
|
|
82
76
|
return { answer: "We have Double room with a view of the sea and a single room with a view of the pool, and a suite with a view of the city." }
|
|
83
77
|
})
|
|
84
|
-
agents.accomodationAgent.tools.
|
|
78
|
+
agents.accomodationAgent.tools.get_room_detail_tool.bind(async (state, input) => {
|
|
85
79
|
return { answer: "The Double room with a view of the sea has a king size bed, a private balcony, and a view of the sea." }
|
|
86
80
|
})
|
|
87
81
|
|
|
@@ -1,42 +1,37 @@
|
|
|
1
1
|
---
|
|
2
|
-
apiVersion:
|
|
2
|
+
apiVersion: agentnet/v1alpha1
|
|
3
3
|
kind: AgentDefinition
|
|
4
4
|
metadata:
|
|
5
5
|
name: entrypoint
|
|
6
|
-
namespace:
|
|
6
|
+
namespace: smartexample
|
|
7
7
|
spec:
|
|
8
8
|
io:
|
|
9
9
|
- type: NatsIO
|
|
10
10
|
bindings:
|
|
11
|
-
discoveryTopic:
|
|
11
|
+
discoveryTopic: smartexample.discovery
|
|
12
12
|
acceptedNetworks:
|
|
13
|
-
- "
|
|
13
|
+
- "smartexample.*"
|
|
14
14
|
store:
|
|
15
|
-
type:
|
|
15
|
+
type: Postgres
|
|
16
16
|
llm:
|
|
17
|
-
provider:
|
|
18
|
-
model:
|
|
19
|
-
|
|
17
|
+
provider: GPT
|
|
18
|
+
model: gpt-4.1-2025-04-14
|
|
19
|
+
instructions: |
|
|
20
20
|
You are a highly advanced triage agent.
|
|
21
21
|
Prioritize clarity and helpfulness.
|
|
22
22
|
Use tools effectively to gather information.
|
|
23
|
-
config:
|
|
24
|
-
temperature: 0.5
|
|
25
|
-
toolConfig:
|
|
26
|
-
functionCallingConfig:
|
|
27
|
-
mode: 'auto'
|
|
28
23
|
|
|
29
24
|
---
|
|
30
|
-
apiVersion:
|
|
25
|
+
apiVersion: agentnet/v1alpha1
|
|
31
26
|
kind: AgentDefinition
|
|
32
27
|
metadata:
|
|
33
28
|
name: accomodation
|
|
34
|
-
namespace:
|
|
29
|
+
namespace: smartexample
|
|
35
30
|
spec:
|
|
36
31
|
io:
|
|
37
32
|
- type: NatsIO
|
|
38
33
|
bindings:
|
|
39
|
-
discoveryTopic:
|
|
34
|
+
discoveryTopic: smartexample.discovery
|
|
40
35
|
store:
|
|
41
36
|
type: Postgres
|
|
42
37
|
|
|
@@ -96,16 +91,16 @@ spec:
|
|
|
96
91
|
- question
|
|
97
92
|
|
|
98
93
|
---
|
|
99
|
-
apiVersion:
|
|
94
|
+
apiVersion: agentnet/v1alpha1
|
|
100
95
|
kind: AgentDefinition
|
|
101
96
|
metadata:
|
|
102
97
|
name: review
|
|
103
|
-
namespace:
|
|
98
|
+
namespace: smartexample
|
|
104
99
|
spec:
|
|
105
100
|
io:
|
|
106
101
|
- type: NatsIO
|
|
107
102
|
bindings:
|
|
108
|
-
discoveryTopic:
|
|
103
|
+
discoveryTopic: smartexample.discovery
|
|
109
104
|
store:
|
|
110
105
|
type: Postgres
|
|
111
106
|
|
|
@@ -147,16 +142,16 @@ spec:
|
|
|
147
142
|
- hotelName
|
|
148
143
|
|
|
149
144
|
---
|
|
150
|
-
apiVersion:
|
|
145
|
+
apiVersion: agentnet/v1alpha1
|
|
151
146
|
kind: AgentDefinition
|
|
152
147
|
metadata:
|
|
153
148
|
name: booking
|
|
154
|
-
namespace:
|
|
149
|
+
namespace: smartexample
|
|
155
150
|
spec:
|
|
156
151
|
io:
|
|
157
152
|
- type: NatsIO
|
|
158
153
|
bindings:
|
|
159
|
-
discoveryTopic:
|
|
154
|
+
discoveryTopic: smartexample.discovery
|
|
160
155
|
store:
|
|
161
156
|
type: Postgres
|
|
162
157
|
|
|
@@ -217,16 +212,16 @@ spec:
|
|
|
217
212
|
- roomName
|
|
218
213
|
|
|
219
214
|
---
|
|
220
|
-
apiVersion:
|
|
215
|
+
apiVersion: agentnet/v1alpha1
|
|
221
216
|
kind: AgentDefinition
|
|
222
217
|
metadata:
|
|
223
218
|
name: pricing
|
|
224
|
-
namespace:
|
|
219
|
+
namespace: smartexample
|
|
225
220
|
spec:
|
|
226
221
|
io:
|
|
227
222
|
- type: NatsIO
|
|
228
223
|
bindings:
|
|
229
|
-
discoveryTopic:
|
|
224
|
+
discoveryTopic: smartexample.discovery
|
|
230
225
|
store:
|
|
231
226
|
type: Postgres
|
|
232
227
|
|
|
@@ -57,11 +57,19 @@ const agentClient = AgentClient()
|
|
|
57
57
|
const message = new Message({
|
|
58
58
|
content: "What rooms do you have from 2025-05-25 to 2025-05-30 for 3 guests For the hotel Flora? Give me the review of the hotel Flora",
|
|
59
59
|
session: {
|
|
60
|
-
id: "67a71e42-a7d8-1db2-ad17-
|
|
60
|
+
id: "67a71e42-a7d8-1db2-ad17-64e1c8546b20"
|
|
61
61
|
}
|
|
62
62
|
})
|
|
63
63
|
const res = await agentClient.queryIo(io, 'entrypoint', message)
|
|
64
64
|
console.log("=======\n", res.getContent())
|
|
65
65
|
console.log("=======\n", res.getSession())
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
|
|
67
|
+
const message2 = new Message({
|
|
68
|
+
content: "Quanto costa la camera doppia del Flora per il 10-05-2025 per due persone? Prenotala se costa meno di 100€ la camera double con vista mare per il 10-05-2025 al hotel Flora",
|
|
69
|
+
session: {
|
|
70
|
+
id: "67a71e42-a7d8-1db2-ad17-64e1c8546b20"
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
const res2 = await agentClient.queryIo(io, 'entrypoint', message2)
|
|
74
|
+
console.log("=======\n", res2.getContent())
|
|
75
|
+
console.log("=======\n", res2.getSession())
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentnet",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent library used by Smartness",
|
|
6
|
-
"main": "index.js",
|
|
6
|
+
"main": "src/index.js",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"test": "node --experimental-vm-modules ./node_modules/.bin/jest --rootDir=src/tests"
|
|
9
9
|
},
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'fs'
|
|
2
2
|
import { parse } from 'yaml'
|
|
3
3
|
import { Gemini } from "../index.js"
|
|
4
|
+
import { GPT } from "../index.js"
|
|
4
5
|
import { Agent } from "./agent.js"
|
|
5
6
|
import { logger } from "../utils/logger.js"
|
|
6
7
|
import { ConfigurationError } from "../errors/index.js"
|
|
@@ -10,8 +11,7 @@ import { validateApiVersion, DEFAULT_API_VERSION, API_VERSIONS } from '../utils/
|
|
|
10
11
|
* Version handlers for different API versions
|
|
11
12
|
*/
|
|
12
13
|
const VERSION_HANDLERS = {
|
|
13
|
-
'
|
|
14
|
-
'agentnet.io/v1alpha1': processV1Alpha1Definition
|
|
14
|
+
'agentnet/v1alpha1': processV1Alpha1Definition
|
|
15
15
|
// Additional version handlers can be added here as the API evolves
|
|
16
16
|
};
|
|
17
17
|
|
|
@@ -139,6 +139,9 @@ async function loadLlmProvider(providerName) {
|
|
|
139
139
|
if (providerName === 'Gemini') {
|
|
140
140
|
return Gemini;
|
|
141
141
|
}
|
|
142
|
+
if (providerName === 'GPT') {
|
|
143
|
+
return GPT;
|
|
144
|
+
}
|
|
142
145
|
|
|
143
146
|
try {
|
|
144
147
|
return global[providerName] || await import(providerName);
|
|
@@ -209,11 +212,14 @@ async function configureLLM(agentBuilder, llmSpec) {
|
|
|
209
212
|
|
|
210
213
|
const llmProviderInstance = await loadLlmProvider(llmSpec.provider);
|
|
211
214
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
215
|
+
const config = {}
|
|
216
|
+
for (const key in llmSpec) {
|
|
217
|
+
if (key !== 'provider') {
|
|
218
|
+
config[key] = llmSpec[key];
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return agentBuilder.withLLM(llmProviderInstance, config);
|
|
217
223
|
}
|
|
218
224
|
|
|
219
225
|
/**
|
package/src/agent/executor.js
CHANGED
|
@@ -34,7 +34,7 @@ async function emit(hooks, event, data) {
|
|
|
34
34
|
* @param {Array} tools - Tool definitions
|
|
35
35
|
* @param {Array} handoffs - Handoff definitions
|
|
36
36
|
*/
|
|
37
|
-
export function makeToolsAndHandoffsMap(toolsAndHandoffsMap, tools, handoffs) {
|
|
37
|
+
export function makeToolsAndHandoffsMap(llmType, toolsAndHandoffsMap, tools, handoffs) {
|
|
38
38
|
if (!tools) {
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
@@ -71,6 +71,11 @@ export function makeToolsAndHandoffsMap(toolsAndHandoffsMap, tools, handoffs) {
|
|
|
71
71
|
logger.warn('Skipping invalid handoff definition', { handoff });
|
|
72
72
|
continue;
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
// TODO: Remove this once we have a better way to handle handoffs
|
|
76
|
+
if (llmType === 'openai') {
|
|
77
|
+
handoff.schema.type = 'function'
|
|
78
|
+
}
|
|
74
79
|
|
|
75
80
|
// Add handoff schema to tools list
|
|
76
81
|
toolsAndHandoffsMap.tools.push(handoff.schema);
|
|
@@ -295,12 +300,6 @@ export async function build(
|
|
|
295
300
|
error: error
|
|
296
301
|
});
|
|
297
302
|
|
|
298
|
-
// Add error message to conversation
|
|
299
|
-
contents.push({
|
|
300
|
-
role: 'system',
|
|
301
|
-
content: `Error: ${error.message}`
|
|
302
|
-
});
|
|
303
|
-
|
|
304
303
|
// If we haven't hit max runs, try again
|
|
305
304
|
if (run < maxRuns - 1) {
|
|
306
305
|
logger.info(`Continuing after error in agent ${agentName}`);
|
package/src/agent/runtime.js
CHANGED
package/src/llm/base.js
CHANGED
|
@@ -82,12 +82,12 @@ export class BaseLLM {
|
|
|
82
82
|
* @param {Object} toolsAndHandoffsMap - Map of available tools
|
|
83
83
|
* @returns {Promise<any>} Result of the tool execution
|
|
84
84
|
*/
|
|
85
|
-
async executeToolCall(toolCall, name, args, state,
|
|
85
|
+
async executeToolCall(toolCall, name, args, state, toolsAndHandoffsMap) {
|
|
86
86
|
logger.debug(`Executing tool from ${this.type}`, {
|
|
87
87
|
toolName: name,
|
|
88
88
|
argsPreview: JSON.stringify(args).substring(0, 100)
|
|
89
89
|
});
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
try {
|
|
92
92
|
if (!toolsAndHandoffsMap[name] || !toolsAndHandoffsMap[name].function) {
|
|
93
93
|
throw new Error(`Tool "${name}" not found or has no function implementation`);
|
|
@@ -95,7 +95,7 @@ export class BaseLLM {
|
|
|
95
95
|
|
|
96
96
|
let result = null;
|
|
97
97
|
if (toolsAndHandoffsMap[name].type === 'handoff') {
|
|
98
|
-
result = await toolsAndHandoffsMap[name].function(
|
|
98
|
+
result = await toolsAndHandoffsMap[name].function(state, args);
|
|
99
99
|
// Process handoff results if needed
|
|
100
100
|
this.processHandoffResult(result, state);
|
|
101
101
|
} else {
|
|
@@ -106,7 +106,7 @@ export class BaseLLM {
|
|
|
106
106
|
return result;
|
|
107
107
|
|
|
108
108
|
} catch (error) {
|
|
109
|
-
logger.error(`Error executing tool "${name}"`,
|
|
109
|
+
logger.error(`Error executing tool "${name}"`, error.message);
|
|
110
110
|
throw error;
|
|
111
111
|
}
|
|
112
112
|
}
|
package/src/llm/gemini.js
CHANGED
|
@@ -65,6 +65,7 @@ class GeminiLLM extends BaseLLM {
|
|
|
65
65
|
});
|
|
66
66
|
return res;
|
|
67
67
|
} catch (error) {
|
|
68
|
+
console.log(error)
|
|
68
69
|
logger.error('Gemini API error', {
|
|
69
70
|
error,
|
|
70
71
|
modelName: input.model
|
|
@@ -93,7 +94,7 @@ class GeminiLLM extends BaseLLM {
|
|
|
93
94
|
const name = toolCall.name;
|
|
94
95
|
|
|
95
96
|
try {
|
|
96
|
-
const result = await super.executeToolCall(toolCall, name, args, state,
|
|
97
|
+
const result = await super.executeToolCall(toolCall, name, args, state, toolsAndHandoffsMap);
|
|
97
98
|
|
|
98
99
|
// Add function call and response to conversation in Gemini-specific format
|
|
99
100
|
const function_response_part = {
|
|
@@ -128,7 +129,6 @@ class GeminiLLM extends BaseLLM {
|
|
|
128
129
|
// Handle simple text response
|
|
129
130
|
if (response.text !== undefined) {
|
|
130
131
|
logger.debug('Gemini response contains text, returning directly');
|
|
131
|
-
conversation.push({ role: 'model', parts: [{ text: response.text }] });
|
|
132
132
|
return response.text;
|
|
133
133
|
}
|
|
134
134
|
|
package/src/llm/gpt.js
CHANGED
|
@@ -50,14 +50,14 @@ class OpenAILLM extends BaseLLM {
|
|
|
50
50
|
conversationLength: conversation.length,
|
|
51
51
|
toolsCount: toolsAndHandoffsMap.tools.length
|
|
52
52
|
});
|
|
53
|
-
|
|
53
|
+
//console.log(JSON.stringify(input, null, 2))
|
|
54
54
|
try {
|
|
55
55
|
const response = await client.responses.create(input);
|
|
56
56
|
logger.debug('OpenAI response received');
|
|
57
57
|
return response;
|
|
58
58
|
} catch (error) {
|
|
59
59
|
logger.error('OpenAI API error', {
|
|
60
|
-
error,
|
|
60
|
+
error: error.message,
|
|
61
61
|
modelName: input.model
|
|
62
62
|
});
|
|
63
63
|
|
|
@@ -90,7 +90,7 @@ class OpenAILLM extends BaseLLM {
|
|
|
90
90
|
callId: toolCall.call_id
|
|
91
91
|
});
|
|
92
92
|
|
|
93
|
-
const result = await super.executeToolCall(toolCall, name, args, state,
|
|
93
|
+
const result = await super.executeToolCall(toolCall, name, args, state, toolsAndHandoffsMap);
|
|
94
94
|
conversation.push(toolCall);
|
|
95
95
|
|
|
96
96
|
const resultString = typeof result === 'string' ? result : JSON.stringify(result);
|
|
@@ -129,7 +129,6 @@ class OpenAILLM extends BaseLLM {
|
|
|
129
129
|
async onResponse(state, conversation, toolsAndHandoffsMap, response) {
|
|
130
130
|
if (response.output_text !== undefined && response.output_text.length > 0) {
|
|
131
131
|
logger.debug('OpenAI response contains text, returning directly');
|
|
132
|
-
conversation.push({ role: 'model', parts: [{ text: response.output_text }] });
|
|
133
132
|
return response.output_text;
|
|
134
133
|
}
|
|
135
134
|
|
package/src/store/store.js
CHANGED
|
@@ -191,10 +191,12 @@ export function memoryStore () {
|
|
|
191
191
|
connect: async function () {},
|
|
192
192
|
disconnect: async function () {},
|
|
193
193
|
set: async function (key, value) {
|
|
194
|
+
console.log('Setting state', key, value)
|
|
194
195
|
state[key] = value
|
|
195
196
|
return state[key]
|
|
196
197
|
},
|
|
197
198
|
get: async function (key) {
|
|
199
|
+
console.log('Getting state', key)
|
|
198
200
|
return state[key] || null
|
|
199
201
|
}
|
|
200
202
|
}
|
package/src/transport/nats.js
CHANGED
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
// Constants
|
|
16
16
|
const HEARTBEAT_INTERVAL = 1000;
|
|
17
17
|
const TIMEOUT_TASK_REQUEST = 60000;
|
|
18
|
-
const MAX_RECONNECT_ATTEMPTS = 5;
|
|
19
18
|
|
|
20
19
|
/**
|
|
21
20
|
* NATS implementation of the Transport interface
|
|
@@ -225,13 +224,14 @@ export class NatsTransport extends Transport {
|
|
|
225
224
|
continue;
|
|
226
225
|
}
|
|
227
226
|
}
|
|
227
|
+
|
|
228
228
|
|
|
229
229
|
// Skip if not accepted
|
|
230
230
|
if (!isAccepted) {
|
|
231
231
|
logger.warn(`Agent ${agentName} does not accept network ${network}`);
|
|
232
232
|
nonAcceptedNetworks[network] = true;
|
|
233
233
|
continue;
|
|
234
|
-
}
|
|
234
|
+
}
|
|
235
235
|
|
|
236
236
|
// Process the schemas from the discovery message
|
|
237
237
|
for (const schema of discoveryMessage.schemas) {
|
|
@@ -242,11 +242,10 @@ export class NatsTransport extends Transport {
|
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
const agentKey = `${network}-${schema.name}`;
|
|
245
|
-
|
|
246
245
|
if (discoveryMessage.agentName !== agentName && !discoveredAgents[agentKey]) {
|
|
247
246
|
logger.info(`${agentName} discovered agent capability: ${discoveryMessage.agentName} with capability ${schema.name}`);
|
|
248
247
|
|
|
249
|
-
const handoffFunction = async (
|
|
248
|
+
const handoffFunction = async (state, input) => {
|
|
250
249
|
try {
|
|
251
250
|
// Use withTimeout to ensure handoffs don't hang
|
|
252
251
|
return await withTimeout(
|
package/src/utils/logger.js
CHANGED
package/src/utils/version.js
CHANGED
|
@@ -5,18 +5,10 @@ import { ConfigurationError } from '../errors/index.js';
|
|
|
5
5
|
* Map of API versions with their compatibility information
|
|
6
6
|
*/
|
|
7
7
|
export const API_VERSIONS = {
|
|
8
|
-
|
|
9
|
-
'smartagent.io/v1alpha1': {
|
|
8
|
+
'agentnet/v1alpha1': {
|
|
10
9
|
isSupported: true,
|
|
11
|
-
isStable:
|
|
12
|
-
minEngineVersion: '0.
|
|
13
|
-
features: ['basic', 'discovery', 'handoffs']
|
|
14
|
-
},
|
|
15
|
-
// Agentnet API versions
|
|
16
|
-
'agentnet.io/v1alpha1': {
|
|
17
|
-
isSupported: true,
|
|
18
|
-
isStable: false,
|
|
19
|
-
minEngineVersion: '0.8.0',
|
|
10
|
+
isStable: true,
|
|
11
|
+
minEngineVersion: '0.0.4',
|
|
20
12
|
features: ['basic', 'discovery', 'handoffs', 'advanced-routing']
|
|
21
13
|
}
|
|
22
14
|
};
|
|
@@ -24,19 +16,19 @@ export const API_VERSIONS = {
|
|
|
24
16
|
/**
|
|
25
17
|
* Default API version to use when none is specified
|
|
26
18
|
*/
|
|
27
|
-
export const DEFAULT_API_VERSION = '
|
|
19
|
+
export const DEFAULT_API_VERSION = 'agentnet/v1alpha1';
|
|
28
20
|
|
|
29
21
|
/**
|
|
30
22
|
* Latest stable API version
|
|
31
23
|
*/
|
|
32
|
-
export const LATEST_STABLE_VERSION = 'agentnet
|
|
24
|
+
export const LATEST_STABLE_VERSION = 'agentnet/v1alpha1';
|
|
33
25
|
|
|
34
26
|
/**
|
|
35
27
|
* Version upgrade paths map
|
|
36
28
|
* Defines valid upgrade paths between versions
|
|
37
29
|
*/
|
|
38
30
|
export const VERSION_UPGRADE_PATHS = {
|
|
39
|
-
'
|
|
31
|
+
'agentnet/v1alpha1': ['agentnet/v1alpha1']
|
|
40
32
|
};
|
|
41
33
|
|
|
42
34
|
/**
|
|
@@ -154,18 +146,18 @@ export function getUpgradeOptions(fromVersion) {
|
|
|
154
146
|
*/
|
|
155
147
|
const VERSION_MIGRATIONS = {
|
|
156
148
|
// Migration from smartagent.io/v1alpha1 to agentnet.io/v1alpha1
|
|
157
|
-
|
|
149
|
+
'smartagent.io/v1alpha1->agentnet.io/v1alpha1': (definition) => {
|
|
158
150
|
// Deep clone the definition to avoid modifying the original
|
|
159
151
|
const newDef = JSON.parse(JSON.stringify(definition));
|
|
160
152
|
|
|
161
153
|
// Update the apiVersion
|
|
162
|
-
newDef.apiVersion = 'agentnet
|
|
154
|
+
newDef.apiVersion = 'agentnet/v1alpha1';
|
|
163
155
|
|
|
164
156
|
// Handle specific field migrations
|
|
165
157
|
// Example: rename or restructure fields as needed
|
|
166
158
|
|
|
167
159
|
// Log the migration
|
|
168
|
-
logger.info(`Migrated agent definition from smartagent.io/v1alpha1 to agentnet
|
|
160
|
+
logger.info(`Migrated agent definition from smartagent.io/v1alpha1 to agentnet/v1alpha1`, {
|
|
169
161
|
agentName: newDef.metadata?.name
|
|
170
162
|
});
|
|
171
163
|
|
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import { parse, stringify } from 'yaml';
|
|
6
|
-
import { migrateDefinition, validateApiVersion, API_VERSIONS, LATEST_STABLE_VERSION } from '../utils/version.js';
|
|
7
|
-
import { logger } from '../utils/logger.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Print command usage instructions
|
|
11
|
-
*/
|
|
12
|
-
function printUsage() {
|
|
13
|
-
console.log(`
|
|
14
|
-
Agent Definition Version Migration Utility
|
|
15
|
-
|
|
16
|
-
Usage:
|
|
17
|
-
node migrate-version.js <input-file> [options]
|
|
18
|
-
|
|
19
|
-
Options:
|
|
20
|
-
--output <file> Output file (default: adds '-migrated' to input filename)
|
|
21
|
-
--version <ver> Target API version (default: ${LATEST_STABLE_VERSION})
|
|
22
|
-
--check Only check if migration is needed, don't perform it
|
|
23
|
-
--quiet Suppress informational output
|
|
24
|
-
--help Show this help message
|
|
25
|
-
|
|
26
|
-
Examples:
|
|
27
|
-
node migrate-version.js ./agents.yaml
|
|
28
|
-
node migrate-version.js ./agents.yaml --version agentnet.io/v1alpha1
|
|
29
|
-
node migrate-version.js ./agents.yaml --output ./agents-new.yaml
|
|
30
|
-
node migrate-version.js ./agents.yaml --check
|
|
31
|
-
`);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Parse command line arguments
|
|
36
|
-
* @returns {Object} Parsed arguments
|
|
37
|
-
*/
|
|
38
|
-
function parseArgs() {
|
|
39
|
-
const args = process.argv.slice(2);
|
|
40
|
-
const result = {
|
|
41
|
-
inputFile: null,
|
|
42
|
-
outputFile: null,
|
|
43
|
-
targetVersion: LATEST_STABLE_VERSION,
|
|
44
|
-
checkOnly: false,
|
|
45
|
-
quiet: false,
|
|
46
|
-
help: false
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
for (let i = 0; i < args.length; i++) {
|
|
50
|
-
const arg = args[i];
|
|
51
|
-
|
|
52
|
-
if (arg === '--help' || arg === '-h') {
|
|
53
|
-
result.help = true;
|
|
54
|
-
} else if (arg === '--output' || arg === '-o') {
|
|
55
|
-
result.outputFile = args[++i];
|
|
56
|
-
} else if (arg === '--version' || arg === '-v') {
|
|
57
|
-
result.targetVersion = args[++i];
|
|
58
|
-
} else if (arg === '--check' || arg === '-c') {
|
|
59
|
-
result.checkOnly = true;
|
|
60
|
-
} else if (arg === '--quiet' || arg === '-q') {
|
|
61
|
-
result.quiet = true;
|
|
62
|
-
} else if (!result.inputFile) {
|
|
63
|
-
result.inputFile = arg;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return result;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Get default output filename based on input filename
|
|
72
|
-
* @param {string} inputFile - Input file path
|
|
73
|
-
* @param {string} targetVersion - Target API version
|
|
74
|
-
* @returns {string} Default output file path
|
|
75
|
-
*/
|
|
76
|
-
function getDefaultOutputFile(inputFile, targetVersion) {
|
|
77
|
-
const parsedPath = path.parse(inputFile);
|
|
78
|
-
const versionSuffix = targetVersion.replace(/\//g, '-');
|
|
79
|
-
return path.join(
|
|
80
|
-
parsedPath.dir,
|
|
81
|
-
`${parsedPath.name}-${versionSuffix}${parsedPath.ext}`
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Log a message if not in quiet mode
|
|
87
|
-
* @param {string} message - Message to log
|
|
88
|
-
* @param {boolean} isError - Whether this is an error message
|
|
89
|
-
* @param {boolean} quiet - Whether quiet mode is enabled
|
|
90
|
-
*/
|
|
91
|
-
function log(message, isError = false, quiet = false) {
|
|
92
|
-
if (isError || !quiet) {
|
|
93
|
-
console.log(message);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Process and migrate a YAML file containing agent definitions
|
|
99
|
-
* @param {string} content - YAML content
|
|
100
|
-
* @param {string} targetVersion - Target API version
|
|
101
|
-
* @param {boolean} checkOnly - Only check, don't modify
|
|
102
|
-
* @returns {Object} Migration results including modified content
|
|
103
|
-
*/
|
|
104
|
-
function processYamlFile(content, targetVersion, checkOnly) {
|
|
105
|
-
// Split the YAML content by document separator
|
|
106
|
-
const documents = content.split(/^---$/m)
|
|
107
|
-
.map(s => s.trim())
|
|
108
|
-
.filter(s => s);
|
|
109
|
-
|
|
110
|
-
const result = {
|
|
111
|
-
migrated: false,
|
|
112
|
-
migratedCount: 0,
|
|
113
|
-
alreadyUpToDateCount: 0,
|
|
114
|
-
failedCount: 0,
|
|
115
|
-
needsMigration: false,
|
|
116
|
-
updatedContent: null,
|
|
117
|
-
failures: []
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
// Process each document
|
|
121
|
-
const processedDocs = [];
|
|
122
|
-
|
|
123
|
-
for (let i = 0; i < documents.length; i++) {
|
|
124
|
-
try {
|
|
125
|
-
const docContent = documents[i];
|
|
126
|
-
const doc = parse(docContent);
|
|
127
|
-
|
|
128
|
-
// Skip non-agent definitions
|
|
129
|
-
if (!doc || doc.kind !== 'AgentDefinition') {
|
|
130
|
-
processedDocs.push(docContent);
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Check if migration is needed
|
|
135
|
-
const currentVersion = doc.apiVersion || 'smartagent.io/v1alpha1';
|
|
136
|
-
const agentName = doc.metadata?.name || `[Document ${i+1}]`;
|
|
137
|
-
|
|
138
|
-
if (currentVersion === targetVersion) {
|
|
139
|
-
result.alreadyUpToDateCount++;
|
|
140
|
-
log(`Agent "${agentName}" is already at version ${targetVersion}`);
|
|
141
|
-
processedDocs.push(docContent);
|
|
142
|
-
continue;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
result.needsMigration = true;
|
|
146
|
-
|
|
147
|
-
// If only checking, skip migration
|
|
148
|
-
if (checkOnly) {
|
|
149
|
-
processedDocs.push(docContent);
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Perform migration
|
|
154
|
-
const migratedDoc = migrateDefinition(doc, targetVersion);
|
|
155
|
-
result.migratedCount++;
|
|
156
|
-
result.migrated = true;
|
|
157
|
-
|
|
158
|
-
// Convert back to YAML and add to processed docs
|
|
159
|
-
processedDocs.push(stringify(migratedDoc));
|
|
160
|
-
|
|
161
|
-
log(`Successfully migrated agent "${agentName}" from ${currentVersion} to ${targetVersion}`);
|
|
162
|
-
|
|
163
|
-
} catch (error) {
|
|
164
|
-
result.failedCount++;
|
|
165
|
-
result.failures.push({
|
|
166
|
-
documentIndex: i,
|
|
167
|
-
error: error.message
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
// Keep original document on failure
|
|
171
|
-
processedDocs.push(documents[i]);
|
|
172
|
-
|
|
173
|
-
log(`Error processing document ${i+1}: ${error.message}`, true);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Combine the processed documents back into a single YAML file
|
|
178
|
-
result.updatedContent = processedDocs.join('\n---\n');
|
|
179
|
-
|
|
180
|
-
return result;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Main function
|
|
185
|
-
*/
|
|
186
|
-
async function main() {
|
|
187
|
-
const args = parseArgs();
|
|
188
|
-
|
|
189
|
-
// Show help if requested or no input file
|
|
190
|
-
if (args.help || !args.inputFile) {
|
|
191
|
-
printUsage();
|
|
192
|
-
process.exit(args.help ? 0 : 1);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Validate target version
|
|
196
|
-
if (!API_VERSIONS[args.targetVersion]) {
|
|
197
|
-
log(`Error: Unsupported target version: ${args.targetVersion}`, true);
|
|
198
|
-
log(`Supported versions: ${Object.keys(API_VERSIONS).join(', ')}`, true);
|
|
199
|
-
process.exit(1);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
try {
|
|
203
|
-
// Set default output file if not specified
|
|
204
|
-
if (!args.outputFile && !args.checkOnly) {
|
|
205
|
-
args.outputFile = getDefaultOutputFile(args.inputFile, args.targetVersion);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Read input file
|
|
209
|
-
const content = fs.readFileSync(args.inputFile, 'utf8');
|
|
210
|
-
|
|
211
|
-
// Process the file
|
|
212
|
-
const result = processYamlFile(content, args.targetVersion, args.checkOnly);
|
|
213
|
-
|
|
214
|
-
// Output results
|
|
215
|
-
if (result.needsMigration) {
|
|
216
|
-
if (args.checkOnly) {
|
|
217
|
-
log(`Migration needed: ${result.alreadyUpToDateCount} up-to-date, ${result.failedCount + documents.length - result.alreadyUpToDateCount} need migration`);
|
|
218
|
-
process.exit(10); // Special exit code indicating migration needed
|
|
219
|
-
} else if (result.migrated) {
|
|
220
|
-
// Write the output file
|
|
221
|
-
fs.writeFileSync(args.outputFile, result.updatedContent);
|
|
222
|
-
|
|
223
|
-
log(`
|
|
224
|
-
Migration completed:
|
|
225
|
-
- ${result.migratedCount} agent definitions migrated
|
|
226
|
-
- ${result.alreadyUpToDateCount} already up-to-date
|
|
227
|
-
- ${result.failedCount} failures
|
|
228
|
-
- Output written to: ${args.outputFile}
|
|
229
|
-
`);
|
|
230
|
-
}
|
|
231
|
-
} else {
|
|
232
|
-
log(`No migration needed. All agent definitions are already at version ${args.targetVersion}`);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Exit with error if any migrations failed
|
|
236
|
-
if (result.failedCount > 0) {
|
|
237
|
-
process.exit(1);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
} catch (error) {
|
|
241
|
-
log(`Error: ${error.message}`, true);
|
|
242
|
-
process.exit(1);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Run the main function
|
|
247
|
-
main().catch(error => {
|
|
248
|
-
console.error('Unhandled error:', error);
|
|
249
|
-
process.exit(1);
|
|
250
|
-
});
|