@runfusion/fusion 0.70.2 → 0.71.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.
Files changed (100) hide show
  1. package/dist/bin.js +174 -7
  2. package/dist/child-process-worker.js +30 -6
  3. package/dist/client/.vite/manifest.json +246 -246
  4. package/dist/client/assets/{AgentDetailView-UMM9DyW-.js → AgentDetailView-BvY24zNh.js} +1 -1
  5. package/dist/client/assets/{AgentPermissionPolicyEditor-BfNZUiDb.js → AgentPermissionPolicyEditor-CYvJw48-.js} +1 -1
  6. package/dist/client/assets/{AgentsView-DtC-DVyX.js → AgentsView-BWkWEfNs.js} +3 -3
  7. package/dist/client/assets/{ChatView-sDJXcOwT.js → ChatView-BhlVq9Re.js} +1 -1
  8. package/dist/client/assets/{CommandCenter-B7BECRSV.js → CommandCenter-DingokjC.js} +1 -1
  9. package/dist/client/assets/{DevServerView-CyW7l6rY.js → DevServerView-kfNJk83M.js} +1 -1
  10. package/dist/client/assets/{DirectoryPicker-BT3OeDJ3.js → DirectoryPicker-Cluyep4u.js} +1 -1
  11. package/dist/client/assets/{DocumentsView-Dbn8T4ZT.js → DocumentsView-Bwc5HSg7.js} +1 -1
  12. package/dist/client/assets/{EvalsView-DGOBPt3P.js → EvalsView-BEr_MhJ4.js} +1 -1
  13. package/dist/client/assets/{ExperimentalAgentOnboardingModal-Beno0EK8.js → ExperimentalAgentOnboardingModal-CZK-KtFP.js} +1 -1
  14. package/dist/client/assets/{GoalsView-BLxtocMB.js → GoalsView-B_Qrm8po.js} +1 -1
  15. package/dist/client/assets/{InsightsView-DjTpiw1S.js → InsightsView-BfbclBHM.js} +1 -1
  16. package/dist/client/assets/{MemoryView-BvAhPVCo.js → MemoryView-V9Y08BtR.js} +1 -1
  17. package/dist/client/assets/{PiExtensionsManager-Di3Q9J6V.js → PiExtensionsManager-B7fl5l3O.js} +1 -1
  18. package/dist/client/assets/{PluginManager-reQpowmU.js → PluginManager-H32X557C.js} +1 -1
  19. package/dist/client/assets/{PullRequestView-DLDz9RXL.js → PullRequestView-Dhz86tnJ.js} +1 -1
  20. package/dist/client/assets/{ResearchView-BpdpPwyr.js → ResearchView-DEObk9J2.js} +1 -1
  21. package/dist/client/assets/{SecretsView-BHu1JHnH.js → SecretsView-DFEWUbXI.js} +1 -1
  22. package/dist/client/assets/{SessionTerminal-rtlAx2uQ.js → SessionTerminal-CwfTrmor.js} +1 -1
  23. package/dist/client/assets/{SettingsModal-B7m-bZlG.js → SettingsModal-2mlwjfVZ.js} +1 -1
  24. package/dist/client/assets/{SettingsModal-Dxz7-SNa.js → SettingsModal-H1TNebmF.js} +3 -3
  25. package/dist/client/assets/{SettingsTextareaRow-5Vb6XYSC.js → SettingsTextareaRow-ByeSU4Pi.js} +1 -1
  26. package/dist/client/assets/{SetupWizardModal-BixsaVgv.js → SetupWizardModal-BFZnVJX1.js} +2 -2
  27. package/dist/client/assets/{SkillsView-CNQaKfLx.js → SkillsView-DScNdDRz.js} +1 -1
  28. package/dist/client/assets/{ThemeDropdown-Bhz3TH1Z.js → ThemeDropdown-BKl0kouU.js} +1 -1
  29. package/dist/client/assets/{TodoView-Ccr5rxPw.js → TodoView-_HojIE_Y.js} +1 -1
  30. package/dist/client/assets/{WorkflowNodeEditor-BeY_3iQR.js → WorkflowNodeEditor-CoQYdUYX.js} +1 -1
  31. package/dist/client/assets/{app-bX7Aarj6.js → app-0sCAWTFb.js} +1 -1
  32. package/dist/client/assets/{app-BFkCDjfl.js → app-Cndq8AGV.js} +1 -1
  33. package/dist/client/assets/{app-Bx4Tg9WL.js → app-CqpqmC8O.js} +1 -1
  34. package/dist/client/assets/{app-BwKqEIVs.js → app-DjxXVWX9.js} +1 -1
  35. package/dist/client/assets/{app-gasJpw6T.js → app-DrnsOtt9.js} +1 -1
  36. package/dist/client/assets/{app-BLTqCjPk.js → app-Kb21Gl_h.js} +1 -1
  37. package/dist/client/assets/{architectureDiagram-3BPJPVTR-DbmZMyHk.js → architectureDiagram-3BPJPVTR-vIoH_tGm.js} +1 -1
  38. package/dist/client/assets/{blockDiagram-GPEHLZMM-BkspaqvN.js → blockDiagram-GPEHLZMM-BqjSE9AM.js} +1 -1
  39. package/dist/client/assets/{c4Diagram-AAUBKEIU-BfOk6DAf.js → c4Diagram-AAUBKEIU-TWEWVE4T.js} +1 -1
  40. package/dist/client/assets/channel-hhQEu5zM.js +1 -0
  41. package/dist/client/assets/{chunk-2J33WTMH-DbL54v_S.js → chunk-2J33WTMH-CJM3p9Fh.js} +1 -1
  42. package/dist/client/assets/{chunk-4BX2VUAB-VAUWnfVr.js → chunk-4BX2VUAB-Bf_1wJ7O.js} +1 -1
  43. package/dist/client/assets/{chunk-55IACEB6-C5h7MxPM.js → chunk-55IACEB6-CI4ThikJ.js} +1 -1
  44. package/dist/client/assets/{chunk-727SXJPM-CCc56jyj.js → chunk-727SXJPM-C2TasaKk.js} +1 -1
  45. package/dist/client/assets/{chunk-AQP2D5EJ-CUK6s79q.js → chunk-AQP2D5EJ-BqKUxt3g.js} +1 -1
  46. package/dist/client/assets/{chunk-FMBD7UC4-COFczZ8r.js → chunk-FMBD7UC4-CdK77AxG.js} +1 -1
  47. package/dist/client/assets/{chunk-ND2GUHAM-BXTcFeIM.js → chunk-ND2GUHAM-TE8zbIZ3.js} +1 -1
  48. package/dist/client/assets/{chunk-QZHKN3VN-BEYAo7eA.js → chunk-QZHKN3VN-7lgttGIx.js} +1 -1
  49. package/dist/client/assets/classDiagram-4FO5ZUOK-C2Thhy7D.js +1 -0
  50. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-C2Thhy7D.js +1 -0
  51. package/dist/client/assets/{cose-bilkent-S5V4N54A-DqQ74MrB.js → cose-bilkent-S5V4N54A-DsK8EBeo.js} +1 -1
  52. package/dist/client/assets/{dagre-BM42HDAG-D1DsLIdG.js → dagre-BM42HDAG-COza1ss6.js} +1 -1
  53. package/dist/client/assets/{dashboard-view-DFy7Ta-E.js → dashboard-view-D_etacMS.js} +1 -1
  54. package/dist/client/assets/{dashboard-view-D5F_ho0i.js → dashboard-view-ILJ_vnYK.js} +1 -1
  55. package/dist/client/assets/{dashboard-view-CgBE7XiJ.js → dashboard-view-JEFD-Zgw.js} +1 -1
  56. package/dist/client/assets/{diagram-2AECGRRQ-p-547bXh.js → diagram-2AECGRRQ-Co_F0-vp.js} +1 -1
  57. package/dist/client/assets/{diagram-5GNKFQAL-BE9UnZuh.js → diagram-5GNKFQAL-BD_n7vU0.js} +1 -1
  58. package/dist/client/assets/{diagram-KO2AKTUF-BHTLL-vQ.js → diagram-KO2AKTUF-SFnuzet_.js} +1 -1
  59. package/dist/client/assets/{diagram-LMA3HP47-CWLbQcuj.js → diagram-LMA3HP47-CFYeR0mH.js} +1 -1
  60. package/dist/client/assets/{diagram-OG6HWLK6-CXUiMHIE.js → diagram-OG6HWLK6-DOVfqKgw.js} +1 -1
  61. package/dist/client/assets/{erDiagram-TEJ5UH35-Dre62Vsd.js → erDiagram-TEJ5UH35-DkeW3bDN.js} +1 -1
  62. package/dist/client/assets/{flowDiagram-I6XJVG4X-BFeMnep3.js → flowDiagram-I6XJVG4X-CVaNMQl_.js} +1 -1
  63. package/dist/client/assets/{folder-open-s7aQO2Ib.js → folder-open-BY1Gp9Wf.js} +1 -1
  64. package/dist/client/assets/{ganttDiagram-6RSMTGT7-CfrUWiHI.js → ganttDiagram-6RSMTGT7-BQJ0x5Hq.js} +1 -1
  65. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-KjKsgpva.js → gitGraphDiagram-PVQCEYII-CIt0P2Lg.js} +1 -1
  66. package/dist/client/assets/{index-DF2cd-e3.js → index-ClPjlOHJ.js} +168 -168
  67. package/dist/client/assets/index-GJLKrqhe.css +1 -0
  68. package/dist/client/assets/{infoDiagram-5YYISTIA-Cb_8B_3K.js → infoDiagram-5YYISTIA-B1KKCn80.js} +1 -1
  69. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-8jtlcCaf.js → ishikawaDiagram-YF4QCWOH-CzG1cEeg.js} +1 -1
  70. package/dist/client/assets/{journeyDiagram-JHISSGLW-O6X0tJvH.js → journeyDiagram-JHISSGLW-CNB7oM4Q.js} +1 -1
  71. package/dist/client/assets/{kanban-definition-UN3LZRKU-BetEnps7.js → kanban-definition-UN3LZRKU-D8vXTzfs.js} +1 -1
  72. package/dist/client/assets/{mermaid.core-CZbT2qhF.js → mermaid.core-BUhJJv1M.js} +4 -4
  73. package/dist/client/assets/{mindmap-definition-RKZ34NQL-BRjDmxQK.js → mindmap-definition-RKZ34NQL-y_XyU0Us.js} +1 -1
  74. package/dist/client/assets/{pieDiagram-4H26LBE5-CJHx1ZvR.js → pieDiagram-4H26LBE5-MB9aZtTc.js} +1 -1
  75. package/dist/client/assets/{puzzle-BJEQBgfR.js → puzzle-CE00Ce2g.js} +1 -1
  76. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-D49nAI3y.js → quadrantDiagram-W4KKPZXB-hF7q33gK.js} +1 -1
  77. package/dist/client/assets/{requirementDiagram-4Y6WPE33-BM4Uv6Jr.js → requirementDiagram-4Y6WPE33-BIOIzbEd.js} +1 -1
  78. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-RSKSlyjr.js → sankeyDiagram-5OEKKPKP-BpLzUxJ8.js} +1 -1
  79. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BXpcHAnr.js → sequenceDiagram-3UESZ5HK-CLXamQhZ.js} +1 -1
  80. package/dist/client/assets/{shield-alert-DcsqJWMG.js → shield-alert-BhLVV0rp.js} +1 -1
  81. package/dist/client/assets/{standing-instructions-template-CUYzx5D8.js → standing-instructions-template-96KSNan7.js} +1 -1
  82. package/dist/client/assets/{stateDiagram-AJRCARHV-CavU8Ef4.js → stateDiagram-AJRCARHV-CPRWhQtZ.js} +1 -1
  83. package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-Cq-9bJPI.js → stateDiagram-v2-BHNVJYJU-8GvpOVMc.js} +1 -1
  84. package/dist/client/assets/{timeline-definition-PNZ67QCA-7fHh3hS9.js → timeline-definition-PNZ67QCA-BAAldJMW.js} +1 -1
  85. package/dist/client/assets/{upload-DNwFaPfV.js → upload-DbKZcYCW.js} +1 -1
  86. package/dist/client/assets/{users-D-kPhpXu.js → users-ccVe3aKQ.js} +1 -1
  87. package/dist/client/assets/{vennDiagram-CIIHVFJN-mCh9G6D5.js → vennDiagram-CIIHVFJN-DGSAcrfx.js} +1 -1
  88. package/dist/client/assets/{wardley-L42UT6IY-DEu4AYE9.js → wardley-L42UT6IY-CLGvNiAx.js} +1 -1
  89. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DRL0ZyeQ.js → wardleyDiagram-YWT4CUSO-BhU8FLGx.js} +1 -1
  90. package/dist/client/assets/{xychartDiagram-2RQKCTM6-DUpC-GBX.js → xychartDiagram-2RQKCTM6-BQ6AzTfE.js} +1 -1
  91. package/dist/client/index.html +2 -2
  92. package/dist/client/version.json +1 -1
  93. package/dist/extension.js +30 -6
  94. package/dist/plugins/fusion-plugin-dependency-graph/.bundled.reload-1.js +8084 -0
  95. package/dist/plugins/fusion-plugin-grok-runtime/.bundled.reload-2.js +26479 -0
  96. package/package.json +1 -1
  97. package/dist/client/assets/channel-CABKCAbA.js +0 -1
  98. package/dist/client/assets/classDiagram-4FO5ZUOK-DgshwmmF.js +0 -1
  99. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DgshwmmF.js +0 -1
  100. package/dist/client/assets/index-Co20nJU4.css +0 -1
