@agentxjs/core 1.9.10-dev → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +342 -0
- package/dist/RpcClient-BcJ_zAGu.d.ts +304 -0
- package/dist/agent/engine/internal/index.d.ts +20 -15
- package/dist/agent/engine/internal/index.js +1 -2
- package/dist/agent/engine/mealy/index.js +0 -1
- package/dist/agent/index.d.ts +4 -4
- package/dist/agent/index.js +15 -15
- package/dist/agent/types/index.d.ts +4 -4
- package/dist/agent/types/index.js +1 -2
- package/dist/bash/index.d.ts +29 -0
- package/dist/bash/index.js +7 -0
- package/dist/{bus-uF1DM2ox.d.ts → bus-C9FLWIu8.d.ts} +3 -1
- package/dist/{chunk-K6WXQ2RW.js → chunk-23UUBQXR.js} +1 -2
- package/dist/chunk-23UUBQXR.js.map +1 -0
- package/dist/chunk-BHOD5PKR.js +55 -0
- package/dist/chunk-BHOD5PKR.js.map +1 -0
- package/dist/{chunk-I7GYR3MN.js → chunk-DEAR6N3O.js} +77 -91
- package/dist/chunk-DEAR6N3O.js.map +1 -0
- package/dist/chunk-FI7WQFGV.js +37 -0
- package/dist/chunk-FI7WQFGV.js.map +1 -0
- package/dist/{chunk-AT5P47YA.js → chunk-JTKCV7IS.js} +9 -9
- package/dist/chunk-JTKCV7IS.js.map +1 -0
- package/dist/{chunk-E5FPOAPO.js → chunk-LTVNPHST.js} +1 -1
- package/dist/chunk-LTVNPHST.js.map +1 -0
- package/dist/chunk-SKS7S2RY.js +1 -0
- package/dist/common/logger/index.js +0 -2
- package/dist/common/logger/index.js.map +1 -1
- package/dist/container/index.d.ts +3 -4
- package/dist/container/index.js +0 -2
- package/dist/container/index.js.map +1 -1
- package/dist/driver/index.d.ts +2 -310
- package/dist/event/index.d.ts +4 -4
- package/dist/event/index.js +1 -2
- package/dist/event/types/index.d.ts +4 -10
- package/dist/event/types/index.js +1 -2
- package/dist/{event-CDuTzs__.d.ts → event-DNWOBSBO.d.ts} +3 -4
- package/dist/image/index.d.ts +9 -5
- package/dist/image/index.js +5 -2
- package/dist/image/index.js.map +1 -1
- package/dist/index-CuS1i5V-.d.ts +609 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +16 -16
- package/dist/{message-BMrMm1pq.d.ts → message-03TJzvIX.d.ts} +10 -33
- package/dist/mq/index.js +0 -2
- package/dist/mq/index.js.map +1 -1
- package/dist/network/index.d.ts +3 -291
- package/dist/network/index.js +3 -14
- package/dist/network/index.js.map +1 -1
- package/dist/persistence/index.d.ts +2 -155
- package/dist/platform/index.d.ts +76 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/runtime/index.d.ts +26 -59
- package/dist/runtime/index.js +117 -33
- package/dist/runtime/index.js.map +1 -1
- package/dist/session/index.d.ts +4 -52
- package/dist/session/index.js +4 -51
- package/dist/session/index.js.map +1 -1
- package/dist/types-aE74Eo6G.d.ts +90 -0
- package/package.json +10 -5
- package/src/agent/__tests__/engine/internal/messageAssemblerProcessor.test.ts +291 -87
- package/src/agent/__tests__/engine/internal/turnTrackerProcessor.test.ts +56 -75
- package/src/agent/engine/MealyMachine.ts +1 -1
- package/src/agent/engine/internal/messageAssemblerProcessor.ts +99 -114
- package/src/agent/engine/internal/turnTrackerProcessor.ts +23 -27
- package/src/agent/types/event.ts +0 -4
- package/src/agent/types/index.ts +1 -3
- package/src/agent/types/message.ts +9 -43
- package/src/bash/index.ts +21 -0
- package/src/bash/tool.ts +57 -0
- package/src/bash/types.ts +108 -0
- package/src/driver/index.ts +1 -0
- package/src/driver/types.ts +122 -4
- package/src/event/__tests__/EventBus.test.ts +1 -1
- package/src/event/types/agent.ts +0 -11
- package/src/event/types/command.ts +3 -1
- package/src/image/Image.ts +11 -1
- package/src/image/types.ts +8 -2
- package/src/network/RpcClient.ts +21 -20
- package/src/network/index.ts +1 -1
- package/src/persistence/types.ts +5 -2
- package/src/platform/index.ts +21 -0
- package/src/platform/types.ts +84 -0
- package/src/runtime/AgentXRuntime.ts +184 -57
- package/src/runtime/__tests__/AgentXRuntime.test.ts +343 -0
- package/src/runtime/index.ts +7 -19
- package/src/runtime/types.ts +10 -62
- package/dist/chunk-7D4SUZUM.js +0 -38
- package/dist/chunk-AT5P47YA.js.map +0 -1
- package/dist/chunk-E5FPOAPO.js.map +0 -1
- package/dist/chunk-I7GYR3MN.js.map +0 -1
- package/dist/chunk-K6WXQ2RW.js.map +0 -1
- package/dist/workspace/index.d.ts +0 -111
- package/dist/wrapper-Y3UTVU2E.js +0 -3635
- package/dist/wrapper-Y3UTVU2E.js.map +0 -1
- package/src/workspace/index.ts +0 -27
- package/src/workspace/types.ts +0 -131
- /package/dist/{workspace → bash}/index.js.map +0 -0
- /package/dist/{chunk-7D4SUZUM.js.map → chunk-SKS7S2RY.js.map} +0 -0
- /package/dist/{workspace → platform}/index.js +0 -0
package/src/image/Image.ts
CHANGED
|
@@ -49,6 +49,10 @@ export class ImageImpl implements Image {
|
|
|
49
49
|
return this.record.mcpServers;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
get customData(): Record<string, unknown> | undefined {
|
|
53
|
+
return this.record.customData;
|
|
54
|
+
}
|
|
55
|
+
|
|
52
56
|
get createdAt(): number {
|
|
53
57
|
return this.record.createdAt;
|
|
54
58
|
}
|
|
@@ -76,6 +80,7 @@ export class ImageImpl implements Image {
|
|
|
76
80
|
description: config.description,
|
|
77
81
|
systemPrompt: config.systemPrompt,
|
|
78
82
|
mcpServers: config.mcpServers,
|
|
83
|
+
customData: config.customData,
|
|
79
84
|
createdAt: now,
|
|
80
85
|
updatedAt: now,
|
|
81
86
|
};
|
|
@@ -135,12 +140,17 @@ export class ImageImpl implements Image {
|
|
|
135
140
|
/**
|
|
136
141
|
* Update image metadata
|
|
137
142
|
*/
|
|
138
|
-
async update(updates: {
|
|
143
|
+
async update(updates: {
|
|
144
|
+
name?: string;
|
|
145
|
+
description?: string;
|
|
146
|
+
customData?: Record<string, unknown>;
|
|
147
|
+
}): Promise<Image> {
|
|
139
148
|
const now = Date.now();
|
|
140
149
|
const updatedRecord: ImageRecord = {
|
|
141
150
|
...this.record,
|
|
142
151
|
name: updates.name ?? this.record.name,
|
|
143
152
|
description: updates.description ?? this.record.description,
|
|
153
|
+
customData: updates.customData !== undefined ? updates.customData : this.record.customData,
|
|
144
154
|
updatedAt: now,
|
|
145
155
|
};
|
|
146
156
|
|
package/src/image/types.ts
CHANGED
|
@@ -34,13 +34,18 @@ export interface Image {
|
|
|
34
34
|
readonly description: string | undefined;
|
|
35
35
|
readonly systemPrompt: string | undefined;
|
|
36
36
|
readonly mcpServers: Record<string, McpServerConfig> | undefined;
|
|
37
|
+
readonly customData: Record<string, unknown> | undefined;
|
|
37
38
|
readonly createdAt: number;
|
|
38
39
|
readonly updatedAt: number;
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
|
-
* Update image metadata (name, description)
|
|
42
|
+
* Update image metadata (name, description, customData)
|
|
42
43
|
*/
|
|
43
|
-
update(updates: {
|
|
44
|
+
update(updates: {
|
|
45
|
+
name?: string;
|
|
46
|
+
description?: string;
|
|
47
|
+
customData?: Record<string, unknown>;
|
|
48
|
+
}): Promise<Image>;
|
|
44
49
|
|
|
45
50
|
/**
|
|
46
51
|
* Delete this image and its session
|
|
@@ -74,4 +79,5 @@ export interface ImageCreateConfig {
|
|
|
74
79
|
description?: string;
|
|
75
80
|
systemPrompt?: string;
|
|
76
81
|
mcpServers?: Record<string, McpServerConfig>;
|
|
82
|
+
customData?: Record<string, unknown>;
|
|
77
83
|
}
|
package/src/network/RpcClient.ts
CHANGED
|
@@ -39,19 +39,18 @@ import {
|
|
|
39
39
|
} from "./jsonrpc";
|
|
40
40
|
import type { SystemEvent } from "../event/types/base";
|
|
41
41
|
|
|
42
|
-
/**
|
|
43
|
-
* Check if running in browser environment
|
|
44
|
-
*/
|
|
45
|
-
function isBrowser(): boolean {
|
|
46
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
47
|
-
const globalWindow = typeof globalThis !== "undefined" ? (globalThis as any).window : undefined;
|
|
48
|
-
return globalWindow?.document !== undefined;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
42
|
// ============================================================================
|
|
52
43
|
// Types
|
|
53
44
|
// ============================================================================
|
|
54
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Factory function for creating WebSocket instances.
|
|
48
|
+
* Platform layer provides the implementation:
|
|
49
|
+
* - Browser: native WebSocket (default)
|
|
50
|
+
* - Node.js: ws library (via @agentxjs/node-platform)
|
|
51
|
+
*/
|
|
52
|
+
export type WebSocketFactory = (url: string) => WebSocket;
|
|
53
|
+
|
|
55
54
|
/**
|
|
56
55
|
* RpcClient configuration
|
|
57
56
|
*/
|
|
@@ -61,6 +60,12 @@ export interface RpcClientConfig {
|
|
|
61
60
|
*/
|
|
62
61
|
url: string;
|
|
63
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Factory for creating WebSocket instances.
|
|
65
|
+
* If not provided, falls back to the global WebSocket constructor.
|
|
66
|
+
*/
|
|
67
|
+
createWebSocket?: WebSocketFactory;
|
|
68
|
+
|
|
64
69
|
/**
|
|
65
70
|
* Request timeout in milliseconds (default: 30000)
|
|
66
71
|
*/
|
|
@@ -77,7 +82,7 @@ export interface RpcClientConfig {
|
|
|
77
82
|
reconnectDelay?: number;
|
|
78
83
|
|
|
79
84
|
/**
|
|
80
|
-
* Headers for authentication (
|
|
85
|
+
* Headers for authentication (sent in first message after connection)
|
|
81
86
|
*/
|
|
82
87
|
headers?:
|
|
83
88
|
| Record<string, string>
|
|
@@ -172,14 +177,9 @@ export class RpcClient {
|
|
|
172
177
|
|
|
173
178
|
const url = this.config.url;
|
|
174
179
|
|
|
175
|
-
// Create WebSocket
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
ws = new WebSocket(url);
|
|
179
|
-
} else {
|
|
180
|
-
const { default: WS } = await import("ws");
|
|
181
|
-
ws = new WS(url) as unknown as WebSocket;
|
|
182
|
-
}
|
|
180
|
+
// Create WebSocket via injected factory or global WebSocket
|
|
181
|
+
const factory = this.config.createWebSocket ?? ((u: string) => new WebSocket(u));
|
|
182
|
+
const ws = factory(url);
|
|
183
183
|
|
|
184
184
|
this.ws = ws;
|
|
185
185
|
|
|
@@ -191,8 +191,9 @@ export class RpcClient {
|
|
|
191
191
|
console.log("[RpcClient] Connected to", url);
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
-
// Send auth
|
|
195
|
-
|
|
194
|
+
// Send auth headers after connection (for environments where
|
|
195
|
+
// WebSocket constructor doesn't support headers, e.g. browser)
|
|
196
|
+
if (this.config.headers) {
|
|
196
197
|
const headers =
|
|
197
198
|
typeof this.config.headers === "function"
|
|
198
199
|
? await this.config.headers()
|
package/src/network/index.ts
CHANGED
package/src/persistence/types.ts
CHANGED
|
@@ -50,8 +50,8 @@ export interface ContainerRecord {
|
|
|
50
50
|
* Image metadata for storing provider-specific data
|
|
51
51
|
*/
|
|
52
52
|
export interface ImageMetadata {
|
|
53
|
-
/**
|
|
54
|
-
|
|
53
|
+
/** Driver session ID for conversation resume */
|
|
54
|
+
driverSessionId?: string;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
/**
|
|
@@ -93,6 +93,9 @@ export interface ImageRecord {
|
|
|
93
93
|
/** Provider-specific metadata */
|
|
94
94
|
metadata?: ImageMetadata;
|
|
95
95
|
|
|
96
|
+
/** Application-specific custom data (favorites, sort order, tags, etc.) */
|
|
97
|
+
customData?: Record<string, unknown>;
|
|
98
|
+
|
|
96
99
|
/** Creation timestamp (Unix milliseconds) */
|
|
97
100
|
createdAt: number;
|
|
98
101
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform Module
|
|
3
|
+
*
|
|
4
|
+
* AgentXPlatform dependency injection container.
|
|
5
|
+
* Platform packages provide concrete implementations.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import type { AgentXPlatform } from "@agentxjs/core/platform";
|
|
10
|
+
*
|
|
11
|
+
* const platform: AgentXPlatform = {
|
|
12
|
+
* containerRepository,
|
|
13
|
+
* imageRepository,
|
|
14
|
+
* sessionRepository,
|
|
15
|
+
* eventBus,
|
|
16
|
+
* bashProvider, // optional
|
|
17
|
+
* };
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export type { AgentXPlatform } from "./types";
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform Types
|
|
3
|
+
*
|
|
4
|
+
* AgentXPlatform - Dependency injection container for platform capabilities.
|
|
5
|
+
* Platform packages (node-platform, etc.) provide implementations.
|
|
6
|
+
*
|
|
7
|
+
* ```
|
|
8
|
+
* ┌─────────────────────────────────────────────────────────────┐
|
|
9
|
+
* │ AgentXPlatform │
|
|
10
|
+
* │ (Dependency Injection - Platform provides implementations) │
|
|
11
|
+
* │ │
|
|
12
|
+
* │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
13
|
+
* │ │ Repositories│ │ EventBus │ │ Providers │ │
|
|
14
|
+
* │ │ Container │ │ │ │ Bash (opt) │ │
|
|
15
|
+
* │ │ Image │ │ │ │ │ │
|
|
16
|
+
* │ │ Session │ │ │ │ │ │
|
|
17
|
+
* │ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
18
|
+
* └─────────────────────────────────────────────────────────────┘
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import type { ContainerRepository } from "../container/types";
|
|
23
|
+
import type { ImageRepository } from "../image/types";
|
|
24
|
+
import type { SessionRepository } from "../session/types";
|
|
25
|
+
import type { EventBus } from "../event/types";
|
|
26
|
+
import type { BashProvider } from "../bash/types";
|
|
27
|
+
import type { WebSocketFactory } from "../network/RpcClient";
|
|
28
|
+
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// AgentXPlatform - Dependency Injection
|
|
31
|
+
// ============================================================================
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* AgentXPlatform - Collects all dependencies for runtime
|
|
35
|
+
*
|
|
36
|
+
* Platform packages provide implementations of these interfaces.
|
|
37
|
+
* The platform is passed to AgentXRuntime for integration.
|
|
38
|
+
*
|
|
39
|
+
* Required capabilities:
|
|
40
|
+
* - containerRepository, imageRepository, sessionRepository — persistence
|
|
41
|
+
* - eventBus — pub/sub
|
|
42
|
+
*
|
|
43
|
+
* Optional capabilities:
|
|
44
|
+
* - bashProvider — command execution (not all platforms support this)
|
|
45
|
+
*/
|
|
46
|
+
export interface AgentXPlatform {
|
|
47
|
+
/**
|
|
48
|
+
* Container repository for persistence
|
|
49
|
+
*/
|
|
50
|
+
readonly containerRepository: ContainerRepository;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Image repository for persistence
|
|
54
|
+
*/
|
|
55
|
+
readonly imageRepository: ImageRepository;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Session repository for persistence
|
|
59
|
+
*/
|
|
60
|
+
readonly sessionRepository: SessionRepository;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Event bus for pub/sub
|
|
64
|
+
*/
|
|
65
|
+
readonly eventBus: EventBus;
|
|
66
|
+
|
|
67
|
+
// === Optional Providers ===
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Bash provider for command execution
|
|
71
|
+
*
|
|
72
|
+
* Optional — not all platforms support shell execution.
|
|
73
|
+
* Node.js platform provides child_process based implementation.
|
|
74
|
+
*/
|
|
75
|
+
readonly bashProvider?: BashProvider;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* WebSocket factory for creating client connections
|
|
79
|
+
*
|
|
80
|
+
* Optional — browser uses native WebSocket by default.
|
|
81
|
+
* Node.js platform provides ws-based implementation.
|
|
82
|
+
*/
|
|
83
|
+
readonly webSocketFactory?: WebSocketFactory;
|
|
84
|
+
}
|
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
* AgentXRuntimeImpl - Runtime integration implementation
|
|
3
3
|
*
|
|
4
4
|
* Integrates all components to provide agent lifecycle management.
|
|
5
|
-
* Uses
|
|
5
|
+
* Uses Platform dependencies to coordinate Session, Image, Container, etc.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Architecture:
|
|
8
8
|
* - Driver.receive() returns AsyncIterable<DriverStreamEvent>
|
|
9
|
-
* - Runtime
|
|
10
|
-
* -
|
|
9
|
+
* - Runtime emits raw stream events to EventBus
|
|
10
|
+
* - Runtime pushes events through AgentEngine (MealyMachine → Presenter)
|
|
11
|
+
* - Presenter emits message/state/turn events and persists messages
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
import { createLogger } from "commonxjs/logger";
|
|
14
15
|
import type {
|
|
15
|
-
|
|
16
|
+
AgentXPlatform,
|
|
16
17
|
AgentXRuntime,
|
|
17
18
|
RuntimeAgent,
|
|
18
19
|
CreateAgentOptions,
|
|
@@ -20,9 +21,27 @@ import type {
|
|
|
20
21
|
Subscription,
|
|
21
22
|
AgentLifecycle,
|
|
22
23
|
} from "./types";
|
|
23
|
-
import type {
|
|
24
|
+
import type {
|
|
25
|
+
UserContentPart,
|
|
26
|
+
UserMessage,
|
|
27
|
+
AgentEngine,
|
|
28
|
+
StreamEvent,
|
|
29
|
+
AgentOutput,
|
|
30
|
+
AgentPresenter,
|
|
31
|
+
AgentSource,
|
|
32
|
+
Message,
|
|
33
|
+
} from "../agent/types";
|
|
24
34
|
import type { BusEvent } from "../event/types";
|
|
25
|
-
import type {
|
|
35
|
+
import type {
|
|
36
|
+
CreateDriver,
|
|
37
|
+
Driver,
|
|
38
|
+
DriverConfig,
|
|
39
|
+
DriverStreamEvent,
|
|
40
|
+
ToolDefinition,
|
|
41
|
+
} from "../driver/types";
|
|
42
|
+
import { createSession } from "../session/Session";
|
|
43
|
+
import { createBashTool } from "../bash/tool";
|
|
44
|
+
import { createAgent as createAgentEngine } from "../agent/createAgent";
|
|
26
45
|
|
|
27
46
|
const logger = createLogger("runtime/AgentXRuntime");
|
|
28
47
|
|
|
@@ -34,6 +53,7 @@ interface AgentState {
|
|
|
34
53
|
lifecycle: AgentLifecycle;
|
|
35
54
|
subscriptions: Set<() => void>;
|
|
36
55
|
driver: Driver;
|
|
56
|
+
engine: AgentEngine;
|
|
37
57
|
/** Flag to track if a receive operation is in progress */
|
|
38
58
|
isReceiving: boolean;
|
|
39
59
|
}
|
|
@@ -42,14 +62,16 @@ interface AgentState {
|
|
|
42
62
|
* AgentXRuntimeImpl - Runtime implementation
|
|
43
63
|
*/
|
|
44
64
|
export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
45
|
-
readonly
|
|
65
|
+
readonly platform: AgentXPlatform;
|
|
66
|
+
private readonly createDriver: CreateDriver;
|
|
46
67
|
|
|
47
68
|
private agents = new Map<string, AgentState>();
|
|
48
69
|
private globalSubscriptions = new Set<() => void>();
|
|
49
70
|
private isShutdown = false;
|
|
50
71
|
|
|
51
|
-
constructor(
|
|
52
|
-
this.
|
|
72
|
+
constructor(platform: AgentXPlatform, createDriver: CreateDriver) {
|
|
73
|
+
this.platform = platform;
|
|
74
|
+
this.createDriver = createDriver;
|
|
53
75
|
logger.info("AgentXRuntime initialized");
|
|
54
76
|
}
|
|
55
77
|
|
|
@@ -63,7 +85,7 @@ export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
|
63
85
|
const { imageId } = options;
|
|
64
86
|
|
|
65
87
|
// Load image
|
|
66
|
-
const imageRecord = await this.
|
|
88
|
+
const imageRecord = await this.platform.imageRepository.findImageById(imageId);
|
|
67
89
|
if (!imageRecord) {
|
|
68
90
|
throw new Error(`Image not found: ${imageId}`);
|
|
69
91
|
}
|
|
@@ -72,41 +94,102 @@ export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
|
72
94
|
const agentId = options.agentId ?? this.generateAgentId();
|
|
73
95
|
|
|
74
96
|
// Ensure container exists
|
|
75
|
-
const containerExists = await this.
|
|
97
|
+
const containerExists = await this.platform.containerRepository.containerExists(
|
|
76
98
|
imageRecord.containerId
|
|
77
99
|
);
|
|
78
100
|
if (!containerExists) {
|
|
79
101
|
throw new Error(`Container not found: ${imageRecord.containerId}`);
|
|
80
102
|
}
|
|
81
103
|
|
|
82
|
-
// Create
|
|
83
|
-
const
|
|
84
|
-
|
|
104
|
+
// Create Session for driver (MonoDriver needs this to read history)
|
|
105
|
+
const session = createSession({
|
|
106
|
+
sessionId: imageRecord.sessionId,
|
|
85
107
|
imageId,
|
|
108
|
+
containerId: imageRecord.containerId,
|
|
109
|
+
repository: this.platform.sessionRepository,
|
|
86
110
|
});
|
|
87
|
-
await workspace.initialize();
|
|
88
111
|
|
|
89
|
-
//
|
|
112
|
+
// Assemble platform-provided default tools
|
|
113
|
+
const defaultTools: ToolDefinition[] = [];
|
|
114
|
+
if (this.platform.bashProvider) {
|
|
115
|
+
defaultTools.push(createBashTool(this.platform.bashProvider));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Create driver config (apiKey/baseUrl are provided by the createDriver closure)
|
|
90
119
|
const driverConfig: DriverConfig = {
|
|
91
|
-
apiKey:
|
|
92
|
-
baseUrl: process.env.ANTHROPIC_BASE_URL,
|
|
120
|
+
apiKey: "",
|
|
93
121
|
agentId,
|
|
94
122
|
systemPrompt: imageRecord.systemPrompt,
|
|
95
|
-
cwd: workspace.path,
|
|
96
123
|
mcpServers: imageRecord.mcpServers,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
124
|
+
tools: defaultTools.length > 0 ? defaultTools : undefined,
|
|
125
|
+
session, // Inject Session for stateless drivers
|
|
126
|
+
resumeSessionId: imageRecord.metadata?.driverSessionId as string | undefined,
|
|
127
|
+
onSessionIdCaptured: async (driverSessionId: string) => {
|
|
128
|
+
// Persist driver session ID for resume
|
|
129
|
+
await this.platform.imageRepository.updateMetadata(imageId, { driverSessionId });
|
|
101
130
|
},
|
|
102
131
|
};
|
|
103
132
|
|
|
104
|
-
// Create driver using the
|
|
105
|
-
const driver = this.
|
|
133
|
+
// Create driver using the injected CreateDriver function
|
|
134
|
+
const driver = this.createDriver(driverConfig);
|
|
106
135
|
|
|
107
136
|
// Initialize driver
|
|
108
137
|
await driver.initialize();
|
|
109
138
|
|
|
139
|
+
// Create AgentEngine with custom Source and Presenter
|
|
140
|
+
// Source: no-op (Runtime pushes events directly via handleStreamEvent)
|
|
141
|
+
// Presenter: emits message/state/turn events to EventBus + persists messages
|
|
142
|
+
const noopSource: AgentSource = {
|
|
143
|
+
name: "RuntimeSource",
|
|
144
|
+
connect: () => {},
|
|
145
|
+
disconnect: () => {},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const sessionId = imageRecord.sessionId;
|
|
149
|
+
const sessionRepository = this.platform.sessionRepository;
|
|
150
|
+
const eventBus = this.platform.eventBus;
|
|
151
|
+
|
|
152
|
+
const runtimePresenter: AgentPresenter = {
|
|
153
|
+
name: "RuntimePresenter",
|
|
154
|
+
present: (_agentId: string, output: AgentOutput) => {
|
|
155
|
+
const category = categorizeAgentOutput(output.type);
|
|
156
|
+
|
|
157
|
+
// Skip stream events — already emitted by handleDriverEvent
|
|
158
|
+
if (category === "stream") return;
|
|
159
|
+
|
|
160
|
+
// Emit state/message/turn events to EventBus
|
|
161
|
+
eventBus.emit({
|
|
162
|
+
type: output.type,
|
|
163
|
+
timestamp: output.timestamp,
|
|
164
|
+
source: "agent",
|
|
165
|
+
category,
|
|
166
|
+
intent: "notification",
|
|
167
|
+
data: output.data,
|
|
168
|
+
context: {
|
|
169
|
+
agentId,
|
|
170
|
+
imageId,
|
|
171
|
+
containerId: imageRecord.containerId,
|
|
172
|
+
sessionId,
|
|
173
|
+
},
|
|
174
|
+
} as BusEvent);
|
|
175
|
+
|
|
176
|
+
// Persist message events to SessionRepository
|
|
177
|
+
if (category === "message" && output.type !== "user_message") {
|
|
178
|
+
const message = output.data as Message;
|
|
179
|
+
sessionRepository.addMessage(sessionId, message).catch((err) => {
|
|
180
|
+
logger.error("Failed to persist message", { type: output.type, error: err });
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const engine = createAgentEngine({
|
|
187
|
+
agentId,
|
|
188
|
+
bus: this.platform.eventBus,
|
|
189
|
+
source: noopSource,
|
|
190
|
+
presenter: runtimePresenter,
|
|
191
|
+
});
|
|
192
|
+
|
|
110
193
|
// Create runtime agent
|
|
111
194
|
const agent: RuntimeAgent = {
|
|
112
195
|
agentId,
|
|
@@ -118,18 +201,19 @@ export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
|
118
201
|
createdAt: Date.now(),
|
|
119
202
|
};
|
|
120
203
|
|
|
121
|
-
// Store agent state with driver
|
|
204
|
+
// Store agent state with driver and engine
|
|
122
205
|
const state: AgentState = {
|
|
123
206
|
agent,
|
|
124
207
|
lifecycle: "running",
|
|
125
208
|
subscriptions: new Set(),
|
|
126
209
|
driver,
|
|
210
|
+
engine,
|
|
127
211
|
isReceiving: false,
|
|
128
212
|
};
|
|
129
213
|
this.agents.set(agentId, state);
|
|
130
214
|
|
|
131
215
|
// Emit agent_created event
|
|
132
|
-
this.
|
|
216
|
+
this.platform.eventBus.emit({
|
|
133
217
|
type: "agent_created",
|
|
134
218
|
timestamp: Date.now(),
|
|
135
219
|
source: "runtime",
|
|
@@ -185,7 +269,7 @@ export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
|
185
269
|
state.lifecycle = "stopped";
|
|
186
270
|
|
|
187
271
|
// Emit agent_stopped event
|
|
188
|
-
this.
|
|
272
|
+
this.platform.eventBus.emit({
|
|
189
273
|
type: "agent_stopped",
|
|
190
274
|
timestamp: Date.now(),
|
|
191
275
|
source: "runtime",
|
|
@@ -216,7 +300,7 @@ export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
|
216
300
|
state.lifecycle = "running";
|
|
217
301
|
|
|
218
302
|
// Emit agent_resumed event
|
|
219
|
-
this.
|
|
303
|
+
this.platform.eventBus.emit({
|
|
220
304
|
type: "agent_resumed",
|
|
221
305
|
timestamp: Date.now(),
|
|
222
306
|
source: "runtime",
|
|
@@ -240,8 +324,9 @@ export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
|
240
324
|
throw new Error(`Agent not found: ${agentId}`);
|
|
241
325
|
}
|
|
242
326
|
|
|
243
|
-
// Dispose driver
|
|
327
|
+
// Dispose driver and engine
|
|
244
328
|
await state.driver.dispose();
|
|
329
|
+
await state.engine.destroy();
|
|
245
330
|
|
|
246
331
|
// Cleanup subscriptions
|
|
247
332
|
for (const unsub of state.subscriptions) {
|
|
@@ -252,7 +337,7 @@ export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
|
252
337
|
state.lifecycle = "destroyed";
|
|
253
338
|
|
|
254
339
|
// Emit agent_destroyed event
|
|
255
|
-
this.
|
|
340
|
+
this.platform.eventBus.emit({
|
|
256
341
|
type: "agent_destroyed",
|
|
257
342
|
timestamp: Date.now(),
|
|
258
343
|
source: "runtime",
|
|
@@ -305,7 +390,7 @@ export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
|
305
390
|
};
|
|
306
391
|
|
|
307
392
|
// Persist to session
|
|
308
|
-
await this.
|
|
393
|
+
await this.platform.sessionRepository.addMessage(state.agent.sessionId, userMessage);
|
|
309
394
|
|
|
310
395
|
// Emit user_message event (for external subscribers)
|
|
311
396
|
this.emitEvent(state, "user_message", userMessage, actualRequestId);
|
|
@@ -314,7 +399,11 @@ export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
|
314
399
|
agentId,
|
|
315
400
|
requestId: actualRequestId,
|
|
316
401
|
contentPreview:
|
|
317
|
-
typeof content === "string"
|
|
402
|
+
typeof content === "string"
|
|
403
|
+
? content.substring(0, 50)
|
|
404
|
+
: Array.isArray(content)
|
|
405
|
+
? `[${content.length} parts]`
|
|
406
|
+
: `[${typeof content}]`,
|
|
318
407
|
});
|
|
319
408
|
|
|
320
409
|
// Mark as receiving
|
|
@@ -353,12 +442,7 @@ export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
|
353
442
|
state.driver.interrupt();
|
|
354
443
|
|
|
355
444
|
// Emit interrupt event (for external subscribers)
|
|
356
|
-
this.emitEvent(
|
|
357
|
-
state,
|
|
358
|
-
"interrupt",
|
|
359
|
-
{ agentId },
|
|
360
|
-
requestId ?? this.generateRequestId()
|
|
361
|
-
);
|
|
445
|
+
this.emitEvent(state, "interrupt", { agentId }, requestId ?? this.generateRequestId());
|
|
362
446
|
|
|
363
447
|
logger.debug("Interrupt sent", { agentId, requestId });
|
|
364
448
|
}
|
|
@@ -371,7 +455,7 @@ export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
|
371
455
|
throw new Error(`Agent not found: ${agentId}`);
|
|
372
456
|
}
|
|
373
457
|
|
|
374
|
-
const unsub = this.
|
|
458
|
+
const unsub = this.platform.eventBus.onAny((event) => {
|
|
375
459
|
const context = (event as BusEvent & { context?: { agentId?: string } }).context;
|
|
376
460
|
if (context?.agentId === agentId) {
|
|
377
461
|
handler(event);
|
|
@@ -389,7 +473,7 @@ export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
|
389
473
|
}
|
|
390
474
|
|
|
391
475
|
subscribeAll(handler: AgentEventHandler): Subscription {
|
|
392
|
-
const unsub = this.
|
|
476
|
+
const unsub = this.platform.eventBus.onAny(handler);
|
|
393
477
|
this.globalSubscriptions.add(unsub);
|
|
394
478
|
|
|
395
479
|
return {
|
|
@@ -428,25 +512,21 @@ export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
|
428
512
|
/**
|
|
429
513
|
* Handle a single DriverStreamEvent
|
|
430
514
|
*/
|
|
431
|
-
private handleDriverEvent(
|
|
432
|
-
|
|
433
|
-
event: DriverStreamEvent,
|
|
434
|
-
requestId: string
|
|
435
|
-
): void {
|
|
436
|
-
// Map DriverStreamEvent to BusEvent and emit
|
|
515
|
+
private handleDriverEvent(state: AgentState, event: DriverStreamEvent, requestId: string): void {
|
|
516
|
+
// 1. Emit raw stream event to EventBus (for Presentation and other subscribers)
|
|
437
517
|
this.emitEvent(state, event.type, event.data, requestId);
|
|
518
|
+
|
|
519
|
+
// 2. Push to AgentEngine for MealyMachine processing
|
|
520
|
+
// Engine produces message/state/turn events via Presenter
|
|
521
|
+
const streamEvent = toStreamEvent(event);
|
|
522
|
+
state.engine.handleStreamEvent(streamEvent);
|
|
438
523
|
}
|
|
439
524
|
|
|
440
525
|
/**
|
|
441
526
|
* Emit an event to the EventBus
|
|
442
527
|
*/
|
|
443
|
-
private emitEvent(
|
|
444
|
-
|
|
445
|
-
type: string,
|
|
446
|
-
data: unknown,
|
|
447
|
-
requestId: string
|
|
448
|
-
): void {
|
|
449
|
-
this.provider.eventBus.emit({
|
|
528
|
+
private emitEvent(state: AgentState, type: string, data: unknown, requestId: string): void {
|
|
529
|
+
this.platform.eventBus.emit({
|
|
450
530
|
type,
|
|
451
531
|
timestamp: Date.now(),
|
|
452
532
|
source: "runtime",
|
|
@@ -493,9 +573,56 @@ export class AgentXRuntimeImpl implements AgentXRuntime {
|
|
|
493
573
|
}
|
|
494
574
|
}
|
|
495
575
|
|
|
576
|
+
// ============================================================================
|
|
577
|
+
// Helpers
|
|
578
|
+
// ============================================================================
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Convert DriverStreamEvent to agent-layer StreamEvent.
|
|
582
|
+
* Data structures are identical; only "error" type needs renaming.
|
|
583
|
+
*/
|
|
584
|
+
function toStreamEvent(event: DriverStreamEvent): StreamEvent {
|
|
585
|
+
const type = event.type === "error" ? "error_received" : event.type;
|
|
586
|
+
return { type, data: event.data, timestamp: Date.now() } as StreamEvent;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* Categorize AgentOutput type for EventBus emission.
|
|
591
|
+
*/
|
|
592
|
+
function categorizeAgentOutput(type: string): string {
|
|
593
|
+
// Stream layer — already emitted by handleDriverEvent
|
|
594
|
+
const streamTypes = [
|
|
595
|
+
"message_start",
|
|
596
|
+
"message_delta",
|
|
597
|
+
"message_stop",
|
|
598
|
+
"text_delta",
|
|
599
|
+
"tool_use_start",
|
|
600
|
+
"input_json_delta",
|
|
601
|
+
"tool_use_stop",
|
|
602
|
+
"tool_result",
|
|
603
|
+
"error_received",
|
|
604
|
+
];
|
|
605
|
+
if (streamTypes.includes(type)) return "stream";
|
|
606
|
+
|
|
607
|
+
// Message layer
|
|
608
|
+
if (type.endsWith("_message")) return "message";
|
|
609
|
+
|
|
610
|
+
// Turn layer
|
|
611
|
+
if (type.startsWith("turn_")) return "turn";
|
|
612
|
+
|
|
613
|
+
// State layer (default)
|
|
614
|
+
return "state";
|
|
615
|
+
}
|
|
616
|
+
|
|
496
617
|
/**
|
|
497
618
|
* Create an AgentXRuntime instance
|
|
619
|
+
*
|
|
620
|
+
* @param platform - AgentXPlatform with repositories and event bus
|
|
621
|
+
* @param createDriver - Factory function for creating Driver instances per Agent
|
|
498
622
|
*/
|
|
499
|
-
export function createAgentXRuntime(
|
|
500
|
-
|
|
623
|
+
export function createAgentXRuntime(
|
|
624
|
+
platform: AgentXPlatform,
|
|
625
|
+
createDriver: CreateDriver
|
|
626
|
+
): AgentXRuntime {
|
|
627
|
+
return new AgentXRuntimeImpl(platform, createDriver);
|
|
501
628
|
}
|