@xopcai/xopc 0.0.158 → 0.0.159

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.
Files changed (105) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/dashscope/src/image-generation-provider.js +1 -1
  3. package/dist/extensions/fal/src/image-generation-provider.js +1 -1
  4. package/dist/extensions/google/src/image-generation-provider.js +1 -1
  5. package/dist/extensions/telegram/xopc.extension.json +1 -1
  6. package/dist/gateway/static/root/assets/{action-boundary-settings-panel-2p1f4-KA.js → action-boundary-settings-panel-CaRK2vIy.js} +1 -1
  7. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BIl6X2b_.js → agent-avatar-dicebear-BeVf03hx.js} +1 -1
  8. package/dist/gateway/static/root/assets/{agents-bnkKH9EI.js → agents-P05C4A-3.js} +1 -1
  9. package/dist/gateway/static/root/assets/{app-management-settings-panel-CZxw161D.js → app-management-settings-panel-BG2ulMYw.js} +1 -1
  10. package/dist/gateway/static/root/assets/{appearance-settings-CRXNlDhH.js → appearance-settings-0Kjenr2T.js} +1 -1
  11. package/dist/gateway/static/root/assets/{apps-page-l4ripRNG.js → apps-page-DANGrBpN.js} +1 -1
  12. package/dist/gateway/static/root/assets/{archive-plugin-CpVshjXu.js → archive-plugin-ChiNnH1e.js} +1 -1
  13. package/dist/gateway/static/root/assets/{attachment-load-M9WqqJnQ.js → attachment-load-pbBlQR-g.js} +1 -1
  14. package/dist/gateway/static/root/assets/{automation-suggestion-card-CYMsAsYf.js → automation-suggestion-card-CTZDOyDy.js} +1 -1
  15. package/dist/gateway/static/root/assets/{automations-page-Kny7tLiF.js → automations-page-BXfGL_cm.js} +1 -1
  16. package/dist/gateway/static/root/assets/{binary-plugins-Cjn3zb4u.js → binary-plugins-BeZGzpGF.js} +1 -1
  17. package/dist/gateway/static/root/assets/{block-editor-BPKdquaV.js → block-editor-BnDmhN5Z.js} +1 -1
  18. package/dist/gateway/static/root/assets/{browser-settings-page-vr1tXAab.js → browser-settings-page-534luV0B.js} +1 -1
  19. package/dist/gateway/static/root/assets/{capability-presets-api-Bzkcsyzn.js → capability-presets-api-Ii36j_7v.js} +1 -1
  20. package/dist/gateway/static/root/assets/{capability-presets-settings-panel-D4rH4Dax.js → capability-presets-settings-panel-Cl3dw4yh.js} +1 -1
  21. package/dist/gateway/static/root/assets/{channels-settings-Tlhbi5eh.js → channels-settings-M91zFJVi.js} +1 -1
  22. package/dist/gateway/static/root/assets/{connector-logo-ljPKdYKh.js → connector-logo-CiLxuZ8S.js} +1 -1
  23. package/dist/gateway/static/root/assets/{connectors-page-_XfvjXoY.js → connectors-page-CV5UulW6.js} +1 -1
  24. package/dist/gateway/static/root/assets/{desktop-pet-DKUlAgm7.js → desktop-pet-Cil2eSpW.js} +1 -1
  25. package/dist/gateway/static/root/assets/{desktop-pet-settings-aWWzjdza.js → desktop-pet-settings-DwsC6l5F.js} +1 -1
  26. package/dist/gateway/static/root/assets/{directory-picker-path-field-Dmy1035j.js → directory-picker-path-field-CC2VL5Mc.js} +1 -1
  27. package/dist/gateway/static/root/assets/{dreaming-settings-tT4WkBkd.js → dreaming-settings-KY7ZfVsy.js} +1 -1
  28. package/dist/gateway/static/root/assets/{extension-debug-page-CL79q8AH.js → extension-debug-page-C8KBeucs.js} +1 -1
  29. package/dist/gateway/static/root/assets/{extension-page-hq80wkFI.js → extension-page-CV-5Kcyk.js} +1 -1
  30. package/dist/gateway/static/root/assets/{extension-settings-page-BV-9GDfT.js → extension-settings-page-DvUtDrAu.js} +1 -1
  31. package/dist/gateway/static/root/assets/{gateway-config-api-CFqoN2NW.js → gateway-config-api-DXfVeJLc.js} +1 -1
  32. package/dist/gateway/static/root/assets/{gateway-settings-DzR-kM91.js → gateway-settings-BpJ0v56l.js} +1 -1
  33. package/dist/gateway/static/root/assets/{goal-create-dialog-BLjHRtqe.js → goal-create-dialog-lMHD-2CX.js} +1 -1
  34. package/dist/gateway/static/root/assets/{goal-detail-page-BRxeujXh.js → goal-detail-page-yPmF-G7b.js} +1 -1
  35. package/dist/gateway/static/root/assets/{goals-config-api--qJ4qlRq.js → goals-config-api-P8VhLqYF.js} +1 -1
  36. package/dist/gateway/static/root/assets/{goals-page-BaZ3aw4u.js → goals-page-BHTCKobG.js} +1 -1
  37. package/dist/gateway/static/root/assets/{goals-settings-h7x9h5lb.js → goals-settings-DHXyaH_O.js} +1 -1
  38. package/dist/gateway/static/root/assets/{heartbeat-settings-71IhhM3s.js → heartbeat-settings-CNckP_Dv.js} +1 -1
  39. package/dist/gateway/static/root/assets/index-BgZhEOkN.css +1 -0
  40. package/dist/gateway/static/root/assets/{index-EXa_i6BT.js → index-BuqGh2SW.js} +65 -65
  41. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BZGmHvLu.js → keyboard-shortcuts-settings-jXmv1RVX.js} +1 -1
  42. package/dist/gateway/static/root/assets/{local-app-workbench-page-lUpd6lSo.js → local-app-workbench-page-zpp_wciE.js} +1 -1
  43. package/dist/gateway/static/root/assets/{local-apps-page-CiLqrMIh.js → local-apps-page-Cs5LKjtc.js} +1 -1
  44. package/dist/gateway/static/root/assets/{logs-page-FPDTmcWe.js → logs-page-B4CRYqYR.js} +1 -1
  45. package/dist/gateway/static/root/assets/{markdown-split-r1HPWfCU.js → markdown-split-BFqeSNte.js} +1 -1
  46. package/dist/gateway/static/root/assets/{media-plugins-D74kd3hn.js → media-plugins-Cc8379gq.js} +1 -1
  47. package/dist/gateway/static/root/assets/{models-hub-panel-BXrdePhv.js → models-hub-panel-1hdoAoB_.js} +1 -1
  48. package/dist/gateway/static/root/assets/{notes-page-Dgu02514.js → notes-page-DlGU4ipo.js} +1 -1
  49. package/dist/gateway/static/root/assets/{notes-workbench-D-EAhXv1.js → notes-workbench-DQEAZTA5.js} +2 -2
  50. package/dist/gateway/static/root/assets/{page-tabs-hinRdDy3.js → page-tabs-kFOswGlG.js} +1 -1
  51. package/dist/gateway/static/root/assets/{preview-open-alternatives-C7fw3oGy.js → preview-open-alternatives-CvjuvABg.js} +1 -1
  52. package/dist/gateway/static/root/assets/{project-detail-page-BjpB1wrp.js → project-detail-page-Bp9bC7A6.js} +1 -1
  53. package/dist/gateway/static/root/assets/{projects-page-BxyjqOfC.js → projects-page-RNorFXTw.js} +1 -1
  54. package/dist/gateway/static/root/assets/{remote-access-hub-BFv6Upke.js → remote-access-hub-BqRTcM_6.js} +1 -1
  55. package/dist/gateway/static/root/assets/{save-bar-controls-C3aU8-vO.js → save-bar-controls-DwrD7ODx.js} +1 -1
  56. package/dist/gateway/static/root/assets/{schedule-field-DjegExFD.js → schedule-field-Ba4WzTmE.js} +1 -1
  57. package/dist/gateway/static/root/assets/{schema-form-DLubnsql.js → schema-form-DvydL8eF.js} +1 -1
  58. package/dist/gateway/static/root/assets/{sessions-page-BX4DH8J7.js → sessions-page-B2EfW1cm.js} +1 -1
  59. package/dist/gateway/static/root/assets/settings-advanced-gate-CklL85T4.js +1 -0
  60. package/dist/gateway/static/root/assets/{settings-collapsible-section-3syQHsNR.js → settings-collapsible-section-LaQqGGej.js} +1 -1
  61. package/dist/gateway/static/root/assets/{settings-form-section-D4DCZzKg.js → settings-form-section-DruI__qO.js} +1 -1
  62. package/dist/gateway/static/root/assets/{settings-loading-skeleton-c5K85ylS.js → settings-loading-skeleton-UvA-eDhF.js} +1 -1
  63. package/dist/gateway/static/root/assets/{settings-page-DNiDlaRq.js → settings-page-5oCGSebm.js} +1 -1
  64. package/dist/gateway/static/root/assets/{settings-page-layout-iTRY1Hy-.js → settings-page-layout-DG-XMIPu.js} +1 -1
  65. package/dist/gateway/static/root/assets/{setup-status-panel-BH4xQKM9.js → setup-status-panel-D3my1HgB.js} +1 -1
  66. package/dist/gateway/static/root/assets/{share-preview-page-B88Afrhe.js → share-preview-page-FLVeTrRt.js} +1 -1
  67. package/dist/gateway/static/root/assets/{shares-settings-B6kKkvOb.js → shares-settings-DVxgjrsP.js} +1 -1
  68. package/dist/gateway/static/root/assets/{skill-reload-api-DtjS-nUK.js → skill-reload-api-Bcu58ZaF.js} +1 -1
  69. package/dist/gateway/static/root/assets/{skills-page-CQEoPv0u.js → skills-page-CDd-84FE.js} +1 -1
  70. package/dist/gateway/static/root/assets/{system-settings-panel-DtpTq837.js → system-settings-panel-CeK93xVi.js} +1 -1
  71. package/dist/gateway/static/root/assets/{typed-models-lib-ndEnUP3b.js → typed-models-lib-D1Lr2gG0.js} +1 -1
  72. package/dist/gateway/static/root/assets/{user-context-page-Dn2T3itn.js → user-context-page-1OyJnTyR.js} +1 -1
  73. package/dist/gateway/static/root/assets/{voice-api-key-field-wtWc3SfN.js → voice-api-key-field-B2ncRwHS.js} +1 -1
  74. package/dist/gateway/static/root/assets/{work-discovery-page-Ckxhj66e.js → work-discovery-page-BZlY4PZL.js} +1 -1
  75. package/dist/gateway/static/root/assets/{work-item-detail-page-_1QgGPNw.js → work-item-detail-page-DPXMrneY.js} +1 -1
  76. package/dist/gateway/static/root/assets/{work-page-BPdf2iuv.js → work-page-CTERoqyv.js} +1 -1
  77. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-ukmpkj66.js → workflow-run-setup-panel-Bynqe4kV.js} +1 -1
  78. package/dist/gateway/static/root/assets/{workflows-page-DdKTx0Hs.js → workflows-page-CLgsnqFQ.js} +1 -1
  79. package/dist/gateway/static/root/index.html +2 -2
  80. package/dist/package.js +1 -1
  81. package/dist/src/agent/embedded/session-tool-result-guard.js +14 -0
  82. package/dist/src/agent/image/generation/openai-compatible-image-provider.js +1 -1
  83. package/dist/src/agent/service/process-direct-streaming.js +1 -1
  84. package/dist/src/agent/tools/image-generate-tool.js +10 -3
  85. package/dist/src/agent/tools/send-media.js +20 -70
  86. package/dist/src/agent/tools/tool-media.d.ts +9 -0
  87. package/dist/src/agent/tools/tool-media.js +58 -0
  88. package/dist/src/config/agent-profile.js +1 -1
  89. package/dist/src/gateway/agent-run-relay.d.ts +2 -0
  90. package/dist/src/gateway/agent-run-relay.js +114 -14
  91. package/dist/src/gateway/agents-admin.js +1 -1
  92. package/dist/src/gateway/chat-stream/mapper.d.ts +1 -1
  93. package/dist/src/gateway/chat-stream/mapper.js +27 -42
  94. package/dist/src/gateway/chat-stream/thinking-delta-coalescer.d.ts +7 -0
  95. package/dist/src/gateway/chat-stream/thinking-delta-coalescer.js +103 -0
  96. package/dist/src/gateway/hono/sse.d.ts +1 -1
  97. package/dist/src/gateway/hono/sse.js +1 -1
  98. package/dist/src/gateway/service/run-gateway-agent.js +5 -1
  99. package/dist/src/media/session-references.js +9 -6
  100. package/dist/src/session/client-history.d.ts +1 -0
  101. package/dist/src/session/client-history.js +56 -12
  102. package/dist/src/session/types.d.ts +1 -0
  103. package/package.json +1 -1
  104. package/dist/gateway/static/root/assets/index-gpwk8Nro.css +0 -1
  105. package/dist/gateway/static/root/assets/settings-advanced-gate-CJ9MbRP8.js +0 -1