package/dist/bin.js CHANGED
@@ -47419,6 +47419,25 @@ function classifyColumnType(pgCol) {
47419
47419
  }
47420
47420
  return "plain";
47421
47421
  }
47422
+ function stripNulChars(text2) {
47423
+ return text2.includes("\0") ? text2.replace(NUL_CHAR_RE, "") : text2;
47424
+ }
47425
+ function deepStripNulChars(value) {
47426
+ if (typeof value === "string") {
47427
+ return stripNulChars(value);
47428
+ }
47429
+ if (Array.isArray(value)) {
47430
+ return value.map(deepStripNulChars);
47431
+ }
47432
+ if (value !== null && typeof value === "object") {
47433
+ return Object.fromEntries(
47434
+ Object.entries(value).map(
47435
+ ([key, entry]) => [stripNulChars(key), deepStripNulChars(entry)]
47436
+ )
47437
+ );
47438
+ }
47439
+ return value;
47440
+ }
47422
47441
  function convertValue(value, type, nullJsonbFallback, preserveEmptyJsonbString = false) {
47423
47442
  if (value === null || value === void 0) {
47424
47443
  return type === "jsonb" && nullJsonbFallback !== void 0 ? nullJsonbFallback : null;
@@ -47431,12 +47450,12 @@ function convertValue(value, type, nullJsonbFallback, preserveEmptyJsonbString =
47431
47450
  return nullJsonbFallback ?? (preserveEmptyJsonbString ? JSON.stringify(value) : null);
47432
47451
  }
47433
47452
  try {
47434
- return JSON.stringify(JSON.parse(trimmed));
47453
+ return JSON.stringify(deepStripNulChars(JSON.parse(trimmed)));
47435
47454
  } catch {
47436
- return JSON.stringify(value);
47455
+ return JSON.stringify(stripNulChars(value));
47437
47456
  }
47438
47457
  }
47439
- return JSON.stringify(value);
47458
+ return JSON.stringify(deepStripNulChars(value));
47440
47459
  }
