@nextclaw/ncp-toolkit 0.5.15 → 0.5.17

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/dist/index.d.ts CHANGED
@@ -125,8 +125,12 @@ interface AgentSessionStore {
125
125
  event: NcpEndpointEvent;
126
126
  updatedAt: string;
127
127
  }): Promise<void>;
128
+ updateSessionMetadata(params: {
129
+ sessionId: string;
130
+ metadata: Record<string, unknown>;
131
+ updatedAt: string;
132
+ }): Promise<boolean>;
128
133
  saveSession(session: AgentSessionRecord): Promise<void>;
129
- replaceSession(session: AgentSessionRecord): Promise<void>;
130
134
  deleteSession(sessionId: string): Promise<AgentSessionRecord | null>;
131
135
  }
132
136
  //#endregion
@@ -201,7 +205,11 @@ declare class InMemoryAgentSessionStore implements AgentSessionStore {
201
205
  getSession: (sessionId: string) => Promise<AgentSessionRecord | null>;
202
206
  listSessions: () => Promise<AgentSessionRecord[]>;
203
207
  saveSession: (session: AgentSessionRecord) => Promise<void>;
204
- replaceSession: (session: AgentSessionRecord) => Promise<void>;
208
+ updateSessionMetadata: (params: {
209
+ sessionId: string;
210
+ metadata: Record<string, unknown>;
211
+ updatedAt: string;
212
+ }) => Promise<boolean>;
205
213
  deleteSession: (sessionId: string) => Promise<AgentSessionRecord | null>;
206
214
  }
207
215
  //#endregion
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { NcpEventType, isHiddenNcpMessage, sanitizeAssistantReplyTags } from "@nextclaw/ncp";
1
+ import { NcpEventType, consumeNcpRunHandle, createNcpRunHandle, isHiddenNcpMessage, sanitizeAssistantReplyTags } from "@nextclaw/ncp";
2
2
  //#region src/agent/agent-conversation-message-normalizer.ts