@@ -0,0 +1,103 @@
1
+ //#region src/gateway/chat-stream/thinking-delta-coalescer.ts
2
+ const DEFAULT_WINDOW_MS = 24;
3
+ const DEFAULT_MAX_CHARS = 256;
4
+ function isThinkingDelta(event) {
5
+ return event.type === "thinking_delta";
6
+ }
7
+ function belongsToSameThinkingStream(left, right) {
8
+ return left.runId === right.runId && left.sessionKey === right.sessionKey && left.payload.messageId === right.payload.messageId;
9
+ }
10
+ function mergeThinkingDelta(left, right) {
11
+ return {
12
+ ...left,
13
+ payload: {
14
+ ...left.payload,
15
+ delta: left.payload.delta + right.payload.delta
16
+ }
17
+ };
18
+ }
19
+ async function nextBeforeDeadline(next, deadlineAt) {
20
+ let timer;
21
+ try {
22
+ return await Promise.race([next.then((result) => ({
23
+ kind: "next",
24
+ result
25
+ })), new Promise((resolve) => {
26
+ timer = setTimeout(() => resolve({ kind: "timeout" }), Math.max(0, deadlineAt - Date.now()));
27
+ })]);
28
+ } finally {
29
+ if (timer !== void 0) clearTimeout(timer);
30
+ }
31
+ }
32
+ async function* coalesceThinkingDeltas(source, options = {}) {
33
+ const windowMs = options.windowMs ?? DEFAULT_WINDOW_MS;
34
+ const maxChars = options.maxChars ?? DEFAULT_MAX_CHARS;
35
+ if (!Number.isFinite(windowMs) || windowMs <= 0) throw new Error("thinking delta coalescer windowMs must be greater than zero");
36
+ if (!Number.isInteger(maxChars) || maxChars <= 0) throw new Error("thinking delta coalescer maxChars must be a positive integer");
37
+ const iterator = source[Symbol.asyncIterator]();
38
+ let next = iterator.next();
39
+ let pending;
40
+ let deadlineAt = 0;
41
+ try {
42
+ while (true) {
43
+ if (!pending) {
44
+ const result = await next;
45
+ if (result.done) break;
46
+ next = iterator.next();
47
+ if (!isThinkingDelta(result.value)) {
48
+ yield result.value;
49
+ continue;
50
+ }
51
+ pending = result.value;
52
+ deadlineAt = Date.now() + windowMs;
53
+ if (pending.payload.delta.length >= maxChars) {
54
+ yield pending;
55
+ pending = void 0;
56
+ }
57
+ continue;
58
+ }
59
+ const outcome = await nextBeforeDeadline(next, deadlineAt);
60
+ if (outcome.kind === "timeout") {
61
+ yield pending;
62
+ pending = void 0;
63
+ continue;
64
+ }
65
+ const result = outcome.result;
66
+ if (result.done) {
67
+ yield pending;
68
+ pending = void 0;
69
+ break;
70
+ }
71
+ next = iterator.next();
72
+ const event = result.value;
73
+ if (!isThinkingDelta(event) || !belongsToSameThinkingStream(pending, event)) {
74
+ yield pending;
75
+ pending = void 0;
76
+ if (isThinkingDelta(event)) {
77
+ pending = event;
78
+ deadlineAt = Date.now() + windowMs;
79
+ if (pending.payload.delta.length >= maxChars) {
80
+ yield pending;
81
+ pending = void 0;
82
+ }
83
+ } else yield event;
84
+ continue;
85
+ }
86
+ pending = mergeThinkingDelta(pending, event);
87
+ if (pending.payload.delta.length >= maxChars) {
88
+ yield pending;
89
+ pending = void 0;
90
+ }
91
+ }
92
+ } catch (error) {
93
+ if (pending) {
94
+ yield pending;
95
+ pending = void 0;
96
+ }
97
+ throw error;
98
+ } finally {
99
+ await iterator.return?.();
100
+ }
101
+ }
102
+ //#endregion
103
+ export { coalesceThinkingDeltas };
@@ -23,7 +23,7 @@ export declare function createAgentSSEHandler(config: SSEHandlerConfig): (c: Con
23
23
  * POST /api/agent/resume — Re-attach to an in-progress agent run via SSE.
24
24
  *
25
25
  * Request body: { runId, sessionKey }
26
- * The relay replays all buffered events from the beginning and then live-tails
26
+ * The relay replays retained buffered events from the beginning and then live-tails
27
27
  * until the run completes.
28
28
  *
29
29
  * SSE events are identical to those from POST /api/agent.
@@ -168,7 +168,7 @@ function createAgentSSEHandler(config) {
168
168
  * POST /api/agent/resume — Re-attach to an in-progress agent run via SSE.
169
169
  *
170
170
  * Request body: { runId, sessionKey }
171
- * The relay replays all buffered events from the beginning and then live-tails
171
+ * The relay replays retained buffered events from the beginning and then live-tails
172
172
  * until the run completes.
173
173
  *
174
174
  * SSE events are identical to those from POST /api/agent.
@@ -7,6 +7,7 @@ import { shouldSkipWebchatInboundByAbortCutoff } from "../../session/abort-cutof
7
7
  import "../chat-limits.js";
8
8
  import { resolveWebchatSessionKey } from "../resolve-webchat-session-key.js";
9
9
  import { ChatStreamMapper } from "../chat-stream/mapper.js";
10
+ import { coalesceThinkingDeltas } from "../chat-stream/thinking-delta-coalescer.js";
10
11
  import crypto from "crypto";
11
12
  //#region src/gateway/service/run-gateway-agent.ts
12
13
  init_logger();
@@ -90,7 +91,10 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
90
91
  signal: mergedSignal,
91
92
  runId
92
93
  });
