@yeaft/webchat-agent 0.1.1100 → 0.1.1102

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "0.1.1100",
4
- "description": "Remote agent for Yeaft WebChat — connects worker machines to the central server",
3
+ "version": "0.1.1102",
4
+ "description": "Remote worker agent for Yeaft Web Code Agent — connects the native Yeaft engine, CLI providers, and workbench tools",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "bin": {
@@ -1092,7 +1092,7 @@ export class ConversationStore {
1092
1092
  const messages = page.messages.map(m => {
1093
1093
  if (m && m.role === 'assistant' && Array.isArray(m.toolCalls) && m.toolCalls.length > 0) {
1094
1094
  const { toolCalls, ...rest } = m;
1095
- return rest;
1095
+ return { ...rest, toolSummaryCount: toolCalls.length };
1096
1096
  }
1097
1097
  return m;
1098
1098
  });
@@ -695,11 +695,14 @@ function projectPersistedToHistoryEntry(m) {
695
695
  input: tc.input,
696
696
  }));
697
697
  }
698
+ if (Number.isFinite(m.toolSummaryCount) && m.toolSummaryCount > 0) {
699
+ entry.toolSummaryCount = m.toolSummaryCount;
700
+ }
698
701
  if (m.isError) entry.isError = true;
699
702
  if (m.ts) entry.ts = m.ts;
700
703
  else if (m.time) entry.ts = m.time;
701
704
  if (Array.isArray(m.attachments) && m.attachments.length > 0) entry.attachments = m.attachments;
702
- if ((entry.role === 'user' || entry.role === 'assistant') && !entry.content && !entry.attachments && !entry.toolCalls) return null;
705
+ if ((entry.role === 'user' || entry.role === 'assistant') && !entry.content && !entry.attachments && !entry.toolCalls && !entry.toolSummaryCount) return null;
703
706
  return entry;
704
707
  }
705
708
 
@@ -772,16 +775,40 @@ function ensureYeaftConversationId() {
772
775
  return yeaftConversationId;
773
776
  }
774
777
 
