@nextclaw/ncp-toolkit 0.5.3 → 0.5.5

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
@@ -77,6 +77,7 @@ type RuntimeFactoryParams = {
77
77
  stateManager: NcpAgentConversationStateManager;
78
78
  sessionMetadata: Record<string, unknown>;
79
79
  setSessionMetadata: (nextMetadata: Record<string, unknown>) => void;
80
+ resolveAssetContentPath?: (assetUri: string) => string | null;
80
81
  };
81
82
  type CreateRuntimeFn = (params: RuntimeFactoryParams) => NcpAgentRuntime;
82
83
  type AgentSessionRecord = {
package/dist/index.js CHANGED
@@ -998,6 +998,53 @@ function withAutoSessionLabel(params) {
998
998
  label: nextLabel
999
999
  };
1000
1000
  }
1001
+ function findFinalAssistantMessageById(session, messageId) {
1002
+ const normalizedMessageId = messageId.trim();
1003
+ if (!normalizedMessageId) return null;
1004
+ const snapshot = session.stateManager.getSnapshot();
1005
+ for (let index = snapshot.messages.length - 1; index >= 0; index -= 1) {
1006
+ const message = snapshot.messages[index];
1007
+ if (message?.id === normalizedMessageId && message.role === "assistant" && message.status === "final") return message;
1008
+ }
1009
+ return null;
1010
+ }
1011
+ function buildCompletedEventForFinishedRun(session, event) {
1012
+ const messageId = event.payload.messageId?.trim();
1013
+ if (!messageId) throw new Error(`Run finished without messageId for session "${session.sessionId}".`);
1014
+ const completedMessage = findFinalAssistantMessageById(session, messageId);
1015
+ if (!completedMessage) throw new Error(`Run finished without a final assistant message for session "${session.sessionId}" and message "${messageId}".`);
1016
+ return {
1017
+ type: NcpEventType.MessageCompleted,
1018
+ payload: {
1019
+ sessionId: session.sessionId,
1020
+ message: structuredClone(completedMessage)
1021
+ }
1022
+ };
1023
+ }
1024
+ function normalizeSendRunEvent(params) {
1025
+ const { session, event } = params;
1026
+ if (event.type === NcpEventType.MessageCompleted) {
1027
+ if (params.completedMessageSeen) throw new Error(`Multiple final assistant messages were emitted for session "${session.sessionId}".`);
1028
+ return {
1029
+ eventsToPublish: [event],
1030
+ completedMessageSeen: true
1031
+ };
1032
+ }
1033
+ if (event.type === NcpEventType.RunFinished) {
1034
+ if (params.completedMessageSeen) return {
1035
+ eventsToPublish: [event],
1036
+ completedMessageSeen: true
1037
+ };
1038
+ return {
1039
+ eventsToPublish: [buildCompletedEventForFinishedRun(session, event), event],
1040
+ completedMessageSeen: true
1041
+ };
1042
+ }
1043
+ return {
1044
+ eventsToPublish: [event],
1045
+ completedMessageSeen: params.completedMessageSeen
1046
+ };
1047
+ }
1001
1048
  //#endregion
1002
1049
  //#region src/agent/agent-backend/agent-backend-session-persistence.ts
1003
1050
  function readOptionalAgentId(value) {
@@ -1131,18 +1178,25 @@ var DefaultNcpAgentBackend = class {
1131
1178
  default: this.publisher.publish(event);
1132
1179
  }
1133
1180
  };
1134
- subscribe = (listener) => {
1135
- return this.publisher.subscribe(listener);
1136
- };
1181
+ subscribe = (listener) => this.publisher.subscribe(listener);
1137
1182
  send = (envelope, options) => {
1138
1183
  return (async function* (self) {
1139
1184
  await self.ensureStarted();
1140
1185
  const session = await self.sessionRegistry.ensureSession(envelope.sessionId, envelope.metadata);
1141
1186
  const execution = self.startSessionExecution(session, envelope, options?.signal);
1187
+ let completedMessageSeen = false;
1142
1188
  try {
1143
1189
  for await (const event of self.executor.executeRun(session, envelope, execution.controller)) {
1144
- await self.sessionRealtime.publishSessionEvent(session, event);
1145
- yield event;
1190
+ const normalized = normalizeSendRunEvent({
1191
+ session,
1192
+ event,
1193
+ completedMessageSeen
1194
+ });
1195
+ completedMessageSeen = normalized.completedMessageSeen;
1196
+ for (const normalizedEvent of normalized.eventsToPublish) {
1197
+ await self.sessionRealtime.publishSessionEvent(session, normalizedEvent);
1198
+ yield normalizedEvent;
1199
+ }
1146
1200
  }
1147
1201
  if (execution.controller.signal.aborted && !execution.abortHandled) {
1148
1202
  const abortEvent = {
@@ -1159,9 +1213,7 @@ var DefaultNcpAgentBackend = class {
1159
1213
  }
1160
1214
  })(this);
1161
1215
  };
1162
- abort = async (payload) => {
1163
- await this.handleAbort(payload);
1164
- };
1216
+ abort = async (payload) => this.handleAbort(payload);
1165
1217
  stream = (payloadOrParams, opts) => this.sessionRealtime.streamSessionEvents(payloadOrParams, opts);
1166
1218
  listSessions = async () => {
1167
1219
  const summaries = (await this.sessionStore.listSessions()).map((session) => toSessionSummary(session, this.sessionRegistry.getSession(session.sessionId)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/ncp-toolkit",
3
- "version": "0.5.3",
3
+ "version": "0.5.5",
4
4
  "private": false,
5
5
  "description": "Toolkit implementations built on top of the NextClaw Communication Protocol.",
6
6
  "type": "module",
@@ -22,7 +22,7 @@
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.8"
25
+ "@nextclaw/ncp-agent-runtime": "0.3.10"
26
26
  },
27
27
  "scripts": {
28
28
  "build": "tsdown src/index.ts --dts --clean --target es2022 --no-fixedExtension",