@nextclaw/ncp-toolkit 0.4.7 → 0.4.8

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,14 @@ 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>;
131
132
  updateSession(sessionId: string, patch: NcpSessionPatch): Promise<NcpSessionSummary | null>;
132
133
  deleteSession(sessionId: string): Promise<void>;
133
134
  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 NcpEventType6
696
696
  } from "@nextclaw/ncp";
697
697
 
698
698
  // src/errors/ncp-error-exception.ts
@@ -831,65 +831,6 @@ var AgentRunExecutor = class {
831
831
  }
832
832
  };
833
833
 
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
834
  // src/agent/agent-backend/agent-backend-session-utils.ts
894
835
  import { NcpEventType as NcpEventType4 } from "@nextclaw/ncp";
895
836
  function readMessages(snapshot) {
@@ -962,6 +903,138 @@ function buildPersistedLiveSessionRecord(params) {
962
903
  };
963
904
  }
964
905
 
906
+ // src/agent/agent-backend/agent-backend-append-message.ts
907
+ import { NcpEventType as NcpEventType5 } from "@nextclaw/ncp";
908
+ async function appendAgentBackendMessage(params) {
909
+ const normalizedSessionId = params.sessionId.trim();
910
+ if (!normalizedSessionId) {
911
+ return null;
912
+ }
913
+ let liveSession = params.sessionRegistry.getSession(normalizedSessionId);
914
+ if (!liveSession) {
915
+ const storedSession = await params.sessionStore.getSession(normalizedSessionId);
916
+ if (!storedSession) {
917
+ return null;
918
+ }
919
+ liveSession = await params.sessionRegistry.ensureSession(normalizedSessionId);
920
+ }
921
+ const nextMessage = {
922
+ ...structuredClone(params.message),
923
+ sessionId: normalizedSessionId
924
+ };
925
+ const event = {
926
+ type: NcpEventType5.MessageSent,
927
+ payload: {
928
+ sessionId: normalizedSessionId,
929
+ message: nextMessage
930
+ }
931
+ };
932
+ await liveSession.stateManager.dispatch(event);
933
+ params.publisher.publish(event);
934
+ if (liveSession.activeExecution && !liveSession.activeExecution.closed) {
935
+ liveSession.activeExecution.publisher.publish(event);
936
+ }
937
+ await params.persistSession(normalizedSessionId);
938
+ return params.getSession(normalizedSessionId);
939
+ }
940
+
941
+ // src/agent/agent-backend/async-queue.ts
942
+ function createAsyncQueue() {
943
+ const items = [];
944
+ let closed = false;
945
+ let pendingResolve = null;
946
+ const iterable = {
947
+ [Symbol.asyncIterator]() {
948
+ return {
949
+ next: () => {
950
+ if (items.length > 0) {
951
+ return Promise.resolve({
952
+ value: items.shift(),
953
+ done: false
954
+ });
955
+ }
956
+ if (closed) {
957
+ return Promise.resolve({
958
+ value: void 0,
959
+ done: true
960
+ });
961
+ }
962
+ return new Promise((resolve) => {
963
+ pendingResolve = resolve;
964
+ });
965
+ }
966
+ };
967
+ }
968
+ };
969
+ return {
970
+ push(item) {
971
+ if (closed) {
972
+ return;
973
+ }
974
+ if (pendingResolve) {
975
+ const resolve = pendingResolve;
976
+ pendingResolve = null;
977
+ resolve({ value: item, done: false });
978
+ return;
979
+ }
980
+ items.push(item);
981
+ },
982
+ close() {
983
+ if (closed) {
984
+ return;
985
+ }
986
+ closed = true;
987
+ if (pendingResolve) {
988
+ const resolve = pendingResolve;
989
+ pendingResolve = null;
990
+ resolve({
991
+ value: void 0,
992
+ done: true
993
+ });
994
+ }
995
+ },
996
+ iterable
997
+ };
998
+ }
999
+
1000
+ // src/agent/agent-backend/agent-backend-stream.ts
1001
+ async function* streamAgentBackendExecution(params) {
1002
+ const payload = "payload" in params.payloadOrParams && "signal" in params.payloadOrParams ? params.payloadOrParams.payload : params.payloadOrParams;
1003
+ const signal = "payload" in params.payloadOrParams && "signal" in params.payloadOrParams ? params.payloadOrParams.signal : params.opts?.signal ?? new AbortController().signal;
1004
+ const session = params.sessionRegistry.getSession(payload.sessionId);
1005
+ const execution = session?.activeExecution;
1006
+ if (!session || !execution || execution.closed) {
1007
+ return;
1008
+ }
1009
+ const queue = createAsyncQueue();
1010
+ const unsubscribe = execution.publisher.subscribe((event) => {
1011
+ queue.push(event);
1012
+ });
1013
+ const unsubscribeClose = execution.publisher.onClose(() => {
1014
+ queue.close();
1015
+ });
1016
+ const stop = () => {
1017
+ unsubscribe();
1018
+ unsubscribeClose();
1019
+ queue.close();
1020
+ signal.removeEventListener("abort", stop);
1021
+ };
1022
+ signal.addEventListener("abort", stop, { once: true });
1023
+ try {
1024
+ for await (const event of queue.iterable) {
1025
+ if (signal.aborted) {
1026
+ break;
1027
+ }
1028
+ yield event;
1029
+ if (isTerminalEvent(event)) {
1030
+ break;
1031
+ }
1032
+ }
1033
+ } finally {
1034
+ stop();
1035
+ }
1036
+ }
1037
+
965
1038
  // src/agent/agent-backend/event-publisher.ts
