@ycodium-ai/plugin-conversation 0.2.3016 → 0.2.3020

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.js CHANGED
@@ -435,41 +435,6 @@ function applyLiveAnswer(thread, messages, segment, answer) {
435
435
  return { ...thread, running: thread.running || live.streaming, turns };
436
436
  }
437
437
 
438
- // src/ui/sessionMap/toolStrip.ts
439
- function record(value) {
440
- if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
441
- return value;
442
- }
443
- function text(value) {
444
- return typeof value === "string" ? value.trim() : "";
445
- }
446
- function toolTitleFromActivity(payload) {
447
- const root = record(payload);
448
- if (root === null) return "";
449
- const data = record(root.data) ?? root;
450
- const toolLabel = record(data.toolLabel) ?? record(root.toolLabel);
451
- if (toolLabel !== null) {
452
- if (toolLabel.descriptive === false) return "";
453
- const detail = text(toolLabel.detail);
454
- if (detail.length > 0) return detail;
455
- return text(toolLabel.title);
456
- }
457
- return text(root.title);
458
- }
459
- function titlesByCallId(activities) {
460
- const titles = /* @__PURE__ */ new Map();
461
- for (const activity of activities) {
462
- const root = record(activity.payload);
463
- if (root === null) continue;
464
- const data = record(root.data) ?? root;
465
- const callId = text(data.toolCallId) || text(root.toolCallId);
466
- if (callId.length === 0) continue;
467
- const title = toolTitleFromActivity(activity.payload);
468
- if (title.length > 0) titles.set(callId, title);
469
- }
470
- return titles;
471
- }
472
-
473
438
  // src/sessionMap/refreshGate.ts
474
439
  var CARD_REFRESH_MS = 800;
