@agentxjs/core 1.9.1-dev
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/package.json +31 -0
- package/src/agent/AgentStateMachine.ts +151 -0
- package/src/agent/README.md +296 -0
- package/src/agent/__tests__/AgentStateMachine.test.ts +346 -0
- package/src/agent/__tests__/createAgent.test.ts +728 -0
- package/src/agent/__tests__/engine/internal/messageAssemblerProcessor.test.ts +567 -0
- package/src/agent/__tests__/engine/internal/stateEventProcessor.test.ts +315 -0
- package/src/agent/__tests__/engine/internal/turnTrackerProcessor.test.ts +340 -0
- package/src/agent/__tests__/engine/mealy/Mealy.test.ts +370 -0
- package/src/agent/__tests__/engine/mealy/Store.test.ts +123 -0
- package/src/agent/__tests__/engine/mealy/combinators.test.ts +322 -0
- package/src/agent/createAgent.ts +467 -0
- package/src/agent/engine/AgentProcessor.ts +106 -0
- package/src/agent/engine/MealyMachine.ts +184 -0
- package/src/agent/engine/internal/index.ts +35 -0
- package/src/agent/engine/internal/messageAssemblerProcessor.ts +550 -0
- package/src/agent/engine/internal/stateEventProcessor.ts +313 -0
- package/src/agent/engine/internal/turnTrackerProcessor.ts +239 -0
- package/src/agent/engine/mealy/Mealy.ts +308 -0
- package/src/agent/engine/mealy/Processor.ts +70 -0
- package/src/agent/engine/mealy/Sink.ts +56 -0
- package/src/agent/engine/mealy/Source.ts +51 -0
- package/src/agent/engine/mealy/Store.ts +98 -0
- package/src/agent/engine/mealy/combinators.ts +176 -0
- package/src/agent/engine/mealy/index.ts +45 -0
- package/src/agent/index.ts +106 -0
- package/src/agent/types/engine.ts +395 -0
- package/src/agent/types/event.ts +478 -0
- package/src/agent/types/index.ts +197 -0
- package/src/agent/types/message.ts +387 -0
- package/src/common/index.ts +8 -0
- package/src/common/logger/ConsoleLogger.ts +137 -0
- package/src/common/logger/LoggerFactoryImpl.ts +123 -0
- package/src/common/logger/index.ts +26 -0
- package/src/common/logger/types.ts +98 -0
- package/src/container/Container.ts +185 -0
- package/src/container/index.ts +44 -0
- package/src/container/types.ts +71 -0
- package/src/driver/index.ts +42 -0
- package/src/driver/types.ts +363 -0
- package/src/event/EventBus.ts +260 -0
- package/src/event/README.md +237 -0
- package/src/event/__tests__/EventBus.test.ts +251 -0
- package/src/event/index.ts +46 -0
- package/src/event/types/agent.ts +512 -0
- package/src/event/types/base.ts +241 -0
- package/src/event/types/bus.ts +429 -0
- package/src/event/types/command.ts +749 -0
- package/src/event/types/container.ts +471 -0
- package/src/event/types/driver.ts +452 -0
- package/src/event/types/index.ts +26 -0
- package/src/event/types/session.ts +314 -0
- package/src/image/Image.ts +203 -0
- package/src/image/index.ts +36 -0
- package/src/image/types.ts +77 -0
- package/src/index.ts +20 -0
- package/src/mq/OffsetGenerator.ts +48 -0
- package/src/mq/README.md +166 -0
- package/src/mq/__tests__/OffsetGenerator.test.ts +121 -0
- package/src/mq/index.ts +18 -0
- package/src/mq/types.ts +172 -0
- package/src/network/RpcClient.ts +455 -0
- package/src/network/index.ts +76 -0
- package/src/network/jsonrpc.ts +336 -0
- package/src/network/protocol.ts +90 -0
- package/src/network/types.ts +284 -0
- package/src/persistence/index.ts +27 -0
- package/src/persistence/types.ts +226 -0
- package/src/runtime/AgentXRuntime.ts +501 -0
- package/src/runtime/index.ts +56 -0
- package/src/runtime/types.ts +236 -0
- package/src/session/Session.ts +71 -0
- package/src/session/index.ts +25 -0
- package/src/session/types.ts +77 -0
- package/src/workspace/index.ts +27 -0
- package/src/workspace/types.ts +131 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentXRuntimeImpl - Runtime integration implementation
|
|
3
|
+
*
|
|
4
|
+
* Integrates all components to provide agent lifecycle management.
|
|
5
|
+
* Uses Provider dependencies to coordinate Session, Image, Container, etc.
|
|
6
|
+
*
|
|
7
|
+
* New Design:
|
|
8
|
+
* - Driver.receive() returns AsyncIterable<DriverStreamEvent>
|
|
9
|
+
* - Runtime processes events and emits to EventBus
|
|
10
|
+
* - No more EventBus-based communication with Driver
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { createLogger } from "commonxjs/logger";
|
|
14
|
+
import type {
|
|
15
|
+
AgentXProvider,
|
|
16
|
+
AgentXRuntime,
|
|
17
|
+
RuntimeAgent,
|
|
18
|
+
CreateAgentOptions,
|
|
19
|
+
AgentEventHandler,
|
|
20
|
+
Subscription,
|
|
21
|
+
AgentLifecycle,
|
|
22
|
+
} from "./types";
|
|
23
|
+
import type { UserContentPart, UserMessage } from "../agent/types";
|
|
24
|
+
import type { BusEvent } from "../event/types";
|
|
25
|
+
import type { Driver, DriverConfig, DriverStreamEvent } from "../driver/types";
|
|
26
|
+
|
|
27
|
+
const logger = createLogger("runtime/AgentXRuntime");
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Internal agent state
|
|
31
|
+
*/
|
|
32
|
+
interface AgentState {
|
|
33
|
+
agent: RuntimeAgent;
|
|
34
|
+
lifecycle: AgentLifecycle;
|
|
35
|
+
subscriptions: Set<() => void>;
|
|
36
|
+
driver: Driver;
|
|
37
|
+
/** Flag to track if a receive operation is in progress */
|
|
38
|
+
isReceiving: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* AgentXRuntimeImpl - Runtime implementation
|
|
43
|
+
*/
|
|
44
|
+
export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
45
|
+
readonly provider: AgentXProvider;
|
|
46
|
+
|
|
47
|
+
private agents = new Map<string, AgentState>();
|
|
48
|
+
private globalSubscriptions = new Set<() => void>();
|
|
49
|
+
private isShutdown = false;
|
|
50
|
+
|
|
51
|
+
constructor(provider: AgentXProvider) {
|
|
52
|
+
this.provider = provider;
|
|
53
|
+
logger.info("AgentXRuntime initialized");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ==================== Agent Lifecycle ====================
|
|
57
|
+
|
|
58
|
+
async createAgent(options: CreateAgentOptions): Promise<RuntimeAgent> {
|
|
59
|
+
if (this.isShutdown) {
|
|
60
|
+
throw new Error("Runtime is shutdown");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const { imageId } = options;
|
|
64
|
+
|
|
65
|
+
// Load image
|
|
66
|
+
const imageRecord = await this.provider.imageRepository.findImageById(imageId);
|
|
67
|
+
if (!imageRecord) {
|
|
68
|
+
throw new Error(`Image not found: ${imageId}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Generate agent ID
|
|
72
|
+
const agentId = options.agentId ?? this.generateAgentId();
|
|
73
|
+
|
|
74
|
+
// Ensure container exists
|
|
75
|
+
const containerExists = await this.provider.containerRepository.containerExists(
|
|
76
|
+
imageRecord.containerId
|
|
77
|
+
);
|
|
78
|
+
if (!containerExists) {
|
|
79
|
+
throw new Error(`Container not found: ${imageRecord.containerId}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Create workspace
|
|
83
|
+
const workspace = await this.provider.workspaceProvider.create({
|
|
84
|
+
containerId: imageRecord.containerId,
|
|
85
|
+
imageId,
|
|
86
|
+
});
|
|
87
|
+
await workspace.initialize();
|
|
88
|
+
|
|
89
|
+
// Create driver config
|
|
90
|
+
const driverConfig: DriverConfig = {
|
|
91
|
+
apiKey: process.env.ANTHROPIC_API_KEY ?? "",
|
|
92
|
+
baseUrl: process.env.ANTHROPIC_BASE_URL,
|
|
93
|
+
agentId,
|
|
94
|
+
systemPrompt: imageRecord.systemPrompt,
|
|
95
|
+
cwd: workspace.path,
|
|
96
|
+
mcpServers: imageRecord.mcpServers,
|
|
97
|
+
resumeSessionId: imageRecord.metadata?.claudeSdkSessionId as string | undefined,
|
|
98
|
+
onSessionIdCaptured: async (claudeSdkSessionId: string) => {
|
|
99
|
+
// Persist SDK session ID for resume
|
|
100
|
+
await this.provider.imageRepository.updateMetadata(imageId, { claudeSdkSessionId });
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// Create driver using the new CreateDriver function
|
|
105
|
+
const driver = this.provider.createDriver(driverConfig);
|
|
106
|
+
|
|
107
|
+
// Initialize driver
|
|
108
|
+
await driver.initialize();
|
|
109
|
+
|
|
110
|
+
// Create runtime agent
|
|
111
|
+
const agent: RuntimeAgent = {
|
|
112
|
+
agentId,
|
|
113
|
+
imageId,
|
|
114
|
+
containerId: imageRecord.containerId,
|
|
115
|
+
sessionId: imageRecord.sessionId,
|
|
116
|
+
name: imageRecord.name,
|
|
117
|
+
lifecycle: "running",
|
|
118
|
+
createdAt: Date.now(),
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// Store agent state with driver
|
|
122
|
+
const state: AgentState = {
|
|
123
|
+
agent,
|
|
124
|
+
lifecycle: "running",
|
|
125
|
+
subscriptions: new Set(),
|
|
126
|
+
driver,
|
|
127
|
+
isReceiving: false,
|
|
128
|
+
};
|
|
129
|
+
this.agents.set(agentId, state);
|
|
130
|
+
|
|
131
|
+
// Emit agent_created event
|
|
132
|
+
this.provider.eventBus.emit({
|
|
133
|
+
type: "agent_created",
|
|
134
|
+
timestamp: Date.now(),
|
|
135
|
+
source: "runtime",
|
|
136
|
+
category: "lifecycle",
|
|
137
|
+
intent: "notification",
|
|
138
|
+
data: {
|
|
139
|
+
agentId,
|
|
140
|
+
imageId,
|
|
141
|
+
containerId: imageRecord.containerId,
|
|
142
|
+
},
|
|
143
|
+
context: {
|
|
144
|
+
agentId,
|
|
145
|
+
imageId,
|
|
146
|
+
containerId: imageRecord.containerId,
|
|
147
|
+
sessionId: imageRecord.sessionId,
|
|
148
|
+
},
|
|
149
|
+
} as BusEvent);
|
|
150
|
+
|
|
151
|
+
logger.info("Agent created", {
|
|
152
|
+
agentId,
|
|
153
|
+
imageId,
|
|
154
|
+
containerId: imageRecord.containerId,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
return agent;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
getAgent(agentId: string): RuntimeAgent | undefined {
|
|
161
|
+
const state = this.agents.get(agentId);
|
|
162
|
+
return state?.agent;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
getAgents(): RuntimeAgent[] {
|
|
166
|
+
return Array.from(this.agents.values()).map((s) => s.agent);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
getAgentsByContainer(containerId: string): RuntimeAgent[] {
|
|
170
|
+
return Array.from(this.agents.values())
|
|
171
|
+
.filter((s) => s.agent.containerId === containerId)
|
|
172
|
+
.map((s) => s.agent);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async stopAgent(agentId: string): Promise<void> {
|
|
176
|
+
const state = this.agents.get(agentId);
|
|
177
|
+
if (!state) {
|
|
178
|
+
throw new Error(`Agent not found: ${agentId}`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (state.lifecycle === "destroyed") {
|
|
182
|
+
throw new Error(`Agent already destroyed: ${agentId}`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
state.lifecycle = "stopped";
|
|
186
|
+
|
|
187
|
+
// Emit agent_stopped event
|
|
188
|
+
this.provider.eventBus.emit({
|
|
189
|
+
type: "agent_stopped",
|
|
190
|
+
timestamp: Date.now(),
|
|
191
|
+
source: "runtime",
|
|
192
|
+
category: "lifecycle",
|
|
193
|
+
intent: "notification",
|
|
194
|
+
data: { agentId },
|
|
195
|
+
context: {
|
|
196
|
+
agentId,
|
|
197
|
+
imageId: state.agent.imageId,
|
|
198
|
+
containerId: state.agent.containerId,
|
|
199
|
+
sessionId: state.agent.sessionId,
|
|
200
|
+
},
|
|
201
|
+
} as BusEvent);
|
|
202
|
+
|
|
203
|
+
logger.info("Agent stopped", { agentId });
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async resumeAgent(agentId: string): Promise<void> {
|
|
207
|
+
const state = this.agents.get(agentId);
|
|
208
|
+
if (!state) {
|
|
209
|
+
throw new Error(`Agent not found: ${agentId}`);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (state.lifecycle === "destroyed") {
|
|
213
|
+
throw new Error(`Cannot resume destroyed agent: ${agentId}`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
state.lifecycle = "running";
|
|
217
|
+
|
|
218
|
+
// Emit agent_resumed event
|
|
219
|
+
this.provider.eventBus.emit({
|
|
220
|
+
type: "agent_resumed",
|
|
221
|
+
timestamp: Date.now(),
|
|
222
|
+
source: "runtime",
|
|
223
|
+
category: "lifecycle",
|
|
224
|
+
intent: "notification",
|
|
225
|
+
data: { agentId },
|
|
226
|
+
context: {
|
|
227
|
+
agentId,
|
|
228
|
+
imageId: state.agent.imageId,
|
|
229
|
+
containerId: state.agent.containerId,
|
|
230
|
+
sessionId: state.agent.sessionId,
|
|
231
|
+
},
|
|
232
|
+
} as BusEvent);
|
|
233
|
+
|
|
234
|
+
logger.info("Agent resumed", { agentId });
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async destroyAgent(agentId: string): Promise<void> {
|
|
238
|
+
const state = this.agents.get(agentId);
|
|
239
|
+
if (!state) {
|
|
240
|
+
throw new Error(`Agent not found: ${agentId}`);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Dispose driver (new interface, no disconnect needed)
|
|
244
|
+
await state.driver.dispose();
|
|
245
|
+
|
|
246
|
+
// Cleanup subscriptions
|
|
247
|
+
for (const unsub of state.subscriptions) {
|
|
248
|
+
unsub();
|
|
249
|
+
}
|
|
250
|
+
state.subscriptions.clear();
|
|
251
|
+
|
|
252
|
+
state.lifecycle = "destroyed";
|
|
253
|
+
|
|
254
|
+
// Emit agent_destroyed event
|
|
255
|
+
this.provider.eventBus.emit({
|
|
256
|
+
type: "agent_destroyed",
|
|
257
|
+
timestamp: Date.now(),
|
|
258
|
+
source: "runtime",
|
|
259
|
+
category: "lifecycle",
|
|
260
|
+
intent: "notification",
|
|
261
|
+
data: { agentId },
|
|
262
|
+
context: {
|
|
263
|
+
agentId,
|
|
264
|
+
imageId: state.agent.imageId,
|
|
265
|
+
containerId: state.agent.containerId,
|
|
266
|
+
sessionId: state.agent.sessionId,
|
|
267
|
+
},
|
|
268
|
+
} as BusEvent);
|
|
269
|
+
|
|
270
|
+
// Remove from map
|
|
271
|
+
this.agents.delete(agentId);
|
|
272
|
+
|
|
273
|
+
logger.info("Agent destroyed", { agentId });
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ==================== Message Handling ====================
|
|
277
|
+
|
|
278
|
+
async receive(
|
|
279
|
+
agentId: string,
|
|
280
|
+
content: string | UserContentPart[],
|
|
281
|
+
requestId?: string
|
|
282
|
+
): Promise<void> {
|
|
283
|
+
const state = this.agents.get(agentId);
|
|
284
|
+
if (!state) {
|
|
285
|
+
throw new Error(`Agent not found: ${agentId}`);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (state.lifecycle !== "running") {
|
|
289
|
+
throw new Error(`Cannot send message to ${state.lifecycle} agent: ${agentId}`);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (state.isReceiving) {
|
|
293
|
+
throw new Error(`Agent ${agentId} is already processing a message`);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const actualRequestId = requestId ?? this.generateRequestId();
|
|
297
|
+
|
|
298
|
+
// Build user message
|
|
299
|
+
const userMessage: UserMessage = {
|
|
300
|
+
id: this.generateMessageId(),
|
|
301
|
+
role: "user",
|
|
302
|
+
subtype: "user",
|
|
303
|
+
content,
|
|
304
|
+
timestamp: Date.now(),
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
// Persist to session
|
|
308
|
+
await this.provider.sessionRepository.addMessage(state.agent.sessionId, userMessage);
|
|
309
|
+
|
|
310
|
+
// Emit user_message event (for external subscribers)
|
|
311
|
+
this.emitEvent(state, "user_message", userMessage, actualRequestId);
|
|
312
|
+
|
|
313
|
+
logger.debug("User message sent", {
|
|
314
|
+
agentId,
|
|
315
|
+
requestId: actualRequestId,
|
|
316
|
+
contentPreview:
|
|
317
|
+
typeof content === "string" ? content.substring(0, 50) : `[${content.length} parts]`,
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
// Mark as receiving
|
|
321
|
+
state.isReceiving = true;
|
|
322
|
+
|
|
323
|
+
try {
|
|
324
|
+
// Call driver.receive() and process the AsyncIterable
|
|
325
|
+
for await (const event of state.driver.receive(userMessage)) {
|
|
326
|
+
// Convert DriverStreamEvent to BusEvent and emit
|
|
327
|
+
this.handleDriverEvent(state, event, actualRequestId);
|
|
328
|
+
}
|
|
329
|
+
} catch (error) {
|
|
330
|
+
// Emit error event
|
|
331
|
+
this.emitEvent(
|
|
332
|
+
state,
|
|
333
|
+
"error_received",
|
|
334
|
+
{
|
|
335
|
+
message: error instanceof Error ? error.message : String(error),
|
|
336
|
+
errorCode: "runtime_error",
|
|
337
|
+
},
|
|
338
|
+
actualRequestId
|
|
339
|
+
);
|
|
340
|
+
throw error;
|
|
341
|
+
} finally {
|
|
342
|
+
state.isReceiving = false;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
interrupt(agentId: string, requestId?: string): void {
|
|
347
|
+
const state = this.agents.get(agentId);
|
|
348
|
+
if (!state) {
|
|
349
|
+
throw new Error(`Agent not found: ${agentId}`);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Call driver.interrupt() directly
|
|
353
|
+
state.driver.interrupt();
|
|
354
|
+
|
|
355
|
+
// Emit interrupt event (for external subscribers)
|
|
356
|
+
this.emitEvent(
|
|
357
|
+
state,
|
|
358
|
+
"interrupt",
|
|
359
|
+
{ agentId },
|
|
360
|
+
requestId ?? this.generateRequestId()
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
logger.debug("Interrupt sent", { agentId, requestId });
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// ==================== Event Subscription ====================
|
|
367
|
+
|
|
368
|
+
subscribe(agentId: string, handler: AgentEventHandler): Subscription {
|
|
369
|
+
const state = this.agents.get(agentId);
|
|
370
|
+
if (!state) {
|
|
371
|
+
throw new Error(`Agent not found: ${agentId}`);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const unsub = this.provider.eventBus.onAny((event) => {
|
|
375
|
+
const context = (event as BusEvent & { context?: { agentId?: string } }).context;
|
|
376
|
+
if (context?.agentId === agentId) {
|
|
377
|
+
handler(event);
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
state.subscriptions.add(unsub);
|
|
382
|
+
|
|
383
|
+
return {
|
|
384
|
+
unsubscribe: () => {
|
|
385
|
+
unsub();
|
|
386
|
+
state.subscriptions.delete(unsub);
|
|
387
|
+
},
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
subscribeAll(handler: AgentEventHandler): Subscription {
|
|
392
|
+
const unsub = this.provider.eventBus.onAny(handler);
|
|
393
|
+
this.globalSubscriptions.add(unsub);
|
|
394
|
+
|
|
395
|
+
return {
|
|
396
|
+
unsubscribe: () => {
|
|
397
|
+
unsub();
|
|
398
|
+
this.globalSubscriptions.delete(unsub);
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// ==================== Cleanup ====================
|
|
404
|
+
|
|
405
|
+
async shutdown(): Promise<void> {
|
|
406
|
+
if (this.isShutdown) return;
|
|
407
|
+
|
|
408
|
+
logger.info("Shutting down AgentXRuntime...");
|
|
409
|
+
|
|
410
|
+
// Destroy all agents
|
|
411
|
+
const agentIds = Array.from(this.agents.keys());
|
|
412
|
+
for (const agentId of agentIds) {
|
|
413
|
+
await this.destroyAgent(agentId);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Cleanup global subscriptions
|
|
417
|
+
for (const unsub of this.globalSubscriptions) {
|
|
418
|
+
unsub();
|
|
419
|
+
}
|
|
420
|
+
this.globalSubscriptions.clear();
|
|
421
|
+
|
|
422
|
+
this.isShutdown = true;
|
|
423
|
+
logger.info("AgentXRuntime shutdown complete");
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// ==================== Private Helpers ====================
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Handle a single DriverStreamEvent
|
|
430
|
+
*/
|
|
431
|
+
private handleDriverEvent(
|
|
432
|
+
state: AgentState,
|
|
433
|
+
event: DriverStreamEvent,
|
|
434
|
+
requestId: string
|
|
435
|
+
): void {
|
|
436
|
+
// Map DriverStreamEvent to BusEvent and emit
|
|
437
|
+
this.emitEvent(state, event.type, event.data, requestId);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Emit an event to the EventBus
|
|
442
|
+
*/
|
|
443
|
+
private emitEvent(
|
|
444
|
+
state: AgentState,
|
|
445
|
+
type: string,
|
|
446
|
+
data: unknown,
|
|
447
|
+
requestId: string
|
|
448
|
+
): void {
|
|
449
|
+
this.provider.eventBus.emit({
|
|
450
|
+
type,
|
|
451
|
+
timestamp: Date.now(),
|
|
452
|
+
source: "runtime",
|
|
453
|
+
category: this.categorizeEvent(type),
|
|
454
|
+
intent: "notification",
|
|
455
|
+
requestId,
|
|
456
|
+
data,
|
|
457
|
+
context: {
|
|
458
|
+
agentId: state.agent.agentId,
|
|
459
|
+
imageId: state.agent.imageId,
|
|
460
|
+
containerId: state.agent.containerId,
|
|
461
|
+
sessionId: state.agent.sessionId,
|
|
462
|
+
},
|
|
463
|
+
} as BusEvent);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Categorize event type
|
|
468
|
+
*/
|
|
469
|
+
private categorizeEvent(type: string): string {
|
|
470
|
+
if (type.includes("message")) return "message";
|
|
471
|
+
if (type.includes("tool")) return "tool";
|
|
472
|
+
if (type.includes("error") || type.includes("interrupted")) return "error";
|
|
473
|
+
if (type.includes("delta")) return "stream";
|
|
474
|
+
return "stream";
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
private generateAgentId(): string {
|
|
478
|
+
const timestamp = Date.now().toString(36);
|
|
479
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
480
|
+
return `agent_${timestamp}_${random}`;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
private generateRequestId(): string {
|
|
484
|
+
const timestamp = Date.now().toString(36);
|
|
485
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
486
|
+
return `req_${timestamp}_${random}`;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
private generateMessageId(): string {
|
|
490
|
+
const timestamp = Date.now().toString(36);
|
|
491
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
492
|
+
return `msg_${timestamp}_${random}`;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Create an AgentXRuntime instance
|
|
498
|
+
*/
|
|
499
|
+
export function createAgentXRuntime(provider: AgentXProvider): AgentXRuntime {
|
|
500
|
+
return new AgentXRuntimeImpl(provider);
|
|
501
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime Module
|
|
3
|
+
*
|
|
4
|
+
* AgentXProvider and AgentXRuntime interfaces.
|
|
5
|
+
* Platform packages provide concrete implementations.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import type {
|
|
10
|
+
* AgentXProvider,
|
|
11
|
+
* AgentXRuntime,
|
|
12
|
+
* RuntimeAgent,
|
|
13
|
+
* } from "@agentxjs/core/runtime";
|
|
14
|
+
*
|
|
15
|
+
* // Platform provides implementation
|
|
16
|
+
* const provider: AgentXProvider = {
|
|
17
|
+
* containerRepository,
|
|
18
|
+
* imageRepository,
|
|
19
|
+
* sessionRepository,
|
|
20
|
+
* workspaceProvider,
|
|
21
|
+
* driver,
|
|
22
|
+
* eventBus,
|
|
23
|
+
* };
|
|
24
|
+
*
|
|
25
|
+
* const runtime: AgentXRuntime = createRuntime({ provider });
|
|
26
|
+
*
|
|
27
|
+
* // Create agent from image
|
|
28
|
+
* const agent = await runtime.createAgent({ imageId: "img_xxx" });
|
|
29
|
+
*
|
|
30
|
+
* // Send message
|
|
31
|
+
* await runtime.receive(agent.agentId, "Hello!");
|
|
32
|
+
*
|
|
33
|
+
* // Subscribe to events
|
|
34
|
+
* const sub = runtime.subscribe(agent.agentId, (event) => {
|
|
35
|
+
* console.log(event.type, event.data);
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* // Cleanup
|
|
39
|
+
* sub.unsubscribe();
|
|
40
|
+
* await runtime.destroyAgent(agent.agentId);
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
export type {
|
|
45
|
+
AgentLifecycle,
|
|
46
|
+
RuntimeAgent,
|
|
47
|
+
AgentXProvider,
|
|
48
|
+
CreateAgentOptions,
|
|
49
|
+
AgentEventHandler,
|
|
50
|
+
Subscription,
|
|
51
|
+
AgentXRuntime,
|
|
52
|
+
AgentXRuntimeConfig,
|
|
53
|
+
CreateAgentXRuntime,
|
|
54
|
+
} from "./types";
|
|
55
|
+
|
|
56
|
+
export { AgentXRuntimeImpl, createAgentXRuntime } from "./AgentXRuntime";
|