@neta-art/cohub 1.16.1 → 1.17.0

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.
@@ -1300,7 +1300,7 @@ type GenerationStreamIntermediateMessage = {
1300
1300
  };
1301
1301
  type GenerationStreamStateEvent = {
1302
1302
  type: "state";
1303
- source: "snapshot" | "patch" | "progress";
1303
+ source: "patch";
1304
1304
  state: SessionPatchState;
1305
1305
  messageId: string | null;
1306
1306
  messageOrdinal: number | null;
@@ -1329,7 +1329,7 @@ type GenerationStreamErrorEvent = {
1329
1329
  };
1330
1330
  type GenerationStreamOutOfSyncEvent = {
1331
1331
  type: "out_of_sync";
1332
- source: "snapshot" | "patch";
1332
+ source: "patch";
1333
1333
  reason: "duplicate" | "version_mismatch" | "invalid";
1334
1334
  state: SessionPatchState;
1335
1335
  rawEvent: WebsocketEventPayload;
@@ -1353,7 +1353,7 @@ declare class SessionGenerationStreamClient {
1353
1353
  private messageId;
1354
1354
  private messageOrdinal;
1355
1355
  private intermediateMessages;
1356
- private progressState;
1356
+ private patchState;
1357
1357
  constructor(websocketClient: WebsocketClient | null, spaceId: string, sessionId: string);
1358
1358
  subscribe(handlers: GenerationStreamSubscriptionHandlers): () => void;
1359
1359
  private emit;
@@ -1362,9 +1362,7 @@ declare class SessionGenerationStreamClient {
1362
1362
  private addIntermediateMessage;
1363
1363
  private handleAppliedState;
1364
1364
  private prepareMessageBoundary;
1365
- private handleSnapshot;
1366
1365
  private handlePatch;
1367
- private handleProgress;
1368
1366
  private handlePersisted;
1369
1367
  private handleFinalized;
1370
1368
  private handleEvent;
@@ -1397,23 +1395,16 @@ declare class PublicInviteApi {
1397
1395
  //#endregion
1398
1396
  //#region src/apis/spaces.d.ts
1399
1397
  type SessionSubscriptionHandlers = {
1400
- patch?: (event: WebsocketEventPayload) => void;
1401
- /**
1402
- * @deprecated Use `session.subscribeGeneration({ state })` for normalized
1403
- * snapshot/patch/progress generation state.
1404
- */
1405
- patchState?: (result: SessionPatchApplyResult) => void; /** @deprecated Use `session.subscribeGeneration({ state })`. */
1406
- snapshot?: (event: WebsocketEventPayload) => void; /** @deprecated Legacy progress events are normalized by `subscribeGeneration`. */
1407
- progress?: (event: WebsocketEventPayload) => void; /** @deprecated Use `session.subscribeGeneration({ commit, finalized })`. */
1408
- final?: (event: WebsocketEventPayload) => void;
1398
+ patch?: (event: WebsocketEventPayload) => void; /** @deprecated Use `session.subscribeGeneration({ state })`. */
1399
+ patchState?: (result: SessionPatchApplyResult) => void;
1409
1400
  turnUpdated?: (event: WebsocketEventPayload) => void;
1410
1401
  turnFinalized?: (event: WebsocketEventPayload) => void;
1411
1402
  error?: (event: WebsocketEventPayload) => void;
1412
1403
  persisted?: (event: WebsocketEventPayload) => void;
1413
1404
  event?: (event: WebsocketEventPayload) => void;
1414
1405
  };
1415
- type SessionEventName = "turn.patch" | "turn.snapshot" | "turn.progress" | "turn.final" | "turn.updated" | "turn.error" | "message.persisted";
1416
- type SpaceEventName = SessionEventName | "ports.changed" | "event";
1406
+ type SessionEventName = "created" | "updated" | "turn.created" | "turn.patch" | "turn.updated" | "turn.finalized" | "turn.error" | "message.persisted";
1407
+ type SpaceEventName = SessionEventName | "ports.changed" | "task.created" | "task.updated" | "event";
1417
1408
  type SessionSendMessageInput = {
1418
1409
  content: ContentBlock[];
1419
1410
  model?: string;
@@ -320,7 +320,7 @@ const createIdleState = (input) => ({
320
320
  function cloneBlock(block) {
321
321
  return structuredClone(block);
322
322
  }
323
- function getStreamIndex$1(block) {
323
+ function getStreamIndex(block) {
324
324
  const value = block._meta?.streamIndex;
325
325
  return typeof value === "number" && Number.isFinite(value) ? value : null;
326
326
  }
@@ -331,19 +331,19 @@ function blockIdentityCompatible(prev, next) {
331
331
  return true;
332
332
  }
333
333
  function findBlockByStreamIndex(blocks, streamIndex) {
334
- return blocks.findIndex((block) => getStreamIndex$1(block) === streamIndex);
334
+ return blocks.findIndex((block) => getStreamIndex(block) === streamIndex);
335
335
  }
336
336
  function findBlockForReplacement(blocks, streamIndex, nextBlock) {
337
- const compatibleIndex = blocks.findIndex((block) => getStreamIndex$1(block) === streamIndex && blockIdentityCompatible(block, nextBlock));
337
+ const compatibleIndex = blocks.findIndex((block) => getStreamIndex(block) === streamIndex && blockIdentityCompatible(block, nextBlock));
338
338
  if (compatibleIndex >= 0) return compatibleIndex;
339
- const sameStreamIndex = blocks.findIndex((block) => getStreamIndex$1(block) === streamIndex);
339
+ const sameStreamIndex = blocks.findIndex((block) => getStreamIndex(block) === streamIndex);
340
340
  if (sameStreamIndex >= 0 && nextBlock.type !== "tool_use" && nextBlock.type !== "tool_result") return sameStreamIndex;
341
341
  return -1;
342
342
  }
343
343
  function sortBlocksByStreamIndex(blocks) {
344
344
  return [...blocks].sort((a, b) => {
345
- const aIndex = getStreamIndex$1(a);
346
- const bIndex = getStreamIndex$1(b);
345
+ const aIndex = getStreamIndex(a);
346
+ const bIndex = getStreamIndex(b);
347
347
  if (aIndex == null && bIndex == null) return 0;
348
348
  if (aIndex == null) return 1;
349
349
  if (bIndex == null) return -1;
@@ -697,14 +697,6 @@ const createSessionPatchReducer = () => new SessionPatchReducer();
697
697
  //#region src/session-generation-stream.ts
698
698
  const isRecord = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
699
699
  const isContentBlockArray = (value) => Array.isArray(value) && value.every((item) => isRecord(item) && typeof item.type === "string");
700
- const stringField = (record, key) => {
701
- const value = record[key];
702
- return typeof value === "string" ? value : null;
703
- };
704
- const numberField = (record, key) => {
705
- const value = record[key];
706
- return typeof value === "number" && Number.isFinite(value) ? value : null;
707
- };
708
700
  const getMessageKind = (message) => {
709
701
  const kind = message.meta?.messageKind;
710
702
  return typeof kind === "string" ? kind : null;
@@ -737,68 +729,6 @@ function parseAssistantMessageCommit(message) {
737
729
  isFinal: false
738
730
  };
739
731
  }
740
- function cloneContentBlock(block) {
741
- return structuredClone(block);
742
- }
743
- function getStreamIndex(block) {
744
- const value = block._meta?.streamIndex;
745
- return typeof value === "number" && Number.isFinite(value) ? value : null;
746
- }
747
- function findMergeTargetIndex(result, block) {
748
- const streamIndex = getStreamIndex(block);
749
- if (streamIndex != null) return result.findIndex((existing) => existing.type === block.type && getStreamIndex(existing) === streamIndex);
750
- if (block.type === "tool_use") return result.findIndex((existing) => existing.type === "tool_use" && existing.id === block.id);
751
- if (block.type === "tool_result") return result.findIndex((existing) => existing.type === "tool_result" && existing.tool_use_id === block.tool_use_id);
752
- return -1;
753
- }
754
- function mergeStreamingDeltaBlocks(existing, delta) {
755
- if (delta.length === 0) return existing;
756
- const result = existing.map(cloneContentBlock);
757
- for (const block of delta) {
758
- const targetIndex = findMergeTargetIndex(result, block);
759
- if (targetIndex === -1) {
760
- result.push(cloneContentBlock(block));
761
- continue;
762
- }
763
- const target = result[targetIndex];
764
- if (block.type === "text" && target?.type === "text") {
765
- target.text += block.text;
766
- continue;
767
- }
768
- if (block.type === "thinking" && target?.type === "thinking") {
769
- target.thinking += block.thinking;
770
- if (block.signature) target.signature = block.signature;
771
- if (block._meta) target._meta = {
772
- ...target._meta ?? {},
773
- ...block._meta
774
- };
775
- continue;
776
- }
777
- result[targetIndex] = Object.assign(target ?? {}, cloneContentBlock(block));
778
- }
779
- return result;
780
- }
781
- function parseSnapshotMessage(value) {
782
- if (!isRecord(value) || !isContentBlockArray(value.content)) return null;
783
- return {
784
- messageId: stringField(value, "messageId"),
785
- messageOrdinal: numberField(value, "messageOrdinal"),
786
- content: value.content,
787
- ...typeof value.id === "string" ? { id: value.id } : {},
788
- ...typeof value.sessionId === "string" ? { sessionId: value.sessionId } : {},
789
- ...value.role === "user" || value.role === "assistant" || value.role === "system" ? { role: value.role } : {},
790
- ...typeof value.text === "string" ? { text: value.text } : {},
791
- ...typeof value.provider === "string" ? { provider: value.provider } : {},
792
- ...typeof value.model === "string" ? { model: value.model } : {},
793
- ...typeof value.stopReason === "string" ? { stopReason: value.stopReason } : {},
794
- ...typeof value.errorMessage === "string" ? { errorMessage: value.errorMessage } : {},
795
- ...isRecord(value.usage) ? { usage: value.usage } : {},
796
- ...typeof value.durationMs === "number" ? { durationMs: value.durationMs } : {},
797
- ...typeof value.toolCallsObjectKey === "string" ? { toolCallsObjectKey: value.toolCallsObjectKey } : {},
798
- ...isRecord(value.meta) ? { meta: value.meta } : {},
799
- ...typeof value.createdAt === "string" ? { createdAt: value.createdAt } : {}
800
- };
801
- }
802
732
  function messageRecordToIntermediate(message) {
803
733
  if (!isContentBlockArray(message.content) || message.content.length === 0) return null;
804
734
  const meta = isRecord(message.meta) ? message.meta : {};
@@ -838,7 +768,7 @@ var SessionGenerationStreamClient = class SessionGenerationStreamClient {
838
768
  messageId = null;
839
769
  messageOrdinal = null;
840
770
  intermediateMessages = [];
841
- progressState = null;
771
+ patchState = null;
842
772
  constructor(websocketClient, spaceId, sessionId) {
843
773
  this.websocketClient = websocketClient;
844
774
  this.spaceId = spaceId;
@@ -866,7 +796,7 @@ var SessionGenerationStreamClient = class SessionGenerationStreamClient {
866
796
  resetCurrentMessage() {
867
797
  this.messageId = null;
868
798
  this.messageOrdinal = null;
869
- this.progressState = null;
799
+ this.patchState = null;
870
800
  }
871
801
  appendCurrentMessage(state) {
872
802
  if (state.contentBlocks.length === 0) return;
@@ -894,14 +824,14 @@ var SessionGenerationStreamClient = class SessionGenerationStreamClient {
894
824
  if (!result.applied) {
895
825
  this.emit(handlers, {
896
826
  type: "out_of_sync",
897
- source: source === "progress" ? "patch" : source,
827
+ source,
898
828
  reason: result.reason,
899
829
  state: result.state,
900
830
  rawEvent
901
831
  });
902
832
  return;
903
833
  }
904
- this.progressState = result.state;
834
+ this.patchState = result.state;
905
835
  this.messageId = messageId;
906
836
  this.messageOrdinal = messageOrdinal;
907
837
  this.emit(handlers, {
@@ -915,7 +845,7 @@ var SessionGenerationStreamClient = class SessionGenerationStreamClient {
915
845
  });
916
846
  }
917
847
  prepareMessageBoundary(input) {
918
- const current = this.progressState ?? this.reducer.get({
848
+ const current = this.patchState ?? this.reducer.get({
919
849
  spaceId: this.spaceId,
920
850
  sessionId: this.sessionId
921
851
  });
@@ -947,45 +877,6 @@ var SessionGenerationStreamClient = class SessionGenerationStreamClient {
947
877
  }
948
878
  return nextMessageId;
949
879
  }
950
- handleSnapshot(event, handlers) {
951
- const payload = event.payload;
952
- const current = isRecord(payload.current) ? payload.current : null;
953
- const content = current ? current.content : null;
954
- const seq = typeof payload.seq === "number" ? payload.seq : null;
955
- if (!current || !isContentBlockArray(content) || seq === null) {
956
- this.emit(handlers, {
957
- type: "out_of_sync",
958
- source: "snapshot",
959
- reason: "invalid",
960
- state: this.reducer.get({
961
- spaceId: this.spaceId,
962
- sessionId: this.sessionId
963
- }),
964
- rawEvent: event
965
- });
966
- return;
967
- }
968
- const turnId = typeof payload.turnId === "string" ? payload.turnId : null;
969
- const anchorUserMessageId = typeof payload.anchorUserMessageId === "string" ? payload.anchorUserMessageId : null;
970
- const messageOrdinal = numberField(current, "messageOrdinal");
971
- const messageId = this.prepareMessageBoundary({
972
- turnId,
973
- messageId: stringField(current, "messageId"),
974
- messageOrdinal,
975
- anchorUserMessageId
976
- });
977
- this.intermediateMessages = Array.isArray(payload.intermediateMessages) ? payload.intermediateMessages.map(parseSnapshotMessage).filter((message) => message !== null) : [];
978
- const result = this.reducer.applySnapshot({
979
- spaceId: this.spaceId,
980
- sessionId: this.sessionId,
981
- turnId,
982
- seq,
983
- contentBlocks: content,
984
- anchorUserMessageId,
985
- appendPath: stringField(current, "appendPath")
986
- });
987
- this.handleAppliedState(handlers, "snapshot", result, event, messageId, messageOrdinal);
988
- }
989
880
  handlePatch(event, handlers) {
990
881
  const payload = event.payload;
991
882
  const seq = typeof payload.seq === "number" ? payload.seq : null;
@@ -1024,45 +915,6 @@ var SessionGenerationStreamClient = class SessionGenerationStreamClient {
1024
915
  const result = this.reducer.applyPatch(input);
1025
916
  this.handleAppliedState(handlers, "patch", result, event, messageId, messageOrdinal);
1026
917
  }
1027
- handleProgress(event, handlers) {
1028
- const payload = event.payload;
1029
- if (!isContentBlockArray(payload.content)) return;
1030
- const current = this.progressState ?? this.reducer.get({
1031
- spaceId: this.spaceId,
1032
- sessionId: this.sessionId
1033
- });
1034
- const turnId = typeof payload.turnId === "string" ? payload.turnId : current.turnId;
1035
- const anchorUserMessageId = typeof payload.anchorUserMessageId === "string" ? payload.anchorUserMessageId : current.anchorUserMessageId;
1036
- const messageOrdinal = typeof payload.messageOrdinal === "number" ? payload.messageOrdinal : this.messageOrdinal;
1037
- const messageId = this.prepareMessageBoundary({
1038
- turnId,
1039
- messageId: typeof payload.messageId === "string" ? payload.messageId : this.messageId,
1040
- messageOrdinal,
1041
- anchorUserMessageId
1042
- });
1043
- const base = this.progressState?.turnId === turnId ? this.progressState : current;
1044
- const state = {
1045
- ...base,
1046
- spaceId: this.spaceId,
1047
- sessionId: this.sessionId,
1048
- status: "streaming",
1049
- contentBlocks: mergeStreamingDeltaBlocks(base.contentBlocks, payload.content),
1050
- anchorUserMessageId,
1051
- turnId
1052
- };
1053
- this.progressState = state;
1054
- this.messageId = messageId;
1055
- this.messageOrdinal = messageOrdinal;
1056
- this.emit(handlers, {
1057
- type: "state",
1058
- source: "progress",
1059
- state,
1060
- messageId,
1061
- messageOrdinal,
1062
- intermediateMessages: [...this.intermediateMessages],
1063
- rawEvent: event
1064
- });
1065
- }
1066
918
  handlePersisted(event, handlers) {
1067
919
  const message = event.payload.message;
1068
920
  if (!isRecord(message)) return;
@@ -1121,15 +973,9 @@ var SessionGenerationStreamClient = class SessionGenerationStreamClient {
1121
973
  }
1122
974
  handleEvent(event, handlers) {
1123
975
  switch (event.type) {
1124
- case "session.turn.snapshot":
1125
- this.handleSnapshot(event, handlers);
1126
- return;
1127
976
  case "session.turn.patch":
1128
977
  this.handlePatch(event, handlers);
1129
978
  return;
1130
- case "session.turn.progress":
1131
- this.handleProgress(event, handlers);
1132
- return;
1133
979
  case "session.message.persisted":
1134
980
  this.handlePersisted(event, handlers);
1135
981
  return;
@@ -1217,12 +1063,13 @@ const getFilenameFromContentDisposition = (value) => {
1217
1063
  };
1218
1064
  const toSessionEventName = (type) => {
1219
1065
  switch (type) {
1066
+ case "session.created": return "created";
1067
+ case "session.updated": return "updated";
1068
+ case "session.turn.created": return "turn.created";
1220
1069
  case "session.turn.patch": return "turn.patch";
1221
- case "session.turn.snapshot": return "turn.snapshot";
1222
- case "session.turn.progress": return "turn.progress";
1223
1070
  case "session.turn.error": return "turn.error";
1224
1071
  case "session.turn.updated": return "turn.updated";
1225
- case "session.turn.finalized": return "turn.final";
1072
+ case "session.turn.finalized": return "turn.finalized";
1226
1073
  case "session.message.persisted": return "message.persisted";
1227
1074
  default: return null;
1228
1075
  }
@@ -1500,8 +1347,6 @@ var SessionRealtimeClient = class {
1500
1347
  }));
1501
1348
  }
1502
1349
  }
1503
- if (eventName === "turn.snapshot") handlers.snapshot?.(event);
1504
- if (eventName === "turn.progress") handlers.progress?.(event);
1505
1350
  if (eventName === "turn.error") {
1506
1351
  this.patchReducer.fail({
1507
1352
  spaceId: this.spaceId,
@@ -1517,32 +1362,24 @@ var SessionRealtimeClient = class {
1517
1362
  });
1518
1363
  }
1519
1364
  if (eventName === "turn.updated") handlers.turnUpdated?.(event);
1520
- if (eventName === "turn.final") {
1365
+ if (eventName === "turn.finalized") {
1521
1366
  this.patchReducer.complete({
1522
1367
  spaceId: this.spaceId,
1523
1368
  sessionId: this.sessionId,
1524
1369
  turnId: typeof event.payload.turn === "object" && event.payload.turn && "id" in event.payload.turn ? String(event.payload.turn.id) : null
1525
1370
  });
1526
1371
  handlers.turnFinalized?.(event);
1527
- handlers.final?.(event);
1528
- }
1529
- if (isAssistantFinalPersistedEvent(event)) {
1530
- this.patchReducer.complete({
1531
- spaceId: this.spaceId,
1532
- sessionId: this.sessionId,
1533
- turnId: getPersistedMessageTurnId(event)
1534
- });
1535
- handlers.final?.(event);
1536
1372
  }
1373
+ if (isAssistantFinalPersistedEvent(event)) this.patchReducer.complete({
1374
+ spaceId: this.spaceId,
1375
+ sessionId: this.sessionId,
1376
+ turnId: getPersistedMessageTurnId(event)
1377
+ });
1537
1378
  });
1538
1379
  return () => unsubscribe();
1539
1380
  }
1540
1381
  on(type, handler) {
1541
1382
  return this.subscribe({ event: (event) => {
1542
- if (type === "turn.final" && isAssistantFinalPersistedEvent(event)) {
1543
- handler(event);
1544
- return;
1545
- }
1546
1383
  if (toSessionEventName(event.type) === type) handler(event);
1547
1384
  } });
1548
1385
  }
@@ -1656,7 +1493,11 @@ var SpaceEventsApi = class {
1656
1493
  handler(event);
1657
1494
  return;
1658
1495
  }
1659
- if (type === "turn.final" && isAssistantFinalPersistedEvent(event)) {
1496
+ if (type === "task.created" && event.type === "task.created") {
1497
+ handler(event);
1498
+ return;
1499
+ }
1500
+ if (type === "task.updated" && event.type === "task.updated") {
1660
1501
  handler(event);
1661
1502
  return;
1662
1503
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub",
3
- "version": "1.16.1",
3
+ "version": "1.17.0",
4
4
  "description": "Cohub SDK for spaces, sessions, checkpoints, and realtime agent collaboration.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,