@nextclaw/ncp-toolkit 0.4.7 → 0.4.9

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
@@ -121,13 +121,15 @@ declare class DefaultNcpAgentBackend implements NcpAgentServerEndpoint, NcpSessi
121
121
  subscribe(listener: (event: NcpEndpointEvent) => void): () => void;
122
122
  send(envelope: NcpRequestEnvelope, options?: NcpAgentRunSendOptions): AsyncIterable<NcpEndpointEvent>;
123
123
  abort(payload: NcpMessageAbortPayload): Promise<void>;
124
- stream(payloadOrParams: NcpStreamRequestPayload | {
124
+ stream: (payloadOrParams: NcpStreamRequestPayload | {
125
125
  payload: NcpStreamRequestPayload;
126
126
  signal: AbortSignal;
127
- }, opts?: NcpAgentRunStreamOptions): AsyncIterable<NcpEndpointEvent>;
127
+ }, opts?: NcpAgentRunStreamOptions) => AsyncIterable<NcpEndpointEvent>;
128
128
  listSessions(): Promise<NcpSessionSummary[]>;
129
129
  listSessionMessages(sessionId: string): Promise<NcpMessage[]>;
130
130
  getSession(sessionId: string): Promise<NcpSessionSummary | null>;
131
+ appendMessage: (sessionId: string, message: NcpMessage) => Promise<NcpSessionSummary | null>;
132
+ updateToolCallResult: (sessionId: string, toolCallId: string, content: unknown) => Promise<NcpSessionSummary | null>;
131
133
  updateSession(sessionId: string, patch: NcpSessionPatch): Promise<NcpSessionSummary | null>;
132
134
  deleteSession(sessionId: string): Promise<void>;
133
135
  private ensureStarted;