475
440
  var CardRefreshGate = class {
@@ -649,6 +614,134 @@ async function executionOf(ctx, threadId) {
649
614
  return executionRow(execution);
650
615
  }
651
616
 
617
+ // src/sessionMap/threadReads.ts
618
+ import {
619
+ isThreadNotFound,
620
+ threadOrNull,
621
+ THREAD_ACTIVITIES_LIST_LIMIT,
622
+ THREAD_MESSAGES_LIST_LIMIT,
623
+ TOOL_LIFECYCLE_ACTIVITY_KINDS
624
+ } from "@ycodium-ai/plugin-api";
625
+
626
+ // src/ui/sessionMap/toolStrip.ts
627
+ function record(value) {
628
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
629
+ return value;
630
+ }
631
+ function text(value) {
632
+ return typeof value === "string" ? value.trim() : "";
633
+ }
634
+ function toolTitleFromActivity(payload) {
635
+ const root = record(payload);
636
+ if (root === null) return "";
637
+ const data = record(root.data) ?? root;
638
+ const toolLabel = record(data.toolLabel) ?? record(root.toolLabel);
639
+ if (toolLabel !== null) {
640
+ if (toolLabel.descriptive === false) return "";
641
+ const detail = text(toolLabel.detail);
642
+ if (detail.length > 0) return detail;
643
+ return text(toolLabel.title);
644
+ }
645
+ return text(root.title);
646
+ }
647
+ function titlesByCallId(activities) {
648
+ const titles = /* @__PURE__ */ new Map();
649
+ for (const activity of activities) {
650
+ const root = record(activity.payload);
651
+ if (root === null) continue;
652
+ const data = record(root.data) ?? root;
653
+ const callId = text(data.toolCallId) || text(root.toolCallId);
654
+ if (callId.length === 0) continue;
655
+ const title = toolTitleFromActivity(activity.payload);
656
+ if (title.length > 0) titles.set(callId, title);
657
+ }
658
+ return titles;
659
+ }
660
+
661
+ // src/sessionMap/threadReads.ts
662
+ var MESSAGES_PAGE = THREAD_MESSAGES_LIST_LIMIT;
663
+ var ACTIVITIES_PAGE = THREAD_ACTIVITIES_LIST_LIMIT;
664
+ var MAX_TITLE_ACTIVITIES = 500;
665
+ var TOOL_ACTIVITY_KINDS = [...TOOL_LIFECYCLE_ACTIVITY_KINDS];
666
+ var messageOf = (item) => ({
667
+ messageId: item.id,
668
+ role: item.role,
669
+ text: item.text
670
+ });
671
+ async function readTranscript(threads, threadId) {
672
+ const newestFirst = [];
673
+ let cursor = null;
674
+ try {
675
+ do {
676
+ const page = await threads.messages.list({
677
+ threadId,
678
+ limit: MESSAGES_PAGE,
679
+ cursor
680
+ });
681
+ newestFirst.push(...page.items.map(messageOf));
682
+ cursor = page.nextCursor;
683
+ } while (cursor !== null);
684
+ } catch (error) {
685
+ if (isThreadNotFound(error)) return null;
686
+ throw error;
687
+ }
688
+ return newestFirst.toReversed();
689
+ }
690
+ async function readToolTitles(threads, threadId) {
691
+ const titles = /* @__PURE__ */ new Map();
692
+ let cursor = null;
693
+ let remaining = MAX_TITLE_ACTIVITIES;
694
+ try {
695
+ do {
696
+ const page = await threads.activities.list({
697
+ threadId,
698
+ kinds: TOOL_ACTIVITY_KINDS,
699
+ limit: Math.min(ACTIVITIES_PAGE, remaining),
700
+ cursor
701
+ });
702
+ remaining -= page.items.length;
703
+ const oldestFirst = page.items.toReversed().map((item) => ({ payload: "payload" in item ? item.payload : void 0 }));
704
+ for (const [callId, title] of titlesByCallId(oldestFirst)) {
705
+ if (!titles.has(callId)) titles.set(callId, title);
706
+ }
707
+ cursor = page.items.length === 0 ? null : page.nextCursor;
708
+ } while (cursor !== null && remaining > 0);
709
+ } catch (error) {
710
+ if (isThreadNotFound(error)) return /* @__PURE__ */ new Map();
711
+ throw error;
712
+ }
713
+ return titles;
714
+ }
715
+ async function readDetail(threads, threadId) {
716
+ const thread = await threadOrNull(threads, threadId);
717
+ if (thread === null) return { found: false, messages: [] };
718
+ let latest;
719
+ try {
720
+ latest = await threads.messages.list({
721
+ threadId,
722
+ limit: MAX_DETAIL_MESSAGES,
723
+ includeTotal: true
724
+ });
725
+ } catch (error) {
726
+ if (isThreadNotFound(error)) return { found: false, messages: [] };
727
+ throw error;
728
+ }
729
+ return {
730
+ found: true,
731
+ title: thread.title,
732
+ omitted: Math.max(0, (latest.total ?? 0) - latest.items.length),
733
+ messages: latest.items.toReversed().map((message) => {
734
+ const clipped = clipText(message.text, MAX_DETAIL_TEXT);
735
+ return {
736
+ messageId: message.id,
737
+ role: message.role,
738
+ text: clipped.text,
739
+ truncated: clipped.truncated
740
+ };
741
+ })
742
+ };
743
+ }
744
+
652
745
  // src/sessionMap/mapLive.ts
653
746
  function createSessionMapHub(ctx, canvas, options = {}) {
654
747
  return new SessionMapHub(ctx, canvas, options.timers !== false);
@@ -831,7 +924,7 @@ var SessionMapHub = class {
831
924
  if (live !== void 0) {
832
925
  const message = await this.ctx.projections.getThreadMessage(live.messageId);
833
926
  if (message !== null) {
834
- this.transcripts.upsert(threadId, messageOf(message));
927
+ this.transcripts.upsert(threadId, messageOf2(message));
835
928
  const clipped = clipText(message.text, MAX_CARD_TEXT);
836
929
  answer = { text: clipped.text, truncated: clipped.truncated };
837
930
  }
@@ -854,9 +947,8 @@ var SessionMapHub = class {
854
947
  }
855
948
  async seedTranscript(threadId) {
856
949
  if (this.transcripts.has(threadId)) return;
857
- const thread = await this.ctx.projections.getThread(threadId, { includeActivities: true });
858
- this.transcripts.seed(threadId, transcriptOf(thread));
859
- this.rememberTitles(threadId, titlesByCallId(thread?.activities ?? []));
950
+ this.transcripts.seed(threadId, await readTranscript(this.ctx.threads, threadId) ?? []);
951
+ this.rememberTitles(threadId, await readToolTitles(this.ctx.threads, threadId));
860
952
  }
861
953
  rememberTitles(threadId, titles) {
862
954
  if (titles.size === 0) return;
@@ -877,15 +969,14 @@ var SessionMapHub = class {
877
969
  if (pending !== void 0) {
878
970
  for (const messageId of pending) {
879
971
  const message = await this.ctx.projections.getThreadMessage(messageId);
880
- if (message !== null) this.transcripts.upsert(threadId, messageOf(message));
972
+ if (message !== null) this.transcripts.upsert(threadId, messageOf2(message));
881
973
  }
882
974
  }
883
975
  return this.transcripts.get(threadId) ?? [];
884
976
  }
885
977
  async loadParent(threadId) {
886
978
  if (!this.transcripts.has(threadId)) {
887
- const thread = await this.ctx.projections.getThread(threadId);
888
- this.transcripts.seed(threadId, transcriptOf(thread));
979
+ this.transcripts.seed(threadId, await readTranscript(this.ctx.threads, threadId) ?? []);
889
980
  }
890
981
  return this.transcripts.get(threadId) ?? [];
891
982
  }
@@ -954,11 +1045,7 @@ function messageIdOf(event) {
954
1045
  const messageId = readString(event.payload.messageId);
955
1046
  return messageId.length > 0 ? messageId : null;
956
1047
  }
957
- function transcriptOf(thread) {
958
- if (thread === null) return [];
959
- return thread.messages.map(messageOf);
960
- }
961
- function messageOf(message) {
1048
+ function messageOf2(message) {
962
1049
  return { messageId: message.messageId, role: message.role, text: message.text };
963
1050
  }
964
1051
  function jsonValue(value) {
@@ -1046,7 +1133,7 @@ function activateSessionMap(ctx) {
1046
1133
  properties: { threadId: { type: "string" } },
1047
1134
  required: ["threadId"]
1048
1135
  },
1049
- handle: async (payload) => detailOf(ctx, readString(payload["threadId"]))
1136
+ handle: async (payload) => readDetail(ctx.threads, readString(payload["threadId"]))
1050
1137
  });
1051
1138
  ctx.command({
1052
1139
  name: "preferences",
@@ -1187,32 +1274,6 @@ function activateSessionMap(ctx) {
1187
1274
  )
1188
1275
  });
1189
1276
  }
1190
- function transcriptOf2(thread) {
1191
- if (thread === null) return [];
1192
- return thread.messages.map(messageOf2);
1193
- }
1194
- function messageOf2(message) {
1195
- return { messageId: message.messageId, role: message.role, text: message.text };
1196
- }
1197
- async function detailOf(ctx, threadId) {
1198
- const thread = await ctx.projections.getThread(threadId);
1199
- if (thread === null) return { found: false, messages: [] };
1200
- const tail = thread.messages.slice(-MAX_DETAIL_MESSAGES);
1201
- return {
1202
- found: true,
1203
- title: thread.title,
1204
- omitted: Math.max(0, thread.messages.length - tail.length),
1205
- messages: tail.map((message) => {
1206
- const clipped = clipText(message.text, MAX_DETAIL_TEXT);
1207
- return {
1208
- messageId: message.messageId,
1209
- role: message.role,
1210
- text: clipped.text,
1211
- truncated: clipped.truncated
1212
- };
1213
- })
1214
- };
1215
- }
1216
1277
  async function createSession(ctx, projectId, text2, refresh) {
1217
1278
  const trimmed = text2.trim();
1218
1279
  if (trimmed.length === 0) return { ok: false, code: "empty" };
@@ -1261,9 +1322,9 @@ async function sendFollowUp(ctx, threadId, text2, refresh) {
1261
1322
  async function forkSession(ctx, threadId, messageId, text2, refresh) {
1262
1323
  const trimmed = text2.trim();
1263
1324
  if (trimmed.length === 0) return { ok: false, code: "empty" };
1264
- const thread = await ctx.projections.getThread(threadId);
1265
- if (thread === null) return { ok: false, code: "missing-thread" };
1266
- const anchor = resolveForkAnchor(transcriptOf2(thread), messageId);
1325
+ const transcript = await readTranscript(ctx.threads, threadId);
1326
+ if (transcript === null) return { ok: false, code: "missing-thread" };
1327
+ const anchor = resolveForkAnchor(transcript, messageId);
1267
1328
  if (anchor === null) return { ok: false, code: "no-user-message" };
1268
1329
  const execution = await executionOf(ctx, threadId);
1269
1330
  const childId = NodeCrypto.randomUUID();
@@ -1319,7 +1380,7 @@ function abort(signal) {
1319
1380
  // src/index.ts
1320
1381
  var index_default = definePlugin({
1321
1382
  id: "conversation",
1322
- apiVersion: 8,
1383
+ apiVersion: 9,
1323
1384
  activate(ctx) {
1324
1385
  activateSessionMap(ctx);
1325
1386
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/plugin-conversation",
3
- "version": "0.2.3016",
3
+ "version": "0.2.3020",
4
4
  "description": "The conversation surface: chat, trajectory, and session map, the input card, the queue, and turn navigation.",
5
5
  "keywords": [
6
6
  "chat",
@@ -41,7 +41,7 @@
41
41
  "tailwindcss": "^4.0.0",
42
42
  "typescript": "~6.0.3",
43
43
  "vite-plus": "0.2.2",
44
- "@ycodium-ai/plugin-api": "0.2.3016",
44
+ "@ycodium-ai/plugin-api": "0.2.3020",
45
45
  "ycodium-composer-tokens": "0.0.0",
46
46
  "ycodium-workspace-path": "0.0.0"
47
47
  },