@rubytech/create-maxy 1.0.880 → 1.0.881

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.
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Maxy</title>
7
7
  <link rel="icon" href="/favicon.ico">
8
- <script type="module" crossorigin src="/assets/admin-CCEuBnaK.js"></script>
8
+ <script type="module" crossorigin src="/assets/admin-BN_z-2Bm.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/chunk-DD-I1_y5.js">
10
10
  <link rel="modulepreload" crossorigin href="/assets/jsx-runtime-BWYXu1CT.js">
11
11
  <link rel="modulepreload" crossorigin href="/assets/preload-helper-qlgyTAkD.js">
@@ -27,6 +27,7 @@ import {
27
27
  ensureLogDir,
28
28
  ensureVnc,
29
29
  findMissingPlugins,
30
+ getBundleMtimeIso,
30
31
  getDefaultAccountId,
31
32
  hasStubAccountDir,
32
33
  hashPassword,
@@ -75,7 +76,7 @@ import {
75
76
  vncLog,
76
77
  waitForExit,
77
78
  writeChromiumWrapper
78
- } from "./chunk-ICY65BIH.js";
79
+ } from "./chunk-KMVUUVHM.js";
79
80
  import {
80
81
  CDP_PORT,
81
82
  COMMERCIAL_MODE,
@@ -119,10 +120,11 @@ import {
119
120
  CLOUDFLARE_TASK_DIAGNOSTICS,
120
121
  appendCloudflareSteps,
121
122
  completeCloudflareTask,
123
+ findMostRecentTerminalCloudflareTask,
122
124
  openCloudflareTask,
123
125
  readTunnelState,
124
126
  resolveUnitGoneVerdict
125
- } from "./chunk-Q5J4NI6Q.js";
127
+ } from "./chunk-LVC7NKZ2.js";
126
128
  import {
127
129
  GREETING_DIRECTIVE,
128
130
  HAIKU_MODEL,
@@ -8436,6 +8438,24 @@ function resolveJsonlPath(homeDir, accountDir, agentSessionId) {
8436
8438
 
8437
8439
  // server/routes/admin/sessions.ts
8438
8440
  import { homedir } from "os";
8441
+ var healPending = /* @__PURE__ */ new Map();
8442
+ function markHealPending(accountId, attachmentId) {
8443
+ let set = healPending.get(accountId);
8444
+ if (!set) {
8445
+ set = /* @__PURE__ */ new Set();
8446
+ healPending.set(accountId, set);
8447
+ }
8448
+ set.add(attachmentId);
8449
+ }
8450
+ function clearHealPending(accountId, attachmentId) {
8451
+ const set = healPending.get(accountId);
8452
+ if (!set) return;
8453
+ set.delete(attachmentId);
8454
+ if (set.size === 0) healPending.delete(accountId);
8455
+ }
8456
+ function isHealPending(accountId, attachmentId) {
8457
+ return healPending.get(accountId)?.has(attachmentId) ?? false;
8458
+ }
8439
8459
  function validateAndShapeAttachments(raws, conversationAccountId, conversationId, messageId, streamLogPath) {
8440
8460
  const chips = [];
8441
8461
  let valid = 0;
@@ -8790,12 +8810,17 @@ app18.post("/:id/resume", async (c) => {
8790
8810
  textOffset: c2.textOffset
8791
8811
  };
8792
8812
  if (!c2.artefactAttachmentId || !c2.artefactMimeType || !c2.artefactTitle) return base;
8813
+ markHealPending(accountId, c2.artefactAttachmentId);
8793
8814
  try {
8794
8815
  const dataObj = JSON.parse(c2.data);
8795
8816
  const bytesPick = pickComponentBytes(dataObj);
8796
- if (!bytesPick) return base;
8817
+ if (!bytesPick) {
8818
+ clearHealPending(accountId, c2.artefactAttachmentId);
8819
+ return base;
8820
+ }
8797
8821
  const filename = bytesPick.mimeType === "text/html" ? `${c2.artefactTitle}.html` : `${c2.artefactTitle}.md`;
8798
8822
  await storeComponentArtefact(accountId, c2.artefactAttachmentId, bytesPick.mimeType, bytesPick.content, filename);
8823
+ clearHealPending(accountId, c2.artefactAttachmentId);
8799
8824
  appendFileSync4(
8800
8825
  streamLogPath,
8801
8826
  `[${(/* @__PURE__ */ new Date()).toISOString()}] [render-component-persist] heal componentName=${c2.name} attachmentId=${c2.artefactAttachmentId.slice(0, 8)} mimeType=${bytesPick.mimeType} bytes=${bytesPick.content.length} outcome=ok
@@ -8808,6 +8833,7 @@ app18.post("/:id/resume", async (c) => {
8808
8833
  artefactTitle: c2.artefactTitle
8809
8834
  };
8810
8835
  } catch (writeErr) {
8836
+ clearHealPending(accountId, c2.artefactAttachmentId);
8811
8837
  const reason2 = writeErr instanceof Error ? writeErr.message : String(writeErr);
8812
8838
  appendFileSync4(
8813
8839
  streamLogPath,
@@ -9632,6 +9658,23 @@ app23.post("/setup", requireAdminSession, async (c) => {
9632
9658
  if (publicFqdn) heldInputs.public = publicFqdn;
9633
9659
  if (apex) heldInputs.apex = apex;
9634
9660
  log(`phase=submit-received admin=${adminFqdn} public=${publicFqdn ?? "absent"} apex=${apex ?? "absent"}`);
9661
+ const bundleMtimeIso = getBundleMtimeIso();
9662
+ try {
9663
+ const prior = await findMostRecentTerminalCloudflareTask(accountId, correlationId);
9664
+ if (prior && prior.outcome === "failed") {
9665
+ const bundleNewer = bundleMtimeIso !== "unknown" && bundleMtimeIso > prior.completedAt;
9666
+ const branch = bundleNewer ? "re-invoke" : "surface-error";
9667
+ log(`retry-decision bundleMtime=${bundleMtimeIso} lastErrorAt=${prior.completedAt} branch=${branch}`);
9668
+ if (branch === "surface-error") {
9669
+ const literal = prior.errorMessage ?? CLOUDFLARE_TASK_DIAGNOSTICS.scriptExitedNonzero;
9670
+ return err("script", literal);
9671
+ }
9672
+ } else {
9673
+ log(`retry-decision bundleMtime=${bundleMtimeIso} lastErrorAt=none branch=proceed`);
9674
+ }
9675
+ } catch (e) {
9676
+ log(`retry-decision lookup-failed reason="${e instanceof Error ? e.message : String(e)}" branch=proceed`);
9677
+ }
9635
9678
  const account = resolveAccount();
9636
9679
  if (!account) {
9637
9680
  return err("script", "No account on disk for this device \u2014 re-run installer.");
@@ -12365,6 +12408,10 @@ app34.post("/", requireAdminSession, async (c) => {
12365
12408
  }
12366
12409
  const accountDir = resolve17(ACCOUNTS_DIR, accountId);
12367
12410
  const resolved = await resolveSavePath(body.id, accountId, accountDir);
12411
+ if (resolved.kind === "heal-race") {
12412
+ c.header("Retry-After", "2");
12413
+ return c.json({ error: "heal-race", reason: resolved.reason }, 503);
12414
+ }
12368
12415
  if (resolved.kind === "reject") {
12369
12416
  console.error(
12370
12417
  `[admin/sidebar-artefact-save] auth-rejected reason=${resolved.reason} path=${body.id}`
@@ -12416,7 +12463,35 @@ async function resolveSavePath(id, accountId, accountDir) {
12416
12463
  if (UUID_RE6.test(id)) {
12417
12464
  const dir = resolve17(ATTACHMENTS_ROOT, accountId, id);
12418
12465
  if (!existsSync19(dir)) {
12419
- return { kind: "reject", status: 400, reason: "not-found" };
12466
+ const attShort = id.slice(0, 8);
12467
+ if (isHealPending(accountId, id)) {
12468
+ console.error(`[admin/sidebar-artefact-save] heal-race attachmentId=${attShort} outcome=503-retry source=heal-pending`);
12469
+ return { kind: "heal-race", reason: "dir-pending" };
12470
+ }
12471
+ const session = getSession();
12472
+ try {
12473
+ const result = await session.run(
12474
+ `MATCH (k:KnowledgeDocument {accountId: $accountId, attachmentId: $attachmentId})
12475
+ RETURN count(k) AS cnt`,
12476
+ { accountId, attachmentId: id }
12477
+ );
12478
+ const cnt = result.records[0]?.get("cnt")?.toNumber?.() ?? 0;
12479
+ if (cnt > 0) {
12480
+ console.error(`[admin/sidebar-artefact-save] heal-race attachmentId=${attShort} outcome=503-retry source=neo4j-row`);
12481
+ return { kind: "heal-race", reason: "dir-pending" };
12482
+ }
12483
+ console.error(`[admin/sidebar-artefact-save] heal-race attachmentId=${attShort} outcome=400-terminal`);
12484
+ return { kind: "reject", status: 400, reason: "not-found" };
12485
+ } catch (neoErr) {
12486
+ const reason = neoErr instanceof Error ? neoErr.message.slice(0, 120) : String(neoErr).slice(0, 120);
12487
+ console.error(`[admin/sidebar-artefact-save] heal-race attachmentId=${attShort} outcome=neo4j-fail reason="${reason}"`);
12488
+ return { kind: "heal-race", reason: "neo4j-fail" };
12489
+ } finally {
12490
+ try {
12491
+ await session.close();
12492
+ } catch {
12493
+ }
12494
+ }
12420
12495
  }
12421
12496
  try {
12422
12497
  validateFilePathInAccount(dir, resolve17(ATTACHMENTS_ROOT, accountId));
@@ -13624,7 +13699,7 @@ autoDeliverPremiumPlugins(bootEntitlement?.purchasedPlugins ?? void 0);
13624
13699
  (async () => {
13625
13700
  if (!bootAccount) return;
13626
13701
  try {
13627
- const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-HUTXJQXO.js");
13702
+ const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-CY6QL6CY.js");
13628
13703
  const result = await recoverRunningCloudflareTasks(
13629
13704
  bootAccount.accountId,
13630
13705
  configDirForWhatsApp,