93
- for await (const event of eventStream) yield* emitAndYield(mapper.map(event));
94
+ const mappedEvents = (async function* () {
95
+ for await (const event of eventStream) yield* mapper.map(event);
96
+ })();
97
+ for await (const event of coalesceThinkingDeltas(mappedEvents)) yield* emitAndYield([event]);
94
98
  const endStatus = mergedSignal.aborted ? "cancelled" : "success";
95
99
  const endSummary = mergedSignal.aborted ? "Interrupted" : "Message processed successfully";
96
100
  yield* emitAndYield(mapper.end(endStatus, endSummary));
@@ -1,25 +1,28 @@
1
1
  import { tryParseMediaUri } from "./uri.js";
2
2
  import { deleteMediaBuffer } from "./store.js";
3
3
  //#region src/media/session-references.ts
4
- function collectFromValue(value, out) {
4
+ function collectFromValue(value, out, seen) {
5
5
  if (!value) return;
6
6
  if (typeof value === "string") {
7
7
  if (value.startsWith("media://")) out.add(value.trim());
8
8
  return;
9
9
  }
10
10
  if (Array.isArray(value)) {
11
- for (const item of value) collectFromValue(item, out);
11
+ if (seen.has(value)) return;
12
+ seen.add(value);
13
+ for (const item of value) collectFromValue(item, out, seen);
12
14
  return;
13
15
  }
14
16
  if (typeof value !== "object") return;
17
+ if (seen.has(value)) return;
18
+ seen.add(value);
15
19
  const record = value;
16
- if (typeof record.uri === "string" && record.uri.startsWith("media://")) out.add(record.uri.trim());
17
- if (Array.isArray(record.media)) collectFromValue(record.media, out);
18
- if (Array.isArray(record.attachments)) collectFromValue(record.attachments, out);
20
+ for (const nested of Object.values(record)) collectFromValue(nested, out, seen);
19
21
  }
20
22
  function collectMediaUrisFromMessages(messages) {
21
23
  const out = /* @__PURE__ */ new Set();
22
- for (const message of messages) collectFromValue(message, out);
24
+ const seen = /* @__PURE__ */ new WeakSet();
25
+ for (const message of messages) collectFromValue(message, out, seen);
23
26
  return out;
24
27
  }
25
28
  function messagesReferenceMediaUri(messages, uri) {
@@ -36,6 +36,7 @@ export interface ClientHistoryMessage {
36
36
  args?: unknown;
37
37
  result?: string;
38
38
  isError?: boolean;
39
+ details?: unknown;
39
40
  }>;
40
41
  }
41
42
  export declare function flattenMessageContent(content: string | unknown[]): string;
@@ -33,22 +33,65 @@ function collectToolResults(messages) {
33
33
  if (!id || typeof id !== "string") continue;
34
34
  map.set(id, {
35
35
  text: flattenMessageContent(m.content),
36
- isError: m.isError
36
+ isError: m.isError,
37
+ details: m.details
37
38
  });
38
39
  }
39
40
  return map;
40
41
  }