3
3
  function cloneConversationMessage(message) {
4
4
  return {
@@ -522,6 +522,7 @@ var DefaultNcpAgentConversationStateManager = class {
522
522
  };
523
523
  upsertMessage = (message) => {
524
524
  const normalizedMessage = normalizeConversationMessage(message);
525
+ if (this.streamingMessage?.id === normalizedMessage.id) this.streamingMessage = null;
525
526
  const messageIndex = this.messages.findIndex((item) => item.id === normalizedMessage.id);
526
527
  if (messageIndex < 0) {
527
528
  this.messages = [...this.messages, normalizedMessage];
@@ -596,7 +597,7 @@ function createAgentClientFromServer(server) {
596
597
  switch (event.type) {
597
598
  case NcpEventType.MessageRequest:
598
599
  assertMaterializedEnvelope(event.payload);
599
- await consume(server.send(event.payload));
600
+ await consumeNcpRunHandle(server.send(event.payload), createNcpRunHandle(event.payload));
600
601
  return;
601
602
  case NcpEventType.MessageStreamRequest:
602
603
  await consume(server.stream(event.payload));
@@ -612,7 +613,7 @@ function createAgentClientFromServer(server) {
612
613
  },
613
614
  async send(envelope) {
614
615
  assertMaterializedEnvelope(envelope);
615
- await consume(server.send(envelope));
616
+ return await consumeNcpRunHandle(server.send(envelope), createNcpRunHandle(envelope));
616
617
  },
617
618
  async stream(payload) {
618
619
  await consume(server.stream(payload));
@@ -900,9 +901,9 @@ var AgentBackendSessionRealtime = class {
900
901
  }
901
902
  publishSessionEvent = async (session, event, options = {}) => {
902
903
  if (options.dispatchToStateManager) await session.stateManager.dispatch(event);
904
+ if (options.persistSession !== false) await this.params.persistSessionEvent(session, event);
903
905
  this.params.publishEndpointEvent(event);
904
906
  session.publisher.publish(event);
905
- if (options.persistSession !== false) await this.params.persistSessionEvent(session, event);
906
907
  };
907
908
  streamSessionEvents = (payloadOrParams, opts) => {
908
909
  return (async function* (self) {
@@ -981,7 +982,7 @@ function readOptionalAgentId$1(value) {
981
982
  }
982
983
  function readMessages(snapshot) {
983
984
  const messages = snapshot.messages.map((message) => structuredClone(message));
984
- if (snapshot.streamingMessage) messages.push(structuredClone(snapshot.streamingMessage));
985
+ if (snapshot.streamingMessage && !messages.some((message) => message.id === snapshot.streamingMessage?.id)) messages.push(structuredClone(snapshot.streamingMessage));
985
986
  return messages;
986
987
  }
987
988
  function readSessionActivityAt(summary) {
@@ -1159,27 +1160,6 @@ function readOptionalAgentId(value) {
1159
1160
  function readAgentIdFromMetadata(metadata) {
1160
1161
  return readOptionalAgentId(metadata?.agent_id) ?? readOptionalAgentId(metadata?.agentId);
1161
1162
  }
1162
- function resolvePersistedAgentId(params) {
1163
- const { liveSession, storedSession } = params;
1164
- return readOptionalAgentId(liveSession?.agentId) ?? readOptionalAgentId(storedSession?.agentId) ?? readAgentIdFromMetadata(liveSession?.metadata) ?? readAgentIdFromMetadata(storedSession?.metadata);
1165
- }
1166
- function buildUpdatedSessionRecord(params) {
1167
- const { liveSession, patch, sessionId, storedSession, updatedAt } = params;
1168
- const nextMetadata = patch.metadata === null ? {} : patch.metadata ? structuredClone(patch.metadata) : structuredClone(liveSession?.metadata ?? storedSession?.metadata ?? {});
1169
- if (liveSession) liveSession.metadata = structuredClone(nextMetadata);
1170
- const agentId = resolvePersistedAgentId({
1171
- liveSession,
1172
- storedSession
1173
- });
1174
- return {
1175
- sessionId,
1176
- ...agentId ? { agentId } : {},
1177
- messages: liveSession ? readMessages(liveSession.stateManager.getSnapshot()) : storedSession?.messages.map((message) => structuredClone(message)) ?? [],
1178
- createdAt: storedSession?.createdAt ?? liveSession?.createdAt ?? updatedAt,
1179
- updatedAt,
1180
- metadata: nextMetadata
1181
- };
1182
- }
1183
1163
  function buildPersistedLiveSessionRecord(params) {
1184
1164
  const { session, sessionId, updatedAt } = params;
1185
1165
  const messages = readMessages(session.stateManager.getSnapshot());
@@ -1263,6 +1243,12 @@ const DEFAULT_SUPPORTED_PART_TYPES = [
1263
1243
  const disposeRuntime = async (runtime) => {
1264
1244
  await runtime.dispose?.();
1265
1245
  };
1246
+ function buildUpdatedMetadata(params) {
1247
+ const { liveSession, patch, storedSession } = params;
1248
+ if (patch.metadata === null) return {};
1249
+ if (patch.metadata) return structuredClone(patch.metadata);
1250
+ return structuredClone(liveSession?.metadata ?? storedSession?.metadata ?? {});
1251
+ }
1266
1252
  var DefaultNcpAgentBackend = class {
1267
1253
  manifest;
1268
1254
  sessionStore;
@@ -1434,13 +1420,18 @@ var DefaultNcpAgentBackend = class {
1434
1420
  const liveSession = this.sessionRegistry.getSession(sessionId);
1435
1421
  const storedSession = await this.sessionStore.getSession(sessionId);
1436
1422
  if (!liveSession && !storedSession) return null;
1437
- await this.sessionStore.replaceSession(buildUpdatedSessionRecord({
1438
- sessionId,
1439
- patch,
1423
+ const metadata = buildUpdatedMetadata({
1440
1424
  liveSession,
1441
- storedSession,
1442
- updatedAt: now()
1443
- }));
1425
+ patch,
1426
+ storedSession
1427
+ });
1428
+ const updatedAt = now();
1429
+ if (liveSession) liveSession.metadata = structuredClone(metadata);
1430
+ await this.sessionStore.updateSessionMetadata({
1431
+ sessionId,
1432
+ metadata,
1433
+ updatedAt
1434
+ });
1444
1435
  return this.getSession(sessionId);
1445
1436
  };
1446
1437
  deleteSession = async (sessionId) => {
@@ -1500,8 +1491,16 @@ var InMemoryAgentSessionStore = class {
1500
1491
  saveSession = async (session) => {
1501
1492
  this.sessions.set(session.sessionId, structuredClone(session));
1502
1493
  };
1503
- replaceSession = async (session) => {
1504
- this.sessions.set(session.sessionId, structuredClone(session));
1494
+ updateSessionMetadata = async (params) => {
1495
+ const { metadata, sessionId, updatedAt } = params;
1496
+ const session = this.sessions.get(sessionId);
1497
+ if (!session) return false;
1498
+ this.sessions.set(sessionId, {
1499
+ ...session,
1500
+ metadata: structuredClone(metadata),
1501
+ updatedAt
1502
+ });
1503
+ return true;
1505
1504
  };
1506
1505
  deleteSession = async (sessionId) => {
1507
1506
  const session = this.sessions.get(sessionId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/ncp-toolkit",
3
- "version": "0.5.15",
3
+ "version": "0.5.17",
4
4
  "private": false,
5
5
  "description": "Toolkit implementations built on top of the NextClaw Communication Protocol.",
6
6
  "type": "module",
@@ -15,14 +15,14 @@
15
15
  "dist"
16
16
  ],
17
17
  "dependencies": {
18
- "@nextclaw/ncp": "0.5.10"
18
+ "@nextclaw/ncp": "0.5.12"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/node": "^20.17.6",
22
22
  "prettier": "^3.3.3",
23
23
  "typescript": "^5.6.3",
24
24
  "vitest": "^4.1.2",
25
- "@nextclaw/ncp-agent-runtime": "0.3.20"
25
+ "@nextclaw/ncp-agent-runtime": "0.3.22"
26
26
  },
27
27
  "scripts": {
28
28
  "build": "tsdown src/index.ts --dts --clean --target es2022 --no-fixedExtension",