775
- function emitVisibleHistoryReplay({ store, sessionId, limit, beforeSeq = null, mode = 'recent' }) {
776
- const visiblePage = sessionId
777
- ? loadVisibleGroupHistoryPage(store, sessionId, limit, beforeSeq)
778
- : { messages: limit > 0 ? (store.loadRecent?.(limit) || []) : [], oldestSeq: null, hasMore: false };
779
- const replayEntries = sessionId
780
- ? visiblePage.messages
781
- : visiblePage.messages
782
- .map(projectPersistedToVisibleHistoryEntry)
783
- .filter(Boolean);
778
+ function projectVisibleHistoryChunkMessages(messages = []) {
779
+ return (messages || [])
780
+ .map(m => ({
781
+ ...(m.id ? { id: m.id } : {}),
782
+ role: m.role,
783
+ content: m.content,
784
+ ts: m.ts || m.time || null,
785
+ sessionId: m.sessionId || null,
786
+ threadId: m.threadId || m.turnId || 'main',
787
+ turnId: m.turnId || m.threadId || 'main',
788
+ ...(Array.isArray(m.attachments) && m.attachments.length > 0 ? { attachments: hydrateHistoryAttachmentPreviews(m.attachments) } : {}),
789
+ ...(m.speakerVpId ? { speakerVpId: m.speakerVpId } : {}),
790
+ ...(Number.isFinite(m.toolSummaryCount) && m.toolSummaryCount > 0
791
+ ? { toolSummaryCount: m.toolSummaryCount }
792
+ : (Array.isArray(m.toolCalls) && m.toolCalls.length > 0 ? { toolSummaryCount: m.toolCalls.length } : {})),
793
+ }));
794
+ }
784
795
 
796
+ function emitHistoryChunk({ sessionId, messages, mode = 'older', oldestSeq = null, hasMore = false, latestSeq = null, afterSeq = null, turns = null }) {
797
+ sendToServer({
798
+ type: 'yeaft_history_chunk',
799
+ conversationId: yeaftConversationId,
800
+ sessionId,
801
+ mode,
802
+ messages: projectVisibleHistoryChunkMessages(messages),
803
+ oldestSeq,
804
+ hasMore: !!hasMore,
805
+ latestSeq,
806
+ afterSeq,
807
+ turns,
808
+ });
809
+ }
810
+
811
+ function emitLegacyHistoryOutputFrames(replayEntries) {
785
812
  for (const entry of replayEntries) {
786
813
  if (entry.role === 'user') {
787
814
  sendSessionOutputFrame({
@@ -822,6 +849,44 @@ function emitVisibleHistoryReplay({ store, sessionId, limit, beforeSeq = null, m
822
849
  sendSessionOutputFrame({ type: 'result', result_text: '' }, envelopeOpts);
823
850
  }
824
851
  }
852
+ }
853
+
854
+ function emitVisibleHistoryReplay({ store, sessionId, limit, beforeSeq = null, mode = 'recent' }) {
855
+ const visiblePage = sessionId
856
+ ? loadVisibleGroupHistoryPage(store, sessionId, limit, beforeSeq)
857
+ : { messages: limit > 0 ? (store.loadRecent?.(limit) || []) : [], oldestSeq: null, hasMore: false };
858
+ const replayEntries = sessionId
859
+ ? visiblePage.messages
860
+ : visiblePage.messages
861
+ .map(projectPersistedToVisibleHistoryEntry)
862
+ .filter(Boolean);
863
+
864
+ if (sessionId) {
865
+ const latestSeq = replayEntries.length
866
+ ? parseSeqFromId(replayEntries[replayEntries.length - 1]?.id)
867
+ : null;
868
+ emitHistoryChunk({
869
+ sessionId,
870
+ messages: replayEntries,
871
+ mode,
872
+ oldestSeq: visiblePage.oldestSeq,
873
+ hasMore: visiblePage.hasMore,
874
+ latestSeq: Number.isFinite(latestSeq) ? latestSeq : null,
875
+ turns: limit,
876
+ });
877
+ sendSessionEvent({
878
+ type: 'history_loaded',
879
+ mode,
880
+ count: replayEntries.length,
881
+ sessionId,
882
+ hasMore: visiblePage.hasMore,
883
+ oldestSeq: visiblePage.oldestSeq,
884
+ latestSeq: Number.isFinite(latestSeq) ? latestSeq : null,
885
+ });
886
+ return;
887
+ }
888
+
889
+ emitLegacyHistoryOutputFrames(replayEntries);
825
890
 
826
891
  const latestSeq = replayEntries.length
827
892
  ? parseSeqFromId(replayEntries[replayEntries.length - 1]?.id)
@@ -4492,24 +4557,13 @@ export async function handleYeaftLoadHistory(msg) {
4492
4557
  const delta = afterSeq !== null && typeof coldStore.loadAfterSeqByGroup === 'function'
4493
4558
  ? coldStore.loadAfterSeqByGroup(sessionId, afterSeq)
4494
4559
  : { messages: [], latestSeq: null };
4495
- for (const entry of delta.messages) {
4496
- if (entry.role === 'user') {
4497
- sendSessionOutputFrame({
4498
- type: 'user',
4499
- message: { content: entry.content, id: entry.id || null },
4500
- ts: entry.ts || null,
4501
- }, { sessionId: entry.sessionId || null, threadId: entry.threadId || 'main', turnId: entry.turnId || entry.threadId || 'main' });
4502
- } else if (entry.role === 'assistant') {
4503
- const envelopeOpts = { sessionId: entry.sessionId || null, threadId: entry.threadId || 'main', turnId: entry.turnId || entry.threadId || 'main' };
4504
- if (entry.speakerVpId) envelopeOpts.vpId = entry.speakerVpId;
4505
- sendSessionOutputFrame({
4506
- type: 'assistant',
4507
- message: { id: entry.id || null, content: [{ type: 'text', text: entry.content }] },
4508
- ts: entry.ts || null,
4509
- }, envelopeOpts);
4510
- sendSessionOutputFrame({ type: 'result', result_text: '' }, envelopeOpts);
4511
- }
4512
- }
4560
+ emitHistoryChunk({
4561
+ sessionId,
4562
+ messages: delta.messages,
4563
+ mode: 'delta',
4564
+ latestSeq: delta.latestSeq,
4565
+ afterSeq,
4566
+ });
4513
4567
  sendSessionEvent({ type: 'history_loaded', mode: 'delta', count: delta.messages.length, sessionId, latestSeq: delta.latestSeq, afterSeq });
4514
4568
  } else {
4515
4569
  emitVisibleHistoryReplay({ store: coldStore, sessionId, limit, mode: 'recent' });
@@ -4585,32 +4639,13 @@ export async function handleYeaftLoadHistory(msg) {
4585
4639
  }
4586
4640
  if (sessionId && afterSeq !== null && typeof session.conversationStore.loadAfterSeqByGroup === 'function') {
4587
4641
  const delta = session.conversationStore.loadAfterSeqByGroup(sessionId, afterSeq);
4588
- for (const entry of delta.messages) {
4589
- if (entry.role === 'user') {
4590
- sendSessionOutputFrame({
4591
- type: 'user',
4592
- message: {
4593
- content: entry.content,
4594
- id: entry.id || null,
4595
- ...(Array.isArray(entry.attachments) && entry.attachments.length > 0 ? { attachments: hydrateHistoryAttachmentPreviews(entry.attachments) } : {}),
4596
- },
4597
- ts: entry.ts || null,
4598
- }, { sessionId: entry.sessionId || null, threadId: entry.threadId || 'main', turnId: entry.turnId || entry.threadId || 'main' });
4599
- } else if (entry.role === 'assistant') {
4600
- const envelopeOpts = {
4601
- sessionId: entry.sessionId || null,
4602
- threadId: entry.threadId || 'main',
4603
- turnId: entry.turnId || entry.threadId || 'main',
4604
- };
4605
- if (entry.speakerVpId) envelopeOpts.vpId = entry.speakerVpId;
4606
- sendSessionOutputFrame({
4607
- type: 'assistant',
4608
- message: { id: entry.id || null, content: [{ type: 'text', text: entry.content }] },
4609
- ts: entry.ts || null,
4610
- }, envelopeOpts);
4611
- sendSessionOutputFrame({ type: 'result', result_text: '' }, envelopeOpts);
4612
- }
4613
- }
4642
+ emitHistoryChunk({
4643
+ sessionId,
4644
+ messages: delta.messages,
4645
+ mode: 'delta',
4646
+ latestSeq: delta.latestSeq,
4647
+ afterSeq,
4648
+ });
4614
4649
  sendSessionEvent({
4615
4650
  type: 'history_loaded',
4616
4651
  mode: 'delta',
@@ -4640,49 +4675,24 @@ export async function handleYeaftLoadHistory(msg) {
4640
4675
  .map(projectPersistedToVisibleHistoryEntry)
4641
4676
  .filter(Boolean);
4642
4677
 
4643
- for (const entry of replayEntries) {
4644
- if (entry.role === 'user') {
4645
- sendSessionOutputFrame({
4646
- type: 'user',
4647
- message: {
4648
- content: entry.content,
4649
- id: entry.id || null,
4650
- ...(Array.isArray(entry.attachments) && entry.attachments.length > 0 ? { attachments: hydrateHistoryAttachmentPreviews(entry.attachments) } : {}),
4651
- },
4652
- ts: entry.ts || null,
4653
- }, { sessionId: entry.sessionId || null, threadId: entry.threadId || 'main', turnId: entry.turnId || entry.threadId || 'main' });
4654
- } else if (entry.role === 'assistant') {
4655
- // speakerVpId rides on the envelope so the frontend can route this
4656
- // replayed assistant text to the correct VP track. Without it, the
4657
- // history replay would merge replies from different VPs onto one
4658
- // anonymous assistant turn.
4659
- const envelopeOpts = {
4660
- sessionId: entry.sessionId || null,
4661
- threadId: entry.threadId || 'main',
4662
- turnId: entry.turnId || entry.threadId || 'main',
4663
- };
4664
- if (entry.speakerVpId) envelopeOpts.vpId = entry.speakerVpId;
4665
- sendSessionOutputFrame({
4666
- type: 'assistant',
4667
- message: { id: entry.id || null, content: [{ type: 'text', text: entry.content }] },
4668
- ts: entry.ts || null,
4669
- }, envelopeOpts);
4670
- if (Array.isArray(entry.toolCalls) && entry.toolCalls.length > 0) {
4671
- sendSessionOutputFrame({
4672
- type: 'assistant',
4673
- message: {
4674
- content: [{
4675
- type: 'tool_summary',
4676
- count: entry.toolCalls.length,
4677
- omittedCount: entry.toolCalls.length,
4678
- source: 'history',
4679
- }],
4680
- },
4681
- ts: entry.ts || null,
4682
- }, envelopeOpts);
4683
- }
4684
- sendSessionOutputFrame({ type: 'result', result_text: '' }, envelopeOpts);
4685
- }
4678
+ let latestSeq = null;
4679
+ if (replayEntries.length > 0 && typeof session.conversationStore.getMessageSeqById === 'function') {
4680
+ const last = replayEntries[replayEntries.length - 1];
4681
+ if (last && last.id) latestSeq = session.conversationStore.getMessageSeqById(last.id);
4682
+ }
4683
+
4684
+ if (sessionId) {
4685
+ emitHistoryChunk({
4686
+ sessionId,
4687
+ messages: replayEntries,
4688
+ mode: 'recent',
4689
+ oldestSeq: visiblePage.oldestSeq,
4690
+ hasMore: visiblePage.hasMore,
4691
+ latestSeq,
4692
+ turns: limit,
4693
+ });
4694
+ } else {
4695
+ emitLegacyHistoryOutputFrames(replayEntries);
4686
4696
  }
4687
4697
 
4688
4698
  // Compute the pagination cursor for the bootstrap load so the frontend
@@ -4706,15 +4716,6 @@ export async function handleYeaftLoadHistory(msg) {
4706
4716
  hasCompactSummaryFlag = session.conversationStore.hasAnyCompactSummaryForSession(sessionId);
4707
4717
  }
4708
4718
 
4709
- // Latest seq cursor in the recent-mode reply lets the frontend stamp its
4710
- // delta cursor on first paint, so the next session-switch can ask for
4711
- // afterSeq instead of a full recent-N replay.
4712
- let latestSeq = null;
4713
- if (replayEntries.length > 0 && typeof session.conversationStore.getMessageSeqById === 'function') {
4714
- const last = replayEntries[replayEntries.length - 1];
4715
- if (last && last.id) latestSeq = session.conversationStore.getMessageSeqById(last.id);
4716
- }
4717
-
4718
4719
  sendSessionEvent({
4719
4720
  type: 'history_loaded',
4720
4721
  mode: 'recent',
@@ -4744,15 +4745,8 @@ export async function handleYeaftLoadHistory(msg) {
4744
4745
  */
4745
4746
  export async function handleYeaftLoadMoreHistory(msg) {
4746
4747
  const sessionId = (msg && typeof msg.sessionId === 'string' && msg.sessionId) || null;
4747
- const emit = (payload) => sendToServer({
4748
- type: 'yeaft_history_chunk',
4749
- conversationId: yeaftConversationId,
4750
- sessionId,
4751
- ...payload,
4752
- });
4753
-
4754
4748
  if (!session || !sessionId) {
4755
- emit({ messages: [], oldestSeq: null, hasMore: false });
4749
+ emitHistoryChunk({ sessionId, messages: [], mode: 'older', oldestSeq: null, hasMore: false });
4756
4750
  return;
4757
4751
  }
4758
4752
 
@@ -4771,23 +4765,13 @@ export async function handleYeaftLoadMoreHistory(msg) {
4771
4765
  // user / assistant text rows. Internal reflection/system-only rows stay
4772
4766
  // server-side, and stable ids + speaker attribution ride with each row
4773
4767
  // so older-history prepend renders exactly like refresh replay.
4774
- const projected = (result.messages || [])
4775
- .map(m => ({
4776
- ...(m.id ? { id: m.id } : {}),
4777
- role: m.role,
4778
- content: m.content,
4779
- ts: m.ts || m.time || null,
4780
- sessionId: m.sessionId || null,
4781
- threadId: m.threadId || m.turnId || 'main',
4782
- turnId: m.turnId || m.threadId || 'main',
4783
- ...(Array.isArray(m.attachments) && m.attachments.length > 0 ? { attachments: hydrateHistoryAttachmentPreviews(m.attachments) } : {}),
4784
- ...(m.speakerVpId ? { speakerVpId: m.speakerVpId } : {}),
4785
- }));
4786
-
4787
- emit({
4788
- messages: projected,
4768
+ emitHistoryChunk({
4769
+ sessionId,
4770
+ messages: result.messages || [],
4771
+ mode: 'older',
4789
4772
  oldestSeq: result.oldestSeq,
4790
4773
  hasMore: !!result.hasMore,
4774
+ turns,
4791
4775
  });
4792
4776
  }
4793
4777