47441
47460
  case "bytea": {
47442
47461
  if (Buffer.isBuffer(value)) {
@@ -47454,7 +47473,7 @@ function convertValue(value, type, nullJsonbFallback, preserveEmptyJsonbString =
47454
47473
  case "identity":
47455
47474
  case "generated":
47456
47475
  default:
47457
- return value;
47476
+ return typeof value === "string" ? stripNulChars(value) : value;
47458
47477
  }
47459
47478
  }
47460
47479
  function createQuarterProgressReporter(sourceRows, onCopyProgress) {
@@ -47479,7 +47498,7 @@ function tagLegacyCell(value) {
47479
47498
  if (typeof value === "number" || typeof value === "bigint") {
47480
47499
  return { type: "number", value: Object.is(value, -0) ? "-0" : String(value) };
47481
47500
  }
47482
- return { type: "text", value: String(value) };
47501
+ return { type: "text", value: stripNulChars(String(value)) };
47483
47502
  }
47484
47503
  function canonicalizeLegacyRows(rows, occurrences = /* @__PURE__ */ new Map()) {
47485
47504
  return rows.map((row) => {
@@ -47947,7 +47966,7 @@ async function computeTargetCanonicalRows(db, pgSchema2, table, cols, projectId)
47947
47966
  return canonical;
47948
47967
  }).sort();
47949
47968
  }
47950
- var log4, INSERT_BATCH_SIZE, LEGACY_PRESERVATION_TARGETS, SQLITE_MIGRATION_STATE_TABLE, CENTRAL_SQLITE_MIGRATION_KEY, DryRunRollback;
47969
+ var log4, INSERT_BATCH_SIZE, LEGACY_PRESERVATION_TARGETS, SQLITE_MIGRATION_STATE_TABLE, CENTRAL_SQLITE_MIGRATION_KEY, DryRunRollback, NUL_CHAR_RE;
47951
47970
  var init_sqlite_migrator = __esm({
47952
47971
  "../core/src/postgres/sqlite-migrator.ts"() {
47953
47972
  "use strict";
@@ -47972,6 +47991,7 @@ var init_sqlite_migrator = __esm({
47972
47991
  this.name = "DryRunRollback";
47973
47992
  }
47974
47993
  };
47994
+ NUL_CHAR_RE = /\u0000/g;
47975
47995
  }
47976
47996
  });
47977
47997
 
@@ -59739,6 +59759,10 @@ async function createTaskStoreForBackend(options) {
59739
59759
  */
59740
59760
  onProgress: (event) => {
59741
59761
  log5.log(`startup-factory: SQLite migration \u2014 ${formatMigrationProgress2(event)}`);
59762
+ try {
59763
+ options.onMigrationProgress?.(event);
59764
+ } catch {
59765
+ }
59742
59766
  }
59743
59767
  });
59744
59768
  const failedTables = report.tables.filter((table) => !table.skipped && !table.verified);
@@ -382718,6 +382742,137 @@ var init_port_prompt = __esm({
382718
382742
  }
382719
382743
  });
