@bivy/bivy 0.20.9-staging.24 → 0.20.9-staging.26

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 (106) hide show
  1. package/dist/agent-instructions.js +2 -1
  2. package/dist/harness/checkpoint.js +0 -0
  3. package/dist/runtime/tool-call-map.js +1 -1
  4. package/dist/runtime/tool-trace.js +1 -1
  5. package/dist/session/message-components.js +84 -4
  6. package/dist/session/transcript-persistence.js +35 -5
  7. package/package.json +1 -1
  8. package/web/assets/AutomationsView-DmpG0A2d.js +51 -0
  9. package/web/assets/{ChangesCard-ByhRAYmh.js → ChangesCard-MnYxEII6.js} +1 -1
  10. package/web/assets/{LibraryView-J-kA-Jm3.js → LibraryView-Dgy0RDJ9.js} +1 -1
  11. package/web/assets/{ProviderConnect-BH8tKbe1.js → ProviderConnect-BPKzKW-3.js} +1 -1
  12. package/web/assets/{SessionList-DZO4taQR.js → SessionList-qxtogmTB.js} +1 -1
  13. package/web/assets/{Settings-DV61uqOo.js → Settings-Bq4kmS2N.js} +3 -3
  14. package/web/assets/{Sheet-D7p0lXGX.js → Sheet-BStsfXWj.js} +1 -1
  15. package/web/assets/{Terminal-CmuN7G25.js → Terminal-B7uN0hzl.js} +1 -1
  16. package/web/assets/{VoiceSettings-CShtnKWL.js → VoiceSettings-DVOJ7bhm.js} +1 -1
  17. package/web/assets/{abnfDiagram-VCTEODGH-D95pekeA.js → abnfDiagram-VCTEODGH-DMJ9w-Gd.js} +1 -1
  18. package/web/assets/architecture-7GRP2DOG-C8QAIGJw.js +1 -0
  19. package/web/assets/{architectureDiagram-5GKGNRK7-DI1_GW-J.js → architectureDiagram-5GKGNRK7-ChXoo05D.js} +1 -1
  20. package/web/assets/{blockDiagram-I7D4REHJ-QSlF6isg.js → blockDiagram-I7D4REHJ-DZX289s_.js} +1 -1
  21. package/web/assets/{c4Diagram-7LVT6UL2-DHi3FF4B.js → c4Diagram-7LVT6UL2-DWrh10Ke.js} +1 -1
  22. package/web/assets/channel-Cegd5v_e.js +1 -0
  23. package/web/assets/{chunk-4HAMMTFA-JQBmUbHj.js → chunk-4HAMMTFA-BMUPp7ah.js} +1 -1
  24. package/web/assets/{chunk-75Z2AOVW-BMwWVudc.js → chunk-75Z2AOVW-S_Lqeycl.js} +1 -1
  25. package/web/assets/{chunk-DU6HZSFF-CAY7bniW.js → chunk-DU6HZSFF-ByvxKoJE.js} +1 -1
  26. package/web/assets/{chunk-F27PBJKO-CgE1EFzj.js → chunk-F27PBJKO-DV2WohGL.js} +1 -1
  27. package/web/assets/{chunk-GMAD6QVW-DwNlSP9L.js → chunk-GMAD6QVW-DMHrNFhF.js} +1 -1
  28. package/web/assets/{chunk-GVQU2GXP-fGVxCD_F.js → chunk-GVQU2GXP-CBJMgIgv.js} +1 -1
  29. package/web/assets/{chunk-IMKFNOWR-BD1WeML6.js → chunk-IMKFNOWR-BBYSJuSR.js} +1 -1
  30. package/web/assets/{chunk-L3NEJ4N5-DJYkNPNf.js → chunk-L3NEJ4N5-CBfNG4NB.js} +1 -1
  31. package/web/assets/{chunk-OSK3NFVY-C0m069z_.js → chunk-OSK3NFVY-DhTm62Wo.js} +1 -1
  32. package/web/assets/{chunk-P2QGCYS3-IDYngoaS.js → chunk-P2QGCYS3-C8KBtXRm.js} +1 -1
  33. package/web/assets/{chunk-POPQ4Y6H-KXcxqr3K.js → chunk-POPQ4Y6H-1ZdD_cfb.js} +1 -1
  34. package/web/assets/{chunk-PWAF6VOD-BdvyAV_O.js → chunk-PWAF6VOD-bVFoxXgJ.js} +1 -1
  35. package/web/assets/{chunk-SHT3W25Y-uNq-Jutp.js → chunk-SHT3W25Y-PZoRcBIi.js} +1 -1
  36. package/web/assets/{chunk-SVP7TREG-mp7c-iQn.js → chunk-SVP7TREG-YqptXnk5.js} +1 -1
  37. package/web/assets/{chunk-TICWLB2K-BvPLestV.js → chunk-TICWLB2K-BXdDCPmK.js} +1 -1
  38. package/web/assets/classDiagram-ZZMXUADV-C1F2-BOm.js +1 -0
  39. package/web/assets/classDiagram-v2-VYDZK3BY-C1F2-BOm.js +1 -0
  40. package/web/assets/{cynefin-OW5HDTMX-CBFkS-bt.js → cynefin-OW5HDTMX-B1yk_pYn.js} +1 -1
  41. package/web/assets/{cynefinDiagram-5FMLGOSQ-CDNgEMTb.js → cynefinDiagram-5FMLGOSQ-VIFTAKKv.js} +1 -1
  42. package/web/assets/{dagre-GXQ25YYZ-DGNVoeyR.js → dagre-GXQ25YYZ-xlSUoorU.js} +1 -1
  43. package/web/assets/{diagram-S7CK7UJ4-D55nw9Kx.js → diagram-S7CK7UJ4-DHSlluS0.js} +1 -1
  44. package/web/assets/{diagram-UQ7AKVKN-DUgGiXxV.js → diagram-UQ7AKVKN-BobUeJCF.js} +1 -1
  45. package/web/assets/{diagram-VSXAHHWV-CC45e9Ne.js → diagram-VSXAHHWV-Djm_2Ydy.js} +1 -1
  46. package/web/assets/{diagram-VX7I27RA-D15ywN82.js → diagram-VX7I27RA-CixOqShF.js} +1 -1
  47. package/web/assets/{diagram-Z3DM3KII-BoYYMFGb.js → diagram-Z3DM3KII-DXYwUQvp.js} +1 -1
  48. package/web/assets/{ebnfDiagram-PWID7BFC-CQtBznEw.js → ebnfDiagram-PWID7BFC-bGfwjP4s.js} +1 -1
  49. package/web/assets/{erDiagram-RLTQ6QDP-CInRjf9X.js → erDiagram-RLTQ6QDP-BkL3bf_c.js} +1 -1
  50. package/web/assets/eventmodeling-NTZA5JFV-Cx_Qoqa9.js +1 -0
  51. package/web/assets/flowDiagram-HODETNUW-CzzUtl9c.js +1 -0
  52. package/web/assets/{ganttDiagram-EL5Y4UJY-Do547IJT.js → ganttDiagram-EL5Y4UJY-CQZN3YeS.js} +1 -1
  53. package/web/assets/{gitGraph-4MIJSDKK-DpOO8SSi.js → gitGraph-4MIJSDKK-DZnCbmQI.js} +1 -1
  54. package/web/assets/{gitGraphDiagram-WWUBYQGX-lUszrVZk.js → gitGraphDiagram-WWUBYQGX-DsE3BvGm.js} +1 -1
  55. package/web/assets/{index-DyWi0mtQ.js → index-Cwu0Upat.js} +2 -2
  56. package/web/assets/{info-A6RAGUB7-DhOV6aVh.js → info-A6RAGUB7-CiQhcF59.js} +1 -1
  57. package/web/assets/{infoDiagram-27XIBGKW-Mw7oZ5cm.js → infoDiagram-27XIBGKW-BK7_G-Rv.js} +1 -1
  58. package/web/assets/{ishikawaDiagram-5VMMS53U-EpL3kS56.js → ishikawaDiagram-5VMMS53U-DwEXkGbl.js} +1 -1
  59. package/web/assets/{journeyDiagram-3NMN7TZE-D51yEH4E.js → journeyDiagram-3NMN7TZE-BFEfYmn1.js} +1 -1
  60. package/web/assets/{kanban-definition-UXKFOSKX-Y1vRkTVO.js → kanban-definition-UXKFOSKX-BGHHTvjY.js} +1 -1
  61. package/web/assets/{mermaid-parser.core-DtPxdsjO.js → mermaid-parser.core-BicayJF_.js} +3 -3
  62. package/web/assets/{mermaid.core-BylpZcyV.js → mermaid.core-CFd-eua3.js} +4 -4
  63. package/web/assets/{mindmap-definition-YA3MSWOX-Dr1fA4iP.js → mindmap-definition-YA3MSWOX-dXnvoZdd.js} +1 -1
  64. package/web/assets/mount-COlEtDSc.js +36 -0
  65. package/web/assets/{packet-AYTQ26CC-CVpucVjd.js → packet-AYTQ26CC-Dlk4XpLp.js} +1 -1
  66. package/web/assets/{pegDiagram-XKGWAZYB-BuCuf1WI.js → pegDiagram-XKGWAZYB-CrqdR0_-.js} +1 -1
  67. package/web/assets/{pie-WAS4IAKB-BN--YcSz.js → pie-WAS4IAKB-BkO3XUQE.js} +1 -1
  68. package/web/assets/{pieDiagram-E7YTZNPT-PxXq9Wbi.js → pieDiagram-E7YTZNPT-BFDb2LSV.js} +1 -1
  69. package/web/assets/{quadrantDiagram-AXDQQJYC-CGMxreo-.js → quadrantDiagram-AXDQQJYC-DaNSrCCT.js} +1 -1
  70. package/web/assets/{radar-RG4KPBEZ-BsLIKubu.js → radar-RG4KPBEZ-BWrmhxp6.js} +1 -1
  71. package/web/assets/{railroad-74A4TZTK-BaODjM48.js → railroad-74A4TZTK-Cu7Q7Rok.js} +1 -1
  72. package/web/assets/railroad-abnf-HS5TGJTU-BlfjFDjh.js +1 -0
  73. package/web/assets/railroad-ebnf-LZEXJU2U-wQByly-B.js +1 -0
  74. package/web/assets/railroad-peg-WCYAUIDC-CzTmW96x.js +1 -0
  75. package/web/assets/{railroadDiagram-O6MQD6OU-NP3WJzji.js → railroadDiagram-O6MQD6OU-CjDi9ktT.js} +1 -1
  76. package/web/assets/{requirementDiagram-BXWQKSXE-Cn7OywoW.js → requirementDiagram-BXWQKSXE-C5_u4Gsv.js} +1 -1
  77. package/web/assets/{sankeyDiagram-P5KCCOFB-DoA_CUXe.js → sankeyDiagram-P5KCCOFB-BRGbnGwX.js} +1 -1
  78. package/web/assets/{sequenceDiagram-WJ2MYXX4-BeQ1-1N-.js → sequenceDiagram-WJ2MYXX4-C5YMU5on.js} +1 -1
  79. package/web/assets/{settingsRoute-D-ab1eq6.js → settingsRoute-D-Q_gBJG.js} +1 -1
  80. package/web/assets/{stateDiagram-D77RDMKH-Xybtc6th.js → stateDiagram-D77RDMKH-5EO5EMUS.js} +1 -1
  81. package/web/assets/stateDiagram-v2-MP3YSRHH-Bxmq54qM.js +1 -0
  82. package/web/assets/{swimlanes-42K2YHIH-veQmznpW.js → swimlanes-42K2YHIH-C3hju0RN.js} +1 -1
  83. package/web/assets/swimlanesDiagram-VR7AAH4N-upM6VKK6.js +8 -0
  84. package/web/assets/{timeline-definition-24CTP7MA-BBVe5_6z.js → timeline-definition-24CTP7MA-CHCn7Xv6.js} +1 -1
  85. package/web/assets/{treeView-Q6P3EWNA-Df3D8cEZ.js → treeView-Q6P3EWNA-CUNcz5ji.js} +1 -1
  86. package/web/assets/{treemap-WGGIJYW6-6iHVqa82.js → treemap-WGGIJYW6-CcOyHQjm.js} +1 -1
  87. package/web/assets/{useStore-DfbH52Ke.js → useStore-BcTuuxB0.js} +14 -14
  88. package/web/assets/{vennDiagram-4TSXK5OY-CyQGYbPH.js → vennDiagram-4TSXK5OY-YlBK7CKj.js} +1 -1
  89. package/web/assets/{wardley-WFR3VGLG-CGUFnP6r.js → wardley-WFR3VGLG-Dlu1wm0W.js} +1 -1
  90. package/web/assets/{wardleyDiagram-VM6X3IG4-CP6JTfZH.js → wardleyDiagram-VM6X3IG4-Cx9Tx2TY.js} +1 -1
  91. package/web/assets/{xychartDiagram-S5SC5T6Z-CstvHVdE.js → xychartDiagram-S5SC5T6Z-B5SG3mCC.js} +1 -1
  92. package/web/index.html +1 -1
  93. package/web/sw.js +1 -1
  94. package/web/assets/AutomationsView-mNcBWLfE.js +0 -51
  95. package/web/assets/architecture-7GRP2DOG-DiErcdh3.js +0 -1
  96. package/web/assets/channel-TvCeL5MC.js +0 -1
  97. package/web/assets/classDiagram-ZZMXUADV-CALjeLnc.js +0 -1
  98. package/web/assets/classDiagram-v2-VYDZK3BY-CALjeLnc.js +0 -1
  99. package/web/assets/eventmodeling-NTZA5JFV-CgH8QXUw.js +0 -1
  100. package/web/assets/flowDiagram-HODETNUW-DX6VKISm.js +0 -1
  101. package/web/assets/mount-Cor9KvF7.js +0 -36
  102. package/web/assets/railroad-abnf-HS5TGJTU-lWb-MdON.js +0 -1
  103. package/web/assets/railroad-ebnf-LZEXJU2U-BfxClIBE.js +0 -1
  104. package/web/assets/railroad-peg-WCYAUIDC-CP1dqeI1.js +0 -1
  105. package/web/assets/stateDiagram-v2-MP3YSRHH-9Y820F_3.js +0 -1
  106. package/web/assets/swimlanesDiagram-VR7AAH4N-SD8MeZXH.js +0 -8
