@rubytech/create-maxy-code 0.1.547 → 0.1.549

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 (113) hide show
  1. package/dist/index.js +14 -0
  2. package/package.json +2 -2
  3. package/payload/platform/lib/routine-templates/dist/index.d.ts +22 -16
  4. package/payload/platform/lib/routine-templates/dist/index.d.ts.map +1 -1
  5. package/payload/platform/lib/routine-templates/dist/index.js +15 -10
  6. package/payload/platform/lib/routine-templates/dist/index.js.map +1 -1
  7. package/payload/platform/lib/routine-templates/dist/roster.d.ts +3 -3
  8. package/payload/platform/lib/routine-templates/dist/roster.d.ts.map +1 -1
  9. package/payload/platform/lib/routine-templates/src/__tests__/seed.test.ts +15 -11
  10. package/payload/platform/lib/routine-templates/src/index.ts +23 -17
  11. package/payload/platform/lib/routine-templates/src/roster.ts +3 -3
  12. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +48 -14
  13. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +11 -0
  14. package/payload/platform/plugins/docs/references/admin-ui.md +47 -13
  15. package/payload/platform/plugins/scheduling/PLUGIN.md +12 -0
  16. package/payload/platform/plugins/scheduling/mcp/dist/index.js +6 -2
  17. package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
  18. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/update-summary.test.d.ts +2 -0
  19. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/update-summary.test.d.ts.map +1 -0
  20. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/update-summary.test.js +54 -0
  21. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/update-summary.test.js.map +1 -0
  22. package/payload/platform/plugins/scheduling/mcp/dist/lib/update-summary.d.ts +17 -0
  23. package/payload/platform/plugins/scheduling/mcp/dist/lib/update-summary.d.ts.map +1 -0
  24. package/payload/platform/plugins/scheduling/mcp/dist/lib/update-summary.js +43 -0
  25. package/payload/platform/plugins/scheduling/mcp/dist/lib/update-summary.js.map +1 -0
  26. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-routine-description.test.d.ts +2 -0
  27. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-routine-description.test.d.ts.map +1 -0
  28. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-routine-description.test.js +87 -0
  29. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-routine-description.test.js.map +1 -0
  30. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/description-coverage.test.d.ts +2 -0
  31. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/description-coverage.test.d.ts.map +1 -0
  32. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/description-coverage.test.js +123 -0
  33. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/description-coverage.test.js.map +1 -0
  34. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +36 -0
  35. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
  36. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +89 -0
  37. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
  38. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +13 -1
  39. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
  40. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-routine-description.d.ts +35 -0
  41. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-routine-description.d.ts.map +1 -0
  42. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-routine-description.js +56 -0
  43. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-routine-description.js.map +1 -0
  44. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-summary.test.d.ts +2 -0
  45. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-summary.test.d.ts.map +1 -0
  46. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-summary.test.js +80 -0
  47. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-summary.test.js.map +1 -0
  48. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts +2 -1
  49. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts.map +1 -1
  50. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js +19 -1
  51. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js.map +1 -1
  52. package/payload/platform/plugins/telegram/PLUGIN.md +2 -0
  53. package/payload/platform/plugins/telegram/mcp/dist/index.js +47 -47
  54. package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -1
  55. package/payload/platform/plugins/telegram/mcp/dist/lib/secret-path.d.ts +16 -0
  56. package/payload/platform/plugins/telegram/mcp/dist/lib/secret-path.d.ts.map +1 -0
  57. package/payload/platform/plugins/telegram/mcp/dist/lib/secret-path.js +50 -0
  58. package/payload/platform/plugins/telegram/mcp/dist/lib/secret-path.js.map +1 -0
  59. package/payload/platform/plugins/telegram/mcp/dist/lib/webhook-url.d.ts +8 -0
  60. package/payload/platform/plugins/telegram/mcp/dist/lib/webhook-url.d.ts.map +1 -0
  61. package/payload/platform/plugins/telegram/mcp/dist/lib/webhook-url.js +12 -0
  62. package/payload/platform/plugins/telegram/mcp/dist/lib/webhook-url.js.map +1 -0
  63. package/payload/platform/plugins/telegram/references/setup-guide.md +2 -0
  64. package/payload/platform/plugins/telegram/skills/configure/SKILL.md +6 -1
  65. package/payload/platform/scripts/check-routine-roster-doc.mjs +127 -0
  66. package/payload/platform/services/telegram-channel/dist/notification.d.ts +8 -3
  67. package/payload/platform/services/telegram-channel/dist/notification.d.ts.map +1 -1
  68. package/payload/platform/services/telegram-channel/dist/notification.js +10 -3
  69. package/payload/platform/services/telegram-channel/dist/notification.js.map +1 -1
  70. package/payload/platform/services/telegram-channel/dist/server.js +1 -1
  71. package/payload/platform/services/telegram-channel/dist/server.js.map +1 -1
  72. package/payload/platform/services/telegram-channel/dist/turn-follow.d.ts +28 -0
  73. package/payload/platform/services/telegram-channel/dist/turn-follow.d.ts.map +1 -1
  74. package/payload/platform/services/telegram-channel/dist/turn-follow.js +33 -1
  75. package/payload/platform/services/telegram-channel/dist/turn-follow.js.map +1 -1
  76. package/payload/platform/services/webchat-channel/dist/notification.d.ts +8 -3
  77. package/payload/platform/services/webchat-channel/dist/notification.d.ts.map +1 -1
  78. package/payload/platform/services/webchat-channel/dist/notification.js +10 -3
  79. package/payload/platform/services/webchat-channel/dist/notification.js.map +1 -1
  80. package/payload/platform/services/webchat-channel/dist/server.js +1 -1
  81. package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
  82. package/payload/platform/services/webchat-channel/dist/turn-follow.d.ts +28 -0
  83. package/payload/platform/services/webchat-channel/dist/turn-follow.d.ts.map +1 -1
  84. package/payload/platform/services/webchat-channel/dist/turn-follow.js +33 -1
  85. package/payload/platform/services/webchat-channel/dist/turn-follow.js.map +1 -1
  86. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +28 -4
  87. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
  88. package/payload/platform/services/whatsapp-channel/dist/notification.js +30 -7
  89. package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
  90. package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -1
  91. package/payload/platform/services/whatsapp-channel/dist/server.js +13 -5
  92. package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
  93. package/payload/platform/services/whatsapp-channel/dist/targets.d.ts +2 -0
  94. package/payload/platform/services/whatsapp-channel/dist/targets.d.ts.map +1 -1
  95. package/payload/platform/services/whatsapp-channel/dist/targets.js +14 -1
  96. package/payload/platform/services/whatsapp-channel/dist/targets.js.map +1 -1
  97. package/payload/platform/services/whatsapp-channel/dist/turn-follow.d.ts +28 -0
  98. package/payload/platform/services/whatsapp-channel/dist/turn-follow.d.ts.map +1 -1
  99. package/payload/platform/services/whatsapp-channel/dist/turn-follow.js +34 -1
  100. package/payload/platform/services/whatsapp-channel/dist/turn-follow.js.map +1 -1
  101. package/payload/server/{chunk-MHNHG3GL.js → chunk-G6ULACHG.js} +1 -1
  102. package/payload/server/{chunk-Q33KT7YJ.js → chunk-JOVREC6E.js} +117 -1
  103. package/payload/server/{chunk-WGMIUXXG.js → chunk-SKYZG6OT.js} +11 -0
  104. package/payload/server/{manager-W32LVPCT.js → manager-2VEJKVEO.js} +2 -2
  105. package/payload/server/maxy-edge.js +2 -2
  106. package/payload/server/public/assets/routines-OGFXwTFO.js +2 -0
  107. package/payload/server/public/assets/routines-OGFXwTFO.js.br +0 -0
  108. package/payload/server/public/assets/routines-OGFXwTFO.js.gz +0 -0
  109. package/payload/server/public/routines.html +1 -1
  110. package/payload/server/server.js +285 -170
  111. package/payload/server/public/assets/routines-Ds0yz7_C.js +0 -2
  112. package/payload/server/public/assets/routines-Ds0yz7_C.js.br +0 -0
  113. package/payload/server/public/assets/routines-Ds0yz7_C.js.gz +0 -0
@@ -55,12 +55,21 @@ function isConsumedInbound(ev) {
55
55
  // counting them would multiply each inbound. They are never counted.
56
56
  return false;
57
57
  }