382720
382744
 
382745
+ // src/commands/migration-holding-server.ts
382746
+ import { createServer as createServer6 } from "node:http";
382747
+ function renderHoldingPage() {
382748
+ return `<!doctype html>
382749
+ <html lang="en">
382750
+ <head>
382751
+ <meta charset="utf-8">
382752
+ <meta name="viewport" content="width=device-width, initial-scale=1">
382753
+ <title>Fusion \u2014 starting</title>
382754
+ <style>
382755
+ :root { color-scheme: dark; }
382756
+ body {
382757
+ margin: 0; min-height: 100vh; display: flex; align-items: center; justify-content: center;
382758
+ background: #0b0e14; color: #e6e9ef;
382759
+ font: 15px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
382760
+ }
382761
+ .card { max-width: 30rem; padding: 2rem; text-align: center; }
382762
+ .spinner {
382763
+ width: 2.25rem; height: 2.25rem; margin: 0 auto 1.25rem;
382764
+ border: 3px solid rgba(59, 130, 246, 0.25); border-top-color: #3b82f6;
382765
+ border-radius: 50%; animation: spin 0.9s linear infinite;
382766
+ }
382767
+ @keyframes spin { to { transform: rotate(360deg); } }
382768
+ h1 { font-size: 1.15rem; margin: 0 0 0.5rem; font-weight: 600; }
382769
+ p { margin: 0 0 0.75rem; color: #9aa4b2; }
382770
+ .progress { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.85rem; color: #7fb1ff; min-height: 1.5em; overflow-wrap: anywhere; }
382771
+ .offline { color: #f0883e; }
382772
+ </style>
382773
+ </head>
382774
+ <body>
382775
+ <div class="card" role="status" aria-live="polite">
382776
+ <div class="spinner" aria-hidden="true"></div>
382777
+ <h1 id="title">Fusion is starting\u2026</h1>
382778
+ <p id="subtitle">If a database migration is needed it runs now and can take a few minutes for large projects. This page reloads automatically when the dashboard is ready.</p>
382779
+ <div class="progress" id="progress"></div>
382780
+ </div>
382781
+ <script>
382782
+ (function () {
382783
+ var failures = 0;
382784
+ var sawMigration = false;
382785
+ async function poll() {
382786
+ try {
382787
+ var res = await fetch("/api/health", { cache: "no-store" });
382788
+ if (!res.ok) return;
382789
+ failures = 0;
382790
+ var data = await res.json();
382791
+ if (data && (data.status === "starting" || data.status === "migrating")) {
382792
+ if (data.status === "migrating") {
382793
+ sawMigration = true;
382794
+ document.getElementById("title").textContent = "Database migration in progress";
382795
+ }
382796
+ var label = data.migration && data.migration.label;
382797
+ if (label) document.getElementById("progress").textContent = label;
382798
+ return;
382799
+ }
382800
+ location.reload();
382801
+ } catch (err) {
382802
+ failures += 1;
382803
+ if (failures >= 8) {
382804
+ document.getElementById("progress").innerHTML =
382805
+ '<span class="offline">Cannot reach Fusion \u2014 it may have stopped. Check the terminal, then reload.</span>';
382806
+ }
382807
+ }
382808
+ }
382809
+ poll();
382810
+ setInterval(poll, 1500);
382811
+ })();
382812
+ </script>
382813
+ </body>
382814
+ </html>`;
382815
+ }
382816
+ async function startMigrationHoldingServer(options) {
382817
+ let latest = null;
382818
+ const server = createServer6((req, res) => {
382819
+ const url2 = req.url ?? "/";
382820
+ if (url2 === "/api/health" || url2.startsWith("/api/health?")) {
382821
+ res.writeHead(200, { "content-type": "application/json", "cache-control": "no-store" });
382822
+ res.end(JSON.stringify({
382823
+ status: latest ? "migrating" : "starting",
382824
+ holding: true,
382825
+ migration: latest ? {
382826
+ active: true,
382827
+ phase: latest.phase,
382828
+ label: formatMigrationProgress(latest),
382829
+ ..."table" in latest ? { table: latest.table, tableIndex: latest.tableIndex, tableCount: latest.tableCount } : {},
382830
+ ...latest.phase === "table-progress" ? { processedRows: latest.processedRows, sourceRows: latest.sourceRows } : {}
382831
+ } : { active: false }
382832
+ }));
382833
+ return;
382834
+ }
382835
+ if (url2.startsWith("/api/")) {
382836
+ res.writeHead(503, { "content-type": "application/json", "retry-after": "2" });
382837
+ res.end(JSON.stringify({ error: "Fusion is starting (database migration may be in progress)" }));
382838
+ return;
382839
+ }
382840
+ res.writeHead(503, { "content-type": "text/html; charset=utf-8", "retry-after": "2", "cache-control": "no-store" });
382841
+ res.end(renderHoldingPage());
382842
+ });
382843
+ const bound = await new Promise((resolve96) => {
382844
+ server.once("error", (error48) => {
382845
+ options.log?.(`migration holding page not available (${error48.code ?? error48.message}); continuing boot without it`);
382846
+ resolve96(false);
382847
+ });
382848
+ server.listen(options.port, options.host, () => resolve96(true));
382849
+ });
382850
+ if (!bound) return null;
382851
+ const address = server.address();
382852
+ const port = typeof address === "object" && address !== null ? address.port : options.port;
382853
+ let closed = null;
382854
+ return {
382855
+ port,
382856
+ setMigrationProgress(event) {
382857
+ latest = event;
382858
+ },
382859
+ close() {
382860
+ if (closed) return closed;
382861
+ closed = new Promise((resolve96) => {
382862
+ server.close(() => resolve96());
382863
+ server.closeAllConnections();
382864
+ });
382865
+ return closed;
382866
+ }
382867
+ };
382868
+ }
382869
+ var init_migration_holding_server = __esm({
382870
+ "src/commands/migration-holding-server.ts"() {
382871
+ "use strict";
382872
+ init_src2();
382873
+ }
382874
+ });
382875
+
382721
382876
  // src/commands/ensure-project-registered.ts