package/dist/index.js CHANGED
@@ -692,7 +692,7 @@ async function consume(events) {
692
692
 
693
693
  // src/agent/agent-backend/agent-backend.ts
694
694
  import {
695
- NcpEventType as NcpEventType5
695
+ NcpEventType as NcpEventType8
696
696
  } from "@nextclaw/ncp";
697
697
 
698
698
  // src/errors/ncp-error-exception.ts
@@ -777,23 +777,28 @@ function cloneMessages(messages) {
777
777
  }
778
778
 
779
779
  // src/agent/agent-backend/agent-run-executor.ts
780
+ import {
781
+ isHiddenNcpMessage
782
+ } from "@nextclaw/ncp";
780
783
  import { NcpEventType as NcpEventType3 } from "@nextclaw/ncp";
781
784
  var AgentRunExecutor = class {
782
785
  constructor(persistSession) {
783
786
  this.persistSession = persistSession;
784
787
  }
785
788
  async *executeRun(session, envelope, controller) {
786
- const messageSent = {
787
- type: NcpEventType3.MessageSent,
788
- payload: {
789
- sessionId: envelope.sessionId,
790
- message: structuredClone(envelope.message),
791
- metadata: envelope.metadata
792
- }
793
- };
794
- await session.stateManager.dispatch(messageSent);
795
- await this.persistSession(envelope.sessionId);
796
- yield structuredClone(messageSent);
789
+ if (!isHiddenNcpMessage(envelope.message)) {
790
+ const messageSent = {
791
+ type: NcpEventType3.MessageSent,
792
+ payload: {
793
+ sessionId: envelope.sessionId,
794
+ message: structuredClone(envelope.message),
795
+ metadata: envelope.metadata
796
+ }
797
+ };
798
+ await session.stateManager.dispatch(messageSent);
799
+ await this.persistSession(envelope.sessionId);
800
+ yield structuredClone(messageSent);
801
+ }
797
802
  try {
798
803
  for await (const event of session.runtime.run(
799
804
  {
@@ -831,65 +836,6 @@ var AgentRunExecutor = class {
831
836
  }
832
837
  };
833
838
 
834
- // src/agent/agent-backend/async-queue.ts
835
- function createAsyncQueue() {
836
- const items = [];
837
- let closed = false;
838
- let pendingResolve = null;
839
- const iterable = {
840
- [Symbol.asyncIterator]() {
841
- return {
842
- next: () => {
843
- if (items.length > 0) {
844
- return Promise.resolve({
845
- value: items.shift(),
846
- done: false
847
- });
848
- }
849
- if (closed) {
850
- return Promise.resolve({
851
- value: void 0,
852
- done: true
853
- });
854
- }
855
- return new Promise((resolve) => {
856
- pendingResolve = resolve;
857
- });
858
- }
859
- };
860
- }
861
- };
862
- return {
863
- push(item) {
864
- if (closed) {
865
- return;
866
- }
867
- if (pendingResolve) {
868
- const resolve = pendingResolve;
869
- pendingResolve = null;
870
- resolve({ value: item, done: false });
871
- return;
872
- }
873
- items.push(item);
874
- },
875
- close() {
876
- if (closed) {
877
- return;
878
- }
879
- closed = true;
880
- if (pendingResolve) {
881
- const resolve = pendingResolve;
882
- pendingResolve = null;
883
- resolve({
884
- value: void 0,
885
- done: true
886
- });
887
- }
888
- },
889
- iterable
890
- };
891
- }
892
-
893
839
  // src/agent/agent-backend/agent-backend-session-utils.ts
894
840
  import { NcpEventType as NcpEventType4 } from "@nextclaw/ncp";
895
841
  function readMessages(snapshot) {
@@ -962,6 +908,175 @@ function buildPersistedLiveSessionRecord(params) {
962
908
  };
963
909
  }
964
910
 
911
+ // src/agent/agent-backend/agent-backend-update-tool-call-result.ts
912
+ import { NcpEventType as NcpEventType5 } from "@nextclaw/ncp";
913
+ async function updateAgentBackendToolCallResult(params) {
914
+ const normalizedSessionId = params.sessionId.trim();
915
+ const normalizedToolCallId = params.toolCallId.trim();
916
+ if (!normalizedSessionId || !normalizedToolCallId) {
917
+ return null;
918
+ }
919
+ const liveSession = await params.sessionRegistry.ensureSession(normalizedSessionId);
920
+ const event = {
921
+ type: NcpEventType5.MessageToolCallResult,
922
+ payload: {
923
+ sessionId: normalizedSessionId,
924
+ toolCallId: normalizedToolCallId,
925
+ content: params.content
926
+ }
927
+ };
928
+ await liveSession.stateManager.dispatch(event);
929
+ params.publisher.publish(event);
930
+ if (liveSession.activeExecution && !liveSession.activeExecution.closed) {
931
+ liveSession.activeExecution.publisher.publish(event);
932
+ }
933
+ await params.persistSession(normalizedSessionId);
934
+ return params.getSession(normalizedSessionId);
935
+ }
936
+
937
+ // src/agent/agent-backend/agent-backend-append-message.ts
938
+ import { NcpEventType as NcpEventType6 } from "@nextclaw/ncp";
939
+ async function appendAgentBackendMessage(params) {
940
+ const normalizedSessionId = params.sessionId.trim();
941
+ if (!normalizedSessionId) {
942
+ return null;
943
+ }
944
+ let liveSession = params.sessionRegistry.getSession(normalizedSessionId);
945
+ if (!liveSession) {
946
+ const storedSession = await params.sessionStore.getSession(normalizedSessionId);
947
+ if (!storedSession) {
948
+ return null;
949
+ }
950
+ liveSession = await params.sessionRegistry.ensureSession(normalizedSessionId);
951
+ }
952
+ const nextMessage = {
953
+ ...structuredClone(params.message),
954
+ sessionId: normalizedSessionId
955
+ };
956
+ const event = {
957
+ type: NcpEventType6.MessageSent,
958
+ payload: {
959
+ sessionId: normalizedSessionId,
960
+ message: nextMessage
961
+ }
962
+ };
963
+ await liveSession.stateManager.dispatch(event);
964
+ params.publisher.publish(event);
965
+ if (liveSession.activeExecution && !liveSession.activeExecution.closed) {
966
+ liveSession.activeExecution.publisher.publish(event);
967
+ }
968
+ await params.persistSession(normalizedSessionId);
969
+ return params.getSession(normalizedSessionId);
970
+ }
971
+
972
+ // src/agent/agent-backend/agent-backend-stream.ts
973
+ import { NcpEventType as NcpEventType7 } from "@nextclaw/ncp";
974
+
975
+ // src/agent/agent-backend/async-queue.ts
976
+ function createAsyncQueue() {
977
+ const items = [];
978
+ let closed = false;
979
+ let pendingResolve = null;
980
+ const iterable = {
981
+ [Symbol.asyncIterator]() {
982
+ return {
983
+ next: () => {
984
+ if (items.length > 0) {
985
+ return Promise.resolve({
986
+ value: items.shift(),
987
+ done: false
988
+ });
989
+ }
990
+ if (closed) {
991
+ return Promise.resolve({
992
+ value: void 0,
993
+ done: true
994
+ });
995
+ }
996
+ return new Promise((resolve) => {
997
+ pendingResolve = resolve;
998
+ });
999
+ }
1000
+ };
1001
+ }
1002
+ };
1003
+ return {
1004
+ push(item) {
1005
+ if (closed) {
1006
+ return;
1007
+ }
1008
+ if (pendingResolve) {
1009
+ const resolve = pendingResolve;
1010
+ pendingResolve = null;
1011
+ resolve({ value: item, done: false });
1012
+ return;
1013
+ }
1014
+ items.push(item);
1015
+ },
1016
+ close() {
1017
+ if (closed) {
1018
+ return;
1019
+ }
1020
+ closed = true;
1021
+ if (pendingResolve) {
1022
+ const resolve = pendingResolve;
1023
+ pendingResolve = null;
1024
+ resolve({
1025
+ value: void 0,
1026
+ done: true
1027
+ });
1028
+ }
1029
+ },
1030
+ iterable
1031
+ };
1032
+ }
1033
+
1034
+ // src/agent/agent-backend/agent-backend-stream.ts
1035
+ async function* streamAgentBackendExecution(params) {
1036
+ const payload = "payload" in params.payloadOrParams && "signal" in params.payloadOrParams ? params.payloadOrParams.payload : params.payloadOrParams;
1037
+ const signal = "payload" in params.payloadOrParams && "signal" in params.payloadOrParams ? params.payloadOrParams.signal : params.opts?.signal ?? new AbortController().signal;
1038
+ const session = params.sessionRegistry.getSession(payload.sessionId);
1039
+ const execution = session?.activeExecution;
1040
+ if (!session || !execution || execution.closed) {
1041
+ if (session) {
1042
+ yield {
1043
+ type: NcpEventType7.RunFinished,
1044
+ payload: {
1045
+ sessionId: payload.sessionId
1046
+ }
1047
+ };
1048
+ }
1049
+ return;
1050
+ }
1051
+ const queue = createAsyncQueue();
1052
+ const unsubscribe = execution.publisher.subscribe((event) => {
1053
+ queue.push(event);
1054
+ });
1055
+ const unsubscribeClose = execution.publisher.onClose(() => {
1056
+ queue.close();
1057
+ });
1058
+ const stop = () => {
1059
+ unsubscribe();
1060
+ unsubscribeClose();
1061
+ queue.close();
1062
+ signal.removeEventListener("abort", stop);
1063
+ };
1064
+ signal.addEventListener("abort", stop, { once: true });
1065
+ try {
1066
+ for await (const event of queue.iterable) {
1067
+ if (signal.aborted) {
1068
+ break;
1069
+ }
1070
+ yield event;
1071
+ if (isTerminalEvent(event)) {
1072
+ break;
1073
+ }
1074
+ }
1075
+ } finally {
1076
+ stop();
1077
+ }
1078
+ }
1079
+
965
1080
  // src/agent/agent-backend/event-publisher.ts
966
1081
  var EventPublisher = class {
967
1082
  listeners = /* @__PURE__ */ new Set();
@@ -1008,18 +1123,7 @@ var EventPublisher = class {
1008
1123
  };
1009
1124
 
1010
1125
  // src/agent/agent-backend/agent-backend.ts
1011
- var DEFAULT_SUPPORTED_PART_TYPES = [
1012
- "text",
1013
- "file",
1014
- "source",
1015
- "step-start",
1016
- "reasoning",
1017
- "tool-invocation",
1018
- "card",
1019
- "rich-text",
1020
- "action",
1021
- "extension"
1022
- ];
1126
+ var DEFAULT_SUPPORTED_PART_TYPES = ["text", "file", "source", "step-start", "reasoning", "tool-invocation", "card", "rich-text", "action", "extension"];
1023
1127
  var DefaultNcpAgentBackend = class {
1024
1128
  manifest;
1025
1129
  sessionStore;
@@ -1053,7 +1157,7 @@ var DefaultNcpAgentBackend = class {
1053
1157
  return;
1054
1158
  }
1055
1159
  this.started = true;
1056
- this.publisher.publish({ type: NcpEventType5.EndpointReady });
1160
+ this.publisher.publish({ type: NcpEventType8.EndpointReady });
1057
1161
  }
1058
1162
  async stop() {
1059
1163
  if (!this.started) {
@@ -1074,13 +1178,13 @@ var DefaultNcpAgentBackend = class {
1074
1178
  async emit(event) {
1075
1179
  await this.ensureStarted();
1076
1180
  switch (event.type) {
1077
- case NcpEventType5.MessageRequest:
1181
+ case NcpEventType8.MessageRequest:
1078
1182
  await this.handleRequest(event.payload);
1079
1183
  return;
1080
- case NcpEventType5.MessageStreamRequest:
1184
+ case NcpEventType8.MessageStreamRequest:
1081
1185
  await this.streamToSubscribers(event.payload);
1082
1186
  return;
1083
- case NcpEventType5.MessageAbort:
1187
+ case NcpEventType8.MessageAbort:
1084
1188
  await this.handleAbort(event.payload);
1085
1189
  return;
1086
1190
  default:
@@ -1115,42 +1219,11 @@ var DefaultNcpAgentBackend = class {
1115
1219
  async abort(payload) {
1116
1220
  await this.handleAbort(payload);
1117
1221
  }
1118
- async *stream(payloadOrParams, opts) {
1119
- const payload = "payload" in payloadOrParams && "signal" in payloadOrParams ? payloadOrParams.payload : payloadOrParams;
1120
- const signal = "payload" in payloadOrParams && "signal" in payloadOrParams ? payloadOrParams.signal : opts?.signal ?? new AbortController().signal;
1121
- const session = this.sessionRegistry.getSession(payload.sessionId);
1122
- const execution = session?.activeExecution;
1123
- if (!session || !execution || execution.closed) {
1124
- return;
1125
- }
1126
- const queue = createAsyncQueue();
1127
- const unsubscribe = execution.publisher.subscribe((event) => {
1128
- queue.push(event);
1129
- });
1130
- const unsubscribeClose = execution.publisher.onClose(() => {
1131
- queue.close();
1132
- });
1133
- const stop = () => {
1134
- unsubscribe();
1135
- unsubscribeClose();
1136
- queue.close();
1137
- signal.removeEventListener("abort", stop);
1138
- };
1139
- signal.addEventListener("abort", stop, { once: true });
1140
- try {
1141
- for await (const event of queue.iterable) {
1142
- if (signal.aborted) {
1143
- break;
1144
- }
1145
- yield event;
1146
- if (isTerminalEvent(event)) {
1147
- break;
1148
- }
1149
- }
1150
- } finally {
1151
- stop();
1152
- }
1153
- }
1222
+ stream = (payloadOrParams, opts) => streamAgentBackendExecution({
1223
+ payloadOrParams,
1224
+ opts,
1225
+ sessionRegistry: this.sessionRegistry
1226
+ });
1154
1227
  async listSessions() {
1155
1228
  const storedSessions = await this.sessionStore.listSessions();
1156
1229
  const summaries = storedSessions.map(
@@ -1175,6 +1248,30 @@ var DefaultNcpAgentBackend = class {
1175
1248
  const storedSession = await this.sessionStore.getSession(sessionId);
1176
1249
  return storedSession ? toSessionSummary(storedSession, liveSession) : liveSession ? toLiveSessionSummary(liveSession) : null;
1177
1250
  }
1251
+ appendMessage = async (sessionId, message) => {
1252
+ await this.ensureStarted();
1253
+ return appendAgentBackendMessage({
1254
+ sessionId,
1255
+ message,
1256
+ sessionRegistry: this.sessionRegistry,
1257
+ sessionStore: this.sessionStore,
1258
+ publisher: this.publisher,
1259
+ persistSession: async (nextSessionId) => this.persistSession(nextSessionId),
1260
+ getSession: async (nextSessionId) => this.getSession(nextSessionId)
1261
+ });
1262
+ };
1263
+ updateToolCallResult = async (sessionId, toolCallId, content) => {
1264
+ await this.ensureStarted();
1265
+ return updateAgentBackendToolCallResult({
1266
+ sessionId,
1267
+ toolCallId,
1268
+ content,
1269
+ sessionRegistry: this.sessionRegistry,
1270
+ publisher: this.publisher,
1271
+ persistSession: async (nextSessionId) => this.persistSession(nextSessionId),
1272
+ getSession: async (nextSessionId) => this.getSession(nextSessionId)
1273
+ });
1274
+ };
1178
1275
  async updateSession(sessionId, patch) {
1179
1276
  const liveSession = this.sessionRegistry.getSession(sessionId);
1180
1277
  const storedSession = await this.sessionStore.getSession(sessionId);
@@ -1271,7 +1368,7 @@ var DefaultNcpAgentBackend = class {
1271
1368
  }
1272
1369
  async createAbortEvent(sessionId, messageId) {
1273
1370
  const abortEvent = {
1274
- type: NcpEventType5.MessageAbort,
1371
+ type: NcpEventType8.MessageAbort,
1275
1372
  payload: {
1276
1373
  sessionId,
1277
1374
  ...messageId ? { messageId } : {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/ncp-toolkit",
3
- "version": "0.4.7",
3
+ "version": "0.4.9",
4
4
  "private": false,
5
5
  "description": "Toolkit implementations built on top of the NextClaw Communication Protocol.",
6
6
  "type": "module",
@@ -15,7 +15,7 @@
15
15
  "dist"
16
16
  ],
17
17
  "dependencies": {
18
- "@nextclaw/ncp": "0.4.1"
18
+ "@nextclaw/ncp": "0.4.2"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/node": "^20.17.6",
@@ -23,7 +23,7 @@
23
23
  "tsup": "^8.3.5",
24
24
  "typescript": "^5.6.3",
25
25
  "vitest": "^2.1.2",
26
- "@nextclaw/ncp-agent-runtime": "0.3.1"
26
+ "@nextclaw/ncp-agent-runtime": "0.3.2"
27
27
  },
28
28
  "scripts": {
29
29
  "build": "tsup src/index.ts --format esm --dts --out-dir dist",