@nextclaw/ncp-toolkit 0.4.9 → 0.4.10

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +42 -34
  2. package/dist/index.js +160 -141
  3. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -8,32 +8,33 @@ declare class DefaultNcpAgentConversationStateManager implements NcpAgentConvers
8
8
  private readonly listeners;
9
9
  private readonly toolCallMessageIdByCallId;
10
10
  private readonly toolCallArgsRawByCallId;
11
+ private lastSettledRunId;
11
12
  private snapshotCache;
12
13
  private snapshotVersion;
13
14
  private stateVersion;
14
- getSnapshot(): NcpAgentConversationSnapshot;
15
- subscribe(listener: (snapshot: NcpAgentConversationSnapshot) => void): () => boolean;
16
- reset(): void;
17
- hydrate(payload: NcpAgentConversationHydrationParams): void;
18
- dispatch(event: NcpEndpointEvent): Promise<void>;
19
- handleMessageSent(payload: NcpMessageSentPayload): void;
20
- handleMessageAbort(payload: NcpMessageAbortPayload): void;
21
- handleMessageTextStart(payload: NcpTextStartPayload): void;
22
- handleMessageTextDelta(payload: NcpTextDeltaPayload): void;
23
- handleMessageTextEnd(payload: NcpTextEndPayload): void;
24
- handleMessageReasoningStart(payload: NcpReasoningStartPayload): void;
25
- handleMessageReasoningDelta(payload: NcpReasoningDeltaPayload): void;
26
- handleMessageReasoningEnd(payload: NcpReasoningEndPayload): void;
27
- handleMessageToolCallStart(payload: NcpToolCallStartPayload): void;
28
- handleMessageToolCallArgs(payload: NcpToolCallArgsPayload): void;
29
- handleMessageToolCallArgsDelta(payload: NcpToolCallArgsDeltaPayload): void;
30
- handleMessageToolCallEnd(payload: NcpToolCallEndPayload): void;
31
- handleMessageToolCallResult(payload: NcpToolCallResultPayload): void;
32
- handleRunStarted(payload: NcpRunStartedPayload): void;
33
- handleRunFinished(_payload: NcpRunFinishedPayload): void;
34
- handleRunError(payload: NcpRunErrorPayload): void;
35
- handleRunMetadata(payload: NcpRunMetadataPayload): void;
36
- handleEndpointError(payload: NcpError): void;
15
+ getSnapshot: () => NcpAgentConversationSnapshot;
16
+ subscribe: (listener: (snapshot: NcpAgentConversationSnapshot) => void) => () => boolean;
17
+ reset: () => void;
18
+ hydrate: (payload: NcpAgentConversationHydrationParams) => void;
19
+ dispatch: (event: NcpEndpointEvent) => Promise<void>;
20
+ handleMessageSent: (payload: NcpMessageSentPayload) => void;
21
+ handleMessageAbort: (payload: NcpMessageAbortPayload) => void;
22
+ handleMessageTextStart: (payload: NcpTextStartPayload) => void;
23
+ handleMessageTextDelta: (payload: NcpTextDeltaPayload) => void;
24
+ handleMessageTextEnd: (payload: NcpTextEndPayload) => void;
25
+ handleMessageReasoningStart: (payload: NcpReasoningStartPayload) => void;
26
+ handleMessageReasoningDelta: (payload: NcpReasoningDeltaPayload) => void;
27
+ handleMessageReasoningEnd: (payload: NcpReasoningEndPayload) => void;
28
+ handleMessageToolCallStart: (payload: NcpToolCallStartPayload) => void;
29
+ handleMessageToolCallArgs: (payload: NcpToolCallArgsPayload) => void;
30
+ handleMessageToolCallArgsDelta: (payload: NcpToolCallArgsDeltaPayload) => void;
31
+ handleMessageToolCallEnd: (payload: NcpToolCallEndPayload) => void;
32
+ handleMessageToolCallResult: (payload: NcpToolCallResultPayload) => void;
33
+ handleRunStarted: (payload: NcpRunStartedPayload) => void;
34
+ handleRunFinished: (payload: NcpRunFinishedPayload) => void;
35
+ handleRunError: (payload: NcpRunErrorPayload) => void;
36
+ handleRunMetadata: (payload: NcpRunMetadataPayload) => void;
37
+ handleEndpointError: (payload: NcpError) => void;
37
38
  private applyToolCallArgs;
38
39
  private ensureStreamingMessage;
39
40
  private resolveToolCallTargetMessage;
@@ -42,6 +43,8 @@ declare class DefaultNcpAgentConversationStateManager implements NcpAgentConvers
42
43
  private replaceStreamingMessage;