382722
382877
  import { exec as exec48 } from "node:child_process";
382723
382878
  import { existsSync as existsSync83, mkdirSync as mkdirSync17 } from "node:fs";
@@ -392638,9 +392793,17 @@ async function runDashboard(port, opts = {}) {
392638
392793
  }
392639
392794
  ensureProcessDiagnostics(runtimeLogger);
392640
392795
  const logPhase = (message, scope = "dashboard") => logSink.log(message, scope);
392796
+ const migrationHoldingServer = await startMigrationHoldingServer({
392797
+ port: selectedPort,
392798
+ host: selectedHost,
392799
+ log: (message) => logSink.log(message, "dashboard")
392800
+ });
392641
392801
  const dashboardBackendBoot = await phaseTime(
392642
392802
  "backend.factory",
392643
- () => createTaskStoreForBackend({ rootDir: cwd }),
392803
+ () => createTaskStoreForBackend({
392804
+ rootDir: cwd,
392805
+ onMigrationProgress: (event) => migrationHoldingServer?.setMigrationProgress(event)
392806
+ }),
392644
392807
  logPhase
392645
392808
  );
392646
392809
  store = dashboardBackendBoot.taskStore;
@@ -393839,6 +394002,9 @@ async function runDashboard(port, opts = {}) {
393839
394002
  }