41
- function toolCallsWithResults(tool_calls, results) {
42
- if (!tool_calls?.length) return void 0;
42
+ function collectMessageToolCalls(content, openAiToolCalls, rawToolCalls) {
43
43
  const out = [];
44
- for (const tc of tool_calls) {
45
- const res = results.get(tc.id);
44
+ const seen = /* @__PURE__ */ new Set();
45
+ const add = (call) => {
46
+ const key = call.id ? `id:${call.id}` : `position:${out.length}`;
47
+ if (seen.has(key)) return;
48
+ seen.add(key);
49
+ out.push(call);
50
+ };
51
+ for (const call of openAiToolCalls ?? []) add({
52
+ id: call.id,
53
+ name: call.function.name,
54
+ args: safeJsonParseArguments(call.function.arguments)
55
+ });
56
+ for (const item of Array.isArray(rawToolCalls) ? rawToolCalls : []) {
57
+ if (!item || typeof item !== "object") continue;
58
+ const call = item;
59
+ const name = typeof call.name === "string" ? call.name : void 0;
60
+ if (!name) continue;
61
+ add({
62
+ id: typeof call.id === "string" ? call.id : void 0,
63
+ name,
64
+ args: call.args ?? call.arguments ?? call.input
65
+ });
66
+ }
67
+ for (const item of Array.isArray(content) ? content : []) {
68
+ if (!item || typeof item !== "object") continue;
69
+ const call = item;
70
+ if (call.type !== "toolCall" && call.type !== "tool_use" && call.type !== "tool_call") continue;
71
+ const fn = call.function && typeof call.function === "object" ? call.function : void 0;
72
+ const name = typeof call.name === "string" ? call.name : typeof fn?.name === "string" ? fn.name : void 0;
73
+ if (!name) continue;
74
+ const rawArgs = call.arguments ?? call.args ?? call.input ?? fn?.arguments;
75
+ add({
76
+ id: typeof call.id === "string" ? call.id : void 0,
77
+ name,
78
+ args: typeof rawArgs === "string" ? safeJsonParseArguments(rawArgs) : rawArgs
79
+ });
80
+ }
81
+ return out.length ? out : void 0;
82
+ }
83
+ function toolCallsWithResults(toolCalls, results) {
84
+ if (!toolCalls?.length) return void 0;
85
+ const out = [];
86
+ for (const call of toolCalls) {
87
+ const res = call.id ? results.get(call.id) : void 0;
46
88
  out.push({
47
- id: tc.id,
48
- name: tc.function.name,
49
- args: safeJsonParseArguments(tc.function.arguments),
89
+ id: call.id,
90
+ name: call.name,
91
+ args: call.args,
50
92
  result: res?.text,
51
- isError: res?.isError
93
+ isError: res?.isError,
94
+ details: res?.details
52
95
  });
53
96
  }
54
97
  return out.length ? out : void 0;
@@ -74,7 +117,7 @@ function messagesToClientHistory(messages, opts) {
74
117
  }
75
118
  if (m.role === "assistant") {
76
119
  const text = flattenMessageContent(m.content);
77
- const toolCalls = toolCallsWithResults(m.tool_calls, results);
120
+ const toolCalls = toolCallsWithResults(collectMessageToolCalls(m.content, m.tool_calls), results);
78
121
  out.push({
79
122
  role: "assistant",
80
123
  content: text,
@@ -108,7 +151,8 @@ function collectHistoryToolResults(messages) {
108
151
  if (!id || typeof id !== "string") continue;
109
152
  map.set(id, {
110
153
  text: flattenMessageContent(m.content ?? ""),
111
- isError: m.isError
154
+ isError: m.isError,
155
+ details: m.details
112
156
  });
113
157
  }
114
158
  return map;
@@ -380,7 +424,7 @@ function transcriptRowsToClientHistory(rows, opts) {
380
424
  ...rawContent ? { rawContent } : {},
381
425
  ...displayIndex !== void 0 ? { displayIndex } : {},
382
426
  timestamp: parseTimestampValue(messageRow.timestamp),
383
- toolCalls: toolCallsWithResults(messageRow.tool_calls ?? messageRow.toolCalls, results)
427
+ toolCalls: toolCallsWithResults(collectMessageToolCalls(messageRow.content, messageRow.tool_calls, messageRow.toolCalls), results)
384
428
  });
385
429
  }
386
430
  return out;
@@ -16,6 +16,7 @@ export interface Message {
16
16
  tool_call_id$?: string;
17
17
  toolName?: string;
18
18
  isError?: boolean;
19
+ details?: unknown;
19
20
  name?: string;
20
21
  /** Token usage from the LLM response (assistant messages only). */
21
22
  usage?: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xopcai/xopc",
3
- "version": "0.0.158",
3
+ "version": "0.0.159",
4
4
  "description": "Local-first AI system that remembers context, coordinates AI, and sustains long-term progress.",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",