58
+ /** A usage figure the row actually reported, or -1. */
59
+ function usageNum(v) {
60
+ return typeof v === 'number' && Number.isFinite(v) ? v : -1;
61
+ }
58
62
  /** Fold one turn's JSONL line strings into the delivery decision. Pure. */
59
63
  export function reduceTurnFromLines(lines) {
60
64
  let replied = false;
61
65
  let finalText = '';
62
66
  let reachedEndTurn = false;
63
67
  let consumedInbounds = 0;
68
+ let cacheReadTokens = -1;
69
+ let inputTokens = -1;
70
+ let outputTokens = -1;
71
+ let thinkingBlocks = 0;
72
+ let thinkingChars = 0;
64
73
  for (const line of lines) {
65
74
  if (!line)
66
75
  continue;
@@ -78,6 +87,24 @@ export function reduceTurnFromLines(lines) {
78
87
  }
79
88
  const msg = ev.message;
80
89
  const isEnd = msg?.stop_reason === 'end_turn';
90
+ // Task 2364 — counted ahead of the content-shape guard below so every
91
+ // assistant row in the turn contributes, not only the end_turn row.
92
+ if (msg && Array.isArray(msg.content)) {
93
+ for (const block of msg.content) {
94
+ if (block?.type !== 'thinking')
95
+ continue;
96
+ thinkingBlocks++;
97
+ if (typeof block.thinking === 'string')
98
+ thinkingChars += block.thinking.length;
99
+ }
100
+ }
101
+ // The segment holds exactly one end_turn row and it is the last line
102
+ // (followTurnEnds cuts a new segment at each one), so this assigns once.
103
+ if (isEnd) {
104
+ cacheReadTokens = usageNum(msg?.usage?.cache_read_input_tokens);
105
+ inputTokens = usageNum(msg?.usage?.input_tokens);
106
+ outputTokens = usageNum(msg?.usage?.output_tokens);
107
+ }
81
108
  if (!msg || !Array.isArray(msg.content)) {
82
109
  if (isEnd) {
83
110
  reachedEndTurn = true;
@@ -99,7 +126,13 @@ export function reduceTurnFromLines(lines) {
99
126
  finalText = endText;
100
127
  }
101
128
  }
102
- return { replied, finalText, reachedEndTurn, consumedInbounds };
129
+ return {
130
+ replied,
131
+ finalText,
132
+ reachedEndTurn,
133
+ consumedInbounds,
134
+ context: { cacheReadTokens, inputTokens, outputTokens, thinkingBlocks, thinkingChars },
135
+ };
103
136
  }
104
137
  /** True iff `line` is an assistant message with stop_reason 'end_turn'. */
105
138
  function isAssistantEndTurn(line) {
@@ -1 +1 @@
1
- {"version":3,"file":"turn-follow.js","sourceRoot":"","sources":["../src/turn-follow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"turn-follow.js","sourceRoot":"","sources":["../src/turn-follow.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@ import {
8
8
  getUserTimezone,
9
9
  isValidAccountId,
10
10
  registerLoop
11
- } from "./chunk-WGMIUXXG.js";
11
+ } from "./chunk-SKYZG6OT.js";
12
12
  import {
13
13
  __commonJS,
14
14
  __require,
@@ -12,7 +12,7 @@ import {
12
12
  getConversationOwner,
13
13
  isValidAccountId,
14
14
  registerLoop
15
- } from "./chunk-WGMIUXXG.js";
15
+ } from "./chunk-SKYZG6OT.js";
16
16
 
17
17
  // node_modules/hono/dist/compose.js
18
18
  var compose = (middleware, onError, onNotFound) => {
@@ -3618,6 +3618,99 @@ function escapeHtml(str) {
3618
3618
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
3619
3619
  }
3620
3620
 
3621
+ // app/lib/pwa.ts
3622
+ var PWA_SURFACES = [
3623
+ {
3624
+ surface: "admin",
3625
+ shellFile: "index.html",
3626
+ manifestPath: "/manifest-admin.webmanifest",
3627
+ nameSuffix: "",
3628
+ startUrl: "/",
3629
+ scope: "/",
3630
+ id: "/?pwa=admin"
3631
+ },
3632
+ {
3633
+ surface: "operator",
3634
+ shellFile: "operator.html",
3635
+ manifestPath: "/manifest-operator.webmanifest",
3636
+ nameSuffix: " Operator",
3637
+ startUrl: "/",
3638
+ scope: "/",
3639
+ id: "/?pwa=operator"
3640
+ },
3641
+ {
3642
+ surface: "chat",
3643
+ shellFile: "chat.html",
3644
+ manifestPath: "/manifest-chat.webmanifest",
3645
+ nameSuffix: " Chat",
3646
+ startUrl: "/chat",
3647
+ scope: "/chat",
3648
+ id: "/chat?pwa=chat"
3649
+ }
3650
+ ];
3651
+ var MANIFEST_CONTENT_TYPE = "application/manifest+json";
3652
+ var SW_CONTENT_TYPE = "application/javascript";
3653
+ function pwaSurfaceForShell(file) {
3654
+ return PWA_SURFACES.find((s) => s.shellFile === file);
3655
+ }
3656
+ function buildManifest(s, b) {
3657
+ const name = `${b.productName}${s.nameSuffix}`;
3658
+ return {
3659
+ id: s.id,
3660
+ name,
3661
+ short_name: name,
3662
+ start_url: s.startUrl,
3663
+ scope: s.scope,
3664
+ display: "standalone",
3665
+ theme_color: b.themeColor,
3666
+ background_color: b.backgroundColor,
3667
+ // Explicit 192/512 `any` icons (iOS/macOS composite transparency onto black,
3668
+ // so these are opaque) plus a wider-safe-zone `maskable` entry for Android's
3669
+ // circular crop. background_color sets only the splash; the tile background
3670
+ // is baked into the PNGs.
3671
+ icons: [
3672
+ { src: b.appIcon192, sizes: "192x192", purpose: "any" },
3673
+ { src: b.appIcon512, sizes: "512x512", purpose: "any" },
3674
+ { src: b.maskableIcon, sizes: "512x512", purpose: "maskable" }
3675
+ ]
3676
+ };
3677
+ }
3678
+ function escAttr(s) {
3679
+ return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
3680
+ }
3681
+ function swRegisterScript(s) {
3682
+ return [
3683
+ "<script>",
3684
+ "if('serviceWorker' in navigator){navigator.serviceWorker.register('/sw.js').catch(function(e){",
3685
+ `try{fetch('/api/_client-error',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({kind:'event',source:'pwa',op:'sw-register-fail',surface:'${s.surface}',scope:'${s.scope}',err:String((e&&e.message)||e)}),keepalive:true}).catch(function(){});}catch(_){}`,
3686
+ "});}",
3687
+ "</script>"
3688
+ ].join("\n");
3689
+ }
3690
+ function installHeadLines(manifestPath, b) {
3691
+ return [
3692
+ `<link rel="manifest" href="${escAttr(manifestPath)}">`,
3693
+ `<link rel="apple-touch-icon" href="${escAttr(b.appleTouchIcon)}">`,
3694
+ // Both the standards-based and the legacy Apple capable meta: Chromium
3695
+ // deprecates `apple-mobile-web-app-capable` in favour of
3696
+ // `mobile-web-app-capable`, while iOS Safari still reads the apple one.
3697
+ '<meta name="mobile-web-app-capable" content="yes">',
3698
+ '<meta name="apple-mobile-web-app-capable" content="yes">',
3699
+ `<meta name="theme-color" content="${escAttr(b.themeColor)}">`
3700
+ ];
3701
+ }
3702
+ function pwaHeadTags(s, b) {
3703
+ return [...installHeadLines(s.manifestPath, b), swRegisterScript(s)].join("\n");
3704
+ }
3705
+ function pwaCensus(d) {
3706
+ const manifestLinked = PWA_SURFACES.filter((s) => {
3707
+ const html = d.shellHtml(s.shellFile);
3708
+ return html != null && html.includes(`"${s.manifestPath}"`);
3709
+ }).length;
3710
+ const iconsPresent = d.iconExists() ? PWA_SURFACES.length : 0;
3711
+ return { surfaces: PWA_SURFACES.length, manifestLinked, iconsPresent };
3712
+ }
3713
+
3621
3714
  // app/lib/auth-gate.ts
3622
3715
  function canAccessAdmin(input) {
3623
3716
  const client = resolveClientIp(input.remoteAddress, input.xForwardedFor);
@@ -3649,6 +3742,21 @@ function parseCookieValue(cookieHeader, name) {
3649
3742
  function isApiRequestPath(path) {
3650
3743
  return path.startsWith("/api/");
3651
3744
  }
3745
+ var PWA_PUBLIC_PATHS = /* @__PURE__ */ new Set(["/sw.js", ...PWA_SURFACES.map((s) => s.manifestPath)]);
3746
+ function isRemoteAuthBypassPath(path) {
3747
+ return path === "/favicon.ico" || path.startsWith("/assets/") || path.startsWith("/brand/") || // Public free/busy is read by the booking page (a separate Cloudflare Pages
3748
+ // origin) against the brand host with no admin cookie. It is public by
3749
+ // design — open slots only, no :Meeting detail — so it bypasses the gate
3750
+ // exactly like /brand/. The detail-leak guard lives in the route + its test.
3751
+ path === "/api/calendar/free-busy" || // Task 2365 — Telegram POSTs the webhook from its own servers, which hold
3752
+ // no __remote_session cookie and can never obtain one, so every delivery
3753
+ // was answered 401 here before the route ever ran. The route authenticates
3754
+ // the request itself against the per-account secret header
3755
+ // (server/routes/telegram.ts), exactly the request-borne-auth precedent the
3756
+ // free-busy entry above sets. The trailing slash keeps a sibling path such
3757
+ // as /api/telegram-admin/ outside the exemption.
3758
+ path.startsWith("/api/telegram/") || PWA_PUBLIC_PATHS.has(path);
3759
+ }
3652
3760
 
3653
3761
  // app/lib/agent-slug-pattern.ts
3654
3762
  var AGENT_SLUG_PATTERN = /^\/([a-z][a-z0-9-]{2,49})$/;
@@ -4387,9 +4495,17 @@ export {
4387
4495
  recordFailedAttempt,
4388
4496
  clearRateLimit,
4389
4497
  renderLoginPage,
4498
+ PWA_SURFACES,
4499
+ MANIFEST_CONTENT_TYPE,
4500
+ SW_CONTENT_TYPE,
4501
+ pwaSurfaceForShell,
4502
+ buildManifest,
4503
+ pwaHeadTags,
4504
+ pwaCensus,
4390
4505
  canAccessAdmin,
4391
4506
  parseCookieValue,
4392
4507
  isApiRequestPath,
4508
+ isRemoteAuthBypassPath,
4393
4509
  AGENT_SLUG_PATTERN,
4394
4510
  PUBLIC_ALLOWED_PREFIXES,
4395
4511
  PUBLIC_ALLOWED_EXACT,
@@ -752,6 +752,16 @@ async function preloadEmbedModel() {
752
752
  );
753
753
  }
754
754
  }
755
+ async function embedForWrite(text) {
756
+ try {
757
+ return await embed(text);
758
+ } catch (err) {
759
+ console.error(
760
+ `[embed-write] op=skip reason=embedder-unavailable detail=${err instanceof Error ? err.message : String(err)}`
761
+ );
762
+ return [];
763
+ }
764
+ }
755
765
  var sessionStoreRef = null;
756
766
  function getCachedSessionId(cacheKey) {
757
767
  return sessionStoreRef?.get(cacheKey)?.sessionId;
@@ -2196,6 +2206,7 @@ export {
2196
2206
  runUserProfileReconcile,
2197
2207
  embed,
2198
2208
  preloadEmbedModel,
2209
+ embedForWrite,
2199
2210
  GREETING_DIRECTIVE,
2200
2211
  ensureConversation,
2201
2212
  ensureSessionConversation,
@@ -30,8 +30,8 @@ import {
30
30
  startConnection,
31
31
  stopConnection,
32
32
  storeMessage
33
- } from "./chunk-MHNHG3GL.js";
34
- import "./chunk-WGMIUXXG.js";
33
+ } from "./chunk-G6ULACHG.js";
34
+ import "./chunk-SKYZG6OT.js";
35
35
  import "./chunk-HYQNUVGO.js";
36
36
  export {
37
37
  buildNotifyPending,
@@ -19,12 +19,12 @@ import {
19
19
  screencastLog,
20
20
  vncLog,
21
21
  websockifyLog
22
- } from "./chunk-Q33KT7YJ.js";
22
+ } from "./chunk-JOVREC6E.js";
23
23
  import {
24
24
  CDP_PORT,
25
25
  LOG_DIR,
26
26
  WEBSOCKIFY_PORT
27
- } from "./chunk-WGMIUXXG.js";
27
+ } from "./chunk-SKYZG6OT.js";
28
28
  import "./chunk-HYQNUVGO.js";
29
29
 
30
30
  // server/edge.ts
@@ -0,0 +1,2 @@
1
+ import{o as e}from"./chunk-CltuBf4Z.js";import{F as t,G as n,L as r,M as i,O as a,V as o,Y as s,Z as c,_ as l,at as u,ct as d,f,j as p,k as m,m as h,nt as g,ot as _,v}from"./useMediaQuery-_mMln3Fu.js";import{k as y,m as b,t as x}from"./AdminShell-DVBAMUCy.js";import{t as S}from"./clock-CfDdatjp.js";import{t as C}from"./wrench-BO-l46rF.js";import{r as w}from"./file-download-DbNIjWiK.js";var ee=c(`circle-pause`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`line`,{x1:`10`,x2:`10`,y1:`15`,y2:`9`,key:`c1nkhi`}],[`line`,{x1:`14`,x2:`14`,y1:`15`,y2:`9`,key:`h65svq`}]]),te=c(`circle-play`,[[`path`,{d:`M9 9.003a1 1 0 0 1 1.517-.859l4.997 2.997a1 1 0 0 1 0 1.718l-4.997 2.997A1 1 0 0 1 9 14.996z`,key:`kmsa83`}],[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}]]),T=c(`history`,[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`,key:`1357e3`}],[`path`,{d:`M3 3v5h5`,key:`1xhq8a`}],[`path`,{d:`M12 7v5l4 2`,key:`1fdv2h`}]]),E=_(),D=e(d(),1),O=[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`];function k(e,t){if(e===`*`)return{kind:`any`,value:0,rangeStart:null,rangeEnd:null,step:1};let n=e.match(/^(\*|\d+-\d+)\/(\d+)$/);if(n){let e=Number(n[2]);if(e<1)return null;if(n[1]===`*`)return{kind:`step`,value:0,rangeStart:null,rangeEnd:null,step:e};let[r,i]=n[1].split(`-`).map(Number);return r>t||i>t||r>i?null:{kind:`step`,value:0,rangeStart:r,rangeEnd:i,step:e}}let r=e.match(/^(\d+)-(\d+)$/);if(r){let e=Number(r[1]),n=Number(r[2]);return e>t||n>t||e>n?null:{kind:`step`,value:0,rangeStart:e,rangeEnd:n,step:1}}if(/^\d+$/.test(e)){let n=Number(e);return n>t?null:{kind:`fixed`,value:n,rangeStart:null,rangeEnd:null,step:1}}return null}function A(e){return String(e).padStart(2,`0`)}function j(e){if(e===`*`)return null;let t=e.match(/^(\d+)-(\d+)$/);if(t){let e=Number(t[1]),n=Number(t[2]);return e>7||n>7||e>n?`invalid`:`${O[e%7]} to ${O[n%7]}`}let n=e.split(`,`);return n.length>0&&n.every(e=>/^\d+$/.test(e)&&Number(e)<=7)?n.map(e=>O[Number(e)%7]).join(`, `):`invalid`}function M(e){let t=e.trim().split(/\s+/);if(t.length!==5)return e;let[n,r,i,a,o]=t;if(a!==`*`||i!==`*`&&!/^\d+$/.test(i)||i!==`*`&&(Number(i)<1||Number(i)>31))return e;let s=k(n,59),c=k(r,23);if(!s||!c)return e;let l=j(o);if(l===`invalid`||s.kind===`step`&&s.rangeStart!==null||(s.kind===`any`&&(s={kind:`step`,value:0,rangeStart:null,rangeEnd:null,step:1}),c.kind===`step`&&c.step===1&&c.rangeStart===null&&(c={kind:`any`,value:0,rangeStart:null,rangeEnd:null,step:1}),i!==`*`&&!(s.kind===`fixed`&&c.kind===`fixed`&&o===`*`))||s.kind===`step`&&c.kind===`step`&&c.step>1)return e;let u=l?`, ${l}`:``,d=e=>e.rangeStart+Math.floor((e.rangeEnd-e.rangeStart)/e.step)*e.step;if(s.kind===`step`){let e=s.step===1?`Every minute`:`Every ${s.step} minutes`;return c.kind===`any`?`${e}${u}`:c.kind===`fixed`?`${e}, ${A(c.value)}:00 to ${A(c.value)}:59${u}`:`${e}, ${A(c.rangeStart)}:00 to ${A(d(c))}:00${u}`}if(c.kind===`step`){let e=A(s.value),t=s.value===0?``:` at :${e}`;return c.rangeStart===null?`Every ${c.step} hours${t}${u}`:c.step===1?`Hourly, ${A(c.rangeStart)}:${e} to ${A(c.rangeEnd)}:${e}${u}`:`Every ${c.step} hours, ${A(c.rangeStart)}:${e} to ${A(d(c))}:${e}${u}`}if(c.kind===`any`)return`${s.value===0?`Every hour`:`Every hour at :${A(s.value)}`}${u}`;let f=`${A(c.value)}:${A(s.value)}`;return i===`*`?l?`${l} at ${f}`:`Daily at ${f}`:`Monthly on day ${Number(i)} at ${f}`}var N={timeMode:`at`,minute:0,hour:9,interval:1,window:null,dayMode:`every`,weekdays:[],dayOfMonth:1};function P(e){let t=e.match(/^(\d+)-(\d+)$/);if(t){let e=Number(t[1]),n=Number(t[2]);if(e>7||n>7||e>n)return null;let r=[];for(let t=e;t<=n;t+=1)r.push(t%7);return[...new Set(r)].sort((e,t)=>e-t)}let n=e.split(`,`);return n.every(e=>/^\d+$/.test(e)&&Number(e)<=7)?[...new Set(n.map(e=>Number(e)%7))].sort((e,t)=>e-t):null}function F(e){let t=e.trim().split(/\s+/);if(t.length!==5)return null;let[n,r,i,a,o]=t;if(a!==`*`||i!==`*`&&!/^\d+$/.test(i))return null;let s=k(n,59),c=k(r,23);if(!s||!c||s.kind===`step`&&s.rangeStart!==null)return null;let l=`every`,u=[],d=1;if(i!==`*`){if(o!==`*`)return null;let e=Number(i);if(e<1||e>31||s.kind!==`fixed`||c.kind!==`fixed`)return null;l=`dayOfMonth`,d=e}else if(o!==`*`){let e=P(o);if(e===null)return null;l=`weekdays`,u=e}let f={dayMode:l,weekdays:u,dayOfMonth:d};if(s.kind===`any`||s.kind===`step`){if(c.kind===`step`&&c.step>1)return null;let e=s.kind===`any`?1:s.step,t=c.kind===`any`?null:c.kind===`fixed`?{start:c.value,end:c.value}:{start:c.rangeStart,end:c.rangeEnd};return{...N,...f,timeMode:`everyMinutes`,minute:0,interval:e,window:t}}return c.kind===`fixed`?{...N,...f,timeMode:`at`,minute:s.value,hour:c.value}:c.kind===`any`?{...N,...f,timeMode:`everyHours`,minute:s.value,interval:1,window:null}:{...N,...f,timeMode:`everyHours`,minute:s.value,interval:c.step,window:c.rangeStart===null?null:{start:c.rangeStart,end:c.rangeEnd}}}function I(e){return e.dayMode===`dayOfMonth`?[String(e.dayOfMonth),`*`]:e.dayMode===`weekdays`&&e.weekdays.length>0?[`*`,[...e.weekdays].sort((e,t)=>e-t).join(`,`)]:[`*`,`*`]}function L(e){let[t,n]=I(e);if(e.timeMode===`everyMinutes`){let r=e.window===null?`*`:e.window.start===e.window.end?String(e.window.start):`${e.window.start}-${e.window.end}`;return`*/${e.interval} ${r} ${t} * ${n}`}if(e.timeMode===`everyHours`){let r=e.window===null?e.interval===1?`*`:`*/${e.interval}`:e.interval===1?`${e.window.start}-${e.window.end}`:`${e.window.start}-${e.window.end}/${e.interval}`;return`${e.minute} ${r} ${t} * ${n}`}return`${e.minute} ${e.hour} ${t} * ${n}`}var R=g(),z=[{value:1,label:`Mon`},{value:2,label:`Tue`},{value:3,label:`Wed`},{value:4,label:`Thu`},{value:5,label:`Fri`},{value:6,label:`Sat`},{value:0,label:`Sun`}],B=Array.from({length:24},(e,t)=>t),V=e=>String(e).padStart(2,`0`),H={timeMode:`at`,minute:0,hour:9,interval:1,window:null,dayMode:`every`,weekdays:[],dayOfMonth:1};function ne({recurrence:e,onChange:t,disabled:n}){let r=e?F(e):H,[i,a]=(0,D.useState)(r??H),[o]=(0,D.useState)(e!=null&&r==null),[s,c]=(0,D.useState)(e??``);if((0,D.useEffect)(()=>{fetch(`/api/_client-error`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({kind:`event`,source:`routines`,op:`schedule-editor`,mode:o?`raw`:`builder`}),keepalive:!0}).catch(()=>{})},[o]),o)return(0,R.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`Schedule (advanced)`}),(0,R.jsx)(`input`,{type:`text`,className:`routine-raw-cron`,value:s,disabled:n,onChange:e=>{c(e.target.value),t(e.target.value)},"aria-label":`Cron expression`}),(0,R.jsx)(`span`,{className:`routine-raw-note`,children:`This routine uses an advanced schedule, edited as a raw cron expression.`})]});let l=e=>{a(e),t(L(e))},u=e=>{let t=e!==`at`&&i.dayMode===`dayOfMonth`?`every`:i.dayMode;l({...i,timeMode:e,dayMode:t})},d=e=>{let t=e===`weekdays`&&i.weekdays.length===0?[1]:i.weekdays;l({...i,dayMode:e,weekdays:t})},f=e=>{let[t,n]=e.split(`:`);l({...i,hour:Number(t)||0,minute:Number(n)||0})},p=e=>{let t=i.weekdays.includes(e);if(t&&i.weekdays.length===1)return;let n=t?i.weekdays.filter(t=>t!==e):[...i.weekdays,e];l({...i,weekdays:n})},m=e=>l({...i,window:e?{start:0,end:23}:null}),h=(e,t)=>{let n={...i.window??{start:0,end:23},[e]:Number(t)};n.start>n.end&&(e===`start`?n.end=n.start:n.start=n.end),l({...i,window:n})},g=(e,t,n)=>Math.min(n,Math.max(t,Number(e)||t));return(0,R.jsxs)(`div`,{className:`routine-sched`,children:[(0,R.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`How often`}),(0,R.jsxs)(`select`,{"aria-label":`How often`,value:i.timeMode,disabled:n,onChange:e=>u(e.target.value),children:[(0,R.jsx)(`option`,{value:`at`,children:`At a time of day`}),(0,R.jsx)(`option`,{value:`everyMinutes`,children:`Every few minutes`}),(0,R.jsx)(`option`,{value:`everyHours`,children:`Every few hours`})]})]}),i.timeMode===`at`&&(0,R.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`Time of day`}),(0,R.jsx)(`input`,{type:`time`,"aria-label":`Time of day`,value:`${V(i.hour)}:${V(i.minute)}`,disabled:n,onChange:e=>f(e.target.value)})]}),i.timeMode===`everyMinutes`&&(0,R.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`Minutes between runs`}),(0,R.jsx)(`input`,{type:`number`,min:1,max:59,"aria-label":`Minutes between runs`,value:i.interval,disabled:n,onChange:e=>l({...i,interval:g(e.target.value,1,59)})})]}),i.timeMode===`everyHours`&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`Hours between runs`}),(0,R.jsx)(`input`,{type:`number`,min:1,max:23,"aria-label":`Hours between runs`,value:i.interval,disabled:n,onChange:e=>l({...i,interval:g(e.target.value,1,23)})})]}),(0,R.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`Minute of the hour`}),(0,R.jsx)(`input`,{type:`number`,min:0,max:59,"aria-label":`Minute of the hour`,value:i.minute,disabled:n,onChange:e=>l({...i,minute:g(e.target.value,0,59)})})]})]}),i.timeMode!==`at`&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`label`,{className:`cal-modal-field routine-sched-check`,children:[(0,R.jsx)(`input`,{type:`checkbox`,"aria-label":`Only between certain hours`,checked:i.window!==null,disabled:n,onChange:e=>m(e.target.checked)}),(0,R.jsx)(`span`,{children:`Only between certain hours`})]}),i.window!==null&&(0,R.jsxs)(`div`,{className:`routine-sched-row`,children:[(0,R.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`From hour`}),(0,R.jsx)(`select`,{"aria-label":`From hour`,value:i.window.start,disabled:n,onChange:e=>h(`start`,e.target.value),children:B.map(e=>(0,R.jsxs)(`option`,{value:e,children:[V(e),`:00`]},e))})]}),(0,R.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`To hour`}),(0,R.jsx)(`select`,{"aria-label":`To hour`,value:i.window.end,disabled:n,onChange:e=>h(`end`,e.target.value),children:B.map(e=>(0,R.jsxs)(`option`,{value:e,children:[V(e),`:00`]},e))})]})]})]}),(0,R.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`Which days`}),(0,R.jsxs)(`select`,{"aria-label":`Which days`,value:i.dayMode,disabled:n,onChange:e=>d(e.target.value),children:[(0,R.jsx)(`option`,{value:`every`,children:`Every day`}),(0,R.jsx)(`option`,{value:`weekdays`,children:`Specific days`}),i.timeMode===`at`&&(0,R.jsx)(`option`,{value:`dayOfMonth`,children:`A day of the month`})]})]}),i.dayMode===`weekdays`&&(0,R.jsxs)(`div`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`Days`}),(0,R.jsx)(`div`,{className:`routine-weekdays`,children:z.map(e=>(0,R.jsx)(`button`,{type:`button`,className:`routine-weekday${i.weekdays.includes(e.value)?` routine-weekday-on`:``}`,"aria-pressed":i.weekdays.includes(e.value),disabled:n,onClick:()=>p(e.value),children:e.label},e.value))})]}),i.dayMode===`dayOfMonth`&&(0,R.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`Day of month`}),(0,R.jsx)(`select`,{"aria-label":`Day of month`,value:i.dayOfMonth,disabled:n,onChange:e=>l({...i,dayOfMonth:Number(e.target.value)||1}),children:Array.from({length:31},(e,t)=>t+1).map(e=>(0,R.jsx)(`option`,{value:e,children:e},e))})]})]})}function U(e){let t=e.trim().replace(/[\s\-().]/g,``).replace(/^\+/,``);return/^\d{11,15}$/.test(t)?`+${t.slice(0,2)} ${t.slice(2,6)} ${t.slice(6)}`:e}function re(e){if(e.name)return`${e.name} · ${e.label}`;let t=e.channel===`whatsapp`?U(e.destination):e.destination;return`${e.label} · ${t}`}var W={scheduled:`live`,due:`live`,suspended:`stood-down`,cancelled:`inert`,completed:`inert`};function G(e){return e==null||!Object.hasOwn(W,e)?`unknown`:W[e]}var K={finished:`live`,started:`in-flight`,accepted:`in-flight`,open:`in-flight`,failed:`error`,"no-destination":`warning`};function ie(e){return e==null||!Object.hasOwn(K,e)?`unknown`:K[e]}function ae({eventStatus:e}){let t=G(e);return(0,R.jsx)(`span`,{className:`routine-status-dot is-${t}`,"data-state":t,"aria-hidden":`true`})}function oe(e,t){if(!e)return`—`;let n=Date.parse(e);return Number.isFinite(n)?l(new Date(n).toISOString(),t):e}function se(e){return e?e.split(`
2
+ `).filter(e=>e.trim()!==``).reverse():[]}function ce({routine:e,adminFetch:t,onClose:n,onSaved:a,onDeleted:s,onViewRuns:c}){let{zone:l}=v(),[u,d]=(0,D.useState)(!1),[m,g]=(0,D.useState)(!1),[_,y]=(0,D.useState)(null),[x,w]=(0,D.useState)(e),[E,O]=(0,D.useState)(!1),k=x.agentChannel!=null,A=x.eventStatus===`suspended`,[j,N]=(0,D.useState)(!1),[P,F]=(0,D.useState)(e.agentPrompt??``),[I,L]=(0,D.useState)(e.description??``),[z,B]=(0,D.useState)(e.recurrence),[V,H]=(0,D.useState)(e.agentChannel??``),[U,W]=(0,D.useState)(e.agentDestination??``),[G,K]=(0,D.useState)(null),[ie,ce]=(0,D.useState)(null),q=k||x.actionPlugin==null,J=se(x.notes);(0,D.useEffect)(()=>{let e=e=>{e.key===`Escape`&&!m&&n()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[m,n]),(0,D.useEffect)(()=>{if(!u||!q||G!==null)return;let e=!1;return t(`/api/admin/dispatch-destinations`).then(async e=>{if(!e.ok)throw Error(`HTTP ${e.status}`);return await e.json()}).then(t=>{e||K(t.destinations)}).catch(t=>{e||(K([]),ce(t instanceof Error?t.message:`Could not load destinations`))}),()=>{e=!0}},[u,q,G,t]);let Y=(G??[]).filter(e=>e.channel===V),X=V.length>0&&U.length>0,Z=V.length>0&&U.length===0||X&&P.trim().length===0,Q=(0,D.useCallback)(()=>{let e={},t=V.length>0&&U.length>0;(k||t)&&P!==(x.agentPrompt??``)&&(e.agentPrompt=P);let n=I.trim().length>0?I:null;return n!==(x.description??null)&&(e.description=n),z!=null&&z!==(x.recurrence??null)&&(e.recurrence=z),t&&(V!==(x.agentChannel??``)||U!==(x.agentDestination??``))?(e.agentChannel=V,e.agentDestination=U):!t&&V===``&&(x.agentChannel??``)!==``&&(e.agentChannel=null,e.agentDestination=null),e},[k,P,I,z,V,U,x]),le=(0,D.useCallback)(async()=>{let n=Q();if(Object.keys(n).length===0){d(!1);return}g(!0),y(null);try{let r=await t(`/api/admin/routines/${encodeURIComponent(e.eventId)}`,{method:`PATCH`,headers:{"content-type":`application/json`},body:JSON.stringify(n)});if(!r.ok){let e=await r.json().catch(()=>({}));throw Error(e.error??`HTTP ${r.status}`)}let i=await r.json();w(i.routine),F(i.routine.agentPrompt??``),L(i.routine.description??``),B(i.routine.recurrence),H(i.routine.agentChannel??``),W(i.routine.agentDestination??``),a(i.routine),d(!1)}catch(e){y(e instanceof Error?e.message:`Save failed`)}finally{g(!1)}},[t,Q,e.eventId,a]),ue=(0,D.useCallback)(async()=>{if(m)return;if(!j){O(!1),N(!0);return}let n=A?`resume`:`suspend`;g(!0),y(null);try{let r=await t(`/api/admin/routines/${encodeURIComponent(e.eventId)}/${n}`,{method:`POST`});if(!r.ok){let e=await r.json().catch(()=>({}));throw Error(e.error??`HTTP ${r.status}`)}let i=await r.json();w(i.routine),a(i.routine),N(!1)}catch(e){y(e instanceof Error?e.message:`${n} failed`),N(!1)}finally{g(!1)}},[t,m,j,A,e.eventId,a]),de=(0,D.useCallback)(async()=>{if(!m){if(!E){N(!1),O(!0);return}g(!0),y(null);try{let n=await t(`/api/admin/routines/${encodeURIComponent(e.eventId)}`,{method:`DELETE`});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.error??`HTTP ${n.status}`)}s(e.eventId)}catch(e){y(e instanceof Error?e.message:`Delete failed`),O(!1)}finally{g(!1)}}},[t,m,E,e.eventId,s]);return(0,R.jsx)(`div`,{className:`cal-modal-overlay`,onClick:()=>{m||n()},children:(0,R.jsxs)(`div`,{className:`cal-modal ${!u||k||X?`cal-modal-wide`:`cal-modal-dispatch`}`,role:`dialog`,"aria-modal":`true`,"aria-label":u?`Edit routine`:`Routine detail`,onClick:e=>e.stopPropagation(),children:[(0,R.jsxs)(`div`,{className:`cal-modal-header`,children:[(0,R.jsxs)(`span`,{className:`cal-modal-kind`,children:[(0,R.jsx)(b,{size:13}),` Routine`]}),(0,R.jsx)(`button`,{type:`button`,className:`cal-modal-close`,onClick:n,"aria-label":`Close`,autoFocus:!0,disabled:m,children:(0,R.jsx)(p,{size:16})})]}),!u&&(0,R.jsxs)(`div`,{className:`cal-modal-body`,children:[(0,R.jsx)(`div`,{className:`cal-modal-title`,children:x.name??`Untitled routine`}),(0,R.jsxs)(`div`,{className:`cal-modal-row`,children:[(0,R.jsx)(S,{size:14}),(0,R.jsx)(`span`,{children:x.recurrence?M(x.recurrence):`One-time`})]}),(0,R.jsxs)(`div`,{className:`cal-modal-row cal-modal-meta`,children:[(0,R.jsx)(ae,{eventStatus:x.eventStatus}),(0,R.jsxs)(`span`,{children:[`Status: `,x.eventStatus??`unknown`]})]}),(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,R.jsxs)(`span`,{children:[`Next run: `,oe(x.nextRun,l)]})}),(0,R.jsxs)(`div`,{className:`cal-modal-row cal-modal-meta`,children:[(0,R.jsx)(T,{size:14}),(0,R.jsxs)(`span`,{children:[`Last run: `,oe(x.lastTriggered,l),x.lastDispatchResult?` (${x.lastDispatchResult})`:``]})]}),x.description&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,R.jsx)(`span`,{children:`Description`})}),(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-row-top routine-prose`,children:(0,R.jsx)(`span`,{children:x.description})})]}),k?(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`div`,{className:`cal-modal-row`,children:[(0,R.jsx)(h,{channel:x.agentChannel,size:14}),(0,R.jsxs)(`span`,{children:[f[x.agentChannel]??x.agentChannel,` to `,x.agentDestination??`—`]})]}),(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,R.jsx)(`span`,{children:`Instruction sent to the agent`})}),(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-row-top routine-prose`,children:(0,R.jsx)(`span`,{children:x.agentPrompt??`No instruction sent to the agent.`})})]}):x.actionPlugin?(0,R.jsxs)(`div`,{className:`cal-modal-row`,children:[(0,R.jsx)(C,{size:14}),(0,R.jsxs)(`span`,{children:[x.actionPlugin,`.`,x.actionTool,x.actionArgs?` ${x.actionArgs}`:``]})]}):(0,R.jsxs)(`div`,{className:`cal-modal-row`,children:[(0,R.jsx)(S,{size:14}),(0,R.jsx)(`span`,{children:`Scheduled trigger (no dispatch)`})]}),J.length===0?(0,R.jsxs)(`div`,{className:`cal-modal-row cal-modal-meta`,children:[(0,R.jsx)(T,{size:14}),(0,R.jsx)(`span`,{children:`No history recorded.`})]}):(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`div`,{className:`cal-modal-row cal-modal-meta`,children:[(0,R.jsx)(T,{size:14}),(0,R.jsxs)(`span`,{children:[`History (`,J.length,` `,J.length===1?`entry`:`entries`,`)`]})]}),(0,R.jsx)(`div`,{className:`routine-history`,children:J.map((e,t)=>(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:e},t))})]})]}),u&&(0,R.jsxs)(`div`,{className:`cal-modal-body`,children:[q&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`Send to`}),(0,R.jsxs)(`div`,{className:`cal-modal-field-inline`,children:[(0,R.jsxs)(`select`,{value:V,disabled:m,onChange:e=>{H(e.target.value),W(``)},children:[(0,R.jsx)(`option`,{value:``,children:`None (no dispatch)`}),(0,R.jsx)(`option`,{value:`whatsapp`,children:`WhatsApp`}),(0,R.jsx)(`option`,{value:`telegram`,children:`Telegram`})]}),V!==``&&(0,R.jsx)(h,{channel:V,size:16})]})]}),V!==``&&(0,R.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`Destination`}),(0,R.jsxs)(`select`,{value:U,disabled:m||G===null,onChange:e=>W(e.target.value),children:[(0,R.jsx)(`option`,{value:``,children:G===null?`Loading destinations`:Y.length===0?`No registered destinations`:`Choose a destination`}),U!==``&&!Y.some(e=>e.destination===U)&&(0,R.jsxs)(`option`,{value:U,children:[U,` (not in the current list)`]}),Y.map(e=>(0,R.jsx)(`option`,{value:e.destination,children:re(e)},e.destination))]})]}),ie&&(0,R.jsxs)(`div`,{className:`cal-modal-error`,children:[`Could not load destinations: `,ie]})]}),(0,R.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`Description`}),(0,R.jsx)(`input`,{type:`text`,value:I,onChange:e=>L(e.target.value),disabled:m,placeholder:`One line: what this routine is for`})]}),(k||X)&&(0,R.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,R.jsx)(`span`,{children:`Instruction sent to the agent`}),(0,R.jsx)(`textarea`,{className:`cal-modal-textarea`,value:P,onChange:e=>F(e.target.value),disabled:m,rows:16,placeholder:`What should the agent do when this routine fires?`})]}),(0,R.jsx)(ne,{recurrence:x.recurrence,onChange:B,disabled:m})]}),_&&(0,R.jsx)(`div`,{className:`cal-modal-error`,children:_}),(0,R.jsxs)(`div`,{className:`cal-modal-actions`,children:[!u&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:()=>{O(!1),N(!1),d(!0)},disabled:m,children:[(0,R.jsx)(r,{size:14}),` Edit`]}),(0,R.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:()=>c(x),disabled:m,children:[(0,R.jsx)(T,{size:14}),` Runs`]}),(0,R.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:ue,disabled:m,children:[m&&j?(0,R.jsx)(o,{size:14,className:`spin`}):A?(0,R.jsx)(te,{size:14}):(0,R.jsx)(ee,{size:14}),j?A?`Confirm resume`:`Confirm suspend`:A?`Resume`:`Suspend`]}),j&&(0,R.jsx)(`span`,{className:`cal-modal-confirm-text`,children:A?`This routine will run at its next scheduled time. It will not run for the times it missed.`:`This routine stops running until you resume it. Nothing is deleted.`}),(0,R.jsxs)(`button`,{type:`button`,className:`cal-modal-btn cal-modal-btn-danger`,onClick:de,disabled:m,children:[m&&E?(0,R.jsx)(o,{size:14,className:`spin`}):(0,R.jsx)(i,{size:14}),E?`Confirm delete`:`Delete`]})]}),u&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`button`,{type:`button`,className:`cal-modal-btn cal-modal-btn-primary`,onClick:le,disabled:m||Z,children:[m?(0,R.jsx)(o,{size:14,className:`spin`}):null,` Save`]}),(0,R.jsx)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:()=>{d(!1),y(null)},disabled:m,children:`Cancel`})]})]})]})})}function q(e,t){if(!e)return`—`;let n=Date.parse(e);return Number.isFinite(n)?l(new Date(n).toISOString(),t):e}function J(e){return e===null?`—`:e<1e3?`${e} ms`:`${(e/1e3).toFixed(1)} s`}function Y({run:e,routineName:t,onClose:n}){let{zone:r}=v();return(0,D.useEffect)(()=>{let e=e=>{e.key===`Escape`&&n()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[n]),(0,R.jsx)(`div`,{className:`cal-modal-overlay`,onClick:n,children:(0,R.jsxs)(`div`,{className:`cal-modal cal-modal-wide`,role:`dialog`,"aria-modal":`true`,"aria-label":`Run detail`,onClick:e=>e.stopPropagation(),children:[(0,R.jsxs)(`div`,{className:`cal-modal-header`,children:[(0,R.jsx)(`span`,{className:`cal-modal-kind`,children:`Run`}),(0,R.jsx)(`button`,{type:`button`,className:`cal-modal-close`,onClick:n,"aria-label":`Close`,autoFocus:!0,children:(0,R.jsx)(p,{size:16})})]}),(0,R.jsxs)(`div`,{className:`cal-modal-body`,children:[(0,R.jsx)(`div`,{className:`cal-modal-title`,children:t??`Untitled routine`}),e.outputExcerpt!==null&&(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-row-top routine-prose`,"data-testid":`run-output`,children:(0,R.jsx)(`span`,{children:e.outputExcerpt})}),e.outputExcerpt===null&&e.status===`finished`&&(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,"data-testid":`run-output-none`,children:(0,R.jsx)(`span`,{children:`This run finished without sending anything.`})}),(0,R.jsx)(`div`,{className:`cal-modal-row`,children:(0,R.jsx)(`span`,{children:e.status})}),(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,R.jsxs)(`span`,{children:[`Due: `,q(e.scheduledFor,r)]})}),(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,R.jsxs)(`span`,{children:[`Started: `,q(e.startedAt,r)]})}),(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,R.jsxs)(`span`,{children:[`Dispatch ended: `,q(e.endedAt,r),` (`,J(e.ranMs),`)`]})}),(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,R.jsxs)(`span`,{children:[`Output seen: `,q(e.finishedAt,r)]})}),(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,R.jsxs)(`span`,{children:[`Sent to: `,e.target,` · `,e.mode,` · `,e.kind]})}),(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,R.jsxs)(`span`,{children:[`Transport: `,e.dispatchResult??`—`,e.httpStatus===null?``:` (HTTP ${e.httpStatus})`]})}),e.error&&(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-row-top routine-prose`,children:(0,R.jsx)(`span`,{children:e.error})}),(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,R.jsxs)(`span`,{children:[`Conversation: `,e.sessionKey??`—`,e.transcriptOffset===null?``:` at byte ${e.transcriptOffset}`]})}),!e.bounded&&(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,R.jsx)(`span`,{children:`This run shares its conversation with other traffic, so what it produced cannot be separated out. Its status stays at whatever the dispatch reported.`})}),(0,R.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,R.jsxs)(`span`,{children:[`Run `,e.runId]})})]})]})})}function X({status:e}){let t=ie(e);return(0,R.jsx)(`span`,{className:`routine-status-dot is-${t}`,"data-state":t,"aria-hidden":`true`})}var Z=500;function Q(e,t){if(!e)return`—`;let n=Date.parse(e);return Number.isFinite(n)?l(new Date(n).toISOString(),t):e}function le(e){return e===null?`—`:e<1e3?`${e} ms`:`${(e/1e3).toFixed(1)} s`}var ue={channel:`a channel`,destination:`a destination`,prompt:`an instruction`};function de(e){if(e===`no-dispatch-configured`)return`This routine has no dispatch set up, so there was nothing to do.`;if(e===`no-action-plugin`)return`The tool action names no plugin, so nothing ran.`;if(e===`no-action-tool`)return`The tool action names no tool, so nothing ran.`;let t=e.startsWith(`no-`)?e.slice(3).split(`+`):[];if(t.length>0&&t.every(e=>e in ue)){let e=t.map(e=>ue[e]);return`This routine has no ${(e.length===1?e[0]:`${e.slice(0,-1).join(`, `)} and ${e[e.length-1]}`).replace(/^an? /,``)} set, so nothing was sent.`}return e}function fe(e){return e.status===`no-destination`?e.error?de(e.error):`Nothing was dispatched, and no reason was recorded.`:e.status===`failed`?e.error??e.dispatchResult??`The dispatch failed.`:e.status===`open`?`Opened and never closed. The dispatch did not report back.`:null}function pe(e){let t=e.indexOf(`:`);return t<=0?{channel:null,destination:e}:{channel:e.slice(0,t),destination:e.slice(t+1)}}function me(e){return e.outputExcerpt===null?e.status===`finished`?`Finished and sent nothing.`:null:e.outputExcerpt}function he({routine:e,adminFetch:r,cacheKey:i,from:a=`card`,onBack:c}){let{zone:l}=v(),[u,d]=(0,D.useState)([]),[p,m]=(0,D.useState)(!0),[g,_]=(0,D.useState)(null),[y,b]=(0,D.useState)(null),x=(0,D.useRef)(0),S=(0,D.useCallback)(()=>{let t=!1,n=++x.current,i=()=>t||n!==x.current;return m(!0),_(null),r(`/api/admin/routines/${encodeURIComponent(e.eventId)}/runs?limit=${Z}&from=${a}`).then(async e=>{if(i())return;if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.json();i()||d(Array.isArray(t.runs)?t.runs:[])}).catch(e=>{i()||(_(e instanceof Error?e.message:`Failed to load`),d([]))}).finally(()=>{i()||m(!1)}),()=>{t=!0}},[r,e.eventId,a]);(0,D.useEffect)(()=>S(),[S]);let C=(0,D.useCallback)(()=>{w(i,e.eventId)},[i,e.eventId]);return(0,R.jsxs)(`div`,{className:`cal-page`,children:[(0,R.jsx)(`header`,{className:`cal-header`,children:(0,R.jsxs)(`div`,{className:`cal-nav`,children:[(0,R.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:c,children:[(0,R.jsx)(s,{size:14}),` Routines`]}),(0,R.jsx)(`span`,{className:`cal-range-label runs-title`,"data-testid":`runs-title`,title:e.name??`Untitled routine`,children:e.name??`Untitled routine`}),(0,R.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,"data-testid":`runs-refresh`,onClick:S,disabled:p,title:`Refresh runs`,"aria-label":`Refresh runs`,children:[p?(0,R.jsx)(o,{size:14,className:`spin`}):(0,R.jsx)(t,{size:14}),` Refresh`]}),u.length>0&&(0,R.jsx)(`div`,{className:`routine-bulk-actions`,children:(0,R.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:C,children:[(0,R.jsx)(n,{size:14}),` Download all runs`]})})]})}),(0,R.jsxs)(`div`,{className:`cal-body`,children:[g&&(0,R.jsxs)(`div`,{className:`cal-error`,children:[`Could not load runs: `,g]}),!g&&!p&&u.length===0&&(0,R.jsxs)(`div`,{className:`cal-empty`,"data-testid":`runs-empty`,children:[(0,R.jsx)(`p`,{children:`Nothing to show for this routine.`}),(0,R.jsx)(`p`,{children:`That means one of three things, and this page cannot tell them apart: it has never run, it ran but no record was written, or every run it did have is older than the 30 days records are kept for.`}),(0,R.jsxs)(`p`,{children:[`For a repeating routine, the server log settles the middle one: a`,(0,R.jsx)(`code`,{children:` fires-without-records `}),` count above zero names a routine that fired and left no record. It does not distinguish the other two, and it does not cover a one-time routine.`]})]}),u.length>=Z&&(0,R.jsxs)(`div`,{className:`cal-modal-confirm-text`,"data-testid":`runs-capped`,children:[`Showing the most recent `,Z,` runs. There may be more; the download has everything still on record.`]}),(0,R.jsx)(`div`,{className:`routine-list`,children:u.map(e=>{let t=fe(e),n=me(e),{channel:r,destination:i}=pe(e.target);return(0,R.jsxs)(`button`,{type:`button`,className:`admin-card admin-card--padded routine-card`,"data-testid":`run-row-${e.runId}`,onClick:()=>b(e),children:[(0,R.jsxs)(`span`,{className:`admin-card-title routine-card-title run-card-title`,children:[(0,R.jsx)(X,{status:e.status}),` `,e.status]}),(0,R.jsx)(`span`,{className:`routine-card-sched`,children:le(e.ranMs)}),(0,R.jsx)(`span`,{className:`routine-card-target`,children:r?(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(h,{channel:r,size:13}),` `,f[r]??r,` to `,r===`whatsapp`?U(i):i]}):i}),(0,R.jsxs)(`span`,{className:`routine-card-meta`,children:[`Due `,Q(e.scheduledFor,l)]}),n&&(0,R.jsx)(`span`,{className:`routine-card-meta run-card-output`,children:n}),t&&(0,R.jsx)(`span`,{className:`routine-card-meta run-card-detail`,children:t})]},e.runId)})})]}),y&&(0,R.jsx)(Y,{run:y,routineName:e.name,onClose:()=>b(null)})]})}var $=`maxy-admin-session-key`;function ge(e){return e?M(e):`One-time`}function _e(e,t){if(!e)return`—`;let n=Date.parse(e);return Number.isFinite(n)?l(new Date(n).toISOString(),t):e}function ve(){let[e,t]=(0,D.useState)(null),[n,r]=(0,D.useState)(!1),[i,o]=(0,D.useState)(void 0),[s,c]=(0,D.useState)(null),[l,u]=(0,D.useState)(void 0),[d,f]=(0,D.useState)(null),[p,h]=(0,D.useState)(null);(0,D.useEffect)(()=>{let e=!1,n=null;try{n=sessionStorage.getItem($)}catch{}if(!n){r(!0);return}return fetch(`/api/admin/session?session_key=${encodeURIComponent(n)}`).then(async i=>{if(!e){if(i.status===401){try{sessionStorage.removeItem($)}catch{}window.location.href=`/`;return}if(i.ok)try{let e=await i.json();typeof e.businessName==`string`&&o(e.businessName),e.sessionId!==void 0&&c(e.sessionId??null),h(e.role??null),u(e.userName===void 0?null:e.userName),f(e.avatar??null)}catch{}t(n),r(!0)}}).catch(()=>{e||(t(n),r(!0))}),()=>{e=!0}},[]);let g=(0,D.useCallback)(()=>{try{sessionStorage.removeItem($)}catch{}window.location.href=`/`},[]),[_,v]=(0,D.useState)(!1),b=(0,D.useCallback)(async()=>{v(!0);try{let e=await y();if(e){try{sessionStorage.removeItem($)}catch{}window.location.href=`/`}return e}finally{v(!1)}},[]);return n?e?(0,R.jsx)(m,{cacheKey:e,surface:`routines`,onSessionExpired:({code:e,path:t})=>{console.warn(`[admin-auth] outcome=session-expired-redirect code=${e} path=${t} surface=routines`);try{sessionStorage.removeItem($)}catch{}window.location.href=`/`},children:(0,R.jsx)(x,{cacheKey:e,businessName:i,sessionId:s,onLogout:g,onDisconnect:b,disconnecting:_,userName:l,userAvatar:d,role:p,children:(0,R.jsx)(ye,{cacheKey:e})})}):(0,R.jsx)(`div`,{className:`cal-page`,children:(0,R.jsxs)(`div`,{className:`cal-empty`,children:[(0,R.jsx)(`p`,{children:`You are not signed in.`}),(0,R.jsxs)(`p`,{children:[`Open the `,(0,R.jsx)(`a`,{href:`/`,className:`cal-link`,children:`main admin page`}),` and log in, then return here.`]})]})}):(0,R.jsx)(a,{surface:`gate`})}function ye({cacheKey:e}){let{zone:n}=v(),{adminFetch:r,cacheKey:i,sessionRefetchNonce:s}=u({initialCacheKey:e,surface:`routines`}),[c,l]=(0,D.useState)([]),[d,p]=(0,D.useState)(!1),[m,g]=(0,D.useState)(!1),[_,y]=(0,D.useState)(null),[x,w]=(0,D.useState)(null),[E,O]=(0,D.useState)(null),[k,A]=(0,D.useState)(`card`),j=(0,D.useCallback)(()=>{let e=!1;return p(!0),y(null),r(`/api/admin/routines`).then(async t=>{if(e)return;if(!t.ok)throw Error(`HTTP ${t.status}`);let n=await t.json();l(Array.isArray(n.routines)?n.routines:[])}).catch(t=>{e||(y(t instanceof Error?t.message:`Failed to load`),l([]))}).finally(()=>{e||(p(!1),g(!0))}),()=>{e=!0}},[r]);(0,D.useEffect)(()=>j(),[j,s]);let M=(0,D.useCallback)(e=>{l(t=>t.map(t=>t.eventId===e.eventId?e:t)),w(e)},[]),N=(0,D.useCallback)(e=>{l(t=>t.filter(t=>t.eventId!==e)),w(null)},[]),[P,F]=(0,D.useState)(!1),[I,L]=(0,D.useState)(null),z=c.filter(e=>e.eventStatus===`scheduled`).length,B=c.filter(e=>e.suspendedInBulk).length,V=(0,D.useCallback)(async e=>{F(!0),L(null);try{let t=await r(`/api/admin/routines/${e}`,{method:`POST`});if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e.error??`HTTP ${t.status}`)}let n=await t.json(),i=n.refused?.length??0;L(e===`suspend-all`?`Suspended ${n.suspended??0}. Nothing runs on its own until you resume it.`:`Resumed ${n.restored??0}${i>0?`. ${i} could not be resumed and stayed suspended`:``}. Routines you suspended one at a time are still suspended.`),j()}catch(e){L(e instanceof Error?e.message:`Failed`)}finally{F(!1)}},[r,j]);return m?E?(0,R.jsx)(he,{routine:E,adminFetch:r,cacheKey:i,from:k,onBack:()=>O(null)}):(0,R.jsxs)(`div`,{className:`cal-page`,children:[(0,R.jsx)(`header`,{className:`cal-header`,children:(0,R.jsxs)(`div`,{className:`cal-nav`,children:[(0,R.jsxs)(`span`,{className:`cal-range-label`,children:[(0,R.jsx)(b,{size:16}),` Routines`]}),(0,R.jsxs)(`div`,{className:`routine-bulk-actions`,children:[(0,R.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,"data-testid":`routines-refresh`,onClick:j,disabled:d,title:`Refresh routines`,"aria-label":`Refresh routines`,children:[d?(0,R.jsx)(o,{size:14,className:`spin`}):(0,R.jsx)(t,{size:14}),` Refresh`]}),(0,R.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:()=>V(`suspend-all`),disabled:P||z===0,children:[(0,R.jsx)(ee,{size:14}),` Suspend all (`,z,`)`]}),(0,R.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:()=>V(`resume-all`),disabled:P||B===0,children:[(0,R.jsx)(te,{size:14}),` Resume all (`,B,`)`]})]})]})}),(0,R.jsxs)(`div`,{className:`cal-body`,children:[I&&(0,R.jsx)(`div`,{className:`cal-modal-confirm-text`,children:I}),_&&(0,R.jsxs)(`div`,{className:`cal-error`,children:[`Could not load routines: `,_]}),!_&&!d&&c.length===0&&(0,R.jsx)(`div`,{className:`cal-empty`,children:(0,R.jsx)(`p`,{children:`No routines yet.`})}),(0,R.jsx)(`div`,{className:`routine-list`,children:c.map(e=>(0,R.jsxs)(`div`,{className:`admin-card admin-card--padded routine-card-shell`,children:[(0,R.jsxs)(`div`,{role:`button`,tabIndex:0,className:`routine-card`,"data-testid":`routine-card-${e.eventId}`,onClick:()=>w(e),onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),w(e))},children:[(0,R.jsx)(`span`,{className:`admin-card-title routine-card-title`,children:e.name??`Untitled routine`}),e.description&&(0,R.jsx)(`span`,{className:`routine-card-desc`,children:e.description}),(0,R.jsxs)(`span`,{className:`routine-card-sched`,children:[(0,R.jsx)(S,{size:13}),` `,ge(e.recurrence)]}),(0,R.jsx)(`span`,{className:`routine-card-target`,children:e.agentChannel?(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(h,{channel:e.agentChannel,size:13}),` `,f[e.agentChannel]??e.agentChannel,` to `,e.agentDestination??`—`]}):e.actionPlugin?(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(C,{size:13}),` `,e.actionPlugin,`.`,e.actionTool]}):(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(S,{size:13}),` Scheduled trigger`]})}),(0,R.jsxs)(`span`,{className:`routine-card-meta`,children:[(0,R.jsx)(ae,{eventStatus:e.eventStatus}),`Next: `,_e(e.nextRun,n),` · `,e.eventStatus??`unknown`]})]}),(0,R.jsx)(`button`,{type:`button`,className:`routine-card-runs`,"data-testid":`routine-runs-${e.eventId}`,title:`View runs`,"aria-label":`View runs for ${e.name??`this routine`}`,onClick:()=>{A(`card`),O(e)},children:(0,R.jsx)(T,{size:14})})]},e.eventId))})]}),x&&(0,R.jsx)(ce,{routine:x,adminFetch:r,onClose:()=>w(null),onSaved:M,onDeleted:N,onViewRuns:e=>{A(`modal`),w(null),O(e)}})]}):(0,R.jsx)(a,{surface:`gate`})}(0,E.createRoot)(document.getElementById(`root`)).render((0,R.jsx)(ve,{}));
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Routines — Maxy</title>
7
7
  <link rel="icon" href="/favicon.ico">
8
- <script type="module" crossorigin src="/assets/routines-Ds0yz7_C.js"></script>
8
+ <script type="module" crossorigin src="/assets/routines-OGFXwTFO.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/chunk-CltuBf4Z.js">
10
10
  <link rel="modulepreload" crossorigin href="/assets/useMediaQuery-_mMln3Fu.js">
11
11
  <link rel="modulepreload" crossorigin href="/assets/AdminShell-DVBAMUCy.js">