agentxjs 0.0.1
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/LICENSE +21 -0
- package/README.md +602 -0
- package/dist/index.cjs +1292 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +88 -0
- package/dist/index.d.ts +88 -0
- package/dist/index.js +1283 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime/sse/index.cjs +633 -0
- package/dist/runtime/sse/index.cjs.map +1 -0
- package/dist/runtime/sse/index.d.cts +159 -0
- package/dist/runtime/sse/index.d.ts +159 -0
- package/dist/runtime/sse/index.js +621 -0
- package/dist/runtime/sse/index.js.map +1 -0
- package/dist/server/adapters/express.cjs +81 -0
- package/dist/server/adapters/express.cjs.map +1 -0
- package/dist/server/adapters/express.d.cts +75 -0
- package/dist/server/adapters/express.d.ts +75 -0
- package/dist/server/adapters/express.js +78 -0
- package/dist/server/adapters/express.js.map +1 -0
- package/dist/server/adapters/hono.cjs +32 -0
- package/dist/server/adapters/hono.cjs.map +1 -0
- package/dist/server/adapters/hono.d.cts +96 -0
- package/dist/server/adapters/hono.d.ts +96 -0
- package/dist/server/adapters/hono.js +28 -0
- package/dist/server/adapters/hono.js.map +1 -0
- package/dist/server/adapters/index.cjs +135 -0
- package/dist/server/adapters/index.cjs.map +1 -0
- package/dist/server/adapters/index.d.cts +5 -0
- package/dist/server/adapters/index.d.ts +5 -0
- package/dist/server/adapters/index.js +125 -0
- package/dist/server/adapters/index.js.map +1 -0
- package/dist/server/adapters/next.cjs +30 -0
- package/dist/server/adapters/next.cjs.map +1 -0
- package/dist/server/adapters/next.d.cts +107 -0
- package/dist/server/adapters/next.d.ts +107 -0
- package/dist/server/adapters/next.js +25 -0
- package/dist/server/adapters/next.js.map +1 -0
- package/dist/server/index.cjs +1093 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.cts +131 -0
- package/dist/server/index.d.ts +131 -0
- package/dist/server/index.js +1080 -0
- package/dist/server/index.js.map +1 -0
- package/dist/types-Cgfcw91r.d.cts +282 -0
- package/dist/types-Cgfcw91r.d.ts +282 -0
- package/dist/types-OVKV6qpE.d.cts +118 -0
- package/dist/types-OVKV6qpE.d.ts +118 -0
- package/package.json +78 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1292 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var common = require('@agentxjs/common');
|
|
4
|
+
var ky = require('ky');
|
|
5
|
+
var agent = require('@agentxjs/agent');
|
|
6
|
+
var engine = require('@agentxjs/engine');
|
|
7
|
+
var types = require('@agentxjs/types');
|
|
8
|
+
|
|
9
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
|
|
11
|
+
var ky__default = /*#__PURE__*/_interopDefault(ky);
|
|
12
|
+
|
|
13
|
+
var __defProp = Object.defineProperty;
|
|
14
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
15
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
16
|
+
|
|
17
|
+
// src/defineAgent.ts
|
|
18
|
+
function defineAgent(input) {
|
|
19
|
+
const { name, description, systemPrompt } = input;
|
|
20
|
+
return {
|
|
21
|
+
name,
|
|
22
|
+
description,
|
|
23
|
+
systemPrompt
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
var logger = common.createLogger("agentx/DefinitionManager");
|
|
27
|
+
function generateMetaImageId(definitionName) {
|
|
28
|
+
return `meta_${definitionName}`;
|
|
29
|
+
}
|
|
30
|
+
function toDefinitionRecord(definition) {
|
|
31
|
+
const now = /* @__PURE__ */ new Date();
|
|
32
|
+
return {
|
|
33
|
+
name: definition.name,
|
|
34
|
+
description: definition.description,
|
|
35
|
+
systemPrompt: definition.systemPrompt,
|
|
36
|
+
definition,
|
|
37
|
+
source: "code",
|
|
38
|
+
createdAt: now,
|
|
39
|
+
updatedAt: now
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
var DefinitionManagerImpl = class {
|
|
43
|
+
constructor(repository) {
|
|
44
|
+
this.repository = repository;
|
|
45
|
+
// Local cache for sync access
|
|
46
|
+
__publicField(this, "cache", /* @__PURE__ */ new Map());
|
|
47
|
+
}
|
|
48
|
+
register(definition) {
|
|
49
|
+
if (this.cache.has(definition.name)) {
|
|
50
|
+
throw new Error(`Definition already exists: ${definition.name}`);
|
|
51
|
+
}
|
|
52
|
+
this.cache.set(definition.name, definition);
|
|
53
|
+
const definitionRecord = toDefinitionRecord(definition);
|
|
54
|
+
this.repository.saveDefinition(definitionRecord).catch((err) => {
|
|
55
|
+
logger.error("Failed to save definition", { name: definition.name, error: err });
|
|
56
|
+
});
|
|
57
|
+
const metaImageId = generateMetaImageId(definition.name);
|
|
58
|
+
const imageRecord = {
|
|
59
|
+
imageId: metaImageId,
|
|
60
|
+
type: "meta",
|
|
61
|
+
definitionName: definition.name,
|
|
62
|
+
parentImageId: null,
|
|
63
|
+
definition,
|
|
64
|
+
config: {},
|
|
65
|
+
messages: [],
|
|
66
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
67
|
+
};
|
|
68
|
+
this.repository.saveImage(imageRecord).catch((err) => {
|
|
69
|
+
logger.error("Failed to save MetaImage", { definitionName: definition.name, error: err });
|
|
70
|
+
});
|
|
71
|
+
logger.info("Definition registered", {
|
|
72
|
+
name: definition.name,
|
|
73
|
+
metaImageId
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
get(name) {
|
|
77
|
+
return this.cache.get(name);
|
|
78
|
+
}
|
|
79
|
+
list() {
|
|
80
|
+
return Array.from(this.cache.values());
|
|
81
|
+
}
|
|
82
|
+
has(name) {
|
|
83
|
+
return this.cache.has(name);
|
|
84
|
+
}
|
|
85
|
+
unregister(name) {
|
|
86
|
+
const definition = this.cache.get(name);
|
|
87
|
+
if (!definition) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
this.cache.delete(name);
|
|
91
|
+
this.repository.deleteDefinition(name).catch((err) => {
|
|
92
|
+
logger.error("Failed to delete definition", { name, error: err });
|
|
93
|
+
});
|
|
94
|
+
const metaImageId = generateMetaImageId(name);
|
|
95
|
+
this.repository.deleteImage(metaImageId).catch((err) => {
|
|
96
|
+
logger.error("Failed to delete MetaImage", { definitionName: name, error: err });
|
|
97
|
+
});
|
|
98
|
+
logger.info("Definition unregistered", { name });
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
var logger2 = common.createLogger("agentx/ImageManager");
|
|
103
|
+
function generateMetaImageId2(definitionName) {
|
|
104
|
+
return `meta_${definitionName}`;
|
|
105
|
+
}
|
|
106
|
+
function toAgentImage(record) {
|
|
107
|
+
const definition = record.definition;
|
|
108
|
+
if (record.type === "meta") {
|
|
109
|
+
const metaImage = {
|
|
110
|
+
type: "meta",
|
|
111
|
+
imageId: record.imageId,
|
|
112
|
+
definitionName: record.definitionName,
|
|
113
|
+
definition,
|
|
114
|
+
config: record.config,
|
|
115
|
+
messages: [],
|
|
116
|
+
createdAt: record.createdAt
|
|
117
|
+
};
|
|
118
|
+
return metaImage;
|
|
119
|
+
} else {
|
|
120
|
+
return {
|
|
121
|
+
type: "derived",
|
|
122
|
+
imageId: record.imageId,
|
|
123
|
+
parentImageId: record.parentImageId,
|
|
124
|
+
definitionName: record.definitionName,
|
|
125
|
+
definition,
|
|
126
|
+
config: record.config,
|
|
127
|
+
messages: record.messages,
|
|
128
|
+
createdAt: record.createdAt
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
var ImageManagerImpl = class {
|
|
133
|
+
constructor(repository, containerManager, defaultContainerId) {
|
|
134
|
+
__publicField(this, "repository");
|
|
135
|
+
__publicField(this, "containerManager");
|
|
136
|
+
__publicField(this, "defaultContainerId");
|
|
137
|
+
this.repository = repository;
|
|
138
|
+
this.containerManager = containerManager;
|
|
139
|
+
this.defaultContainerId = defaultContainerId;
|
|
140
|
+
}
|
|
141
|
+
async get(imageId) {
|
|
142
|
+
const record = await this.repository.findImageById(imageId);
|
|
143
|
+
if (!record) {
|
|
144
|
+
return void 0;
|
|
145
|
+
}
|
|
146
|
+
return toAgentImage(record);
|
|
147
|
+
}
|
|
148
|
+
async getMetaImage(definitionName) {
|
|
149
|
+
const metaImageId = generateMetaImageId2(definitionName);
|
|
150
|
+
const record = await this.repository.findImageById(metaImageId);
|
|
151
|
+
if (!record || record.type !== "meta") {
|
|
152
|
+
return void 0;
|
|
153
|
+
}
|
|
154
|
+
return toAgentImage(record);
|
|
155
|
+
}
|
|
156
|
+
async list() {
|
|
157
|
+
const records = await this.repository.findAllImages();
|
|
158
|
+
return records.map(toAgentImage);
|
|
159
|
+
}
|
|
160
|
+
async listByDefinition(definitionName) {
|
|
161
|
+
const allRecords = await this.repository.findAllImages();
|
|
162
|
+
const filtered = allRecords.filter((r) => r.definitionName === definitionName);
|
|
163
|
+
return filtered.map(toAgentImage);
|
|
164
|
+
}
|
|
165
|
+
async exists(imageId) {
|
|
166
|
+
return this.repository.imageExists(imageId);
|
|
167
|
+
}
|
|
168
|
+
async delete(imageId) {
|
|
169
|
+
const record = await this.repository.findImageById(imageId);
|
|
170
|
+
if (!record) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
if (record.type === "meta") {
|
|
174
|
+
logger2.warn("Cannot delete MetaImage directly", { imageId });
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
await this.repository.deleteImage(imageId);
|
|
178
|
+
logger2.info("Image deleted", { imageId });
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
async run(imageId, options) {
|
|
182
|
+
logger2.info("Running agent from image", { imageId, containerId: options?.containerId });
|
|
183
|
+
const image = await this.get(imageId);
|
|
184
|
+
if (!image) {
|
|
185
|
+
throw new Error(`Image not found: ${imageId}`);
|
|
186
|
+
}
|
|
187
|
+
let containerId = options?.containerId || this.defaultContainerId;
|
|
188
|
+
if (!containerId) {
|
|
189
|
+
const container = await this.containerManager.create();
|
|
190
|
+
containerId = container.containerId;
|
|
191
|
+
this.defaultContainerId = containerId;
|
|
192
|
+
logger2.debug("Auto-created default container", { containerId });
|
|
193
|
+
}
|
|
194
|
+
return this.containerManager.run(image, containerId);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
var logger3 = common.createLogger("agentx/AgentManager");
|
|
198
|
+
var AgentManager = class {
|
|
199
|
+
constructor(containerManager) {
|
|
200
|
+
this.containerManager = containerManager;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Get an existing agent by ID
|
|
204
|
+
*/
|
|
205
|
+
get(agentId) {
|
|
206
|
+
return this.containerManager.getAgent(agentId);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Check if an agent exists
|
|
210
|
+
*/
|
|
211
|
+
has(agentId) {
|
|
212
|
+
return this.containerManager.hasAgent(agentId);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* List all agents
|
|
216
|
+
*/
|
|
217
|
+
list() {
|
|
218
|
+
return this.containerManager.listAgents();
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Destroy an agent by ID
|
|
222
|
+
*/
|
|
223
|
+
async destroy(agentId) {
|
|
224
|
+
logger3.debug("Destroying agent", { agentId });
|
|
225
|
+
await this.containerManager.destroyAgent(agentId);
|
|
226
|
+
logger3.info("Agent destroyed", { agentId });
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Destroy all agents
|
|
230
|
+
*/
|
|
231
|
+
async destroyAll() {
|
|
232
|
+
const agents = this.containerManager.listAgents();
|
|
233
|
+
logger3.debug("Destroying all agents", { count: agents.length });
|
|
234
|
+
await this.containerManager.destroyAllAgents();
|
|
235
|
+
logger3.info("All agents destroyed", { count: agents.length });
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
var logger4 = common.createLogger("agentx/SessionManager");
|
|
239
|
+
function generateSessionId() {
|
|
240
|
+
const timestamp = Date.now().toString(36);
|
|
241
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
242
|
+
return `session_${timestamp}_${random}`;
|
|
243
|
+
}
|
|
244
|
+
function generateImageId() {
|
|
245
|
+
const timestamp = Date.now().toString(36);
|
|
246
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
247
|
+
return `image_${timestamp}_${random}`;
|
|
248
|
+
}
|
|
249
|
+
var SessionImpl = class _SessionImpl {
|
|
250
|
+
constructor(record, repository, containerManager, defaultContainerId) {
|
|
251
|
+
__publicField(this, "sessionId");
|
|
252
|
+
__publicField(this, "userId");
|
|
253
|
+
__publicField(this, "imageId");
|
|
254
|
+
__publicField(this, "createdAt");
|
|
255
|
+
__publicField(this, "_title");
|
|
256
|
+
__publicField(this, "_updatedAt");
|
|
257
|
+
__publicField(this, "repository");
|
|
258
|
+
__publicField(this, "containerManager");
|
|
259
|
+
__publicField(this, "defaultContainerId");
|
|
260
|
+
this.sessionId = record.sessionId;
|
|
261
|
+
this.userId = record.userId;
|
|
262
|
+
this.imageId = record.imageId;
|
|
263
|
+
this._title = record.title;
|
|
264
|
+
this.createdAt = record.createdAt.getTime();
|
|
265
|
+
this._updatedAt = record.updatedAt.getTime();
|
|
266
|
+
this.repository = repository;
|
|
267
|
+
this.containerManager = containerManager;
|
|
268
|
+
this.defaultContainerId = defaultContainerId;
|
|
269
|
+
}
|
|
270
|
+
get title() {
|
|
271
|
+
return this._title;
|
|
272
|
+
}
|
|
273
|
+
get updatedAt() {
|
|
274
|
+
return this._updatedAt;
|
|
275
|
+
}
|
|
276
|
+
async resume(options) {
|
|
277
|
+
logger4.info("Resuming agent from session", {
|
|
278
|
+
sessionId: this.sessionId,
|
|
279
|
+
imageId: this.imageId,
|
|
280
|
+
containerId: options?.containerId
|
|
281
|
+
});
|
|
282
|
+
let containerId = options?.containerId || this.defaultContainerId;
|
|
283
|
+
if (!containerId) {
|
|
284
|
+
const container = await this.containerManager.create();
|
|
285
|
+
containerId = container.containerId;
|
|
286
|
+
logger4.debug("Auto-created default container for session", {
|
|
287
|
+
containerId,
|
|
288
|
+
sessionId: this.sessionId
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
const agent = await this.containerManager.resume(this, containerId);
|
|
292
|
+
this.collect(agent);
|
|
293
|
+
return agent;
|
|
294
|
+
}
|
|
295
|
+
collect(agent) {
|
|
296
|
+
logger4.debug("Collecting messages from agent", {
|
|
297
|
+
sessionId: this.sessionId,
|
|
298
|
+
agentId: agent.agentId
|
|
299
|
+
});
|
|
300
|
+
const sessionId = this.sessionId;
|
|
301
|
+
const repository = this.repository;
|
|
302
|
+
const saveMessage = (data, role) => {
|
|
303
|
+
const record = {
|
|
304
|
+
messageId: data.id,
|
|
305
|
+
sessionId,
|
|
306
|
+
role,
|
|
307
|
+
content: data,
|
|
308
|
+
createdAt: new Date(data.timestamp ?? Date.now())
|
|
309
|
+
};
|
|
310
|
+
repository.saveMessage(record).catch((error) => {
|
|
311
|
+
logger4.error("Failed to persist message", {
|
|
312
|
+
sessionId,
|
|
313
|
+
messageId: record.messageId,
|
|
314
|
+
error
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
};
|
|
318
|
+
agent.on("user_message", (event) => saveMessage(event.data, "user"));
|
|
319
|
+
agent.on("assistant_message", (event) => saveMessage(event.data, "assistant"));
|
|
320
|
+
agent.on("tool_call_message", (event) => saveMessage(event.data, "tool"));
|
|
321
|
+
agent.on("tool_result_message", (event) => saveMessage(event.data, "tool"));
|
|
322
|
+
}
|
|
323
|
+
async getMessages() {
|
|
324
|
+
logger4.debug("Getting messages for session", { sessionId: this.sessionId });
|
|
325
|
+
const records = await this.repository.findMessagesBySessionId(this.sessionId);
|
|
326
|
+
return records.map((record) => record.content);
|
|
327
|
+
}
|
|
328
|
+
async fork() {
|
|
329
|
+
logger4.info("Forking session", { sessionId: this.sessionId });
|
|
330
|
+
const imageRecord = await this.repository.findImageById(this.imageId);
|
|
331
|
+
if (!imageRecord) {
|
|
332
|
+
throw new Error(`Image not found: ${this.imageId}`);
|
|
333
|
+
}
|
|
334
|
+
const newImageId = generateImageId();
|
|
335
|
+
const newImageRecord = {
|
|
336
|
+
imageId: newImageId,
|
|
337
|
+
type: "derived",
|
|
338
|
+
definitionName: imageRecord.definitionName,
|
|
339
|
+
parentImageId: imageRecord.imageId,
|
|
340
|
+
definition: imageRecord.definition,
|
|
341
|
+
config: imageRecord.config,
|
|
342
|
+
messages: [...imageRecord.messages],
|
|
343
|
+
// Copy messages
|
|
344
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
345
|
+
};
|
|
346
|
+
await this.repository.saveImage(newImageRecord);
|
|
347
|
+
const newSessionId = generateSessionId();
|
|
348
|
+
const now = /* @__PURE__ */ new Date();
|
|
349
|
+
const newSessionRecord = {
|
|
350
|
+
sessionId: newSessionId,
|
|
351
|
+
userId: this.userId,
|
|
352
|
+
imageId: newImageId,
|
|
353
|
+
title: this._title ? `Fork of ${this._title}` : null,
|
|
354
|
+
createdAt: now,
|
|
355
|
+
updatedAt: now
|
|
356
|
+
};
|
|
357
|
+
await this.repository.saveSession(newSessionRecord);
|
|
358
|
+
logger4.info("Session forked", {
|
|
359
|
+
originalSessionId: this.sessionId,
|
|
360
|
+
newSessionId,
|
|
361
|
+
newImageId
|
|
362
|
+
});
|
|
363
|
+
return new _SessionImpl(
|
|
364
|
+
newSessionRecord,
|
|
365
|
+
this.repository,
|
|
366
|
+
this.containerManager,
|
|
367
|
+
this.defaultContainerId
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
async setTitle(title) {
|
|
371
|
+
logger4.debug("Setting session title", { sessionId: this.sessionId, title });
|
|
372
|
+
const now = /* @__PURE__ */ new Date();
|
|
373
|
+
await this.repository.saveSession({
|
|
374
|
+
sessionId: this.sessionId,
|
|
375
|
+
userId: this.userId,
|
|
376
|
+
imageId: this.imageId,
|
|
377
|
+
title,
|
|
378
|
+
createdAt: new Date(this.createdAt),
|
|
379
|
+
updatedAt: now
|
|
380
|
+
});
|
|
381
|
+
this._title = title;
|
|
382
|
+
this._updatedAt = now.getTime();
|
|
383
|
+
logger4.info("Session title updated", { sessionId: this.sessionId, title });
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
var SessionManagerImpl = class {
|
|
387
|
+
constructor(repository, containerManager, defaultContainerId) {
|
|
388
|
+
__publicField(this, "repository");
|
|
389
|
+
__publicField(this, "containerManager");
|
|
390
|
+
__publicField(this, "defaultContainerId");
|
|
391
|
+
this.repository = repository;
|
|
392
|
+
this.containerManager = containerManager;
|
|
393
|
+
this.defaultContainerId = defaultContainerId;
|
|
394
|
+
}
|
|
395
|
+
async create(imageId, userId) {
|
|
396
|
+
const sessionId = generateSessionId();
|
|
397
|
+
const now = /* @__PURE__ */ new Date();
|
|
398
|
+
const record = {
|
|
399
|
+
sessionId,
|
|
400
|
+
userId,
|
|
401
|
+
imageId,
|
|
402
|
+
title: null,
|
|
403
|
+
createdAt: now,
|
|
404
|
+
updatedAt: now
|
|
405
|
+
};
|
|
406
|
+
await this.repository.saveSession(record);
|
|
407
|
+
logger4.info("Session created", { sessionId, imageId, userId });
|
|
408
|
+
return new SessionImpl(record, this.repository, this.containerManager, this.defaultContainerId);
|
|
409
|
+
}
|
|
410
|
+
async get(sessionId) {
|
|
411
|
+
const record = await this.repository.findSessionById(sessionId);
|
|
412
|
+
if (!record) return void 0;
|
|
413
|
+
return new SessionImpl(record, this.repository, this.containerManager, this.defaultContainerId);
|
|
414
|
+
}
|
|
415
|
+
async has(sessionId) {
|
|
416
|
+
return this.repository.sessionExists(sessionId);
|
|
417
|
+
}
|
|
418
|
+
async list() {
|
|
419
|
+
const records = await this.repository.findAllSessions();
|
|
420
|
+
return records.map(
|
|
421
|
+
(r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
async listByImage(imageId) {
|
|
425
|
+
const records = await this.repository.findSessionsByImageId(imageId);
|
|
426
|
+
return records.map(
|
|
427
|
+
(r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
async listByUser(userId) {
|
|
431
|
+
const records = await this.repository.findSessionsByUserId(userId);
|
|
432
|
+
return records.map(
|
|
433
|
+
(r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
async destroy(sessionId) {
|
|
437
|
+
await this.repository.deleteSession(sessionId);
|
|
438
|
+
logger4.info("Session destroyed", { sessionId });
|
|
439
|
+
}
|
|
440
|
+
async destroyByImage(imageId) {
|
|
441
|
+
await this.repository.deleteSessionsByImageId(imageId);
|
|
442
|
+
logger4.info("Sessions destroyed by image", { imageId });
|
|
443
|
+
}
|
|
444
|
+
async destroyAll() {
|
|
445
|
+
const sessions = await this.repository.findAllSessions();
|
|
446
|
+
for (const session of sessions) {
|
|
447
|
+
await this.repository.deleteSession(session.sessionId);
|
|
448
|
+
}
|
|
449
|
+
logger4.info("All sessions destroyed");
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
var logger5 = common.createLogger("agentx/ErrorManager");
|
|
453
|
+
var ErrorManager = class {
|
|
454
|
+
constructor() {
|
|
455
|
+
__publicField(this, "handlers", /* @__PURE__ */ new Set());
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Handle an error from any agent
|
|
459
|
+
*
|
|
460
|
+
* Called internally when an agent emits an error event.
|
|
461
|
+
* 1. Default logging (always)
|
|
462
|
+
* 2. Custom handlers (user-registered)
|
|
463
|
+
*/
|
|
464
|
+
handle(agentId, error, event) {
|
|
465
|
+
this.logError(agentId, error);
|
|
466
|
+
for (const handler of this.handlers) {
|
|
467
|
+
try {
|
|
468
|
+
handler.handle(agentId, error, event);
|
|
469
|
+
} catch (e) {
|
|
470
|
+
logger5.error("ErrorHandler failed", { error: e });
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Add a custom error handler
|
|
476
|
+
*/
|
|
477
|
+
addHandler(handler) {
|
|
478
|
+
this.handlers.add(handler);
|
|
479
|
+
return () => {
|
|
480
|
+
this.handlers.delete(handler);
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Remove an error handler
|
|
485
|
+
*/
|
|
486
|
+
removeHandler(handler) {
|
|
487
|
+
this.handlers.delete(handler);
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Default error logging
|
|
491
|
+
*/
|
|
492
|
+
logError(agentId, error) {
|
|
493
|
+
const prefix = `[${agentId}] ${error.category}/${error.code}`;
|
|
494
|
+
if (error.severity === "fatal") {
|
|
495
|
+
logger5.error(`${prefix}: ${error.message}`, { error });
|
|
496
|
+
} else if (error.severity === "error") {
|
|
497
|
+
logger5.error(`${prefix}: ${error.message}`);
|
|
498
|
+
} else {
|
|
499
|
+
logger5.warn(`${prefix}: ${error.message}`);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
var ApiError = class extends Error {
|
|
504
|
+
constructor(code, message, details) {
|
|
505
|
+
super(message);
|
|
506
|
+
this.code = code;
|
|
507
|
+
this.details = details;
|
|
508
|
+
this.name = "ApiError";
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
function createHttpClient(options) {
|
|
512
|
+
return ky__default.default.create({
|
|
513
|
+
prefixUrl: options.baseUrl.replace(/\/+$/, ""),
|
|
514
|
+
headers: options.headers,
|
|
515
|
+
timeout: options.timeout || 3e4,
|
|
516
|
+
hooks: {
|
|
517
|
+
afterResponse: [
|
|
518
|
+
async (_request, _options, response) => {
|
|
519
|
+
if (!response.ok) {
|
|
520
|
+
const data = await response.json().catch(() => ({}));
|
|
521
|
+
throw new ApiError(
|
|
522
|
+
data.error?.code || "UNKNOWN_ERROR",
|
|
523
|
+
data.error?.message || `Request failed: ${response.status}`,
|
|
524
|
+
data.error?.details
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
return response;
|
|
528
|
+
}
|
|
529
|
+
]
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
var logger6 = common.createLogger("agentx/ContainerManager");
|
|
534
|
+
function generateContainerId() {
|
|
535
|
+
const timestamp = Date.now().toString(36);
|
|
536
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
537
|
+
return `container_${timestamp}_${random}`;
|
|
538
|
+
}
|
|
539
|
+
function generateAgentId() {
|
|
540
|
+
const timestamp = Date.now().toString(36);
|
|
541
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
542
|
+
return `agent_${timestamp}_${random}`;
|
|
543
|
+
}
|
|
544
|
+
var ContainerManagerImpl = class {
|
|
545
|
+
constructor(runtime, repository) {
|
|
546
|
+
__publicField(this, "agents", /* @__PURE__ */ new Map());
|
|
547
|
+
__publicField(this, "engine");
|
|
548
|
+
__publicField(this, "runtime");
|
|
549
|
+
__publicField(this, "repository");
|
|
550
|
+
this.runtime = runtime;
|
|
551
|
+
this.repository = repository;
|
|
552
|
+
this.engine = new engine.AgentEngine();
|
|
553
|
+
}
|
|
554
|
+
// ==================== Container Lifecycle ====================
|
|
555
|
+
async create(config) {
|
|
556
|
+
const containerId = generateContainerId();
|
|
557
|
+
const now = Date.now();
|
|
558
|
+
const record = {
|
|
559
|
+
containerId,
|
|
560
|
+
createdAt: now,
|
|
561
|
+
updatedAt: now,
|
|
562
|
+
config
|
|
563
|
+
};
|
|
564
|
+
await this.repository.saveContainer(record);
|
|
565
|
+
logger6.info("Container created", { containerId });
|
|
566
|
+
return record;
|
|
567
|
+
}
|
|
568
|
+
async get(containerId) {
|
|
569
|
+
return this.repository.findContainerById(containerId);
|
|
570
|
+
}
|
|
571
|
+
async list() {
|
|
572
|
+
return this.repository.findAllContainers();
|
|
573
|
+
}
|
|
574
|
+
async delete(containerId) {
|
|
575
|
+
const exists = await this.repository.containerExists(containerId);
|
|
576
|
+
if (!exists) {
|
|
577
|
+
return false;
|
|
578
|
+
}
|
|
579
|
+
await this.repository.deleteContainer(containerId);
|
|
580
|
+
logger6.info("Container deleted", { containerId });
|
|
581
|
+
return true;
|
|
582
|
+
}
|
|
583
|
+
async exists(containerId) {
|
|
584
|
+
return this.repository.containerExists(containerId);
|
|
585
|
+
}
|
|
586
|
+
// ==================== Agent Runtime ====================
|
|
587
|
+
async run(image, containerId) {
|
|
588
|
+
logger6.info("Running agent from image", {
|
|
589
|
+
imageId: image.imageId,
|
|
590
|
+
containerId
|
|
591
|
+
});
|
|
592
|
+
const container = await this.repository.findContainerById(containerId);
|
|
593
|
+
if (!container) {
|
|
594
|
+
throw new Error(`Container not found: ${containerId}`);
|
|
595
|
+
}
|
|
596
|
+
let agentId;
|
|
597
|
+
if (this.runtime.agentIdResolver) {
|
|
598
|
+
agentId = await this.runtime.agentIdResolver.resolveForRun(image.imageId, containerId);
|
|
599
|
+
} else {
|
|
600
|
+
agentId = generateAgentId();
|
|
601
|
+
}
|
|
602
|
+
const context = {
|
|
603
|
+
agentId,
|
|
604
|
+
createdAt: Date.now()
|
|
605
|
+
};
|
|
606
|
+
const sandbox = this.runtime.createSandbox(containerId);
|
|
607
|
+
const driver = this.runtime.createDriver(image.definition, context, sandbox);
|
|
608
|
+
const agent$1 = new agent.AgentInstance(image.definition, context, this.engine, driver, sandbox);
|
|
609
|
+
this.agents.set(agentId, agent$1);
|
|
610
|
+
logger6.info("Agent started", {
|
|
611
|
+
agentId,
|
|
612
|
+
imageId: image.imageId,
|
|
613
|
+
containerId,
|
|
614
|
+
definitionName: image.definition.name
|
|
615
|
+
});
|
|
616
|
+
return agent$1;
|
|
617
|
+
}
|
|
618
|
+
async resume(session, containerId) {
|
|
619
|
+
logger6.info("Resuming agent from session", {
|
|
620
|
+
sessionId: session.sessionId,
|
|
621
|
+
imageId: session.imageId,
|
|
622
|
+
containerId
|
|
623
|
+
});
|
|
624
|
+
const container = await this.repository.findContainerById(containerId);
|
|
625
|
+
if (!container) {
|
|
626
|
+
throw new Error(`Container not found: ${containerId}`);
|
|
627
|
+
}
|
|
628
|
+
const imageRecord = await this.repository.findImageById(session.imageId);
|
|
629
|
+
if (!imageRecord) {
|
|
630
|
+
throw new Error(`Image not found: ${session.imageId}`);
|
|
631
|
+
}
|
|
632
|
+
let agentId;
|
|
633
|
+
if (this.runtime.agentIdResolver) {
|
|
634
|
+
agentId = await this.runtime.agentIdResolver.resolveForResume(session.sessionId, containerId);
|
|
635
|
+
} else {
|
|
636
|
+
agentId = generateAgentId();
|
|
637
|
+
}
|
|
638
|
+
const context = {
|
|
639
|
+
agentId,
|
|
640
|
+
createdAt: Date.now()
|
|
641
|
+
};
|
|
642
|
+
const sandbox = this.runtime.createSandbox(containerId);
|
|
643
|
+
const definition = imageRecord.definition;
|
|
644
|
+
const driver = this.runtime.createDriver(definition, context, sandbox);
|
|
645
|
+
const agent$1 = new agent.AgentInstance(definition, context, this.engine, driver, sandbox);
|
|
646
|
+
this.agents.set(agentId, agent$1);
|
|
647
|
+
logger6.info("Agent resumed", {
|
|
648
|
+
agentId,
|
|
649
|
+
sessionId: session.sessionId,
|
|
650
|
+
imageId: session.imageId,
|
|
651
|
+
containerId
|
|
652
|
+
});
|
|
653
|
+
return agent$1;
|
|
654
|
+
}
|
|
655
|
+
async destroyAgent(agentId) {
|
|
656
|
+
const agent = this.agents.get(agentId);
|
|
657
|
+
if (!agent) {
|
|
658
|
+
logger6.warn("Agent not found for destroy", { agentId });
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
logger6.debug("Destroying agent", { agentId });
|
|
662
|
+
await agent.destroy();
|
|
663
|
+
this.agents.delete(agentId);
|
|
664
|
+
logger6.info("Agent destroyed", { agentId });
|
|
665
|
+
}
|
|
666
|
+
getAgent(agentId) {
|
|
667
|
+
return this.agents.get(agentId);
|
|
668
|
+
}
|
|
669
|
+
hasAgent(agentId) {
|
|
670
|
+
return this.agents.has(agentId);
|
|
671
|
+
}
|
|
672
|
+
listAgents() {
|
|
673
|
+
return Array.from(this.agents.values());
|
|
674
|
+
}
|
|
675
|
+
async destroyAllAgents() {
|
|
676
|
+
const agentIds = Array.from(this.agents.keys());
|
|
677
|
+
logger6.debug("Destroying all agents", { count: agentIds.length });
|
|
678
|
+
await Promise.all(agentIds.map((id) => this.destroyAgent(id)));
|
|
679
|
+
logger6.info("All agents destroyed", { count: agentIds.length });
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
// src/AgentX.ts
|
|
684
|
+
var logger7 = common.createLogger("agentx/AgentX");
|
|
685
|
+
function createAgentX(runtime, options) {
|
|
686
|
+
logger7.info("Creating AgentX instance", { runtime: runtime.name });
|
|
687
|
+
if (!runtime.repository) {
|
|
688
|
+
throw new Error("Runtime must have a repository for persistence");
|
|
689
|
+
}
|
|
690
|
+
const repository = runtime.repository;
|
|
691
|
+
const containerManager = new ContainerManagerImpl(runtime, repository);
|
|
692
|
+
const errorManager = new ErrorManager();
|
|
693
|
+
const definitionManager = new DefinitionManagerImpl(repository);
|
|
694
|
+
const agentManager = new AgentManager(containerManager);
|
|
695
|
+
const imageManager = new ImageManagerImpl(repository, containerManager, options?.containerId);
|
|
696
|
+
const sessionManager = new SessionManagerImpl(repository, containerManager, options?.containerId);
|
|
697
|
+
logger7.debug("AgentX instance created", { runtime: runtime.name });
|
|
698
|
+
return {
|
|
699
|
+
mode: "local",
|
|
700
|
+
containers: containerManager,
|
|
701
|
+
definitions: definitionManager,
|
|
702
|
+
images: imageManager,
|
|
703
|
+
agents: agentManager,
|
|
704
|
+
sessions: sessionManager,
|
|
705
|
+
errors: errorManager
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
var PersistentSSEConnection = class {
|
|
709
|
+
constructor(serverUrl, agentId, sseParams = {}) {
|
|
710
|
+
this.serverUrl = serverUrl;
|
|
711
|
+
this.agentId = agentId;
|
|
712
|
+
this.sseParams = sseParams;
|
|
713
|
+
__publicField(this, "eventSource", null);
|
|
714
|
+
__publicField(this, "messageQueue", []);
|
|
715
|
+
__publicField(this, "activeIterators", /* @__PURE__ */ new Set());
|
|
716
|
+
__publicField(this, "isDone", false);
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Initialize SSE connection
|
|
720
|
+
*/
|
|
721
|
+
connect() {
|
|
722
|
+
if (this.eventSource) {
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
let sseUrl = `${this.serverUrl}/agents/${this.agentId}/sse`;
|
|
726
|
+
if (Object.keys(this.sseParams).length > 0) {
|
|
727
|
+
const params = new URLSearchParams(this.sseParams);
|
|
728
|
+
sseUrl += `?${params.toString()}`;
|
|
729
|
+
}
|
|
730
|
+
this.eventSource = new EventSource(sseUrl);
|
|
731
|
+
const handleEvent = (event) => {
|
|
732
|
+
try {
|
|
733
|
+
const data = JSON.parse(event.data);
|
|
734
|
+
if (this.activeIterators.size > 0) {
|
|
735
|
+
const iterator = this.activeIterators.values().next().value;
|
|
736
|
+
if (iterator) {
|
|
737
|
+
this.activeIterators.delete(iterator);
|
|
738
|
+
iterator.resolve({ value: data, done: false });
|
|
739
|
+
}
|
|
740
|
+
} else {
|
|
741
|
+
this.messageQueue.push(data);
|
|
742
|
+
}
|
|
743
|
+
} catch {
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
const handleError = () => {
|
|
747
|
+
this.isDone = true;
|
|
748
|
+
this.eventSource?.close();
|
|
749
|
+
this.eventSource = null;
|
|
750
|
+
for (const iterator of this.activeIterators) {
|
|
751
|
+
iterator.reject(new Error("SSE connection error"));
|
|
752
|
+
}
|
|
753
|
+
this.activeIterators.clear();
|
|
754
|
+
};
|
|
755
|
+
for (const eventType of types.STREAM_EVENT_TYPE_NAMES) {
|
|
756
|
+
this.eventSource.addEventListener(eventType, handleEvent);
|
|
757
|
+
}
|
|
758
|
+
this.eventSource.addEventListener("error", handleEvent);
|
|
759
|
+
this.eventSource.onmessage = handleEvent;
|
|
760
|
+
this.eventSource.onerror = handleError;
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Create an async iterable for a single receive() call
|
|
764
|
+
*
|
|
765
|
+
* This iterator continues until a final message_stop is received (stopReason !== "tool_use").
|
|
766
|
+
* For tool calls, this means it will span multiple message_start/message_stop cycles.
|
|
767
|
+
* The SSE connection itself remains open for future receive() calls.
|
|
768
|
+
*/
|
|
769
|
+
createIterator() {
|
|
770
|
+
const connection = this;
|
|
771
|
+
return {
|
|
772
|
+
[Symbol.asyncIterator]() {
|
|
773
|
+
let turnComplete = false;
|
|
774
|
+
return {
|
|
775
|
+
async next() {
|
|
776
|
+
if (connection.messageQueue.length > 0) {
|
|
777
|
+
const event = connection.messageQueue.shift();
|
|
778
|
+
if (event.type === "message_stop") {
|
|
779
|
+
const stopReason = event.data.stopReason;
|
|
780
|
+
if (stopReason !== "tool_use") {
|
|
781
|
+
turnComplete = true;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
return { value: event, done: false };
|
|
785
|
+
}
|
|
786
|
+
if (turnComplete) {
|
|
787
|
+
return { done: true, value: void 0 };
|
|
788
|
+
}
|
|
789
|
+
if (connection.isDone) {
|
|
790
|
+
return { done: true, value: void 0 };
|
|
791
|
+
}
|
|
792
|
+
return new Promise((resolve, reject) => {
|
|
793
|
+
const wrappedResolve = (result) => {
|
|
794
|
+
if (!result.done) {
|
|
795
|
+
if (result.value.type === "message_stop") {
|
|
796
|
+
const stopReason = result.value.data.stopReason;
|
|
797
|
+
if (stopReason !== "tool_use") {
|
|
798
|
+
turnComplete = true;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
resolve(result);
|
|
803
|
+
};
|
|
804
|
+
const iterator = { resolve: wrappedResolve, reject };
|
|
805
|
+
connection.activeIterators.add(iterator);
|
|
806
|
+
});
|
|
807
|
+
},
|
|
808
|
+
async return() {
|
|
809
|
+
return { done: true, value: void 0 };
|
|
810
|
+
}
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
/**
|
|
816
|
+
* Close the connection
|
|
817
|
+
*/
|
|
818
|
+
close() {
|
|
819
|
+
this.isDone = true;
|
|
820
|
+
if (this.eventSource) {
|
|
821
|
+
this.eventSource.close();
|
|
822
|
+
this.eventSource = null;
|
|
823
|
+
}
|
|
824
|
+
for (const iterator of this.activeIterators) {
|
|
825
|
+
iterator.reject(new Error("Connection closed"));
|
|
826
|
+
}
|
|
827
|
+
this.activeIterators.clear();
|
|
828
|
+
this.messageQueue = [];
|
|
829
|
+
}
|
|
830
|
+
};
|
|
831
|
+
function createSSEDriver(config) {
|
|
832
|
+
const { serverUrl, agentId, headers = {}, sseParams = {} } = config;
|
|
833
|
+
let connection = null;
|
|
834
|
+
return {
|
|
835
|
+
name: "SSEDriver",
|
|
836
|
+
async *receive(message) {
|
|
837
|
+
if (!connection) {
|
|
838
|
+
connection = new PersistentSSEConnection(serverUrl, agentId, sseParams);
|
|
839
|
+
connection.connect();
|
|
840
|
+
}
|
|
841
|
+
const messageUrl = `${serverUrl}/agents/${agentId}/messages`;
|
|
842
|
+
const response = await fetch(messageUrl, {
|
|
843
|
+
method: "POST",
|
|
844
|
+
headers: {
|
|
845
|
+
"Content-Type": "application/json",
|
|
846
|
+
...headers
|
|
847
|
+
},
|
|
848
|
+
body: JSON.stringify({
|
|
849
|
+
content: typeof message.content === "string" ? message.content : message.content
|
|
850
|
+
})
|
|
851
|
+
});
|
|
852
|
+
if (!response.ok) {
|
|
853
|
+
const errorBody = await response.json().catch(() => ({}));
|
|
854
|
+
throw new Error(errorBody.error?.message || `HTTP ${response.status}`);
|
|
855
|
+
}
|
|
856
|
+
yield* connection.createIterator();
|
|
857
|
+
},
|
|
858
|
+
interrupt() {
|
|
859
|
+
const interruptUrl = `${serverUrl}/agents/${agentId}/interrupt`;
|
|
860
|
+
fetch(interruptUrl, {
|
|
861
|
+
method: "POST",
|
|
862
|
+
headers: {
|
|
863
|
+
"Content-Type": "application/json",
|
|
864
|
+
...headers
|
|
865
|
+
}
|
|
866
|
+
}).catch(() => {
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
var logger8 = common.createLogger("agentx/RemoteRepository");
|
|
872
|
+
var RemoteRepository = class {
|
|
873
|
+
constructor(options) {
|
|
874
|
+
__publicField(this, "client");
|
|
875
|
+
this.client = createHttpClient({
|
|
876
|
+
baseUrl: options.serverUrl,
|
|
877
|
+
headers: options.headers
|
|
878
|
+
});
|
|
879
|
+
logger8.debug("RemoteRepository created", { serverUrl: options.serverUrl });
|
|
880
|
+
}
|
|
881
|
+
// ==================== Definition ====================
|
|
882
|
+
async saveDefinition(record) {
|
|
883
|
+
await this.client.put(`definitions/${record.name}`, { json: record });
|
|
884
|
+
}
|
|
885
|
+
async findDefinitionByName(name) {
|
|
886
|
+
try {
|
|
887
|
+
const result = await this.client.get(`definitions/${name}`).json();
|
|
888
|
+
return this.parseDefinitionRecord(result);
|
|
889
|
+
} catch (error) {
|
|
890
|
+
if (this.isNotFound(error)) return null;
|
|
891
|
+
throw error;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
async findAllDefinitions() {
|
|
895
|
+
const result = await this.client.get("definitions").json();
|
|
896
|
+
return result.map((r) => this.parseDefinitionRecord(r));
|
|
897
|
+
}
|
|
898
|
+
async deleteDefinition(name) {
|
|
899
|
+
await this.client.delete(`definitions/${name}`);
|
|
900
|
+
}
|
|
901
|
+
async definitionExists(name) {
|
|
902
|
+
try {
|
|
903
|
+
await this.client.head(`definitions/${name}`);
|
|
904
|
+
return true;
|
|
905
|
+
} catch {
|
|
906
|
+
return false;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
// ==================== Image ====================
|
|
910
|
+
async saveImage(record) {
|
|
911
|
+
await this.client.put(`images/${record.imageId}`, { json: record });
|
|
912
|
+
}
|
|
913
|
+
async findImageById(imageId) {
|
|
914
|
+
try {
|
|
915
|
+
const result = await this.client.get(`images/${imageId}`).json();
|
|
916
|
+
return this.parseImageRecord(result);
|
|
917
|
+
} catch (error) {
|
|
918
|
+
if (this.isNotFound(error)) return null;
|
|
919
|
+
throw error;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
async findAllImages() {
|
|
923
|
+
const result = await this.client.get("images").json();
|
|
924
|
+
return result.map((r) => this.parseImageRecord(r));
|
|
925
|
+
}
|
|
926
|
+
async deleteImage(imageId) {
|
|
927
|
+
await this.client.delete(`images/${imageId}`);
|
|
928
|
+
}
|
|
929
|
+
async imageExists(imageId) {
|
|
930
|
+
try {
|
|
931
|
+
await this.client.head(`images/${imageId}`);
|
|
932
|
+
return true;
|
|
933
|
+
} catch {
|
|
934
|
+
return false;
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
// ==================== Session ====================
|
|
938
|
+
async saveSession(record) {
|
|
939
|
+
await this.client.put(`sessions/${record.sessionId}`, { json: record });
|
|
940
|
+
}
|
|
941
|
+
async findSessionById(sessionId) {
|
|
942
|
+
try {
|
|
943
|
+
const result = await this.client.get(`sessions/${sessionId}`).json();
|
|
944
|
+
return this.parseSessionRecord(result);
|
|
945
|
+
} catch (error) {
|
|
946
|
+
if (this.isNotFound(error)) return null;
|
|
947
|
+
throw error;
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
async findSessionsByImageId(imageId) {
|
|
951
|
+
const result = await this.client.get(`images/${imageId}/sessions`).json();
|
|
952
|
+
return result.map((r) => this.parseSessionRecord(r));
|
|
953
|
+
}
|
|
954
|
+
async findSessionsByUserId(userId) {
|
|
955
|
+
const result = await this.client.get(`users/${userId}/sessions`).json();
|
|
956
|
+
return result.map((r) => this.parseSessionRecord(r));
|
|
957
|
+
}
|
|
958
|
+
async findAllSessions() {
|
|
959
|
+
const result = await this.client.get("sessions").json();
|
|
960
|
+
return result.map((r) => this.parseSessionRecord(r));
|
|
961
|
+
}
|
|
962
|
+
async deleteSession(sessionId) {
|
|
963
|
+
await this.client.delete(`sessions/${sessionId}`);
|
|
964
|
+
}
|
|
965
|
+
async deleteSessionsByImageId(imageId) {
|
|
966
|
+
await this.client.delete(`images/${imageId}/sessions`);
|
|
967
|
+
}
|
|
968
|
+
async sessionExists(sessionId) {
|
|
969
|
+
try {
|
|
970
|
+
await this.client.head(`sessions/${sessionId}`);
|
|
971
|
+
return true;
|
|
972
|
+
} catch {
|
|
973
|
+
return false;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
// ==================== Message ====================
|
|
977
|
+
/**
|
|
978
|
+
* Save message - noop in browser
|
|
979
|
+
*
|
|
980
|
+
* Messages are persisted by server-side SessionCollector.
|
|
981
|
+
* Browser-side calls this but it does nothing to avoid duplicate saves.
|
|
982
|
+
*/
|
|
983
|
+
async saveMessage(_record) {
|
|
984
|
+
logger8.debug("saveMessage called (noop in browser)");
|
|
985
|
+
}
|
|
986
|
+
async findMessageById(messageId) {
|
|
987
|
+
try {
|
|
988
|
+
const result = await this.client.get(`messages/${messageId}`).json();
|
|
989
|
+
return this.parseMessageRecord(result);
|
|
990
|
+
} catch (error) {
|
|
991
|
+
if (this.isNotFound(error)) return null;
|
|
992
|
+
throw error;
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
async findMessagesBySessionId(sessionId) {
|
|
996
|
+
const result = await this.client.get(`sessions/${sessionId}/messages`).json();
|
|
997
|
+
return result.map((r) => this.parseMessageRecord(r));
|
|
998
|
+
}
|
|
999
|
+
async deleteMessage(messageId) {
|
|
1000
|
+
await this.client.delete(`messages/${messageId}`);
|
|
1001
|
+
}
|
|
1002
|
+
async deleteMessagesBySessionId(sessionId) {
|
|
1003
|
+
await this.client.delete(`sessions/${sessionId}/messages`);
|
|
1004
|
+
}
|
|
1005
|
+
async countMessagesBySessionId(sessionId) {
|
|
1006
|
+
const result = await this.client.get(`sessions/${sessionId}/messages/count`).json();
|
|
1007
|
+
return result.count;
|
|
1008
|
+
}
|
|
1009
|
+
// ==================== Container ====================
|
|
1010
|
+
async saveContainer(record) {
|
|
1011
|
+
await this.client.put(`containers/${record.containerId}`, { json: record });
|
|
1012
|
+
}
|
|
1013
|
+
async findContainerById(containerId) {
|
|
1014
|
+
try {
|
|
1015
|
+
const result = await this.client.get(`containers/${containerId}`).json();
|
|
1016
|
+
return this.parseContainerRecord(result);
|
|
1017
|
+
} catch (error) {
|
|
1018
|
+
if (this.isNotFound(error)) return null;
|
|
1019
|
+
throw error;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
async findAllContainers() {
|
|
1023
|
+
const result = await this.client.get("containers").json();
|
|
1024
|
+
return result.map((r) => this.parseContainerRecord(r));
|
|
1025
|
+
}
|
|
1026
|
+
async deleteContainer(containerId) {
|
|
1027
|
+
await this.client.delete(`containers/${containerId}`);
|
|
1028
|
+
}
|
|
1029
|
+
async containerExists(containerId) {
|
|
1030
|
+
try {
|
|
1031
|
+
await this.client.head(`containers/${containerId}`);
|
|
1032
|
+
return true;
|
|
1033
|
+
} catch {
|
|
1034
|
+
return false;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
// ==================== Helpers ====================
|
|
1038
|
+
isNotFound(error) {
|
|
1039
|
+
return error?.response?.status === 404;
|
|
1040
|
+
}
|
|
1041
|
+
parseDefinitionRecord(raw) {
|
|
1042
|
+
return {
|
|
1043
|
+
...raw,
|
|
1044
|
+
createdAt: new Date(raw.createdAt),
|
|
1045
|
+
updatedAt: new Date(raw.updatedAt)
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
parseImageRecord(raw) {
|
|
1049
|
+
return {
|
|
1050
|
+
...raw,
|
|
1051
|
+
createdAt: new Date(raw.createdAt)
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
parseSessionRecord(raw) {
|
|
1055
|
+
return {
|
|
1056
|
+
...raw,
|
|
1057
|
+
createdAt: new Date(raw.createdAt),
|
|
1058
|
+
updatedAt: new Date(raw.updatedAt)
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
parseMessageRecord(raw) {
|
|
1062
|
+
return {
|
|
1063
|
+
...raw,
|
|
1064
|
+
createdAt: new Date(raw.createdAt)
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
1067
|
+
parseContainerRecord(raw) {
|
|
1068
|
+
return {
|
|
1069
|
+
...raw
|
|
1070
|
+
// ContainerRecord uses number timestamps, no conversion needed
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
};
|
|
1074
|
+
var _BrowserLogger = class _BrowserLogger {
|
|
1075
|
+
constructor(name, options = {}) {
|
|
1076
|
+
__publicField(this, "name");
|
|
1077
|
+
__publicField(this, "level");
|
|
1078
|
+
__publicField(this, "collapsed");
|
|
1079
|
+
this.name = name;
|
|
1080
|
+
this.level = options.level ?? types.LogLevel.INFO;
|
|
1081
|
+
this.collapsed = options.collapsed ?? true;
|
|
1082
|
+
}
|
|
1083
|
+
debug(message, context) {
|
|
1084
|
+
if (this.isDebugEnabled()) {
|
|
1085
|
+
this.log("DEBUG", message, context);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
info(message, context) {
|
|
1089
|
+
if (this.isInfoEnabled()) {
|
|
1090
|
+
this.log("INFO", message, context);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
warn(message, context) {
|
|
1094
|
+
if (this.isWarnEnabled()) {
|
|
1095
|
+
this.log("WARN", message, context);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
error(message, context) {
|
|
1099
|
+
if (this.isErrorEnabled()) {
|
|
1100
|
+
if (message instanceof Error) {
|
|
1101
|
+
this.log("ERROR", message.message, { ...context, stack: message.stack });
|
|
1102
|
+
} else {
|
|
1103
|
+
this.log("ERROR", message, context);
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
isDebugEnabled() {
|
|
1108
|
+
return this.level <= types.LogLevel.DEBUG;
|
|
1109
|
+
}
|
|
1110
|
+
isInfoEnabled() {
|
|
1111
|
+
return this.level <= types.LogLevel.INFO;
|
|
1112
|
+
}
|
|
1113
|
+
isWarnEnabled() {
|
|
1114
|
+
return this.level <= types.LogLevel.WARN;
|
|
1115
|
+
}
|
|
1116
|
+
isErrorEnabled() {
|
|
1117
|
+
return this.level <= types.LogLevel.ERROR;
|
|
1118
|
+
}
|
|
1119
|
+
log(level, message, context) {
|
|
1120
|
+
const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString();
|
|
1121
|
+
const consoleMethod = this.getConsoleMethod(level);
|
|
1122
|
+
const badgeStyle = _BrowserLogger.BADGE_STYLES[level];
|
|
1123
|
+
const format = `%c${timestamp} %c${level}%c %c[${this.name}]%c ${message}`;
|
|
1124
|
+
const styles = [
|
|
1125
|
+
_BrowserLogger.STYLES.TIMESTAMP,
|
|
1126
|
+
badgeStyle,
|
|
1127
|
+
"",
|
|
1128
|
+
// reset after badge
|
|
1129
|
+
_BrowserLogger.STYLES.NAME,
|
|
1130
|
+
_BrowserLogger.STYLES.MESSAGE
|
|
1131
|
+
];
|
|
1132
|
+
if (context && Object.keys(context).length > 0) {
|
|
1133
|
+
const groupMethod = this.collapsed ? console.groupCollapsed : console.group;
|
|
1134
|
+
groupMethod.call(console, format, ...styles);
|
|
1135
|
+
console.log("Context:", context);
|
|
1136
|
+
console.groupEnd();
|
|
1137
|
+
} else {
|
|
1138
|
+
consoleMethod(format, ...styles);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
getConsoleMethod(level) {
|
|
1142
|
+
switch (level) {
|
|
1143
|
+
case "DEBUG":
|
|
1144
|
+
return console.debug.bind(console);
|
|
1145
|
+
case "INFO":
|
|
1146
|
+
return console.info.bind(console);
|
|
1147
|
+
case "WARN":
|
|
1148
|
+
return console.warn.bind(console);
|
|
1149
|
+
case "ERROR":
|
|
1150
|
+
return console.error.bind(console);
|
|
1151
|
+
default:
|
|
1152
|
+
return console.log.bind(console);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
};
|
|
1156
|
+
// CSS styles for different log levels
|
|
1157
|
+
__publicField(_BrowserLogger, "STYLES", {
|
|
1158
|
+
DEBUG: "color: #6B7280; font-weight: normal;",
|
|
1159
|
+
// gray
|
|
1160
|
+
INFO: "color: #10B981; font-weight: normal;",
|
|
1161
|
+
// green
|
|
1162
|
+
WARN: "color: #F59E0B; font-weight: bold;",
|
|
1163
|
+
// amber
|
|
1164
|
+
ERROR: "color: #EF4444; font-weight: bold;",
|
|
1165
|
+
// red
|
|
1166
|
+
TIMESTAMP: "color: #9CA3AF; font-weight: normal;",
|
|
1167
|
+
// light gray
|
|
1168
|
+
NAME: "color: #8B5CF6; font-weight: normal;",
|
|
1169
|
+
// purple
|
|
1170
|
+
MESSAGE: "color: inherit; font-weight: normal;"
|
|
1171
|
+
});
|
|
1172
|
+
// Badge styles for level indicators
|
|
1173
|
+
__publicField(_BrowserLogger, "BADGE_STYLES", {
|
|
1174
|
+
DEBUG: "background: #E5E7EB; color: #374151; padding: 2px 6px; border-radius: 3px; font-size: 11px;",
|
|
1175
|
+
INFO: "background: #D1FAE5; color: #065F46; padding: 2px 6px; border-radius: 3px; font-size: 11px;",
|
|
1176
|
+
WARN: "background: #FEF3C7; color: #92400E; padding: 2px 6px; border-radius: 3px; font-size: 11px;",
|
|
1177
|
+
ERROR: "background: #FEE2E2; color: #991B1B; padding: 2px 6px; border-radius: 3px; font-size: 11px;"
|
|
1178
|
+
});
|
|
1179
|
+
var BrowserLogger = _BrowserLogger;
|
|
1180
|
+
|
|
1181
|
+
// src/runtime/sse/logger/BrowserLoggerFactory.ts
|
|
1182
|
+
var BrowserLoggerFactory = class {
|
|
1183
|
+
constructor(options = {}) {
|
|
1184
|
+
__publicField(this, "options");
|
|
1185
|
+
__publicField(this, "loggers", /* @__PURE__ */ new Map());
|
|
1186
|
+
this.options = options;
|
|
1187
|
+
}
|
|
1188
|
+
getLogger(name) {
|
|
1189
|
+
if (this.loggers.has(name)) {
|
|
1190
|
+
return this.loggers.get(name);
|
|
1191
|
+
}
|
|
1192
|
+
const logger10 = new BrowserLogger(name, this.options);
|
|
1193
|
+
this.loggers.set(name, logger10);
|
|
1194
|
+
return logger10;
|
|
1195
|
+
}
|
|
1196
|
+
};
|
|
1197
|
+
var logger9 = common.createLogger("agentx/RemoteAgentIdResolver");
|
|
1198
|
+
var RemoteAgentIdResolver = class {
|
|
1199
|
+
constructor(options) {
|
|
1200
|
+
__publicField(this, "client");
|
|
1201
|
+
this.client = createHttpClient({
|
|
1202
|
+
baseUrl: options.serverUrl,
|
|
1203
|
+
headers: options.headers
|
|
1204
|
+
});
|
|
1205
|
+
}
|
|
1206
|
+
async resolveForRun(imageId, containerId) {
|
|
1207
|
+
logger9.debug("Resolving agent ID for run", { imageId, containerId });
|
|
1208
|
+
const response = await this.client.post(`images/${imageId}/run`, {
|
|
1209
|
+
json: { containerId }
|
|
1210
|
+
}).json();
|
|
1211
|
+
logger9.info("Agent ID resolved for run", { imageId, agentId: response.agentId });
|
|
1212
|
+
return response.agentId;
|
|
1213
|
+
}
|
|
1214
|
+
async resolveForResume(sessionId, containerId) {
|
|
1215
|
+
logger9.debug("Resolving agent ID for resume", { sessionId, containerId });
|
|
1216
|
+
const response = await this.client.post(`sessions/${sessionId}/resume`, {
|
|
1217
|
+
json: { containerId }
|
|
1218
|
+
}).json();
|
|
1219
|
+
logger9.info("Agent ID resolved for resume", { sessionId, agentId: response.agentId });
|
|
1220
|
+
return response.agentId;
|
|
1221
|
+
}
|
|
1222
|
+
};
|
|
1223
|
+
|
|
1224
|
+
// src/runtime/sse/SSERuntime.ts
|
|
1225
|
+
var noopSandbox = {
|
|
1226
|
+
name: "browser-noop",
|
|
1227
|
+
workspace: {
|
|
1228
|
+
id: "noop",
|
|
1229
|
+
name: "noop",
|
|
1230
|
+
path: ""
|
|
1231
|
+
// Browser has no local workspace
|
|
1232
|
+
},
|
|
1233
|
+
llm: {
|
|
1234
|
+
name: "noop",
|
|
1235
|
+
provide: () => ({})
|
|
1236
|
+
}
|
|
1237
|
+
};
|
|
1238
|
+
var SSERuntime = class {
|
|
1239
|
+
constructor(config) {
|
|
1240
|
+
__publicField(this, "name", "sse");
|
|
1241
|
+
__publicField(this, "repository");
|
|
1242
|
+
__publicField(this, "loggerFactory");
|
|
1243
|
+
__publicField(this, "agentIdResolver");
|
|
1244
|
+
__publicField(this, "serverUrl");
|
|
1245
|
+
__publicField(this, "headers");
|
|
1246
|
+
__publicField(this, "sseParams");
|
|
1247
|
+
this.serverUrl = config.serverUrl.replace(/\/+$/, "");
|
|
1248
|
+
this.headers = config.headers ?? {};
|
|
1249
|
+
this.sseParams = config.sseParams ?? {};
|
|
1250
|
+
this.loggerFactory = new BrowserLoggerFactory({
|
|
1251
|
+
collapsed: true
|
|
1252
|
+
});
|
|
1253
|
+
common.setLoggerFactory(this.loggerFactory);
|
|
1254
|
+
this.repository = new RemoteRepository({
|
|
1255
|
+
serverUrl: this.serverUrl,
|
|
1256
|
+
headers: this.headers
|
|
1257
|
+
});
|
|
1258
|
+
this.agentIdResolver = new RemoteAgentIdResolver({
|
|
1259
|
+
serverUrl: this.serverUrl,
|
|
1260
|
+
headers: this.headers
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
createSandbox(_containerId) {
|
|
1264
|
+
return noopSandbox;
|
|
1265
|
+
}
|
|
1266
|
+
createDriver(_definition, context, _sandbox) {
|
|
1267
|
+
const driver = createSSEDriver({
|
|
1268
|
+
serverUrl: this.serverUrl,
|
|
1269
|
+
agentId: context.agentId,
|
|
1270
|
+
headers: this.headers,
|
|
1271
|
+
sseParams: this.sseParams
|
|
1272
|
+
});
|
|
1273
|
+
return {
|
|
1274
|
+
...driver,
|
|
1275
|
+
sandbox: noopSandbox
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
createLogger(name) {
|
|
1279
|
+
return this.loggerFactory.getLogger(name);
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
1282
|
+
function sseRuntime(config) {
|
|
1283
|
+
return new SSERuntime(config);
|
|
1284
|
+
}
|
|
1285
|
+
var createSSERuntime = sseRuntime;
|
|
1286
|
+
|
|
1287
|
+
exports.createAgentX = createAgentX;
|
|
1288
|
+
exports.createSSERuntime = createSSERuntime;
|
|
1289
|
+
exports.defineAgent = defineAgent;
|
|
1290
|
+
exports.sseRuntime = sseRuntime;
|
|
1291
|
+
//# sourceMappingURL=index.cjs.map
|
|
1292
|
+
//# sourceMappingURL=index.cjs.map
|