966
1039
  var EventPublisher = class {
967
1040
  listeners = /* @__PURE__ */ new Set();
@@ -1053,7 +1126,7 @@ var DefaultNcpAgentBackend = class {
1053
1126
  return;
1054
1127
  }
1055
1128
  this.started = true;
1056
- this.publisher.publish({ type: NcpEventType5.EndpointReady });
1129
+ this.publisher.publish({ type: NcpEventType6.EndpointReady });
1057
1130
  }
1058
1131
  async stop() {
1059
1132
  if (!this.started) {
@@ -1074,13 +1147,13 @@ var DefaultNcpAgentBackend = class {
1074
1147
  async emit(event) {
1075
1148
  await this.ensureStarted();
1076
1149
  switch (event.type) {
1077
- case NcpEventType5.MessageRequest:
1150
+ case NcpEventType6.MessageRequest:
1078
1151
  await this.handleRequest(event.payload);
1079
1152
  return;
1080
- case NcpEventType5.MessageStreamRequest:
1153
+ case NcpEventType6.MessageStreamRequest:
1081
1154
  await this.streamToSubscribers(event.payload);
1082
1155
  return;
1083
- case NcpEventType5.MessageAbort:
1156
+ case NcpEventType6.MessageAbort:
1084
1157
  await this.handleAbort(event.payload);
1085
1158
  return;
1086
1159
  default:
@@ -1115,42 +1188,11 @@ var DefaultNcpAgentBackend = class {
1115
1188
  async abort(payload) {
1116
1189
  await this.handleAbort(payload);
1117
1190
  }
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
- }
1191
+ stream = (payloadOrParams, opts) => streamAgentBackendExecution({
1192
+ payloadOrParams,
1193
+ opts,
1194
+ sessionRegistry: this.sessionRegistry
1195
+ });
1154
1196
  async listSessions() {
1155
1197
  const storedSessions = await this.sessionStore.listSessions();
1156
1198
  const summaries = storedSessions.map(
@@ -1175,6 +1217,18 @@ var DefaultNcpAgentBackend = class {
1175
1217
  const storedSession = await this.sessionStore.getSession(sessionId);
1176
1218
  return storedSession ? toSessionSummary(storedSession, liveSession) : liveSession ? toLiveSessionSummary(liveSession) : null;
1177
1219
  }
1220
+ appendMessage = async (sessionId, message) => {
1221
+ await this.ensureStarted();
1222
+ return appendAgentBackendMessage({
1223
+ sessionId,
1224
+ message,
1225
+ sessionRegistry: this.sessionRegistry,
1226
+ sessionStore: this.sessionStore,
1227
+ publisher: this.publisher,
1228
+ persistSession: async (nextSessionId) => this.persistSession(nextSessionId),
1229
+ getSession: async (nextSessionId) => this.getSession(nextSessionId)
1230
+ });
1231
+ };
1178
1232
  async updateSession(sessionId, patch) {
1179
1233
  const liveSession = this.sessionRegistry.getSession(sessionId);
1180
1234
  const storedSession = await this.sessionStore.getSession(sessionId);
@@ -1271,7 +1325,7 @@ var DefaultNcpAgentBackend = class {
1271
1325
  }
1272
1326
  async createAbortEvent(sessionId, messageId) {
1273
1327
  const abortEvent = {
1274
- type: NcpEventType5.MessageAbort,
1328
+ type: NcpEventType6.MessageAbort,
1275
1329
  payload: {
1276
1330
  sessionId,
1277
1331
  ...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.8",
4
4
  "private": false,
5
5
  "description": "Toolkit implementations built on top of the NextClaw Communication Protocol.",
6
6
  "type": "module",