@archships/dim-agent-sdk 0.0.4 → 0.0.6
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 +12 -3
- package/dist/dim-agent-sdk/src/agent-core/agent-types.d.ts +2 -1
- package/dist/dim-agent-sdk/src/agent-core/loop-runner.d.ts +1 -0
- package/dist/dim-agent-sdk/src/agent-core/session-state.d.ts +2 -1
- package/dist/dim-agent-sdk/src/agent-core/session.d.ts +46 -7
- package/dist/dim-agent-sdk/src/contracts/event.d.ts +13 -7
- package/dist/dim-agent-sdk/src/contracts/state.d.ts +32 -1
- package/dist/dim-agent-sdk/src/index.d.ts +1 -1
- package/dist/dim-agent-sdk/src/persistence/snapshot-codec.d.ts +2 -1
- package/dist/dim-plugin-api/src/index.d.ts +18 -1
- package/dist/src/index.js +355 -39
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,8 +34,16 @@ const session = await agent.createSession({
|
|
|
34
34
|
systemPrompt: 'You are a coding agent. Use tools when needed.',
|
|
35
35
|
})
|
|
36
36
|
|
|
37
|
-
const
|
|
38
|
-
|
|
37
|
+
const itemId = session.send('Create hello.txt in the current directory and write hello world into it.')
|
|
38
|
+
|
|
39
|
+
for await (const event of session.receive()) {
|
|
40
|
+
if (event.itemId !== itemId)
|
|
41
|
+
continue
|
|
42
|
+
if (event.type === 'text_delta')
|
|
43
|
+
process.stdout.write(event.delta)
|
|
44
|
+
if (event.type === 'done')
|
|
45
|
+
console.log(event.message.content)
|
|
46
|
+
}
|
|
39
47
|
```
|
|
40
48
|
|
|
41
49
|
## Manual
|
|
@@ -48,7 +56,8 @@ console.log(message.content)
|
|
|
48
56
|
|
|
49
57
|
- Canonical content / message / tool / model / state contracts
|
|
50
58
|
- `createAgent()` -> `Agent` -> `Session`
|
|
51
|
-
-
|
|
59
|
+
- Queue-first session flow: `send()`, `sendBatch()`, `steer()`, `receive()`, `getQueueStatus()`
|
|
60
|
+
- Session events: `text_delta`, optional `thinking_delta`, `tool_call`, `plugin_event`, `tool_result`, `done`, `error`
|
|
52
61
|
- Provider adapters: `openai-compatible`, `openai-responses`, `anthropic`, `gemini`, `zenmux`, `aihubmix`, `aihubmix-responses`, `moonshotai`, `deepseek`, `xai`, `xai-responses`
|
|
53
62
|
- Builtin tools: `read`, `write`, `edit`, `exec`
|
|
54
63
|
- Hook-first plugin integration
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DimPlugin } from '@archships/dim-plugin-api';
|
|
2
|
-
import type { CompactionOptions, Message, MessageContentInput, ModelClient, Tool } from '../contracts';
|
|
2
|
+
import type { CompactionOptions, Message, MessageContentInput, MessageQueueConfig, ModelClient, Tool } from '../contracts';
|
|
3
3
|
import type { ContextManager } from '../context';
|
|
4
4
|
import type { StateStore } from '../persistence/store';
|
|
5
5
|
import type { PermissionSpec } from '../services';
|
|
@@ -26,4 +26,5 @@ export interface CreateSessionOptions {
|
|
|
26
26
|
metadata?: Record<string, unknown>;
|
|
27
27
|
messages?: Message[];
|
|
28
28
|
systemPrompt?: MessageContentInput;
|
|
29
|
+
messageQueueConfig?: Partial<MessageQueueConfig>;
|
|
29
30
|
}
|
|
@@ -19,6 +19,7 @@ export interface LoopRunnerDependencies {
|
|
|
19
19
|
export interface LoopRunnerRunOptions {
|
|
20
20
|
signal?: AbortSignal;
|
|
21
21
|
onDone?: (message: AssistantMessage) => Promise<void> | void;
|
|
22
|
+
persistentPromptSegments?: string[];
|
|
22
23
|
}
|
|
23
24
|
export declare class LoopRunner {
|
|
24
25
|
private readonly messageFactory;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CompactionOptions, CompactionState, Message, ModelClient, ModelRef, PluginSessionStateEntry, Usage } from '../contracts';
|
|
1
|
+
import type { CompactionOptions, CompactionState, Message, MessageQueueSnapshot, ModelClient, ModelRef, PluginSessionStateEntry, Usage } from '../contracts';
|
|
2
2
|
import type { ToolRegistry } from '../tools/tool-registry';
|
|
3
3
|
export interface RuntimeSessionState {
|
|
4
4
|
id: string;
|
|
@@ -13,6 +13,7 @@ export interface RuntimeSessionState {
|
|
|
13
13
|
usage: Usage;
|
|
14
14
|
compaction: CompactionState;
|
|
15
15
|
pluginState: Record<string, PluginSessionStateEntry>;
|
|
16
|
+
messageQueue: MessageQueueSnapshot;
|
|
16
17
|
compactionOptions?: CompactionOptions;
|
|
17
18
|
createdAt: number;
|
|
18
19
|
updatedAt: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CompactionOptions, CompactionState, CompactionUpdate, Message, MessageContentInput, MessageQueueConfig, MessageQueueSnapshot, MessageQueueStatus, PendingMessageKind, ModelClient, ModelRef, PluginSessionStateEntry, SessionStatus, SessionSnapshot, SessionStreamEvent, Usage } from '../contracts';
|
|
2
2
|
import type { ContextManager } from '../context';
|
|
3
3
|
import type { StateStore } from '../persistence/store';
|
|
4
4
|
import type { PluginHost } from '../plugin-host/plugin-host';
|
|
@@ -22,6 +22,8 @@ export interface SessionOptions {
|
|
|
22
22
|
usage?: Usage;
|
|
23
23
|
compaction?: CompactionState;
|
|
24
24
|
pluginState?: Record<string, PluginSessionStateEntry>;
|
|
25
|
+
messageQueue?: MessageQueueSnapshot;
|
|
26
|
+
messageQueueConfig?: Partial<MessageQueueConfig>;
|
|
25
27
|
compactionOptions?: CompactionOptions;
|
|
26
28
|
createdAt?: number;
|
|
27
29
|
updatedAt?: number;
|
|
@@ -33,6 +35,15 @@ export interface SessionOptions {
|
|
|
33
35
|
compactionService: DefaultCompactionService;
|
|
34
36
|
pluginStateService: DefaultPluginStateService;
|
|
35
37
|
}
|
|
38
|
+
interface SessionQueueSendOptions {
|
|
39
|
+
priority?: number;
|
|
40
|
+
}
|
|
41
|
+
interface SessionReceiveOptions {
|
|
42
|
+
signal?: AbortSignal;
|
|
43
|
+
}
|
|
44
|
+
interface ClearQueueFilter {
|
|
45
|
+
kind?: PendingMessageKind;
|
|
46
|
+
}
|
|
36
47
|
export declare class Session {
|
|
37
48
|
readonly id: string;
|
|
38
49
|
readonly createdAt: number;
|
|
@@ -46,7 +57,14 @@ export declare class Session {
|
|
|
46
57
|
private readonly compactionService;
|
|
47
58
|
private readonly pluginStateService;
|
|
48
59
|
private readonly pluginControllers;
|
|
60
|
+
private readonly bufferedEvents;
|
|
61
|
+
private readonly stateChangeWaiters;
|
|
49
62
|
private activeRunCount;
|
|
63
|
+
private processingPromise;
|
|
64
|
+
private receiveActive;
|
|
65
|
+
private activeReceiveSignal?;
|
|
66
|
+
private haltProcessingUntilReceive;
|
|
67
|
+
private saveChain;
|
|
50
68
|
constructor(options: SessionOptions);
|
|
51
69
|
get messages(): Message[];
|
|
52
70
|
get usage(): Usage;
|
|
@@ -58,16 +76,37 @@ export declare class Session {
|
|
|
58
76
|
get updatedAt(): number;
|
|
59
77
|
getCwd(): string | undefined;
|
|
60
78
|
setCwd(cwd: string): void;
|
|
79
|
+
send(input: MessageContentInput, options?: SessionQueueSendOptions): string;
|
|
80
|
+
sendBatch(items: Array<{
|
|
81
|
+
input: MessageContentInput;
|
|
82
|
+
options?: SessionQueueSendOptions;
|
|
83
|
+
}>): string[];
|
|
84
|
+
steer(input: MessageContentInput, options?: SessionQueueSendOptions): string;
|
|
85
|
+
cancelQueuedItem(itemId: string): boolean;
|
|
86
|
+
getQueueStatus(): MessageQueueStatus;
|
|
87
|
+
clearQueue(filter?: ClearQueueFilter): number;
|
|
88
|
+
receive(options?: SessionReceiveOptions): AsyncGenerator<SessionStreamEvent, void, void>;
|
|
61
89
|
compact(update: CompactionUpdate): Promise<void>;
|
|
62
90
|
save(): Promise<void>;
|
|
91
|
+
private writeSnapshot;
|
|
63
92
|
toSnapshot(): SessionSnapshot;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
93
|
+
private enqueueItem;
|
|
94
|
+
private onQueueMutated;
|
|
95
|
+
private hasRunnableItems;
|
|
96
|
+
private ensureQueueProcessing;
|
|
97
|
+
private processQueue;
|
|
98
|
+
private dequeueNextRunnableItem;
|
|
99
|
+
private processQueuedItem;
|
|
100
|
+
private attachQueueContext;
|
|
101
|
+
private createErrorEvent;
|
|
102
|
+
private pushBufferedEvent;
|
|
103
|
+
private scheduleSave;
|
|
104
|
+
private persistStateQuietly;
|
|
105
|
+
private enqueueSave;
|
|
106
|
+
private waitForStateChange;
|
|
107
|
+
private notifyStateChange;
|
|
70
108
|
private createLoopRunner;
|
|
71
109
|
private readEstimatedInputTokens;
|
|
72
110
|
private createHookContext;
|
|
73
111
|
}
|
|
112
|
+
export {};
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { SessionErrorPayload, Usage } from './common';
|
|
2
2
|
import type { AssistantMessage } from './message';
|
|
3
|
+
import type { PendingMessageKind } from './state';
|
|
3
4
|
import type { CallToolResult, ToolCall } from './tool';
|
|
5
|
+
export interface SessionQueueEventContext {
|
|
6
|
+
itemId?: string;
|
|
7
|
+
itemKind?: PendingMessageKind;
|
|
8
|
+
priority?: number;
|
|
9
|
+
}
|
|
4
10
|
export interface SessionPluginEvent {
|
|
5
11
|
type: 'plugin_event';
|
|
6
12
|
sessionId: string;
|
|
@@ -8,30 +14,30 @@ export interface SessionPluginEvent {
|
|
|
8
14
|
event: string;
|
|
9
15
|
data?: Record<string, unknown>;
|
|
10
16
|
}
|
|
11
|
-
export type SessionStreamEvent = {
|
|
17
|
+
export type SessionStreamEvent = ({
|
|
12
18
|
type: 'text_delta';
|
|
13
19
|
sessionId: string;
|
|
14
20
|
delta: string;
|
|
15
|
-
} | {
|
|
21
|
+
} & SessionQueueEventContext) | ({
|
|
16
22
|
type: 'thinking_delta';
|
|
17
23
|
sessionId: string;
|
|
18
24
|
delta: string;
|
|
19
|
-
} | {
|
|
25
|
+
} & SessionQueueEventContext) | ({
|
|
20
26
|
type: 'tool_call';
|
|
21
27
|
sessionId: string;
|
|
22
28
|
toolCall: ToolCall;
|
|
23
|
-
} | {
|
|
29
|
+
} & SessionQueueEventContext) | ({
|
|
24
30
|
type: 'tool_result';
|
|
25
31
|
sessionId: string;
|
|
26
32
|
toolCallId: string;
|
|
27
33
|
result: CallToolResult;
|
|
28
|
-
} | SessionPluginEvent | {
|
|
34
|
+
} & SessionQueueEventContext) | (SessionPluginEvent & SessionQueueEventContext) | ({
|
|
29
35
|
type: 'done';
|
|
30
36
|
sessionId: string;
|
|
31
37
|
message: AssistantMessage;
|
|
32
38
|
usage?: Usage;
|
|
33
|
-
} | {
|
|
39
|
+
} & SessionQueueEventContext) | ({
|
|
34
40
|
type: 'error';
|
|
35
41
|
sessionId: string;
|
|
36
42
|
error: SessionErrorPayload;
|
|
37
|
-
};
|
|
43
|
+
} & SessionQueueEventContext);
|
|
@@ -1,10 +1,40 @@
|
|
|
1
1
|
import type { CompactionState } from './compaction';
|
|
2
|
+
import type { MessageContentInput } from './content';
|
|
2
3
|
import type { PluginSessionStateEntry } from './plugin-state';
|
|
3
4
|
import type { Usage } from './common';
|
|
4
5
|
import type { Message } from './message';
|
|
5
6
|
import type { ModelRef } from './model';
|
|
7
|
+
export interface MessageQueueConfig {
|
|
8
|
+
autoProcessQueue: boolean;
|
|
9
|
+
maxQueueSize?: number;
|
|
10
|
+
}
|
|
11
|
+
export type PendingMessageKind = 'user' | 'steer';
|
|
12
|
+
export interface PendingMessage {
|
|
13
|
+
id: string;
|
|
14
|
+
input: MessageContentInput;
|
|
15
|
+
kind: PendingMessageKind;
|
|
16
|
+
priority: number;
|
|
17
|
+
enqueuedAt: number;
|
|
18
|
+
}
|
|
19
|
+
export interface MessageQueueSnapshot {
|
|
20
|
+
items: PendingMessage[];
|
|
21
|
+
config: MessageQueueConfig;
|
|
22
|
+
}
|
|
23
|
+
export interface MessageQueueStatusItem {
|
|
24
|
+
id: string;
|
|
25
|
+
kind: PendingMessageKind;
|
|
26
|
+
priority: number;
|
|
27
|
+
enqueuedAt: number;
|
|
28
|
+
preview: string;
|
|
29
|
+
}
|
|
30
|
+
export interface MessageQueueStatus {
|
|
31
|
+
length: number;
|
|
32
|
+
items: MessageQueueStatusItem[];
|
|
33
|
+
isProcessing: boolean;
|
|
34
|
+
config: MessageQueueConfig;
|
|
35
|
+
}
|
|
6
36
|
export interface SessionSnapshot {
|
|
7
|
-
schemaVersion: 1;
|
|
37
|
+
schemaVersion: 1 | 2;
|
|
8
38
|
sessionId: string;
|
|
9
39
|
model?: ModelRef;
|
|
10
40
|
cwd?: string;
|
|
@@ -15,6 +45,7 @@ export interface SessionSnapshot {
|
|
|
15
45
|
createdAt: number;
|
|
16
46
|
updatedAt: number;
|
|
17
47
|
metadata?: Record<string, unknown>;
|
|
48
|
+
messageQueue?: MessageQueueSnapshot;
|
|
18
49
|
}
|
|
19
50
|
export interface SessionStatus {
|
|
20
51
|
sessionId: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { CallToolResult, CompactionBudgetInfo, CompactionCheckpoint, CompactionEstimator, CompactionEstimatorInput, CompactionOptions, CompactionService, CompactionState, CompactionTriggerReason, CompactionUpdate, ContentBlock, Message, MessageContentInput, ModelAdapter, ModelClient, ModelRequest, ModelStreamEvent, ModelStopReason, ModelRef, PluginSessionStateEntry, PluginStateService, SessionStatus, SessionPluginEvent, SessionSnapshot, SessionStreamEvent, Tool, ToolCall, ToolDefinition, ToolExecutionContext, ToolExecutionPluginEvent, ToolInputSchema, Usage, } from './contracts';
|
|
1
|
+
export type { CallToolResult, CompactionBudgetInfo, CompactionCheckpoint, CompactionEstimator, CompactionEstimatorInput, CompactionOptions, CompactionService, CompactionState, CompactionTriggerReason, CompactionUpdate, ContentBlock, Message, MessageContentInput, MessageQueueConfig, MessageQueueSnapshot, MessageQueueStatus, ModelAdapter, ModelClient, ModelRequest, ModelStreamEvent, ModelStopReason, ModelRef, PluginSessionStateEntry, PendingMessage, PendingMessageKind, PluginStateService, SessionStatus, SessionPluginEvent, SessionSnapshot, SessionStreamEvent, Tool, ToolCall, ToolDefinition, ToolExecutionContext, ToolExecutionPluginEvent, ToolInputSchema, Usage, } from './contracts';
|
|
2
2
|
export { normalizeContent } from './contracts/content-normalize';
|
|
3
3
|
export { Agent, createAgent } from './agent-core/agent';
|
|
4
4
|
export type { CreateAgentOptions } from './agent-core/agent';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CompactionState, Message, ModelRef, PluginSessionStateEntry, SessionSnapshot, Usage } from '../contracts';
|
|
1
|
+
import type { CompactionState, Message, MessageQueueSnapshot, ModelRef, PluginSessionStateEntry, SessionSnapshot, Usage } from '../contracts';
|
|
2
2
|
export interface SnapshotCodecInput {
|
|
3
3
|
sessionId: string;
|
|
4
4
|
model?: ModelRef;
|
|
@@ -10,6 +10,7 @@ export interface SnapshotCodecInput {
|
|
|
10
10
|
createdAt: number;
|
|
11
11
|
updatedAt: number;
|
|
12
12
|
metadata?: Record<string, unknown>;
|
|
13
|
+
messageQueue?: MessageQueueSnapshot;
|
|
13
14
|
}
|
|
14
15
|
export interface SnapshotCodec {
|
|
15
16
|
encode(input: SnapshotCodecInput): SessionSnapshot;
|
|
@@ -279,8 +279,24 @@ export interface Tool {
|
|
|
279
279
|
readonly definition: ToolDefinition;
|
|
280
280
|
execute(args: Record<string, unknown>, context: ToolExecutionContext): Promise<CallToolResult>;
|
|
281
281
|
}
|
|
282
|
+
export interface MessageQueueConfig {
|
|
283
|
+
autoProcessQueue: boolean;
|
|
284
|
+
maxQueueSize?: number;
|
|
285
|
+
}
|
|
286
|
+
export type PendingMessageKind = 'user' | 'steer';
|
|
287
|
+
export interface PendingMessage {
|
|
288
|
+
id: string;
|
|
289
|
+
input: MessageContentInput;
|
|
290
|
+
kind: PendingMessageKind;
|
|
291
|
+
priority: number;
|
|
292
|
+
enqueuedAt: number;
|
|
293
|
+
}
|
|
294
|
+
export interface MessageQueueSnapshot {
|
|
295
|
+
items: PendingMessage[];
|
|
296
|
+
config: MessageQueueConfig;
|
|
297
|
+
}
|
|
282
298
|
export interface SessionSnapshot {
|
|
283
|
-
schemaVersion: 1;
|
|
299
|
+
schemaVersion: 1 | 2;
|
|
284
300
|
sessionId: string;
|
|
285
301
|
model?: ModelRef;
|
|
286
302
|
cwd?: string;
|
|
@@ -291,6 +307,7 @@ export interface SessionSnapshot {
|
|
|
291
307
|
createdAt: number;
|
|
292
308
|
updatedAt: number;
|
|
293
309
|
metadata?: Record<string, unknown>;
|
|
310
|
+
messageQueue?: MessageQueueSnapshot;
|
|
294
311
|
}
|
|
295
312
|
export interface SessionStatus {
|
|
296
313
|
sessionId: string;
|
package/dist/src/index.js
CHANGED
|
@@ -3257,7 +3257,7 @@ class DefaultNotificationBus {
|
|
|
3257
3257
|
class JsonSnapshotCodec {
|
|
3258
3258
|
encode(input) {
|
|
3259
3259
|
return structuredClone({
|
|
3260
|
-
schemaVersion:
|
|
3260
|
+
schemaVersion: 2,
|
|
3261
3261
|
sessionId: input.sessionId,
|
|
3262
3262
|
model: input.model,
|
|
3263
3263
|
cwd: input.cwd,
|
|
@@ -3267,14 +3267,15 @@ class JsonSnapshotCodec {
|
|
|
3267
3267
|
pluginState: input.pluginState,
|
|
3268
3268
|
createdAt: input.createdAt,
|
|
3269
3269
|
updatedAt: input.updatedAt,
|
|
3270
|
-
metadata: input.metadata
|
|
3270
|
+
metadata: input.metadata,
|
|
3271
|
+
messageQueue: input.messageQueue
|
|
3271
3272
|
});
|
|
3272
3273
|
}
|
|
3273
3274
|
decode(value) {
|
|
3274
3275
|
if (!value || typeof value !== "object")
|
|
3275
3276
|
throw new TypeError("Session snapshot must be an object");
|
|
3276
3277
|
const snapshot = value;
|
|
3277
|
-
if (snapshot.schemaVersion !== 1)
|
|
3278
|
+
if (snapshot.schemaVersion !== 1 && snapshot.schemaVersion !== 2)
|
|
3278
3279
|
throw new TypeError("Unsupported session snapshot schemaVersion");
|
|
3279
3280
|
if (typeof snapshot.sessionId !== "string")
|
|
3280
3281
|
throw new TypeError("Session snapshot sessionId is required");
|
|
@@ -3282,6 +3283,12 @@ class JsonSnapshotCodec {
|
|
|
3282
3283
|
throw new TypeError("Session snapshot messages must be an array");
|
|
3283
3284
|
if (typeof snapshot.createdAt !== "number" || typeof snapshot.updatedAt !== "number")
|
|
3284
3285
|
throw new TypeError("Session snapshot timestamps are required");
|
|
3286
|
+
if (snapshot.schemaVersion === 1) {
|
|
3287
|
+
return structuredClone({
|
|
3288
|
+
...snapshot,
|
|
3289
|
+
schemaVersion: 1
|
|
3290
|
+
});
|
|
3291
|
+
}
|
|
3285
3292
|
return structuredClone(snapshot);
|
|
3286
3293
|
}
|
|
3287
3294
|
}
|
|
@@ -3305,6 +3312,25 @@ function addUsage(left, right) {
|
|
|
3305
3312
|
};
|
|
3306
3313
|
}
|
|
3307
3314
|
|
|
3315
|
+
// src/agent-core/errors.ts
|
|
3316
|
+
class SessionExecutionError extends Error {
|
|
3317
|
+
payload;
|
|
3318
|
+
payloadSummary;
|
|
3319
|
+
constructor(payload) {
|
|
3320
|
+
super(payload.message);
|
|
3321
|
+
this.name = "SessionExecutionError";
|
|
3322
|
+
this.payload = payload;
|
|
3323
|
+
this.payloadSummary = stringifyPayload(payload);
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
3326
|
+
function stringifyPayload(payload) {
|
|
3327
|
+
try {
|
|
3328
|
+
return JSON.stringify(payload, null, 2);
|
|
3329
|
+
} catch {
|
|
3330
|
+
return String(payload);
|
|
3331
|
+
}
|
|
3332
|
+
}
|
|
3333
|
+
|
|
3308
3334
|
// src/agent-core/tool-call.ts
|
|
3309
3335
|
function startToolCall(callId, toolName) {
|
|
3310
3336
|
if (!callId.trim())
|
|
@@ -3337,25 +3363,6 @@ function finalizeToolCall(draft) {
|
|
|
3337
3363
|
};
|
|
3338
3364
|
}
|
|
3339
3365
|
|
|
3340
|
-
// src/agent-core/errors.ts
|
|
3341
|
-
class SessionExecutionError extends Error {
|
|
3342
|
-
payload;
|
|
3343
|
-
payloadSummary;
|
|
3344
|
-
constructor(payload) {
|
|
3345
|
-
super(payload.message);
|
|
3346
|
-
this.name = "SessionExecutionError";
|
|
3347
|
-
this.payload = payload;
|
|
3348
|
-
this.payloadSummary = stringifyPayload(payload);
|
|
3349
|
-
}
|
|
3350
|
-
}
|
|
3351
|
-
function stringifyPayload(payload) {
|
|
3352
|
-
try {
|
|
3353
|
-
return JSON.stringify(payload, null, 2);
|
|
3354
|
-
} catch {
|
|
3355
|
-
return String(payload);
|
|
3356
|
-
}
|
|
3357
|
-
}
|
|
3358
|
-
|
|
3359
3366
|
// src/agent-core/model-turn-collector.ts
|
|
3360
3367
|
class DefaultModelTurnCollector {
|
|
3361
3368
|
async* collect(options) {
|
|
@@ -3536,6 +3543,7 @@ class LoopRunner {
|
|
|
3536
3543
|
cwd: state.cwd
|
|
3537
3544
|
}) ?? [];
|
|
3538
3545
|
const promptSegments = [
|
|
3546
|
+
...options.persistentPromptSegments ?? [],
|
|
3539
3547
|
...pendingContextSegments,
|
|
3540
3548
|
...this.contextManager.format(effectiveContext),
|
|
3541
3549
|
...pluginPromptSegments
|
|
@@ -3977,6 +3985,10 @@ class DefaultToolExecutor {
|
|
|
3977
3985
|
}
|
|
3978
3986
|
|
|
3979
3987
|
// src/agent-core/session.ts
|
|
3988
|
+
var DEFAULT_MESSAGE_QUEUE_CONFIG = {
|
|
3989
|
+
autoProcessQueue: true
|
|
3990
|
+
};
|
|
3991
|
+
|
|
3980
3992
|
class Session {
|
|
3981
3993
|
id;
|
|
3982
3994
|
createdAt;
|
|
@@ -3990,7 +4002,14 @@ class Session {
|
|
|
3990
4002
|
compactionService;
|
|
3991
4003
|
pluginStateService;
|
|
3992
4004
|
pluginControllers;
|
|
4005
|
+
bufferedEvents = [];
|
|
4006
|
+
stateChangeWaiters = [];
|
|
3993
4007
|
activeRunCount = 0;
|
|
4008
|
+
processingPromise = null;
|
|
4009
|
+
receiveActive = false;
|
|
4010
|
+
activeReceiveSignal;
|
|
4011
|
+
haltProcessingUntilReceive = false;
|
|
4012
|
+
saveChain = Promise.resolve();
|
|
3994
4013
|
constructor(options) {
|
|
3995
4014
|
const now = Date.now();
|
|
3996
4015
|
this.id = options.id ?? createId("session");
|
|
@@ -4016,10 +4035,16 @@ class Session {
|
|
|
4016
4035
|
usage: options.usage ? { ...options.usage } : createEmptyUsage(),
|
|
4017
4036
|
compaction: cloneCompactionState(options.compaction ?? createEmptyCompactionState()),
|
|
4018
4037
|
pluginState: clonePluginStateMap(options.pluginState),
|
|
4038
|
+
messageQueue: cloneMessageQueueSnapshot(options.messageQueue ?? {
|
|
4039
|
+
items: [],
|
|
4040
|
+
config: createMessageQueueConfig(options.messageQueueConfig)
|
|
4041
|
+
}),
|
|
4019
4042
|
compactionOptions: options.compactionOptions,
|
|
4020
4043
|
createdAt: this.createdAt,
|
|
4021
4044
|
updatedAt: options.updatedAt ?? now
|
|
4022
4045
|
};
|
|
4046
|
+
if (options.messageQueueConfig)
|
|
4047
|
+
this.state.messageQueue.config = createMessageQueueConfig(options.messageQueueConfig, this.state.messageQueue.config);
|
|
4023
4048
|
this.compactionService.registerSession(this.state);
|
|
4024
4049
|
this.pluginStateService.registerSession(this.state);
|
|
4025
4050
|
this.pluginControllers = this.pluginHost?.createSessionControllers({
|
|
@@ -4061,6 +4086,91 @@ class Session {
|
|
|
4061
4086
|
this.state.cwd = cwd;
|
|
4062
4087
|
touchRuntimeSessionState(this.state);
|
|
4063
4088
|
}
|
|
4089
|
+
send(input, options = {}) {
|
|
4090
|
+
return this.enqueueItem("user", input, options);
|
|
4091
|
+
}
|
|
4092
|
+
sendBatch(items) {
|
|
4093
|
+
const maxQueueSize = this.state.messageQueue.config.maxQueueSize;
|
|
4094
|
+
if (maxQueueSize !== undefined && this.state.messageQueue.items.length + items.length > maxQueueSize)
|
|
4095
|
+
throw new SessionExecutionError(createQueueError("DIM_QUEUE_FULL", `Session queue is full (max ${maxQueueSize})`));
|
|
4096
|
+
const prepared = items.map(({ input, options }) => prepareQueueItem("user", input, options));
|
|
4097
|
+
for (const item of prepared)
|
|
4098
|
+
this.state.messageQueue.items.push(item);
|
|
4099
|
+
if (prepared.length > 0)
|
|
4100
|
+
this.onQueueMutated();
|
|
4101
|
+
return prepared.map((item) => item.id);
|
|
4102
|
+
}
|
|
4103
|
+
steer(input, options = {}) {
|
|
4104
|
+
return this.enqueueItem("steer", input, options);
|
|
4105
|
+
}
|
|
4106
|
+
cancelQueuedItem(itemId) {
|
|
4107
|
+
const index = this.state.messageQueue.items.findIndex((item) => item.id === itemId);
|
|
4108
|
+
if (index < 0)
|
|
4109
|
+
return false;
|
|
4110
|
+
this.state.messageQueue.items.splice(index, 1);
|
|
4111
|
+
this.onQueueMutated();
|
|
4112
|
+
return true;
|
|
4113
|
+
}
|
|
4114
|
+
getQueueStatus() {
|
|
4115
|
+
const items = [...this.state.messageQueue.items].sort(compareQueueItems).map((item) => ({
|
|
4116
|
+
id: item.id,
|
|
4117
|
+
kind: item.kind,
|
|
4118
|
+
priority: item.priority,
|
|
4119
|
+
enqueuedAt: item.enqueuedAt,
|
|
4120
|
+
preview: createQueuePreview(item.input)
|
|
4121
|
+
}));
|
|
4122
|
+
return {
|
|
4123
|
+
length: items.length,
|
|
4124
|
+
items,
|
|
4125
|
+
isProcessing: this.processingPromise !== null,
|
|
4126
|
+
config: cloneMessageQueueConfig(this.state.messageQueue.config)
|
|
4127
|
+
};
|
|
4128
|
+
}
|
|
4129
|
+
clearQueue(filter = {}) {
|
|
4130
|
+
const before = this.state.messageQueue.items.length;
|
|
4131
|
+
if (!filter.kind) {
|
|
4132
|
+
this.state.messageQueue.items = [];
|
|
4133
|
+
} else {
|
|
4134
|
+
this.state.messageQueue.items = this.state.messageQueue.items.filter((item) => item.kind !== filter.kind);
|
|
4135
|
+
}
|
|
4136
|
+
const cleared = before - this.state.messageQueue.items.length;
|
|
4137
|
+
if (cleared > 0)
|
|
4138
|
+
this.onQueueMutated();
|
|
4139
|
+
return cleared;
|
|
4140
|
+
}
|
|
4141
|
+
async* receive(options = {}) {
|
|
4142
|
+
if (this.receiveActive)
|
|
4143
|
+
throw new SessionExecutionError(createQueueError("DIM_QUEUE_BUSY", "Only one receive() call can be active for a session"));
|
|
4144
|
+
this.receiveActive = true;
|
|
4145
|
+
this.activeReceiveSignal = options.signal;
|
|
4146
|
+
this.haltProcessingUntilReceive = false;
|
|
4147
|
+
let deliveredEvent = null;
|
|
4148
|
+
try {
|
|
4149
|
+
while (true) {
|
|
4150
|
+
if (deliveredEvent) {
|
|
4151
|
+
deliveredEvent.ack();
|
|
4152
|
+
deliveredEvent = null;
|
|
4153
|
+
}
|
|
4154
|
+
this.ensureQueueProcessing("receive");
|
|
4155
|
+
const nextBufferedEvent = this.bufferedEvents.shift();
|
|
4156
|
+
if (nextBufferedEvent) {
|
|
4157
|
+
deliveredEvent = nextBufferedEvent;
|
|
4158
|
+
yield nextBufferedEvent.event;
|
|
4159
|
+
continue;
|
|
4160
|
+
}
|
|
4161
|
+
if (!this.processingPromise && !this.hasRunnableItems())
|
|
4162
|
+
return;
|
|
4163
|
+
await this.waitForStateChange(options.signal);
|
|
4164
|
+
}
|
|
4165
|
+
} finally {
|
|
4166
|
+
if (deliveredEvent)
|
|
4167
|
+
deliveredEvent.ack();
|
|
4168
|
+
this.receiveActive = false;
|
|
4169
|
+
if (this.activeReceiveSignal === options.signal)
|
|
4170
|
+
this.activeReceiveSignal = undefined;
|
|
4171
|
+
this.notifyStateChange();
|
|
4172
|
+
}
|
|
4173
|
+
}
|
|
4064
4174
|
async compact(update) {
|
|
4065
4175
|
const beforeState = this.getCompactionState();
|
|
4066
4176
|
const estimatedInputTokens = await this.readEstimatedInputTokens();
|
|
@@ -4109,6 +4219,9 @@ class Session {
|
|
|
4109
4219
|
});
|
|
4110
4220
|
}
|
|
4111
4221
|
async save() {
|
|
4222
|
+
return this.enqueueSave();
|
|
4223
|
+
}
|
|
4224
|
+
async writeSnapshot() {
|
|
4112
4225
|
if (!this.stateStore)
|
|
4113
4226
|
return;
|
|
4114
4227
|
let snapshot = this.toSnapshot();
|
|
@@ -4143,37 +4256,181 @@ class Session {
|
|
|
4143
4256
|
pluginState: this.listPluginStates(),
|
|
4144
4257
|
createdAt: this.createdAt,
|
|
4145
4258
|
updatedAt: this.updatedAt,
|
|
4146
|
-
metadata: this.state.metadata ? { ...this.state.metadata } : undefined
|
|
4259
|
+
metadata: this.state.metadata ? { ...this.state.metadata } : undefined,
|
|
4260
|
+
messageQueue: cloneMessageQueueSnapshot(this.state.messageQueue)
|
|
4147
4261
|
});
|
|
4148
4262
|
}
|
|
4149
|
-
|
|
4150
|
-
const
|
|
4151
|
-
|
|
4263
|
+
enqueueItem(kind, input, options) {
|
|
4264
|
+
const maxQueueSize = this.state.messageQueue.config.maxQueueSize;
|
|
4265
|
+
if (maxQueueSize !== undefined && this.state.messageQueue.items.length >= maxQueueSize)
|
|
4266
|
+
throw new SessionExecutionError(createQueueError("DIM_QUEUE_FULL", `Session queue is full (max ${maxQueueSize})`));
|
|
4267
|
+
const item = prepareQueueItem(kind, input, options);
|
|
4268
|
+
this.state.messageQueue.items.push(item);
|
|
4269
|
+
this.onQueueMutated();
|
|
4270
|
+
return item.id;
|
|
4271
|
+
}
|
|
4272
|
+
onQueueMutated() {
|
|
4273
|
+
touchRuntimeSessionState(this.state);
|
|
4274
|
+
this.notifyStateChange();
|
|
4275
|
+
this.scheduleSave();
|
|
4276
|
+
this.ensureQueueProcessing("auto");
|
|
4277
|
+
}
|
|
4278
|
+
hasRunnableItems() {
|
|
4279
|
+
return this.state.messageQueue.items.some((item) => item.kind === "user");
|
|
4280
|
+
}
|
|
4281
|
+
ensureQueueProcessing(source) {
|
|
4282
|
+
if (this.processingPromise)
|
|
4283
|
+
return;
|
|
4284
|
+
if (!this.hasRunnableItems())
|
|
4285
|
+
return;
|
|
4286
|
+
if (this.haltProcessingUntilReceive && source !== "receive")
|
|
4287
|
+
return;
|
|
4288
|
+
const signal = source === "receive" ? this.activeReceiveSignal : undefined;
|
|
4289
|
+
this.processingPromise = this.processQueue(signal).finally(() => {
|
|
4290
|
+
this.processingPromise = null;
|
|
4291
|
+
this.notifyStateChange();
|
|
4292
|
+
if (!this.haltProcessingUntilReceive && this.state.messageQueue.config.autoProcessQueue)
|
|
4293
|
+
this.ensureQueueProcessing("auto");
|
|
4294
|
+
});
|
|
4295
|
+
this.notifyStateChange();
|
|
4296
|
+
}
|
|
4297
|
+
async processQueue(signal) {
|
|
4152
4298
|
while (true) {
|
|
4153
|
-
const
|
|
4154
|
-
if (
|
|
4155
|
-
|
|
4156
|
-
|
|
4299
|
+
const nextItem = this.dequeueNextRunnableItem();
|
|
4300
|
+
if (!nextItem)
|
|
4301
|
+
return;
|
|
4302
|
+
const completed = await this.processQueuedItem(nextItem, signal);
|
|
4303
|
+
await this.persistStateQuietly();
|
|
4304
|
+
if (!completed) {
|
|
4305
|
+
this.haltProcessingUntilReceive = true;
|
|
4306
|
+
return;
|
|
4157
4307
|
}
|
|
4158
4308
|
}
|
|
4159
|
-
if (!doneMessage)
|
|
4160
|
-
throw new Error("Session completed without a final assistant message");
|
|
4161
|
-
return doneMessage;
|
|
4162
4309
|
}
|
|
4163
|
-
|
|
4310
|
+
dequeueNextRunnableItem() {
|
|
4311
|
+
const rankedItems = [...this.state.messageQueue.items].sort(compareQueueItems);
|
|
4312
|
+
const userIndex = rankedItems.findIndex((item) => item.kind === "user");
|
|
4313
|
+
if (userIndex < 0)
|
|
4314
|
+
return null;
|
|
4315
|
+
const userItem = rankedItems[userIndex];
|
|
4316
|
+
const steerItems = rankedItems.slice(0, userIndex).filter((item) => item.kind === "steer");
|
|
4317
|
+
const consumedIds = new Set([userItem.id, ...steerItems.map((item) => item.id)]);
|
|
4318
|
+
this.state.messageQueue.items = this.state.messageQueue.items.filter((item) => !consumedIds.has(item.id));
|
|
4319
|
+
touchRuntimeSessionState(this.state);
|
|
4320
|
+
this.notifyStateChange();
|
|
4321
|
+
return {
|
|
4322
|
+
item: userItem,
|
|
4323
|
+
steerSegments: steerItems.map((item) => contentToText(normalizeContent(item.input)).trim()).filter((segment) => segment.length > 0)
|
|
4324
|
+
};
|
|
4325
|
+
}
|
|
4326
|
+
async processQueuedItem(input, signal) {
|
|
4164
4327
|
const runner = this.createLoopRunner();
|
|
4328
|
+
let emittedError = false;
|
|
4165
4329
|
this.activeRunCount += 1;
|
|
4166
4330
|
try {
|
|
4167
|
-
|
|
4168
|
-
signal
|
|
4169
|
-
|
|
4170
|
-
await this.save();
|
|
4171
|
-
}
|
|
4331
|
+
const iterator = runner.run(this.state, input.item.input, {
|
|
4332
|
+
signal,
|
|
4333
|
+
persistentPromptSegments: input.steerSegments
|
|
4172
4334
|
});
|
|
4335
|
+
while (true) {
|
|
4336
|
+
const next = await iterator.next();
|
|
4337
|
+
if (next.done)
|
|
4338
|
+
return true;
|
|
4339
|
+
const queuedEvent = this.attachQueueContext(next.value, input.item);
|
|
4340
|
+
if (queuedEvent.type === "error")
|
|
4341
|
+
emittedError = true;
|
|
4342
|
+
await this.pushBufferedEvent(queuedEvent);
|
|
4343
|
+
}
|
|
4344
|
+
} catch (error) {
|
|
4345
|
+
if (!emittedError)
|
|
4346
|
+
await this.pushBufferedEvent(this.createErrorEvent(input.item, error));
|
|
4347
|
+
return false;
|
|
4173
4348
|
} finally {
|
|
4174
4349
|
this.activeRunCount = Math.max(0, this.activeRunCount - 1);
|
|
4350
|
+
this.notifyStateChange();
|
|
4175
4351
|
}
|
|
4176
4352
|
}
|
|
4353
|
+
attachQueueContext(event, item) {
|
|
4354
|
+
return {
|
|
4355
|
+
...event,
|
|
4356
|
+
itemId: item.id,
|
|
4357
|
+
itemKind: item.kind,
|
|
4358
|
+
priority: item.priority
|
|
4359
|
+
};
|
|
4360
|
+
}
|
|
4361
|
+
createErrorEvent(item, error) {
|
|
4362
|
+
const payload = error instanceof SessionExecutionError ? error.payload : {
|
|
4363
|
+
code: "runtime_error",
|
|
4364
|
+
message: error instanceof Error ? error.message : String(error)
|
|
4365
|
+
};
|
|
4366
|
+
return {
|
|
4367
|
+
type: "error",
|
|
4368
|
+
sessionId: this.id,
|
|
4369
|
+
error: payload,
|
|
4370
|
+
itemId: item.id,
|
|
4371
|
+
itemKind: item.kind,
|
|
4372
|
+
priority: item.priority
|
|
4373
|
+
};
|
|
4374
|
+
}
|
|
4375
|
+
async pushBufferedEvent(event) {
|
|
4376
|
+
let resolved = false;
|
|
4377
|
+
const ack = () => {
|
|
4378
|
+
if (resolved)
|
|
4379
|
+
return;
|
|
4380
|
+
resolved = true;
|
|
4381
|
+
this.notifyStateChange();
|
|
4382
|
+
};
|
|
4383
|
+
this.bufferedEvents.push({ event, ack });
|
|
4384
|
+
this.notifyStateChange();
|
|
4385
|
+
while (!resolved)
|
|
4386
|
+
await this.waitForStateChange();
|
|
4387
|
+
}
|
|
4388
|
+
scheduleSave() {
|
|
4389
|
+
if (!this.stateStore)
|
|
4390
|
+
return;
|
|
4391
|
+
this.enqueueSave().catch(() => {
|
|
4392
|
+
return;
|
|
4393
|
+
});
|
|
4394
|
+
}
|
|
4395
|
+
async persistStateQuietly() {
|
|
4396
|
+
try {
|
|
4397
|
+
await this.enqueueSave();
|
|
4398
|
+
} catch {}
|
|
4399
|
+
}
|
|
4400
|
+
enqueueSave() {
|
|
4401
|
+
if (!this.stateStore)
|
|
4402
|
+
return Promise.resolve();
|
|
4403
|
+
this.saveChain = this.saveChain.catch(() => {
|
|
4404
|
+
return;
|
|
4405
|
+
}).then(() => this.writeSnapshot());
|
|
4406
|
+
return this.saveChain;
|
|
4407
|
+
}
|
|
4408
|
+
waitForStateChange(signal) {
|
|
4409
|
+
if (signal?.aborted)
|
|
4410
|
+
return Promise.reject(new SessionExecutionError(createQueueError("session_receive_aborted", "Session receive aborted")));
|
|
4411
|
+
return new Promise((resolve, reject) => {
|
|
4412
|
+
const onAbort = () => {
|
|
4413
|
+
cleanup();
|
|
4414
|
+
reject(new SessionExecutionError(createQueueError("session_receive_aborted", "Session receive aborted")));
|
|
4415
|
+
};
|
|
4416
|
+
const resume = () => {
|
|
4417
|
+
cleanup();
|
|
4418
|
+
resolve();
|
|
4419
|
+
};
|
|
4420
|
+
const cleanup = () => {
|
|
4421
|
+
const index = this.stateChangeWaiters.indexOf(resume);
|
|
4422
|
+
if (index >= 0)
|
|
4423
|
+
this.stateChangeWaiters.splice(index, 1);
|
|
4424
|
+
signal?.removeEventListener("abort", onAbort);
|
|
4425
|
+
};
|
|
4426
|
+
this.stateChangeWaiters.push(resume);
|
|
4427
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
4428
|
+
});
|
|
4429
|
+
}
|
|
4430
|
+
notifyStateChange() {
|
|
4431
|
+
while (this.stateChangeWaiters.length > 0)
|
|
4432
|
+
this.stateChangeWaiters.shift()?.();
|
|
4433
|
+
}
|
|
4177
4434
|
createLoopRunner() {
|
|
4178
4435
|
return new LoopRunner({
|
|
4179
4436
|
messageFactory: new DefaultMessageFactory,
|
|
@@ -4221,6 +4478,63 @@ class Session {
|
|
|
4221
4478
|
};
|
|
4222
4479
|
}
|
|
4223
4480
|
}
|
|
4481
|
+
function createMessageQueueConfig(overrides, base = DEFAULT_MESSAGE_QUEUE_CONFIG) {
|
|
4482
|
+
return {
|
|
4483
|
+
autoProcessQueue: overrides?.autoProcessQueue ?? base.autoProcessQueue,
|
|
4484
|
+
maxQueueSize: overrides?.maxQueueSize ?? base.maxQueueSize
|
|
4485
|
+
};
|
|
4486
|
+
}
|
|
4487
|
+
function cloneMessageQueueConfig(config) {
|
|
4488
|
+
return {
|
|
4489
|
+
autoProcessQueue: config.autoProcessQueue,
|
|
4490
|
+
maxQueueSize: config.maxQueueSize
|
|
4491
|
+
};
|
|
4492
|
+
}
|
|
4493
|
+
function clonePendingMessage(item) {
|
|
4494
|
+
return {
|
|
4495
|
+
id: item.id,
|
|
4496
|
+
input: structuredClone(item.input),
|
|
4497
|
+
kind: item.kind,
|
|
4498
|
+
priority: item.priority,
|
|
4499
|
+
enqueuedAt: item.enqueuedAt
|
|
4500
|
+
};
|
|
4501
|
+
}
|
|
4502
|
+
function cloneMessageQueueSnapshot(snapshot) {
|
|
4503
|
+
return {
|
|
4504
|
+
items: snapshot.items.map(clonePendingMessage),
|
|
4505
|
+
config: cloneMessageQueueConfig(snapshot.config)
|
|
4506
|
+
};
|
|
4507
|
+
}
|
|
4508
|
+
function prepareQueueItem(kind, input, options = {}) {
|
|
4509
|
+
const normalizedInput = normalizeContent(input);
|
|
4510
|
+
if (kind === "steer" && contentToText(normalizedInput).trim().length === 0)
|
|
4511
|
+
throw new TypeError("Steer content must contain text");
|
|
4512
|
+
return {
|
|
4513
|
+
id: createId("item"),
|
|
4514
|
+
input: structuredClone(input),
|
|
4515
|
+
kind,
|
|
4516
|
+
priority: options.priority ?? 0,
|
|
4517
|
+
enqueuedAt: Date.now()
|
|
4518
|
+
};
|
|
4519
|
+
}
|
|
4520
|
+
function compareQueueItems(left, right) {
|
|
4521
|
+
if (left.priority !== right.priority)
|
|
4522
|
+
return right.priority - left.priority;
|
|
4523
|
+
if (left.enqueuedAt !== right.enqueuedAt)
|
|
4524
|
+
return left.enqueuedAt - right.enqueuedAt;
|
|
4525
|
+
return left.id.localeCompare(right.id);
|
|
4526
|
+
}
|
|
4527
|
+
function createQueuePreview(input) {
|
|
4528
|
+
const text = contentToText(normalizeContent(input)).trim();
|
|
4529
|
+
if (text.length === 0)
|
|
4530
|
+
return "[non-text content]";
|
|
4531
|
+
if (text.length <= 80)
|
|
4532
|
+
return text;
|
|
4533
|
+
return `${text.slice(0, 77)}...`;
|
|
4534
|
+
}
|
|
4535
|
+
function createQueueError(code, message) {
|
|
4536
|
+
return { code, message };
|
|
4537
|
+
}
|
|
4224
4538
|
|
|
4225
4539
|
// src/agent-core/agent.ts
|
|
4226
4540
|
class Agent {
|
|
@@ -4292,6 +4606,7 @@ class Agent {
|
|
|
4292
4606
|
metadata: options.metadata ?? this.options.metadata,
|
|
4293
4607
|
reasoning: this.options.reasoning,
|
|
4294
4608
|
compactionOptions: this.options.compaction,
|
|
4609
|
+
messageQueueConfig: options.messageQueueConfig,
|
|
4295
4610
|
messages,
|
|
4296
4611
|
pluginHost: this.pluginHost,
|
|
4297
4612
|
contextManager: this.contextManager,
|
|
@@ -4325,6 +4640,7 @@ class Agent {
|
|
|
4325
4640
|
usage: snapshot.usage,
|
|
4326
4641
|
compaction: snapshot.compaction,
|
|
4327
4642
|
pluginState: snapshot.pluginState,
|
|
4643
|
+
messageQueue: snapshot.messageQueue,
|
|
4328
4644
|
compactionOptions: this.options.compaction,
|
|
4329
4645
|
createdAt: snapshot.createdAt,
|
|
4330
4646
|
updatedAt: snapshot.updatedAt,
|
package/package.json
CHANGED