@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,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Events - Session lifecycle, persist, and action events
|
|
3
|
+
*
|
|
4
|
+
* Events for session operations in the event system.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { SystemEvent } from "./base";
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Session Lifecycle Events
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Base SessionLifecycleEvent
|
|
15
|
+
*/
|
|
16
|
+
interface BaseSessionLifecycleEvent<T extends string, D = unknown> extends SystemEvent<
|
|
17
|
+
T,
|
|
18
|
+
D,
|
|
19
|
+
"session",
|
|
20
|
+
"lifecycle",
|
|
21
|
+
"notification"
|
|
22
|
+
> {}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* SessionCreatedEvent - Session was created
|
|
26
|
+
*/
|
|
27
|
+
export interface SessionCreatedEvent extends BaseSessionLifecycleEvent<
|
|
28
|
+
"session_created",
|
|
29
|
+
{
|
|
30
|
+
sessionId: string;
|
|
31
|
+
imageId: string;
|
|
32
|
+
containerId: string;
|
|
33
|
+
title?: string;
|
|
34
|
+
createdAt: number;
|
|
35
|
+
}
|
|
36
|
+
> {}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* SessionDestroyedEvent - Session was destroyed
|
|
40
|
+
*/
|
|
41
|
+
export interface SessionDestroyedEvent extends BaseSessionLifecycleEvent<
|
|
42
|
+
"session_destroyed",
|
|
43
|
+
{
|
|
44
|
+
sessionId: string;
|
|
45
|
+
reason?: string;
|
|
46
|
+
}
|
|
47
|
+
> {}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* SessionLifecycleEvent - All session lifecycle events
|
|
51
|
+
*/
|
|
52
|
+
export type SessionLifecycleEvent = SessionCreatedEvent | SessionDestroyedEvent;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Type guard: is this a SessionLifecycleEvent?
|
|
56
|
+
*/
|
|
57
|
+
export function isSessionLifecycleEvent(event: {
|
|
58
|
+
source?: string;
|
|
59
|
+
category?: string;
|
|
60
|
+
}): event is SessionLifecycleEvent {
|
|
61
|
+
return event.source === "session" && event.category === "lifecycle";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ============================================================================
|
|
65
|
+
// Session Persist Events
|
|
66
|
+
// ============================================================================
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Base SessionPersistRequest
|
|
70
|
+
*/
|
|
71
|
+
interface BaseSessionPersistRequest<T extends string, D = unknown> extends SystemEvent<
|
|
72
|
+
T,
|
|
73
|
+
D,
|
|
74
|
+
"session",
|
|
75
|
+
"persist",
|
|
76
|
+
"request"
|
|
77
|
+
> {}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Base SessionPersistResult
|
|
81
|
+
*/
|
|
82
|
+
interface BaseSessionPersistResult<T extends string, D = unknown> extends SystemEvent<
|
|
83
|
+
T,
|
|
84
|
+
D,
|
|
85
|
+
"session",
|
|
86
|
+
"persist",
|
|
87
|
+
"result"
|
|
88
|
+
> {}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* SessionSaveRequest - Request to save session
|
|
92
|
+
*/
|
|
93
|
+
export interface SessionSaveRequest extends BaseSessionPersistRequest<
|
|
94
|
+
"session_save_request",
|
|
95
|
+
{
|
|
96
|
+
sessionId: string;
|
|
97
|
+
title?: string;
|
|
98
|
+
metadata?: Record<string, unknown>;
|
|
99
|
+
}
|
|
100
|
+
> {}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* SessionSavedEvent - Session was saved
|
|
104
|
+
*/
|
|
105
|
+
export interface SessionSavedEvent extends BaseSessionPersistResult<
|
|
106
|
+
"session_saved",
|
|
107
|
+
{
|
|
108
|
+
sessionId: string;
|
|
109
|
+
savedAt: number;
|
|
110
|
+
}
|
|
111
|
+
> {}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* MessagePersistRequest - Request to persist a message
|
|
115
|
+
*/
|
|
116
|
+
export interface MessagePersistRequest extends BaseSessionPersistRequest<
|
|
117
|
+
"message_persist_request",
|
|
118
|
+
{
|
|
119
|
+
sessionId: string;
|
|
120
|
+
messageId: string;
|
|
121
|
+
role: "user" | "assistant" | "tool_call" | "tool_result";
|
|
122
|
+
content: unknown;
|
|
123
|
+
}
|
|
124
|
+
> {}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* MessagePersistedEvent - Message was persisted
|
|
128
|
+
*/
|
|
129
|
+
export interface MessagePersistedEvent extends BaseSessionPersistResult<
|
|
130
|
+
"message_persisted",
|
|
131
|
+
{
|
|
132
|
+
sessionId: string;
|
|
133
|
+
messageId: string;
|
|
134
|
+
savedAt: number;
|
|
135
|
+
}
|
|
136
|
+
> {}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* SessionPersistEvent - All session persist events
|
|
140
|
+
*/
|
|
141
|
+
export type SessionPersistEvent =
|
|
142
|
+
| SessionSaveRequest
|
|
143
|
+
| SessionSavedEvent
|
|
144
|
+
| MessagePersistRequest
|
|
145
|
+
| MessagePersistedEvent;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Session persist request events
|
|
149
|
+
*/
|
|
150
|
+
export type SessionPersistRequestEvent = SessionSaveRequest | MessagePersistRequest;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Session persist result events
|
|
154
|
+
*/
|
|
155
|
+
export type SessionPersistResultEvent = SessionSavedEvent | MessagePersistedEvent;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Type guard: is this a SessionPersistEvent?
|
|
159
|
+
*/
|
|
160
|
+
export function isSessionPersistEvent(event: {
|
|
161
|
+
source?: string;
|
|
162
|
+
category?: string;
|
|
163
|
+
}): event is SessionPersistEvent {
|
|
164
|
+
return event.source === "session" && event.category === "persist";
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ============================================================================
|
|
168
|
+
// Session Action Events
|
|
169
|
+
// ============================================================================
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Base SessionActionRequest
|
|
173
|
+
*/
|
|
174
|
+
interface BaseSessionActionRequest<T extends string, D = unknown> extends SystemEvent<
|
|
175
|
+
T,
|
|
176
|
+
D,
|
|
177
|
+
"session",
|
|
178
|
+
"action",
|
|
179
|
+
"request"
|
|
180
|
+
> {}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Base SessionActionResult
|
|
184
|
+
*/
|
|
185
|
+
interface BaseSessionActionResult<T extends string, D = unknown> extends SystemEvent<
|
|
186
|
+
T,
|
|
187
|
+
D,
|
|
188
|
+
"session",
|
|
189
|
+
"action",
|
|
190
|
+
"result"
|
|
191
|
+
> {}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* SessionResumeRequest - Request to resume a session
|
|
195
|
+
*/
|
|
196
|
+
export interface SessionResumeRequest extends BaseSessionActionRequest<
|
|
197
|
+
"session_resume_request",
|
|
198
|
+
{
|
|
199
|
+
sessionId: string;
|
|
200
|
+
containerId?: string;
|
|
201
|
+
}
|
|
202
|
+
> {}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* SessionResumedEvent - Session was resumed
|
|
206
|
+
*/
|
|
207
|
+
export interface SessionResumedEvent extends BaseSessionActionResult<
|
|
208
|
+
"session_resumed",
|
|
209
|
+
{
|
|
210
|
+
sessionId: string;
|
|
211
|
+
agentId: string;
|
|
212
|
+
resumedAt: number;
|
|
213
|
+
}
|
|
214
|
+
> {}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* SessionForkRequest - Request to fork a session
|
|
218
|
+
*/
|
|
219
|
+
export interface SessionForkRequest extends BaseSessionActionRequest<
|
|
220
|
+
"session_fork_request",
|
|
221
|
+
{
|
|
222
|
+
sessionId: string;
|
|
223
|
+
newTitle?: string;
|
|
224
|
+
}
|
|
225
|
+
> {}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* SessionForkedEvent - Session was forked
|
|
229
|
+
*/
|
|
230
|
+
export interface SessionForkedEvent extends BaseSessionActionResult<
|
|
231
|
+
"session_forked",
|
|
232
|
+
{
|
|
233
|
+
originalSessionId: string;
|
|
234
|
+
newSessionId: string;
|
|
235
|
+
newImageId: string;
|
|
236
|
+
forkedAt: number;
|
|
237
|
+
}
|
|
238
|
+
> {}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* SessionTitleUpdateRequest - Request to update session title
|
|
242
|
+
*/
|
|
243
|
+
export interface SessionTitleUpdateRequest extends BaseSessionActionRequest<
|
|
244
|
+
"session_title_update_request",
|
|
245
|
+
{
|
|
246
|
+
sessionId: string;
|
|
247
|
+
title: string;
|
|
248
|
+
}
|
|
249
|
+
> {}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* SessionTitleUpdatedEvent - Session title was updated
|
|
253
|
+
*/
|
|
254
|
+
export interface SessionTitleUpdatedEvent extends BaseSessionActionResult<
|
|
255
|
+
"session_title_updated",
|
|
256
|
+
{
|
|
257
|
+
sessionId: string;
|
|
258
|
+
title: string;
|
|
259
|
+
updatedAt: number;
|
|
260
|
+
}
|
|
261
|
+
> {}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* SessionActionEvent - All session action events
|
|
265
|
+
*/
|
|
266
|
+
export type SessionActionEvent =
|
|
267
|
+
| SessionResumeRequest
|
|
268
|
+
| SessionResumedEvent
|
|
269
|
+
| SessionForkRequest
|
|
270
|
+
| SessionForkedEvent
|
|
271
|
+
| SessionTitleUpdateRequest
|
|
272
|
+
| SessionTitleUpdatedEvent;
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Session action request events
|
|
276
|
+
*/
|
|
277
|
+
export type SessionActionRequestEvent =
|
|
278
|
+
| SessionResumeRequest
|
|
279
|
+
| SessionForkRequest
|
|
280
|
+
| SessionTitleUpdateRequest;
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Session action result events
|
|
284
|
+
*/
|
|
285
|
+
export type SessionActionResultEvent =
|
|
286
|
+
| SessionResumedEvent
|
|
287
|
+
| SessionForkedEvent
|
|
288
|
+
| SessionTitleUpdatedEvent;
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Type guard: is this a SessionActionEvent?
|
|
292
|
+
*/
|
|
293
|
+
export function isSessionActionEvent(event: {
|
|
294
|
+
source?: string;
|
|
295
|
+
category?: string;
|
|
296
|
+
}): event is SessionActionEvent {
|
|
297
|
+
return event.source === "session" && event.category === "action";
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// ============================================================================
|
|
301
|
+
// Session Event Union
|
|
302
|
+
// ============================================================================
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* SessionEvent - All session events
|
|
306
|
+
*/
|
|
307
|
+
export type SessionEvent = SessionLifecycleEvent | SessionPersistEvent | SessionActionEvent;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Type guard: is this a session event?
|
|
311
|
+
*/
|
|
312
|
+
export function isSessionEvent(event: { source?: string }): event is SessionEvent {
|
|
313
|
+
return event.source === "session";
|
|
314
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image - Persistent conversation entity
|
|
3
|
+
*
|
|
4
|
+
* Image is the primary entity that users interact with (displayed as "conversation").
|
|
5
|
+
* Agent is a transient runtime instance created from Image.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createLogger } from "commonxjs/logger";
|
|
9
|
+
import type { Image, ImageRecord, ImageContext, ImageCreateConfig } from "./types";
|
|
10
|
+
|
|
11
|
+
const logger = createLogger("image/Image");
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* ImageImpl - Image implementation
|
|
15
|
+
*/
|
|
16
|
+
export class ImageImpl implements Image {
|
|
17
|
+
private constructor(
|
|
18
|
+
private readonly record: ImageRecord,
|
|
19
|
+
private readonly context: ImageContext
|
|
20
|
+
) {}
|
|
21
|
+
|
|
22
|
+
// ==================== Getters ====================
|
|
23
|
+
|
|
24
|
+
get imageId(): string {
|
|
25
|
+
return this.record.imageId;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get containerId(): string {
|
|
29
|
+
return this.record.containerId;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get sessionId(): string {
|
|
33
|
+
return this.record.sessionId;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get name(): string {
|
|
37
|
+
return this.record.name;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get description(): string | undefined {
|
|
41
|
+
return this.record.description;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get systemPrompt(): string | undefined {
|
|
45
|
+
return this.record.systemPrompt;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get mcpServers() {
|
|
49
|
+
return this.record.mcpServers;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
get createdAt(): number {
|
|
53
|
+
return this.record.createdAt;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get updatedAt(): number {
|
|
57
|
+
return this.record.updatedAt;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ==================== Static Factory Methods ====================
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Create a new image (conversation)
|
|
64
|
+
*/
|
|
65
|
+
static async create(config: ImageCreateConfig, context: ImageContext): Promise<ImageImpl> {
|
|
66
|
+
const now = Date.now();
|
|
67
|
+
const imageId = ImageImpl.generateImageId();
|
|
68
|
+
const sessionId = ImageImpl.generateSessionId();
|
|
69
|
+
|
|
70
|
+
// Create image record
|
|
71
|
+
const record: ImageRecord = {
|
|
72
|
+
imageId,
|
|
73
|
+
containerId: config.containerId,
|
|
74
|
+
sessionId,
|
|
75
|
+
name: config.name ?? "New Conversation",
|
|
76
|
+
description: config.description,
|
|
77
|
+
systemPrompt: config.systemPrompt,
|
|
78
|
+
mcpServers: config.mcpServers,
|
|
79
|
+
createdAt: now,
|
|
80
|
+
updatedAt: now,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// Persist image
|
|
84
|
+
await context.imageRepository.saveImage(record);
|
|
85
|
+
|
|
86
|
+
// Create associated session (for message storage)
|
|
87
|
+
await context.sessionRepository.saveSession({
|
|
88
|
+
sessionId,
|
|
89
|
+
imageId,
|
|
90
|
+
containerId: config.containerId,
|
|
91
|
+
createdAt: now,
|
|
92
|
+
updatedAt: now,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
logger.info("Image created", {
|
|
96
|
+
imageId,
|
|
97
|
+
sessionId,
|
|
98
|
+
containerId: config.containerId,
|
|
99
|
+
name: record.name,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return new ImageImpl(record, context);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Load an existing image from storage
|
|
107
|
+
*/
|
|
108
|
+
static async load(imageId: string, context: ImageContext): Promise<ImageImpl | null> {
|
|
109
|
+
const record = await context.imageRepository.findImageById(imageId);
|
|
110
|
+
if (!record) {
|
|
111
|
+
logger.debug("Image not found", { imageId });
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
logger.debug("Image loaded", { imageId, name: record.name });
|
|
116
|
+
return new ImageImpl(record, context);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* List all images in a container
|
|
121
|
+
*/
|
|
122
|
+
static async listByContainer(containerId: string, context: ImageContext): Promise<ImageRecord[]> {
|
|
123
|
+
return context.imageRepository.findImagesByContainerId(containerId);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* List all images
|
|
128
|
+
*/
|
|
129
|
+
static async listAll(context: ImageContext): Promise<ImageRecord[]> {
|
|
130
|
+
return context.imageRepository.findAllImages();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ==================== Instance Methods ====================
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Update image metadata
|
|
137
|
+
*/
|
|
138
|
+
async update(updates: { name?: string; description?: string }): Promise<Image> {
|
|
139
|
+
const now = Date.now();
|
|
140
|
+
const updatedRecord: ImageRecord = {
|
|
141
|
+
...this.record,
|
|
142
|
+
name: updates.name ?? this.record.name,
|
|
143
|
+
description: updates.description ?? this.record.description,
|
|
144
|
+
updatedAt: now,
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
await this.context.imageRepository.saveImage(updatedRecord);
|
|
148
|
+
|
|
149
|
+
logger.info("Image updated", { imageId: this.imageId, updates });
|
|
150
|
+
return new ImageImpl(updatedRecord, this.context);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Delete this image and its session
|
|
155
|
+
*/
|
|
156
|
+
async delete(): Promise<void> {
|
|
157
|
+
// Delete session first (including messages)
|
|
158
|
+
await this.context.sessionRepository.deleteSession(this.sessionId);
|
|
159
|
+
|
|
160
|
+
// Delete image
|
|
161
|
+
await this.context.imageRepository.deleteImage(this.imageId);
|
|
162
|
+
|
|
163
|
+
logger.info("Image deleted", { imageId: this.imageId, sessionId: this.sessionId });
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Get the underlying record
|
|
168
|
+
*/
|
|
169
|
+
toRecord(): ImageRecord {
|
|
170
|
+
return { ...this.record };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ==================== Private Helpers ====================
|
|
174
|
+
|
|
175
|
+
private static generateImageId(): string {
|
|
176
|
+
const timestamp = Date.now().toString(36);
|
|
177
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
178
|
+
return `img_${timestamp}_${random}`;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private static generateSessionId(): string {
|
|
182
|
+
const timestamp = Date.now().toString(36);
|
|
183
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
184
|
+
return `sess_${timestamp}_${random}`;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Create a new Image
|
|
190
|
+
*/
|
|
191
|
+
export async function createImage(
|
|
192
|
+
config: ImageCreateConfig,
|
|
193
|
+
context: ImageContext
|
|
194
|
+
): Promise<Image> {
|
|
195
|
+
return ImageImpl.create(config, context);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Load an existing Image
|
|
200
|
+
*/
|
|
201
|
+
export async function loadImage(imageId: string, context: ImageContext): Promise<Image | null> {
|
|
202
|
+
return ImageImpl.load(imageId, context);
|
|
203
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image Module
|
|
3
|
+
*
|
|
4
|
+
* Manages persistent conversation entities (Images).
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { createImage, loadImage, type ImageRepository } from "@agentxjs/core/image";
|
|
9
|
+
*
|
|
10
|
+
* const context = {
|
|
11
|
+
* imageRepository: myImageRepository,
|
|
12
|
+
* sessionRepository: mySessionRepository,
|
|
13
|
+
* };
|
|
14
|
+
*
|
|
15
|
+
* // Create new image
|
|
16
|
+
* const image = await createImage({
|
|
17
|
+
* containerId: "container-1",
|
|
18
|
+
* name: "My Conversation",
|
|
19
|
+
* systemPrompt: "You are helpful",
|
|
20
|
+
* }, context);
|
|
21
|
+
*
|
|
22
|
+
* // Load existing image
|
|
23
|
+
* const existing = await loadImage("img_xxx", context);
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
export type {
|
|
28
|
+
ImageMetadata,
|
|
29
|
+
ImageRecord,
|
|
30
|
+
ImageRepository,
|
|
31
|
+
Image,
|
|
32
|
+
ImageContext,
|
|
33
|
+
ImageCreateConfig,
|
|
34
|
+
} from "./types";
|
|
35
|
+
|
|
36
|
+
export { ImageImpl, createImage, loadImage } from "./Image";
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image Types
|
|
3
|
+
*
|
|
4
|
+
* Image is the persistent representation of a conversation.
|
|
5
|
+
* Agent is a transient runtime instance created from Image.
|
|
6
|
+
*
|
|
7
|
+
* Lifecycle:
|
|
8
|
+
* - create() → ImageRecord (persistent) + SessionRecord (for messages)
|
|
9
|
+
* - run() → Agent (runtime, in-memory)
|
|
10
|
+
* - stop() / server restart → Agent destroyed, Image remains
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { McpServerConfig } from "../driver/types";
|
|
14
|
+
import type { SessionRepository } from "../persistence/types";
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Re-export from persistence (storage schema)
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
export type { ImageMetadata, ImageRecord, ImageRepository } from "../persistence/types";
|
|
21
|
+
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// Image Interface
|
|
24
|
+
// ============================================================================
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Image - Persistent conversation entity
|
|
28
|
+
*/
|
|
29
|
+
export interface Image {
|
|
30
|
+
readonly imageId: string;
|
|
31
|
+
readonly containerId: string;
|
|
32
|
+
readonly sessionId: string;
|
|
33
|
+
readonly name: string;
|
|
34
|
+
readonly description: string | undefined;
|
|
35
|
+
readonly systemPrompt: string | undefined;
|
|
36
|
+
readonly mcpServers: Record<string, McpServerConfig> | undefined;
|
|
37
|
+
readonly createdAt: number;
|
|
38
|
+
readonly updatedAt: number;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Update image metadata (name, description)
|
|
42
|
+
*/
|
|
43
|
+
update(updates: { name?: string; description?: string }): Promise<Image>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Delete this image and its session
|
|
47
|
+
*/
|
|
48
|
+
delete(): Promise<void>;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get the underlying record
|
|
52
|
+
*/
|
|
53
|
+
toRecord(): import("../persistence/types").ImageRecord;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ============================================================================
|
|
57
|
+
// Image Configuration
|
|
58
|
+
// ============================================================================
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Context needed by Image operations
|
|
62
|
+
*/
|
|
63
|
+
export interface ImageContext {
|
|
64
|
+
imageRepository: import("../persistence/types").ImageRepository;
|
|
65
|
+
sessionRepository: SessionRepository;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Configuration for creating a new Image
|
|
70
|
+
*/
|
|
71
|
+
export interface ImageCreateConfig {
|
|
72
|
+
containerId: string;
|
|
73
|
+
name?: string;
|
|
74
|
+
description?: string;
|
|
75
|
+
systemPrompt?: string;
|
|
76
|
+
mcpServers?: Record<string, McpServerConfig>;
|
|
77
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @agentxjs/core
|
|
3
|
+
*
|
|
4
|
+
* Core library for AgentX framework.
|
|
5
|
+
* Provides types, common utilities, and agent implementation.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Common Utilities
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
export * from "./common";
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Agent (includes all types)
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
export * from "./agent";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OffsetGenerator - Generates monotonically increasing offsets
|
|
3
|
+
*
|
|
4
|
+
* Format: "{timestamp_base36}-{sequence_padded}"
|
|
5
|
+
* Example: "lq5x4g2-0001"
|
|
6
|
+
*
|
|
7
|
+
* This format ensures:
|
|
8
|
+
* - Lexicographic ordering matches temporal ordering
|
|
9
|
+
* - Multiple events in same millisecond get unique offsets
|
|
10
|
+
* - Human-readable and compact
|
|
11
|
+
*/
|
|
12
|
+
export class OffsetGenerator {
|
|
13
|
+
private lastTimestamp = 0;
|
|
14
|
+
private sequence = 0;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Generate a new offset
|
|
18
|
+
*/
|
|
19
|
+
generate(): string {
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
|
|
22
|
+
if (now === this.lastTimestamp) {
|
|
23
|
+
this.sequence++;
|
|
24
|
+
} else {
|
|
25
|
+
this.lastTimestamp = now;
|
|
26
|
+
this.sequence = 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const timestampPart = now.toString(36);
|
|
30
|
+
const sequencePart = this.sequence.toString().padStart(4, "0");
|
|
31
|
+
|
|
32
|
+
return `${timestampPart}-${sequencePart}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Compare two offsets
|
|
37
|
+
* @returns negative if a < b, 0 if a == b, positive if a > b
|
|
38
|
+
*/
|
|
39
|
+
static compare(a: string, b: string): number {
|
|
40
|
+
const [aTime, aSeq] = a.split("-");
|
|
41
|
+
const [bTime, bSeq] = b.split("-");
|
|
42
|
+
|
|
43
|
+
const timeDiff = parseInt(aTime, 36) - parseInt(bTime, 36);
|
|
44
|
+
if (timeDiff !== 0) return timeDiff;
|
|
45
|
+
|
|
46
|
+
return parseInt(aSeq) - parseInt(bSeq);
|
|
47
|
+
}
|
|
48
|
+
}
|