43
44
  private setError;
44
45
  private clearActiveRun;
46
+ private isSettledRunId;
47
+ private markRunAsSettled;
45
48
  private settleStreamingMessage;
46
49
  private notifyListeners;
47
50
  }
@@ -99,6 +102,10 @@ interface AgentSessionStore {
99
102
  type DefaultNcpAgentBackendConfig = {
100
103
  createRuntime: CreateRuntimeFn;
101
104
  sessionStore: AgentSessionStore;
105
+ onSessionRunStatusChanged?: (payload: {
106
+ sessionKey: string;
107
+ status: "running" | "idle";
108
+ }) => void;
102
109
  endpointId?: string;
103
110
  version?: string;
104
111
  metadata?: Record<string, unknown>;
@@ -110,28 +117,29 @@ declare class DefaultNcpAgentBackend implements NcpAgentServerEndpoint, NcpSessi
110
117
  endpointKind: "agent";
111
118
  };
112
119
  private readonly sessionStore;
120
+ private readonly onSessionRunStatusChanged;
113
121
  private readonly sessionRegistry;
114
122
  private readonly executor;
115
123
  private readonly publisher;
116
124
  private started;
117
125
  constructor(config: DefaultNcpAgentBackendConfig);
118
- start(): Promise<void>;
119
- stop(): Promise<void>;
120
- emit(event: NcpEndpointEvent): Promise<void>;
121
- subscribe(listener: (event: NcpEndpointEvent) => void): () => void;
122
- send(envelope: NcpRequestEnvelope, options?: NcpAgentRunSendOptions): AsyncIterable<NcpEndpointEvent>;
123
- abort(payload: NcpMessageAbortPayload): Promise<void>;
126
+ start: () => Promise<void>;
127
+ stop: () => Promise<void>;
128
+ emit: (event: NcpEndpointEvent) => Promise<void>;
129
+ subscribe: (listener: (event: NcpEndpointEvent) => void) => () => void;
130
+ send: (envelope: NcpRequestEnvelope, options?: NcpAgentRunSendOptions) => AsyncIterable<NcpEndpointEvent>;
131
+ abort: (payload: NcpMessageAbortPayload) => Promise<void>;
124
132
  stream: (payloadOrParams: NcpStreamRequestPayload | {
125
133
  payload: NcpStreamRequestPayload;
126
134
  signal: AbortSignal;
127
135
  }, opts?: NcpAgentRunStreamOptions) => AsyncIterable<NcpEndpointEvent>;
128
- listSessions(): Promise<NcpSessionSummary[]>;
129
- listSessionMessages(sessionId: string): Promise<NcpMessage[]>;
130
- getSession(sessionId: string): Promise<NcpSessionSummary | null>;
136
+ listSessions: () => Promise<NcpSessionSummary[]>;
137
+ listSessionMessages: (sessionId: string) => Promise<NcpMessage[]>;
138
+ getSession: (sessionId: string) => Promise<NcpSessionSummary | null>;
131
139
  appendMessage: (sessionId: string, message: NcpMessage) => Promise<NcpSessionSummary | null>;
132
140
  updateToolCallResult: (sessionId: string, toolCallId: string, content: unknown) => Promise<NcpSessionSummary | null>;
133
- updateSession(sessionId: string, patch: NcpSessionPatch): Promise<NcpSessionSummary | null>;
134
- deleteSession(sessionId: string): Promise<void>;
141
+ updateSession: (sessionId: string, patch: NcpSessionPatch) => Promise<NcpSessionSummary | null>;
142
+ deleteSession: (sessionId: string) => Promise<void>;
135
143
  private ensureStarted;
136
144
  private startSessionExecution;
137
145
  private finishSessionExecution;
package/dist/index.js CHANGED
@@ -95,10 +95,11 @@ var DefaultNcpAgentConversationStateManager = class {
95
95
  listeners = /* @__PURE__ */ new Set();
96
96
  toolCallMessageIdByCallId = /* @__PURE__ */ new Map();
97
97
  toolCallArgsRawByCallId = /* @__PURE__ */ new Map();
98
+ lastSettledRunId = null;
98
99
  snapshotCache = null;
99
100
  snapshotVersion = -1;
100
101
  stateVersion = 0;
101
- getSnapshot() {
102
+ getSnapshot = () => {
102
103
  if (this.snapshotCache && this.snapshotVersion === this.stateVersion) {
103
104
  return this.snapshotCache;
104
105
  }
@@ -114,12 +115,12 @@ var DefaultNcpAgentConversationStateManager = class {
114
115
  this.snapshotCache = snapshot;
115
116
  this.snapshotVersion = this.stateVersion;
116
117
  return snapshot;
117
- }
118
- subscribe(listener) {
118
+ };
119
+ subscribe = (listener) => {
119
120
  this.listeners.add(listener);
120
121
  return () => this.listeners.delete(listener);
121
- }
122
- reset() {
122
+ };
123
+ reset = () => {
123
124
  if (this.messages.length === 0 && !this.streamingMessage && !this.error && !this.activeRun && this.toolCallMessageIdByCallId.size === 0 && this.toolCallArgsRawByCallId.size === 0) {
124
125
  return;
125
126
  }
@@ -129,10 +130,11 @@ var DefaultNcpAgentConversationStateManager = class {
129
130
  this.activeRun = null;
130
131
  this.toolCallMessageIdByCallId.clear();
131
132
  this.toolCallArgsRawByCallId.clear();
133
+ this.lastSettledRunId = null;
132
134
  this.stateVersion += 1;
133
135
  this.notifyListeners();
134
- }
135
- hydrate(payload) {
136
+ };
137
+ hydrate = (payload) => {
136
138
  this.messages = payload.messages.map(
137
139
  (message) => normalizeConversationMessage(message)
138
140
  );
@@ -145,10 +147,11 @@ var DefaultNcpAgentConversationStateManager = class {
145
147
  } : null;
146
148
  this.toolCallMessageIdByCallId.clear();
147
149
  this.toolCallArgsRawByCallId.clear();
150
+ this.lastSettledRunId = null;
148
151
  this.stateVersion += 1;
149
152
  this.notifyListeners();
150
- }
151
- async dispatch(event) {
153
+ };
154
+ dispatch = async (event) => {
152
155
  const versionBeforeDispatch = this.stateVersion;
153
156
  switch (event.type) {
154
157
  case NcpEventType.MessageSent:
@@ -211,12 +214,12 @@ var DefaultNcpAgentConversationStateManager = class {
211
214
  if (this.stateVersion !== versionBeforeDispatch) {
212
215
  this.notifyListeners();
213
216
  }
214
- }
215
- handleMessageSent(payload) {
217
+ };
218
+ handleMessageSent = (payload) => {
216
219
  this.upsertMessage(payload.message);
217
220
  this.setError(null);
218
- }
219
- handleMessageAbort(payload) {
221
+ };
222
+ handleMessageAbort = (payload) => {
220
223
  const targetMessageId = payload.messageId?.trim();
221
224
  this.clearActiveRun();
222
225
  this.setError(null);
@@ -241,16 +244,16 @@ var DefaultNcpAgentConversationStateManager = class {
241
244
  );
242
245
  }
243
246
  }
244
- }
245
- handleMessageTextStart(payload) {
247
+ };
248
+ handleMessageTextStart = (payload) => {
246
249
  this.ensureStreamingMessage(
247
250
  payload.sessionId,
248
251
  payload.messageId,
249
252
  "streaming"
250
253
  );
251
254
  this.setError(null);
252
- }
253
- handleMessageTextDelta(payload) {
255
+ };
256
+ handleMessageTextDelta = (payload) => {
254
257
  if (!payload.delta) {
255
258
  return;
256
259
  }
@@ -274,8 +277,8 @@ var DefaultNcpAgentConversationStateManager = class {
274
277
  parts: nextParts,
275
278
  status: "streaming"
276
279
  });
277
- }
278
- handleMessageTextEnd(payload) {
280
+ };
281
+ handleMessageTextEnd = (payload) => {
279
282
  if (this.streamingMessage?.id !== payload.messageId) {
280
283
  return;
281
284
  }
@@ -286,15 +289,15 @@ var DefaultNcpAgentConversationStateManager = class {
286
289
  ...this.streamingMessage,
287
290
  status: "pending"
288
291
  });
289
- }
290
- handleMessageReasoningStart(payload) {
292
+ };
293
+ handleMessageReasoningStart = (payload) => {
291
294
  this.ensureStreamingMessage(
292
295
  payload.sessionId,
293
296
  payload.messageId,
294
297
  "streaming"
295
298
  );
296
- }
297
- handleMessageReasoningDelta(payload) {
299
+ };
300
+ handleMessageReasoningDelta = (payload) => {
298
301
  if (!payload.delta) {
299
302
  return;
300
303
  }
@@ -318,13 +321,13 @@ var DefaultNcpAgentConversationStateManager = class {
318
321
  parts: nextParts,
319
322
  status: "streaming"
320
323
  });
321
- }
322
- handleMessageReasoningEnd(payload) {
324
+ };
325
+ handleMessageReasoningEnd = (payload) => {
323
326
  if (this.streamingMessage?.id !== payload.messageId) {
324
327
  return;
325
328
  }
326
- }
327
- handleMessageToolCallStart(payload) {
329
+ };
330
+ handleMessageToolCallStart = (payload) => {
328
331
  const targetMessage = this.resolveToolCallTargetMessage(
329
332
  payload.sessionId,
330
333
  payload.toolCallId,
@@ -344,12 +347,12 @@ var DefaultNcpAgentConversationStateManager = class {
344
347
  status: "streaming"
345
348
  });
346
349
  this.setError(null);
347
- }
348
- handleMessageToolCallArgs(payload) {
350
+ };
351
+ handleMessageToolCallArgs = (payload) => {
349
352
  this.toolCallArgsRawByCallId.set(payload.toolCallId, payload.args);
350
353
  this.applyToolCallArgs(payload.sessionId, payload.toolCallId, payload.args);
351
- }
352
- handleMessageToolCallArgsDelta(payload) {
354
+ };
355
+ handleMessageToolCallArgsDelta = (payload) => {
353
356
  const currentArgs = this.toolCallArgsRawByCallId.get(payload.toolCallId) ?? "";
354
357
  const nextArgs = `${currentArgs}${payload.delta}`;
355
358
  this.toolCallArgsRawByCallId.set(payload.toolCallId, nextArgs);
@@ -359,8 +362,8 @@ var DefaultNcpAgentConversationStateManager = class {
359
362
  nextArgs,
360
363
  payload.messageId
361
364
  );
362
- }
363
- handleMessageToolCallEnd(payload) {
365
+ };
366
+ handleMessageToolCallEnd = (payload) => {
364
367
  const targetMessage = this.resolveToolCallTargetMessage(
365
368
  payload.sessionId,
366
369
  payload.toolCallId
@@ -378,8 +381,8 @@ var DefaultNcpAgentConversationStateManager = class {
378
381
  parts: nextParts,
379
382
  status: "streaming"
380
383
  });
381
- }
382
- handleMessageToolCallResult(payload) {
384
+ };
385
+ handleMessageToolCallResult = (payload) => {
383
386
  const updated = this.updateMessageContainingToolCall(
384
387
  payload.toolCallId,
385
388
  (targetMessage, existingPart) => {
@@ -412,29 +415,30 @@ var DefaultNcpAgentConversationStateManager = class {
412
415
  status: "streaming"
413
416
  });
414
417
  }
415
- }
416
- handleRunStarted(payload) {
418
+ };
419
+ handleRunStarted = (payload) => {
420
+ if (this.isSettledRunId(payload.runId)) return;
417
421
  this.setError(null);
418
- this.activeRun = {
419
- runId: payload.runId ?? null,
420
- sessionId: payload.sessionId
421
- };
422
+ this.activeRun = { runId: payload.runId ?? null, sessionId: payload.sessionId };
422
423
  this.stateVersion += 1;
423
- }
424
- handleRunFinished(_payload) {
424
+ };
425
+ handleRunFinished = (payload) => {
426
+ this.markRunAsSettled(payload.runId ?? this.activeRun?.runId ?? null);
425
427
  this.settleStreamingMessage("final");
426
428
  this.setError(null);
427
429
  this.clearActiveRun();
428
- }
429
- handleRunError(payload) {
430
+ };
431
+ handleRunError = (payload) => {
432
+ this.markRunAsSettled(payload.runId ?? this.activeRun?.runId ?? null);
430
433
  this.settleStreamingMessage("error");
431
434
  this.setError(buildRuntimeError(payload));
432
435
  this.clearActiveRun();
433
- }
434
- handleRunMetadata(payload) {
436
+ };
437
+ handleRunMetadata = (payload) => {
435
438
  const m = payload.metadata;
436
439
  if (m?.kind === "ready") {
437
440
  const ready = m;
441
+ if (this.isSettledRunId(ready.runId)) return;
438
442
  this.activeRun = {
439
443
  runId: ready.runId ?? this.activeRun?.runId ?? null,
440
444
  sessionId: ready.sessionId ?? this.activeRun?.sessionId,
@@ -442,10 +446,11 @@ var DefaultNcpAgentConversationStateManager = class {
442
446
  };
443
447
  this.stateVersion += 1;
444
448
  } else if (m?.kind === "final") {
449
+ this.markRunAsSettled(payload.runId ?? this.activeRun?.runId ?? null);
445
450
  this.clearActiveRun();
446
451
  }
447
- }
448
- handleEndpointError(payload) {
452
+ };
453
+ handleEndpointError = (payload) => {
449
454
  if (payload.code === "abort-error") {
450
455
  this.handleMessageAbort({
451
456
  sessionId: this.activeRun?.sessionId ?? this.streamingMessage?.sessionId ?? "",
@@ -456,8 +461,8 @@ var DefaultNcpAgentConversationStateManager = class {
456
461
  this.settleStreamingMessage("error");
457
462
  this.clearActiveRun();
458
463
  this.setError(payload);
459
- }
460
- applyToolCallArgs(sessionId, toolCallId, args, messageId) {
464
+ };
465
+ applyToolCallArgs = (sessionId, toolCallId, args, messageId) => {
461
466
  const targetMessage = this.resolveToolCallTargetMessage(
462
467
  sessionId,
463
468
  toolCallId,
@@ -476,8 +481,8 @@ var DefaultNcpAgentConversationStateManager = class {
476
481
  parts: nextParts,
477
482
  status: "streaming"
478
483
  });
479
- }
480
- ensureStreamingMessage(sessionId, messageId, status) {
484
+ };
485
+ ensureStreamingMessage = (sessionId, messageId, status) => {
481
486
  if (this.streamingMessage?.id === messageId) {
482
487
  if (this.streamingMessage.status === status) {
483
488
  return this.streamingMessage;
@@ -534,8 +539,8 @@ var DefaultNcpAgentConversationStateManager = class {
534
539
  };
535
540
  this.replaceStreamingMessage(nextStreamingMessage);
536
541
  return nextStreamingMessage;
537
- }
538
- resolveToolCallTargetMessage(sessionId, toolCallId, messageId) {
542
+ };
543
+ resolveToolCallTargetMessage = (sessionId, toolCallId, messageId) => {
539
544
  const preferredMessageId = messageId?.trim() || this.toolCallMessageIdByCallId.get(toolCallId) || this.streamingMessage?.id || `tool-${toolCallId}`;
540
545
  this.toolCallMessageIdByCallId.set(toolCallId, preferredMessageId);
541
546
  return this.ensureStreamingMessage(
@@ -543,8 +548,8 @@ var DefaultNcpAgentConversationStateManager = class {
543
548
  preferredMessageId,
544
549
  "streaming"
545
550
  );
546
- }
547
- updateMessageContainingToolCall(toolCallId, updater) {
551
+ };
552
+ updateMessageContainingToolCall = (toolCallId, updater) => {
548
553
  if (this.streamingMessage) {
549
554
  const part = findToolInvocationPart(
550
555
  this.streamingMessage.parts,
@@ -575,8 +580,8 @@ var DefaultNcpAgentConversationStateManager = class {
575
580
  return true;
576
581
  }
577
582
  return false;
578
- }
579
- upsertMessage(message) {
583
+ };
584
+ upsertMessage = (message) => {
580
585
  const normalizedMessage = normalizeConversationMessage(message);
581
586
  const messageIndex = this.messages.findIndex(
582
587
  (item) => item.id === normalizedMessage.id
@@ -590,15 +595,15 @@ var DefaultNcpAgentConversationStateManager = class {
590
595
  nextMessages[messageIndex] = normalizedMessage;
591
596
  this.messages = nextMessages;
592
597
  this.stateVersion += 1;
593
- }
594
- replaceStreamingMessage(nextStreamingMessage) {
598
+ };
599
+ replaceStreamingMessage = (nextStreamingMessage) => {
595
600
  if (!nextStreamingMessage && !this.streamingMessage) {
596
601
  return;
597
602
  }
598
603
  this.streamingMessage = nextStreamingMessage ? normalizeConversationMessage(nextStreamingMessage) : null;
599
604
  this.stateVersion += 1;
600
- }
601
- setError(nextError) {
605
+ };
606
+ setError = (nextError) => {
602
607
  const hasSameError = this.error?.code === nextError?.code && this.error?.message === nextError?.message && this.error?.details === nextError?.details && this.error?.cause === nextError?.cause;
603
608
  if (hasSameError) {
604
609
  return;
@@ -608,15 +613,19 @@ var DefaultNcpAgentConversationStateManager = class {
608
613
  details: nextError.details ? { ...nextError.details } : void 0
609
614
  } : null;
610
615
  this.stateVersion += 1;
611
- }
612
- clearActiveRun() {
613
- if (!this.activeRun) {
614
- return;
615
- }
616
+ };
617
+ clearActiveRun = () => {
618
+ if (!this.activeRun) return;
616
619
  this.activeRun = null;
617
620
  this.stateVersion += 1;
618
- }
619
- settleStreamingMessage(status) {
621
+ };
622
+ isSettledRunId = (runId) => {
623
+ return Boolean(runId?.trim()) && runId === this.lastSettledRunId;
624
+ };
625
+ markRunAsSettled = (runId) => {
626
+ this.lastSettledRunId = runId?.trim() || null;
627
+ };
628
+ settleStreamingMessage = (status) => {
620
629
  if (!this.streamingMessage) {
621
630
  return;
622
631
  }
@@ -631,13 +640,11 @@ var DefaultNcpAgentConversationStateManager = class {
631
640
  this.toolCallArgsRawByCallId,
632
641
  settledMessage.id
633
642
  );
634
- }
635
- notifyListeners() {
643
+ };
644
+ notifyListeners = () => {
636
645
  const snapshot = this.getSnapshot();
637
- for (const listener of this.listeners) {
638
- listener(snapshot);
639
- }
640
- }
646
+ for (const listener of this.listeners) listener(snapshot);
647
+ };
641
648
  };
642
649
 
643
650
  // src/agent/agent-client-from-server.ts
@@ -1127,16 +1134,15 @@ var DEFAULT_SUPPORTED_PART_TYPES = ["text", "file", "source", "step-start", "rea
1127
1134
  var DefaultNcpAgentBackend = class {
1128
1135
  manifest;
1129
1136
  sessionStore;
1137
+ onSessionRunStatusChanged;
1130
1138
  sessionRegistry;
1131
1139
  executor;
1132
1140
  publisher;
1133
1141
  started = false;
1134
1142
  constructor(config) {
1135
1143
  this.sessionStore = config.sessionStore;
1136
- this.sessionRegistry = new AgentLiveSessionRegistry(
1137
- this.sessionStore,
1138
- config.createRuntime
1139
- );
1144
+ this.onSessionRunStatusChanged = config.onSessionRunStatusChanged;
1145
+ this.sessionRegistry = new AgentLiveSessionRegistry(this.sessionStore, config.createRuntime);
1140
1146
  this.executor = new AgentRunExecutor(async (sessionId) => this.persistSession(sessionId));
1141
1147
  this.publisher = new EventPublisher();
1142
1148
  this.manifest = {
@@ -1152,14 +1158,14 @@ var DefaultNcpAgentBackend = class {
1152
1158
  metadata: config.metadata
1153
1159
  };
1154
1160
  }
1155
- async start() {
1161
+ start = async () => {
1156
1162
  if (this.started) {
1157
1163
  return;
1158
1164
  }
1159
1165
  this.started = true;
1160
1166
  this.publisher.publish({ type: NcpEventType8.EndpointReady });
1161
- }
1162
- async stop() {
1167
+ };
1168
+ stop = async () => {
1163
1169
  if (!this.started) {
1164
1170
  return;
1165
1171
  }
@@ -1174,8 +1180,8 @@ var DefaultNcpAgentBackend = class {
1174
1180
  this.finishSessionExecution(session, execution);
1175
1181
  }
1176
1182
  this.sessionRegistry.clear();
1177
- }
1178
- async emit(event) {
1183
+ };
1184
+ emit = async (event) => {
1179
1185
  await this.ensureStarted();
1180
1186
  switch (event.type) {
1181
1187
  case NcpEventType8.MessageRequest:
@@ -1190,41 +1196,52 @@ var DefaultNcpAgentBackend = class {
1190
1196
  default:
1191
1197
  this.publisher.publish(event);
1192
1198
  }
1193
- }
1194
- subscribe(listener) {
1199
+ };
1200
+ subscribe = (listener) => {
1195
1201
  return this.publisher.subscribe(listener);
1196
- }
1197
- async *send(envelope, options) {
1198
- await this.ensureStarted();
1199
- const session = await this.sessionRegistry.ensureSession(
1200
- envelope.sessionId,
1201
- envelope.metadata
1202
- );
1203
- const execution = this.startSessionExecution(session, envelope, options?.signal);
1204
- try {
1205
- for await (const event of this.executor.executeRun(session, envelope, execution.controller)) {
1206
- this.publishLiveEvent(execution, event);
1207
- yield event;
1208
- }
1209
- if (execution.controller.signal.aborted && !execution.abortHandled) {
1210
- const abortEvent = await this.createAbortEvent(session.sessionId);
1211
- execution.abortHandled = true;
1212
- this.publishLiveEvent(execution, abortEvent);
1213
- yield abortEvent;
1202
+ };
1203
+ send = (envelope, options) => {
1204
+ return (async function* (self) {
1205
+ await self.ensureStarted();
1206
+ const session = await self.sessionRegistry.ensureSession(
1207
+ envelope.sessionId,
1208
+ envelope.metadata
1209
+ );
1210
+ const execution = self.startSessionExecution(
1211
+ session,
1212
+ envelope,
1213
+ options?.signal
1214
+ );
1215
+ try {
1216
+ for await (const event of self.executor.executeRun(
1217
+ session,
1218
+ envelope,
1219
+ execution.controller
1220
+ )) {
1221
+ self.publishLiveEvent(execution, event);
1222
+ yield event;
1223
+ }
1224
+ if (execution.controller.signal.aborted && !execution.abortHandled) {
1225
+ const abortEvent = await self.createAbortEvent(session.sessionId);
1226
+ execution.abortHandled = true;
1227
+ self.publishLiveEvent(execution, abortEvent);
1228
+ yield abortEvent;
1229
+ }
1230
+ } finally {
1231
+ self.finishSessionExecution(session, execution);
1232
+ await self.persistSession(session.sessionId);
1214
1233
  }
1215
- } finally {
1216
- this.finishSessionExecution(session, execution);
1217
- }
1218
- }
1219
- async abort(payload) {
1234
+ })(this);
1235
+ };
1236
+ abort = async (payload) => {
1220
1237
  await this.handleAbort(payload);
1221
- }
1238
+ };
1222
1239
  stream = (payloadOrParams, opts) => streamAgentBackendExecution({
1223
1240
  payloadOrParams,
1224
1241
  opts,
1225
1242
  sessionRegistry: this.sessionRegistry
1226
1243
  });
1227
- async listSessions() {
1244
+ listSessions = async () => {
1228
1245
  const storedSessions = await this.sessionStore.listSessions();
1229
1246
  const summaries = storedSessions.map(
1230
1247
  (session) => toSessionSummary(session, this.sessionRegistry.getSession(session.sessionId))
@@ -1236,18 +1253,18 @@ var DefaultNcpAgentBackend = class {
1236
1253
  summaries.push(toLiveSessionSummary(liveSession));
1237
1254
  }
1238
1255
  return summaries.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
1239
- }
1240
- async listSessionMessages(sessionId) {
1256
+ };
1257
+ listSessionMessages = async (sessionId) => {
1241
1258
  const liveSession = this.sessionRegistry.getSession(sessionId);
1242
1259
  if (liveSession) return readMessages(liveSession.stateManager.getSnapshot());
1243
1260
  const session = await this.sessionStore.getSession(sessionId);
1244
1261
  return session ? session.messages.map((message) => structuredClone(message)) : [];
1245
- }
1246
- async getSession(sessionId) {
1262
+ };
1263
+ getSession = async (sessionId) => {
1247
1264
  const liveSession = this.sessionRegistry.getSession(sessionId);
1248
1265
  const storedSession = await this.sessionStore.getSession(sessionId);
1249
1266
  return storedSession ? toSessionSummary(storedSession, liveSession) : liveSession ? toLiveSessionSummary(liveSession) : null;
1250
- }
1267
+ };
1251
1268
  appendMessage = async (sessionId, message) => {
1252
1269
  await this.ensureStarted();
1253
1270
  return appendAgentBackendMessage({
@@ -1272,7 +1289,7 @@ var DefaultNcpAgentBackend = class {
1272
1289
  getSession: async (nextSessionId) => this.getSession(nextSessionId)
1273
1290
  });
1274
1291
  };
1275
- async updateSession(sessionId, patch) {
1292
+ updateSession = async (sessionId, patch) => {
1276
1293
  const liveSession = this.sessionRegistry.getSession(sessionId);
1277
1294
  const storedSession = await this.sessionStore.getSession(sessionId);
1278
1295
  if (!liveSession && !storedSession) return null;
@@ -1284,8 +1301,8 @@ var DefaultNcpAgentBackend = class {
1284
1301
  updatedAt: now()
1285
1302
  }));
1286
1303
  return this.getSession(sessionId);
1287
- }
1288
- async deleteSession(sessionId) {
1304
+ };
1305
+ deleteSession = async (sessionId) => {
1289
1306
  const liveSession = this.sessionRegistry.deleteSession(sessionId);
1290
1307
  const execution = liveSession?.activeExecution;
1291
1308
  if (execution) {
@@ -1294,13 +1311,13 @@ var DefaultNcpAgentBackend = class {
1294
1311
  this.closeExecution(execution);
1295
1312
  }
1296
1313
  await this.sessionStore.deleteSession(sessionId);
1297
- }
1298
- async ensureStarted() {
1314
+ };
1315
+ ensureStarted = async () => {
1299
1316
  if (!this.started) {
1300
1317
  await this.start();
1301
1318
  }
1302
- }
1303
- startSessionExecution(session, envelope, signal) {
1319
+ };
1320
+ startSessionExecution = (session, envelope, signal) => {
1304
1321
  if (session.activeExecution && !session.activeExecution.closed) {
1305
1322
  throw new NcpErrorException(
1306
1323
  "runtime-error",
@@ -1322,39 +1339,41 @@ var DefaultNcpAgentBackend = class {
1322
1339
  closed: false
1323
1340
  };
1324
1341
  session.activeExecution = execution;
1342
+ this.onSessionRunStatusChanged?.({ sessionKey: session.sessionId, status: "running" });
1325
1343
  return execution;
1326
- }
1327
- finishSessionExecution(session, execution) {
1344
+ };
1345
+ finishSessionExecution = (session, execution) => {
1328
1346
  if (session.activeExecution === execution) {
1329
1347
  session.activeExecution = null;
1348
+ this.onSessionRunStatusChanged?.({ sessionKey: session.sessionId, status: "idle" });
1330
1349
  }
1331
1350
  this.closeExecution(execution);
1332
- }
1333
- closeExecution(execution) {
1351
+ };
1352
+ closeExecution = (execution) => {
1334
1353
  if (execution.closed) {
1335
1354
  return;
1336
1355
  }
1337
1356
  execution.closed = true;
1338
1357
  execution.publisher.close();
1339
- }
1340
- publishLiveEvent(execution, event) {
1358
+ };
1359
+ publishLiveEvent = (execution, event) => {
1341
1360
  this.publisher.publish(event);
1342
1361
  if (!execution.closed) {
1343
1362
  execution.publisher.publish(event);
1344
1363
  }
1345
- }
1346
- async handleRequest(envelope) {
1364
+ };
1365
+ handleRequest = async (envelope) => {
1347
1366
  for await (const event of this.send(envelope)) {
1348
1367
  void event;
1349
1368
  }
1350
- }
1351
- async streamToSubscribers(payload) {
1369
+ };
1370
+ streamToSubscribers = async (payload) => {
1352
1371
  const signal = new AbortController().signal;
1353
1372
  for await (const event of this.stream({ payload, signal })) {
1354
1373
  void event;
1355
1374
  }
1356
- }
1357
- async handleAbort(payload) {
1375
+ };
1376
+ handleAbort = async (payload) => {
1358
1377
  const session = this.sessionRegistry.getSession(payload.sessionId);
1359
1378
  const execution = session?.activeExecution;
1360
1379
  if (!session || !execution || execution.closed) {
@@ -1365,8 +1384,8 @@ var DefaultNcpAgentBackend = class {
1365
1384
  const abortEvent = await this.createAbortEvent(payload.sessionId, payload.messageId);
1366
1385
  this.publishLiveEvent(execution, abortEvent);
1367
1386
  this.finishSessionExecution(session, execution);
1368
- }
1369
- async createAbortEvent(sessionId, messageId) {
1387
+ };
1388
+ createAbortEvent = async (sessionId, messageId) => {
1370
1389
  const abortEvent = {
1371
1390
  type: NcpEventType8.MessageAbort,
1372
1391
  payload: {
@@ -1380,8 +1399,8 @@ var DefaultNcpAgentBackend = class {
1380
1399
  }
1381
1400
  await this.persistSession(sessionId);
1382
1401
  return abortEvent;
1383
- }
1384
- async persistSession(sessionId) {
1402
+ };
1403
+ persistSession = async (sessionId) => {
1385
1404
  const session = this.sessionRegistry.getSession(sessionId);
1386
1405
  if (!session) return;
1387
1406
  await this.sessionStore.saveSession(buildPersistedLiveSessionRecord({
@@ -1389,7 +1408,7 @@ var DefaultNcpAgentBackend = class {
1389
1408
  session,
1390
1409
  updatedAt: now()
1391
1410
  }));
1392
- }
1411
+ };
1393
1412
  };
1394
1413
 
1395
1414
  // src/agent/agent-backend/in-memory-agent-session-store.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/ncp-toolkit",
3
- "version": "0.4.9",
3
+ "version": "0.4.10",
4
4
  "private": false,
5
5
  "description": "Toolkit implementations built on top of the NextClaw Communication Protocol.",
6
6
  "type": "module",