393840
394003
  }, POLL_MS).unref();
393841
394004
  }
394005
+ if (migrationHoldingServer) {
394006
+ await migrationHoldingServer.close();
394007
+ }
393842
394008
  const server = app.listen(selectedPort, selectedHost);
393843
394009
  server.on("error", (err) => {
393844
394010
  if (err.code === "EADDRINUSE") {
@@ -394548,6 +394714,7 @@ var init_dashboard = __esm({
394548
394714
  init_extension();
394549
394715
  init_task_lifecycle();
394550
394716
  init_port_prompt();
394717
+ init_migration_holding_server();
394551
394718
  init_ensure_project_registered();
394552
394719
  init_provider_settings();
394553
394720
  init_provider_auth2();
@@ -47494,6 +47494,25 @@ function classifyColumnType(pgCol) {
47494
47494
  }
47495
47495
  return "plain";
47496
47496
  }
47497
+ function stripNulChars(text2) {
47498
+ return text2.includes("\0") ? text2.replace(NUL_CHAR_RE, "") : text2;
47499
+ }
47500
+ function deepStripNulChars(value) {
47501
+ if (typeof value === "string") {
47502
+ return stripNulChars(value);
47503
+ }
47504
+ if (Array.isArray(value)) {
47505
+ return value.map(deepStripNulChars);
47506
+ }
47507
+ if (value !== null && typeof value === "object") {
47508
+ return Object.fromEntries(
47509
+ Object.entries(value).map(
47510
+ ([key, entry]) => [stripNulChars(key), deepStripNulChars(entry)]
47511
+ )
47512
+ );
47513
+ }
47514
+ return value;
47515
+ }
47497
47516
  function convertValue(value, type, nullJsonbFallback, preserveEmptyJsonbString = false) {
47498
47517
  if (value === null || value === void 0) {
47499
47518
  return type === "jsonb" && nullJsonbFallback !== void 0 ? nullJsonbFallback : null;
@@ -47506,12 +47525,12 @@ function convertValue(value, type, nullJsonbFallback, preserveEmptyJsonbString =
47506
47525
  return nullJsonbFallback ?? (preserveEmptyJsonbString ? JSON.stringify(value) : null);
47507
47526
  }
47508
47527
  try {
47509
- return JSON.stringify(JSON.parse(trimmed));
47528
+ return JSON.stringify(deepStripNulChars(JSON.parse(trimmed)));
47510
47529
  } catch {
47511
- return JSON.stringify(value);
47530
+ return JSON.stringify(stripNulChars(value));
47512
47531
  }
47513
47532
  }
47514
- return JSON.stringify(value);
47533
+ return JSON.stringify(deepStripNulChars(value));
47515
47534
  }
47516
47535
  case "bytea": {
47517
47536
  if (Buffer.isBuffer(value)) {
@@ -47529,7 +47548,7 @@ function convertValue(value, type, nullJsonbFallback, preserveEmptyJsonbString =
47529
47548
  case "identity":
47530
47549
  case "generated":
47531
47550
  default:
47532
- return value;
47551
+ return typeof value === "string" ? stripNulChars(value) : value;
47533
47552
  }
47534
47553
  }
47535
47554
  function createQuarterProgressReporter(sourceRows, onCopyProgress) {
@@ -47554,7 +47573,7 @@ function tagLegacyCell(value) {
47554
47573
  if (typeof value === "number" || typeof value === "bigint") {
47555
47574
  return { type: "number", value: Object.is(value, -0) ? "-0" : String(value) };
47556
47575
  }
47557
- return { type: "text", value: String(value) };
47576
+ return { type: "text", value: stripNulChars(String(value)) };
47558
47577
  }
47559
47578
  function canonicalizeLegacyRows(rows, occurrences = /* @__PURE__ */ new Map()) {
47560
47579
  return rows.map((row) => {
@@ -48022,7 +48041,7 @@ async function computeTargetCanonicalRows(db, pgSchema2, table, cols, projectId)
48022
48041
  return canonical;
48023
48042
  }).sort();
48024
48043
  }
48025
- var log4, INSERT_BATCH_SIZE, LEGACY_PRESERVATION_TARGETS, SQLITE_MIGRATION_STATE_TABLE, CENTRAL_SQLITE_MIGRATION_KEY, DryRunRollback;
48044
+ var log4, INSERT_BATCH_SIZE, LEGACY_PRESERVATION_TARGETS, SQLITE_MIGRATION_STATE_TABLE, CENTRAL_SQLITE_MIGRATION_KEY, DryRunRollback, NUL_CHAR_RE;
48026
48045
  var init_sqlite_migrator = __esm({
48027
48046
  "../core/src/postgres/sqlite-migrator.ts"() {
48028
48047
  "use strict";
@@ -48047,6 +48066,7 @@ var init_sqlite_migrator = __esm({
48047
48066
  this.name = "DryRunRollback";
48048
48067
  }
48049
48068
  };
48069
+ NUL_CHAR_RE = /\u0000/g;
48050
48070
  }
48051
48071
  });
48052
48072
 
@@ -59814,6 +59834,10 @@ async function createTaskStoreForBackend(options) {
59814
59834
  */
59815
59835
  onProgress: (event) => {
59816
59836
  log5.log(`startup-factory: SQLite migration \u2014 ${formatMigrationProgress2(event)}`);
59837
+ try {
59838
+ options.onMigrationProgress?.(event);
59839
+ } catch {
59840
+ }
59817
59841
  }
59818
59842
  });
59819
59843
  const failedTables = report.tables.filter((table) => !table.skipped && !table.verified);