@@ -38,7 +38,8 @@ export const BIVY_AGENT_NOTE = [
38
38
  "rule. A `.csv`/`.tsv` renders as a table; anything else arrives as a download.",
39
39
  "- Show a NUMBER or a CHART inside your reply: fence a spec as ```bivy. A number is " +
40
40
  '`{"type":"metric","value":"4 650 kWh","label":"per year"}`; a chart is a plain Vega-Lite spec with its data ' +
41
- "inline (`{\"mark\":\"bar\",\"data\":{\"values\":[…]},\"encoding\":{…}}`). A chart cannot fetch a URL — put the data in the spec.",
41
+ "inline, or pointing at a workspace data file with `\"data\":{\"url\":\"data/use.csv\"}` (.csv/.tsv/.json). " +
42
+ "A chart cannot fetch a remote URL.",
42
43
  "- Send a file WITHOUT writing a reply (or from a script): run " +
43
44
  '`bivy attach <path> [--caption "short note"]`, or call the `attach_to_chat` tool if you have it.',
44
45
  "- Something with a UI: `bivy app publish <manifest.json>` (a web server's port, a static build, a terminal) or " +
Binary file
@@ -1,4 +1,4 @@
1
- // SPDX-License-Identifier: FSL-1.1-ALv2
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
2
  // Copyright (c) 2026 Petter André Sjulstad
3
3
  //
4
4
  // Normalized tool-call taxonomy (Universal Agent Harness — fidelity layer).
@@ -1,4 +1,4 @@
1
- // SPDX-License-Identifier: FSL-1.1-ALv2
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
2
  // Copyright (c) 2026 Petter André Sjulstad
3
3
  import fs from "node:fs";
4
4
  import path from "node:path";
@@ -292,11 +292,85 @@ export function componentKind(opts) {
292
292
  // show that yet".
293
293
  return "file";
294
294
  }
295
+ /** How deep into a spec to look for references. Bounded so a pathological
296
+ * nesting cannot turn one message into an unbounded walk. */
297
+ const MAX_SPEC_DEPTH = 8;
295
298
  /**
296
- * Every reference a message makes that Bivy has to resolve — from image syntax
297
- * or from a directive — de-duplicated, in first-seen order, under ONE shared
298
- * cap. One budget across both forms is deliberate: the cost being bounded is
299
- * file reads and persisted bytes, which do not care which syntax asked.
299
+ * Workspace files a SPEC references, by putting a relative path in a `url`
300
+ * field. That is Vega-Lite's `data.url`, which is how a chart points at a
301
+ * dataset rather than carrying every row inline — and the whole spec is walked
302
+ * because Vega-Lite allows one per layer, facet and lookup, not just at the top.
303
+ *
304
+ * Deliberately keyed on the field NAME, not on anything Vega-specific: this
305
+ * file must not learn one kind's schema, and "a `url` field holding a
306
+ * workspace path is a reference" is a rule any future kind can use.
307
+ *
308
+ * A `url` that is not a workspace path (an `https://` address, say) is not
309
+ * returned, and so is never resolved — the view layer refuses those outright
310
+ * rather than letting a chart make the reader's browser fetch it.
311
+ */
312
+ export function specReferences(spec, limit = MAX_COMPONENTS_PER_MESSAGE) {
313
+ const out = [];
314
+ const seen = new Set();
315
+ const walk = (value, depth) => {
316
+ if (out.length >= limit || depth > MAX_SPEC_DEPTH || !value || typeof value !== "object")
317
+ return;
318
+ if (Array.isArray(value)) {
319
+ for (const item of value)
320
+ walk(item, depth + 1);
321
+ return;
322
+ }
323
+ for (const [key, child] of Object.entries(value)) {
324
+ if (key === "url" && typeof child === "string") {
325
+ const ref = unescapeComponentRef(child);
326
+ if (classifyImageTarget(ref) === "workspace" && !seen.has(ref)) {
327
+ seen.add(ref);
328
+ out.push(ref);
329
+ if (out.length >= limit)
330
+ return;
331
+ }
332
+ continue;
333
+ }
334
+ walk(child, depth + 1);
335
+ }
336
+ };
337
+ walk(spec, 0);
338
+ return out;
339
+ }
340
+ /** Each ```bivy fence in `text`, as a parsed spec with its offset. Line-wise,
341
+ * because that is how a fence is defined; an unterminated one yields nothing,
342
+ * which is also how a half-streamed message behaves. */
343
+ function componentFences(text) {
344
+ const out = [];
345
+ const lines = String(text).split("\n");
346
+ let at = 0;
347
+ for (let i = 0; i < lines.length; i++) {
348
+ const line = lines[i] ?? "";
349
+ const start = at;
350
+ at += line.length + 1;
351
+ if (!isComponentFence(line.trim().replace(/^```+/, "")))
352
+ continue;
353
+ const body = [];
354
+ let j = i + 1;
355
+ for (; j < lines.length && !lines[j].trim().startsWith("```"); j++) {
356
+ body.push(lines[j]);
357
+ at += lines[j].length + 1;
358
+ }
359
+ if (j < lines.length)
360
+ at += lines[j].length + 1;
361
+ const spec = parseComponentSpec(body.join("\n"));
362
+ if (spec)
363
+ out.push({ spec, at: start });
364
+ i = j;
365
+ }
366
+ return out;
367
+ }
368
+ /**
369
+ * Every reference a message makes that Bivy has to resolve — from image syntax,
370
+ * from a directive, or from a `url` inside a spec — de-duplicated, in first-seen
371
+ * order, under ONE shared cap. One budget across all three forms is deliberate:
372
+ * the cost being bounded is file reads and persisted bytes, which do not care
373
+ * which syntax asked.
300
374
  */
301
375
  export function extractMessageReferences(text, limit = MAX_COMPONENTS_PER_MESSAGE) {
302
376
  if (!text)
@@ -322,6 +396,12 @@ export function extractMessageReferences(text, limit = MAX_COMPONENTS_PER_MESSAG
322
396
  found.push({ ref: directive.ref, origin: "workspace", syntax: "view", at });
323
397
  at += line.length + 1;
324
398
  }
399
+ // A spec can point at a dataset instead of carrying it (a chart's data.url).
400
+ for (const { spec, at: offset } of componentFences(source)) {
401
+ for (const ref of specReferences(spec, limit)) {
402
+ found.push({ ref, origin: "workspace", syntax: "spec", at: offset });
403
+ }
404
+ }
325
405
  found.sort((a, b) => a.at - b.at);
326
406
  const out = [];
327
407
  const seen = new Set();
@@ -127,13 +127,31 @@ export function createTranscriptPersistence(deps) {
127
127
  }
128
128
  return refs;
129
129
  }
130
+ /** References made by the NEWEST assistant message. These are re-read even
131
+ * when the log already has them, which is what lets an agent overwrite a
132
+ * file and reference it again; see resolveWorkspaceRefs. */
133
+ function refsInLatestMessage(record) {
134
+ const messages = record.session.getMessages();
135
+ for (let i = messages.length - 1; i >= 0; i--) {
136
+ const m = messages[i];
137
+ if (m.role !== "assistant")
138
+ continue;
139
+ return new Set(extractWorkspaceRefs(assistantTextForImageScan(m.content)).map(({ ref }) => ref));
140
+ }
141
+ return new Set();
142
+ }
130
143
  /** Store resolved bytes under `ref` and tell every client, durably and live.
131
144
  * One place, so the remote and workspace resolvers below cannot drift in how
132
145
  * they record what they found. `kind` carries whether the bytes are an image,
133
146
  * which is what lets the view layer pick a renderer for a `::view` that
134
147
  * points at something other than a picture. */
135
- function recordResolvedRef(sessionId, ref, bytes, meta) {
148
+ function recordResolvedRef(sessionId, ref, bytes, meta, previousHash) {
136
149
  const stored = attachmentStore.put(bytes, { name: meta.name, mimeType: meta.mimeType, kind: meta.kind ?? "image" });
150
+ // Content-addressed, so re-reading an unchanged file yields the hash
151
+ // already recorded. Appending that again would grow the log and wake every
152
+ // device for a picture none of them would redraw.
153
+ if (previousHash && stored.hash === previousHash)
154
+ return;
137
155
  eventLog.appendInlineImage(sessionId, { url: ref, ref: stored });
138
156
  eventLog.flush(sessionId);
139
157
  deps.broadcast(deps.stampSessionEvent({ type: "session.event", sessionId, event: { type: "inlineImage", url: ref, ref: stored } }));
@@ -166,12 +184,24 @@ export function createTranscriptPersistence(deps) {
166
184
  const refs = workspaceRefsInTranscript(record);
167
185
  if (!refs.size)
168
186
  return;
169
- const alreadyResolved = new Set(eventLog.readInlineImages(record.id).map(([ref]) => ref));
187
+ const resolved = new Map(eventLog.readInlineImages(record.id));
188
+ // References the agent just made are re-read even when the log already has
189
+ // them. An agent that regenerates out/chart.png and shows it again means
190
+ // the new one; without this it would say "here is the updated chart" above
191
+ // the old picture. Bounded to the newest message, so this costs at most the
192
+ // per-message reference budget in reads per turn rather than re-reading
193
+ // every file the whole session ever mentioned.
194
+ const fresh = refsInLatestMessage(record);
170
195
  for (const [rel, syntax] of refs) {
171
- if (alreadyResolved.has(rel))
196
+ const previous = resolved.get(rel);
197
+ const isFresh = fresh.has(rel);
198
+ if (previous && !isFresh)
172
199
  continue;
173
200
  const failedAt = inlineImageFailedAt.get(rel);
174
- if (failedAt !== undefined && Date.now() - failedAt < INLINE_IMAGE_RETRY_COOLDOWN_MS)
201
+ // A fresh reference ignores the cooldown: the likeliest reason it failed
202
+ // before is that the agent had not written the file yet, and waiting ten
203
+ // minutes to show a file that now exists is worse than one extra read.
204
+ if (!isFresh && failedAt !== undefined && Date.now() - failedAt < INLINE_IMAGE_RETRY_COOLDOWN_MS)
175
205
  continue;
176
206
  const plan = planAttachment({ workspaceDir, filePath: rel, maxBytes: MAX_WORKSPACE_REF_BYTES });
177
207
  if (isAttachPlanError(plan)) {
@@ -189,7 +219,7 @@ export function createTranscriptPersistence(deps) {
189
219
  continue;
190
220
  }
191
221
  try {
192
- recordResolvedRef(record.id, rel, plan.bytes, { name: plan.name, mimeType: plan.mimeType, kind: plan.kind });
222
+ recordResolvedRef(record.id, rel, plan.bytes, { name: plan.name, mimeType: plan.mimeType, kind: plan.kind }, previous?.hash);
193
223
  }
194
224
  catch (error) {
195
225
  console.warn(`[component] ${rel}:`, error instanceof Error ? error.message : String(error));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.20.9-staging.24",
3
+ "version": "0.20.9-staging.26",
4
4
  "type": "module",
5
5
  "license": "AGPL-3.0-only",
6
6
  "description": "Run coding agents on machines you own. Open-source, self-hostable agent workspace.",