@rubytech/create-maxy-code 0.1.556 → 0.1.557
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.
- package/package.json +1 -1
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +6 -0
- package/payload/platform/services/claude-session-manager/dist/subagent-injection-tail.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/subagent-injection-tail.js +87 -7
- package/payload/platform/services/claude-session-manager/dist/subagent-injection-tail.js.map +1 -1
- package/payload/server/public/assets/{routines-Ul6Qj5dz.js → routines-CdqGJwyD.js} +1 -1
- package/payload/server/public/assets/routines-CdqGJwyD.js.br +0 -0
- package/payload/server/public/assets/routines-CdqGJwyD.js.gz +0 -0
- package/payload/server/public/routines.html +1 -1
- package/payload/server/public/assets/routines-Ul6Qj5dz.js.br +0 -0
- package/payload/server/public/assets/routines-Ul6Qj5dz.js.gz +0 -0
package/package.json
CHANGED
|
@@ -9,6 +9,12 @@ Invoked by the admin agent directly.
|
|
|
9
9
|
|
|
10
10
|
This is the platform's release timeline, newest first. Each entry shows the date it shipped and the version it shipped in, so you can tell the operator how current their install is. To compare, read the installed version from `capabilities-here` and match it against the versions below. Keep answers high level and in plain English; this is a summary, not a full commit log.
|
|
11
11
|
|
|
12
|
+
## 2026-08-04 (0.1.557)
|
|
13
|
+
|
|
14
|
+
- The status dot on a one-time routine that has already run now shows it as finished rather than live, matching the card text added in the previous release.
|
|
15
|
+
- The background check that watches for injected instructions no longer raises false alarms. It was flagging any long turn that happened to mention prompt injection somewhere and refusal somewhere else; it now requires the two to sit together, as they do in a real refusal.
|
|
16
|
+
- That same check no longer repeats old alerts every time the assistant restarts. What it has already reported is now remembered on disk alongside the conversation it came from, and a failure to write that record is reported rather than passing silently.
|
|
17
|
+
|
|
12
18
|
## 2026-08-04 (0.1.556)
|
|
13
19
|
|
|
14
20
|
- A one-time routine that has already run now says so on its card, instead of offering a Suspend button that fails when you press it. Cancelled and finished routines each explain why they cannot be restarted.
|
package/payload/platform/services/claude-session-manager/dist/subagent-injection-tail.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagent-injection-tail.d.ts","sourceRoot":"","sources":["../src/subagent-injection-tail.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"subagent-injection-tail.d.ts","sourceRoot":"","sources":["../src/subagent-injection-tail.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAsCpD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAO9D;AAKD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAO/E;AA4DD,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,aAAa,CAAA;IAC1B,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACjE;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,yBAAyB,GAAG,qBAAqB,CAyGlG"}
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
// parent writes (including the Agent tool_result that returns the subagent's
|
|
7
7
|
// output), we scan the subagents dir. Emits one `[agent] op=injection-refused`
|
|
8
8
|
// line per newly-seen refusal turn; it is audit, not enforcement.
|
|
9
|
-
import { readdirSync, readFileSync } from 'node:fs';
|
|
9
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
10
10
|
import { join } from 'node:path';
|
|
11
11
|
import { readSidecar } from './session-sidecar.js';
|
|
12
|
+
import { createSidecarStore } from './sidecar-store.js';
|
|
12
13
|
// Two-signal AND: the text must both recognise the content as untrusted AND
|
|
13
14
|
// record a decision not to act. Requiring both keeps a turn that merely
|
|
14
15
|
// discusses injection (with no refusal) from firing.
|
|
@@ -24,12 +25,36 @@ import { readSidecar } from './session-sidecar.js';
|
|
|
24
25
|
// none of these three phrases were listed. They are refusal-narration
|
|
25
26
|
// vocabulary, not injection discussion: "injected content" names the content as
|
|
26
27
|
// already-judged, and neither of the other two appears in a security review.
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
// Task 2399 adds the locality bound. Without it the conjunction fires on any
|
|
29
|
+
// document long enough to hold both signals independently. Measured over 3,175
|
|
30
|
+
// subagent assistant turns on 2026-08-04: every line the audit had ever emitted
|
|
31
|
+
// came from two review turns, each matching `prompt injection` in a risk list
|
|
32
|
+
// and `refuse` in unrelated prose 2,132 and 2,340 characters away. The two real
|
|
33
|
+
// refusals in the same corpus match 18 characters apart, so 400 is bounded by
|
|
34
|
+
// measurement on both sides rather than chosen — it spans two to three
|
|
35
|
+
// sentences of ordinary prose, which is where a refusal states what it saw and
|
|
36
|
+
// what it did about it.
|
|
37
|
+
const RECOGNITION = /untrusted input|arrived as content inside a tool result|not the addressee|no such tool on this session|prompt injection|injected content|posing as (?:a )?system[- ]reminder|fake (?:system )?instruction/gi;
|
|
38
|
+
const DECLINE = /disregard(?:ed)?|did not act on it|will not act|refus(?:e|ed|ing)|ignor(?:e|ed|ing) (?:it|these|the instruction)/gi;
|
|
39
|
+
const MAX_SIGNAL_GAP = 400;
|
|
40
|
+
// `matchAll` clones the regex internally, so the shared g-flagged constants
|
|
41
|
+
// above carry no `lastIndex` state between calls.
|
|
42
|
+
function matchOffsets(pattern, text) {
|
|
43
|
+
const offsets = [];
|
|
44
|
+
for (const match of text.matchAll(pattern))
|
|
45
|
+
offsets.push(match.index);
|
|
46
|
+
return offsets;
|
|
47
|
+
}
|
|
29
48
|
export function classifyInjectionRefusal(text) {
|
|
30
49
|
if (!text)
|
|
31
50
|
return false;
|
|
32
|
-
|
|
51
|
+
const recognitions = matchOffsets(RECOGNITION, text);
|
|
52
|
+
if (recognitions.length === 0)
|
|
53
|
+
return false;
|
|
54
|
+
const declines = matchOffsets(DECLINE, text);
|
|
55
|
+
if (declines.length === 0)
|
|
56
|
+
return false;
|
|
57
|
+
return recognitions.some((r) => declines.some((d) => Math.abs(r - d) <= MAX_SIGNAL_GAP));
|
|
33
58
|
}
|
|
34
59
|
// The attached channel's reply-tool MCP server is the injection source (its
|
|
35
60
|
// instruction block is what the subagent inherited and rejected). Channels
|
|
@@ -73,6 +98,19 @@ function summarizeSubagentAssistant(rec) {
|
|
|
73
98
|
const attributionAgent = typeof rec.attributionAgent === 'string' ? rec.attributionAgent : '—';
|
|
74
99
|
return { key, text, attributionAgent };
|
|
75
100
|
}
|
|
101
|
+
const seenStore = createSidecarStore({
|
|
102
|
+
suffix: '.injection-seen.json',
|
|
103
|
+
validate: (raw) => {
|
|
104
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw))
|
|
105
|
+
return null;
|
|
106
|
+
const keys = raw.keys;
|
|
107
|
+
if (!Array.isArray(keys))
|
|
108
|
+
return null;
|
|
109
|
+
if (keys.some((k) => typeof k !== 'string'))
|
|
110
|
+
return null;
|
|
111
|
+
return { keys: keys };
|
|
112
|
+
},
|
|
113
|
+
});
|
|
76
114
|
export function createSubagentInjectionTail(deps) {
|
|
77
115
|
// filePath -> set of already-emitted turn keys. Whole-file rescan + key
|
|
78
116
|
// dedupe makes re-scans idempotent without a byte cursor, which is robust
|
|
@@ -80,6 +118,40 @@ export function createSubagentInjectionTail(deps) {
|
|
|
80
118
|
// once a file emits its first refusal, so the common no-refusal file leaves
|
|
81
119
|
// nothing behind and the Map stays bounded to files that actually fired.
|
|
82
120
|
const emitted = new Map();
|
|
121
|
+
// Both helpers run only for a file that has a candidate refusal, never on
|
|
122
|
+
// the common no-refusal path. `loadSeen` runs at most once per file per
|
|
123
|
+
// process, because its result is cached in `emitted`.
|
|
124
|
+
function loadSeen(subagentsDir, file) {
|
|
125
|
+
const record = seenStore.read(subagentsDir, file);
|
|
126
|
+
if (record)
|
|
127
|
+
return new Set(record.keys);
|
|
128
|
+
const path = seenStore.pathFor(subagentsDir, file);
|
|
129
|
+
// Absent is the normal first-refusal case and says nothing. Present but
|
|
130
|
+
// unreadable or failing validation is the case that silently restores the
|
|
131
|
+
// re-emit bug, so it is named.
|
|
132
|
+
if (existsSync(path)) {
|
|
133
|
+
deps.postLogLine('agent', 'warn', `op=injection-seen-unreadable path=${path}`);
|
|
134
|
+
}
|
|
135
|
+
return new Set();
|
|
136
|
+
}
|
|
137
|
+
function persistSeen(subagentsDir, file, seen) {
|
|
138
|
+
// The store returns its writeFileSync/rename failures, but its mkdirSync
|
|
139
|
+
// sits outside that try — a throw from there would escape onParentActivity,
|
|
140
|
+
// abort the rest of this scan, and surface as an fs-watcher subscriber
|
|
141
|
+
// error rather than the named line below. Both classes funnel here.
|
|
142
|
+
let error = null;
|
|
143
|
+
try {
|
|
144
|
+
const res = seenStore.write(subagentsDir, file, { keys: [...seen] });
|
|
145
|
+
if (res.ok)
|
|
146
|
+
return;
|
|
147
|
+
error = res.error;
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
error = err;
|
|
151
|
+
}
|
|
152
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
153
|
+
deps.postLogLine('agent', 'warn', `op=injection-seen-write-failed path=${seenStore.pathFor(subagentsDir, file)} err=${message}`);
|
|
154
|
+
}
|
|
83
155
|
function onParentActivity(parentSessionId, slugDir) {
|
|
84
156
|
const subagentsDir = join(slugDir, parentSessionId, 'subagents');
|
|
85
157
|
let files;
|
|
@@ -107,8 +179,9 @@ export function createSubagentInjectionTail(deps) {
|
|
|
107
179
|
};
|
|
108
180
|
for (const file of files) {
|
|
109
181
|
const filePath = join(subagentsDir, file);
|
|
110
|
-
// `seen` stays undefined until this file emits its first refusal, so
|
|
111
|
-
// no-refusal
|
|
182
|
+
// `seen` stays undefined until this file emits its first refusal, so a
|
|
183
|
+
// no-refusal file occupies neither the Map nor a marker on disk. Its
|
|
184
|
+
// first refusal is what loads the durable record, once per process.
|
|
112
185
|
let seen = emitted.get(filePath);
|
|
113
186
|
let raw;
|
|
114
187
|
try {
|
|
@@ -138,11 +211,18 @@ export function createSubagentInjectionTail(deps) {
|
|
|
138
211
|
continue;
|
|
139
212
|
if (!classifyInjectionRefusal(summary.text))
|
|
140
213
|
continue;
|
|
214
|
+
// The durable record is consulted only now, after classification, so a
|
|
215
|
+
// file that never fires costs no stat and no read.
|
|
141
216
|
if (!seen) {
|
|
142
|
-
seen =
|
|
217
|
+
seen = loadSeen(subagentsDir, file);
|
|
143
218
|
emitted.set(filePath, seen);
|
|
144
219
|
}
|
|
220
|
+
if (seen.has(summary.key))
|
|
221
|
+
continue;
|
|
145
222
|
seen.add(summary.key);
|
|
223
|
+
// Recorded before the line is emitted, so the durable state is never
|
|
224
|
+
// behind what the log claims.
|
|
225
|
+
persistSeen(subagentsDir, file, seen);
|
|
146
226
|
loadSidecar();
|
|
147
227
|
const snippet = JSON.stringify(summary.text.slice(0, 160));
|
|
148
228
|
deps.postLogLine('agent', 'info', `op=injection-refused account=${account} session=${parentSessionId}` +
|
package/payload/platform/services/claude-session-manager/dist/subagent-injection-tail.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagent-injection-tail.js","sourceRoot":"","sources":["../src/subagent-injection-tail.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,mEAAmE;AACnE,sEAAsE;AACtE,0EAA0E;AAC1E,6EAA6E;AAC7E,6EAA6E;AAC7E,+EAA+E;AAC/E,kEAAkE;AAClE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"subagent-injection-tail.js","sourceRoot":"","sources":["../src/subagent-injection-tail.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{o as e,t}from"./chunk-CltuBf4Z.js";import{F as n,G as r,L as i,M as a,O as o,V as s,Y as c,Z as l,_ as u,at as d,ct as f,f as p,j as m,k as h,m as g,nt as _,ot as v,v as y}from"./useMediaQuery-DIm6yGOl.js";import{A as b,m as x,t as S}from"./AdminShell-BVKfxSgh.js";import{t as C}from"./clock-B_xWWLQW.js";import{t as w}from"./triangle-alert-D7zwttJW.js";import{t as ee}from"./wrench-BmXV4Tmh.js";import{r as T}from"./file-download-DiQesOd2.js";var te=l(`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`}]]),ne=l(`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`}]]),E=l(`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`}]]),D=v(),O=e(f(),1),k=[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`];function A(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 j(e){return String(e).padStart(2,`0`)}function M(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`:`${k[e%7]} to ${k[n%7]}`}let n=e.split(`,`);return n.length>0&&n.every(e=>/^\d+$/.test(e)&&Number(e)<=7)?n.map(e=>k[Number(e)%7]).join(`, `):`invalid`}function re(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=A(n,59),c=A(r,23);if(!s||!c)return e;let l=M(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}, ${j(c.value)}:00 to ${j(c.value)}:59${u}`:`${e}, ${j(c.rangeStart)}:00 to ${j(d(c))}:00${u}`}if(c.kind===`step`){let e=j(s.value),t=s.value===0?``:` at :${e}`;return c.rangeStart===null?`Every ${c.step} hours${t}${u}`:c.step===1?`Hourly, ${j(c.rangeStart)}:${e} to ${j(c.rangeEnd)}:${e}${u}`:`Every ${c.step} hours, ${j(c.rangeStart)}:${e} to ${j(d(c))}:${e}${u}`}if(c.kind===`any`)return`${s.value===0?`Every hour`:`Every hour at :${j(s.value)}`}${u}`;let f=`${j(c.value)}:${j(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=A(n,59),c=A(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={scheduled:`live`,due:`live`,suspended:`stood-down`,cancelled:`inert`,completed:`inert`};function z(e){return e==null||!Object.hasOwn(R,e)?`unknown`:R[e]}var B={scheduled:{control:`suspend`,note:null},suspended:{control:`resume`,note:null},due:{control:`none`,note:`This one-time routine has already been dispatched. It will not run again.`},cancelled:{control:`none`,note:`This routine was cancelled and cannot be restarted. Delete it, or create a new one.`},completed:{control:`none`,note:`This routine has finished and will not run again.`}},V={control:`none`,note:`This routine's status is not one this dashboard recognises, so no start or stop is offered.`};function ie(e){return e==null||!Object.hasOwn(B,e)?V:B[e]}var H={finished:`live`,gated:`live`,started:`in-flight`,accepted:`in-flight`,open:`in-flight`,failed:`error`,"no-destination":`warning`};function U(e){return e==null||!Object.hasOwn(H,e)?`unknown`:H[e]}function ae(e){return e===`gated`?`skipped: no work`:e??`unknown`}var W=_(),G=[{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`}],K=Array.from({length:24},(e,t)=>t),q=e=>String(e).padStart(2,`0`),J={timeMode:`at`,minute:0,hour:9,interval:1,window:null,dayMode:`every`,weekdays:[],dayOfMonth:1};function oe({recurrence:e,onChange:t,disabled:n}){let r=e?F(e):J,[i,a]=(0,O.useState)(r??J),[o]=(0,O.useState)(e!=null&&r==null),[s,c]=(0,O.useState)(e??``);if((0,O.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,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Schedule (advanced)`}),(0,W.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,W.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,W.jsxs)(`div`,{className:`routine-sched`,children:[(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`How often`}),(0,W.jsxs)(`select`,{"aria-label":`How often`,value:i.timeMode,disabled:n,onChange:e=>u(e.target.value),children:[(0,W.jsx)(`option`,{value:`at`,children:`At a time of day`}),(0,W.jsx)(`option`,{value:`everyMinutes`,children:`Every few minutes`}),(0,W.jsx)(`option`,{value:`everyHours`,children:`Every few hours`})]})]}),i.timeMode===`at`&&(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Time of day`}),(0,W.jsx)(`input`,{type:`time`,"aria-label":`Time of day`,value:`${q(i.hour)}:${q(i.minute)}`,disabled:n,onChange:e=>f(e.target.value)})]}),i.timeMode===`everyMinutes`&&(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Minutes between runs`}),(0,W.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,W.jsxs)(W.Fragment,{children:[(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Hours between runs`}),(0,W.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,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Minute of the hour`}),(0,W.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,W.jsxs)(W.Fragment,{children:[(0,W.jsxs)(`label`,{className:`cal-modal-field routine-sched-check`,children:[(0,W.jsx)(`input`,{type:`checkbox`,"aria-label":`Only between certain hours`,checked:i.window!==null,disabled:n,onChange:e=>m(e.target.checked)}),(0,W.jsx)(`span`,{children:`Only between certain hours`})]}),i.window!==null&&(0,W.jsxs)(`div`,{className:`routine-sched-row`,children:[(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`From hour`}),(0,W.jsx)(`select`,{"aria-label":`From hour`,value:i.window.start,disabled:n,onChange:e=>h(`start`,e.target.value),children:K.map(e=>(0,W.jsxs)(`option`,{value:e,children:[q(e),`:00`]},e))})]}),(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`To hour`}),(0,W.jsx)(`select`,{"aria-label":`To hour`,value:i.window.end,disabled:n,onChange:e=>h(`end`,e.target.value),children:K.map(e=>(0,W.jsxs)(`option`,{value:e,children:[q(e),`:00`]},e))})]})]})]}),(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Which days`}),(0,W.jsxs)(`select`,{"aria-label":`Which days`,value:i.dayMode,disabled:n,onChange:e=>d(e.target.value),children:[(0,W.jsx)(`option`,{value:`every`,children:`Every day`}),(0,W.jsx)(`option`,{value:`weekdays`,children:`Specific days`}),i.timeMode===`at`&&(0,W.jsx)(`option`,{value:`dayOfMonth`,children:`A day of the month`})]})]}),i.dayMode===`weekdays`&&(0,W.jsxs)(`div`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Days`}),(0,W.jsx)(`div`,{className:`routine-weekdays`,children:G.map(e=>(0,W.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,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Day of month`}),(0,W.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,W.jsx)(`option`,{value:e,children:e},e))})]})]})}function Y(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 se(e){if(e.name)return`${e.name} · ${e.label}`;let t=e.channel===`whatsapp`?Y(e.destination):e.destination;return`${e.label} · ${t}`}function ce({eventStatus:e}){let t=z(e);return(0,W.jsx)(`span`,{className:`routine-status-dot is-${t}`,"data-state":t,"aria-hidden":`true`})}function le(e){return e.agentChannel==null?e.actionPlugin==null?`trigger`:`deterministic`:e.gateTool==null?`agent-every-fire`:`checked-agent`}var ue={"checked-agent":`checks first, model only when there is work`,"agent-every-fire":`model every fire`,deterministic:`runs a tool, no model`,trigger:null};function de(e){if(!e)return[];let t;try{t=JSON.parse(e)}catch{return[]}let n=t?.checks;return Array.isArray(n)?n.flatMap(e=>{if(typeof e!=`object`||!e)return[];let t=e;return typeof t.type==`string`?[{kind:t.type,target:fe(t.type,t)}]:[]}):[]}function fe(e,t){let n=e=>typeof t[e]==`string`?t[e]:null;if(e===`mail`){let e=n(`mailbox`);if(e===null)return null;let t=n(`folder`);return t?`${e}/${t}`:e}return e===`d1`?n(`database`):e===`whatsapp`?n(`scope`):e===`calendar`?n(`connector`):null}function pe(e,t){if(!e)return`—`;let n=Date.parse(e);return Number.isFinite(n)?u(new Date(n).toISOString(),t):e}function me(e){return e?e.split(`
|
|
1
|
+
import{o as e,t}from"./chunk-CltuBf4Z.js";import{F as n,G as r,L as i,M as a,O as o,V as s,Y as c,Z as l,_ as u,at as d,ct as f,f as p,j as m,k as h,m as g,nt as _,ot as v,v as y}from"./useMediaQuery-DIm6yGOl.js";import{A as b,m as x,t as S}from"./AdminShell-BVKfxSgh.js";import{t as C}from"./clock-B_xWWLQW.js";import{t as w}from"./triangle-alert-D7zwttJW.js";import{t as ee}from"./wrench-BmXV4Tmh.js";import{r as T}from"./file-download-DiQesOd2.js";var te=l(`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`}]]),ne=l(`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`}]]),E=l(`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`}]]),D=v(),O=e(f(),1),k=[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`];function A(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 j(e){return String(e).padStart(2,`0`)}function M(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`:`${k[e%7]} to ${k[n%7]}`}let n=e.split(`,`);return n.length>0&&n.every(e=>/^\d+$/.test(e)&&Number(e)<=7)?n.map(e=>k[Number(e)%7]).join(`, `):`invalid`}function re(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=A(n,59),c=A(r,23);if(!s||!c)return e;let l=M(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}, ${j(c.value)}:00 to ${j(c.value)}:59${u}`:`${e}, ${j(c.rangeStart)}:00 to ${j(d(c))}:00${u}`}if(c.kind===`step`){let e=j(s.value),t=s.value===0?``:` at :${e}`;return c.rangeStart===null?`Every ${c.step} hours${t}${u}`:c.step===1?`Hourly, ${j(c.rangeStart)}:${e} to ${j(c.rangeEnd)}:${e}${u}`:`Every ${c.step} hours, ${j(c.rangeStart)}:${e} to ${j(d(c))}:${e}${u}`}if(c.kind===`any`)return`${s.value===0?`Every hour`:`Every hour at :${j(s.value)}`}${u}`;let f=`${j(c.value)}:${j(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=A(n,59),c=A(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={scheduled:`live`,suspended:`stood-down`,due:`inert`,cancelled:`inert`,completed:`inert`};function z(e){return e==null||!Object.hasOwn(R,e)?`unknown`:R[e]}var B={scheduled:{control:`suspend`,note:null},suspended:{control:`resume`,note:null},due:{control:`none`,note:`This one-time routine has already been dispatched. It will not run again.`},cancelled:{control:`none`,note:`This routine was cancelled and cannot be restarted. Delete it, or create a new one.`},completed:{control:`none`,note:`This routine has finished and will not run again.`}},V={control:`none`,note:`This routine's status is not one this dashboard recognises, so no start or stop is offered.`};function ie(e){return e==null||!Object.hasOwn(B,e)?V:B[e]}var H={finished:`live`,gated:`live`,started:`in-flight`,accepted:`in-flight`,open:`in-flight`,failed:`error`,"no-destination":`warning`};function U(e){return e==null||!Object.hasOwn(H,e)?`unknown`:H[e]}function ae(e){return e===`gated`?`skipped: no work`:e??`unknown`}var W=_(),G=[{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`}],K=Array.from({length:24},(e,t)=>t),q=e=>String(e).padStart(2,`0`),J={timeMode:`at`,minute:0,hour:9,interval:1,window:null,dayMode:`every`,weekdays:[],dayOfMonth:1};function oe({recurrence:e,onChange:t,disabled:n}){let r=e?F(e):J,[i,a]=(0,O.useState)(r??J),[o]=(0,O.useState)(e!=null&&r==null),[s,c]=(0,O.useState)(e??``);if((0,O.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,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Schedule (advanced)`}),(0,W.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,W.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,W.jsxs)(`div`,{className:`routine-sched`,children:[(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`How often`}),(0,W.jsxs)(`select`,{"aria-label":`How often`,value:i.timeMode,disabled:n,onChange:e=>u(e.target.value),children:[(0,W.jsx)(`option`,{value:`at`,children:`At a time of day`}),(0,W.jsx)(`option`,{value:`everyMinutes`,children:`Every few minutes`}),(0,W.jsx)(`option`,{value:`everyHours`,children:`Every few hours`})]})]}),i.timeMode===`at`&&(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Time of day`}),(0,W.jsx)(`input`,{type:`time`,"aria-label":`Time of day`,value:`${q(i.hour)}:${q(i.minute)}`,disabled:n,onChange:e=>f(e.target.value)})]}),i.timeMode===`everyMinutes`&&(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Minutes between runs`}),(0,W.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,W.jsxs)(W.Fragment,{children:[(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Hours between runs`}),(0,W.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,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Minute of the hour`}),(0,W.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,W.jsxs)(W.Fragment,{children:[(0,W.jsxs)(`label`,{className:`cal-modal-field routine-sched-check`,children:[(0,W.jsx)(`input`,{type:`checkbox`,"aria-label":`Only between certain hours`,checked:i.window!==null,disabled:n,onChange:e=>m(e.target.checked)}),(0,W.jsx)(`span`,{children:`Only between certain hours`})]}),i.window!==null&&(0,W.jsxs)(`div`,{className:`routine-sched-row`,children:[(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`From hour`}),(0,W.jsx)(`select`,{"aria-label":`From hour`,value:i.window.start,disabled:n,onChange:e=>h(`start`,e.target.value),children:K.map(e=>(0,W.jsxs)(`option`,{value:e,children:[q(e),`:00`]},e))})]}),(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`To hour`}),(0,W.jsx)(`select`,{"aria-label":`To hour`,value:i.window.end,disabled:n,onChange:e=>h(`end`,e.target.value),children:K.map(e=>(0,W.jsxs)(`option`,{value:e,children:[q(e),`:00`]},e))})]})]})]}),(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Which days`}),(0,W.jsxs)(`select`,{"aria-label":`Which days`,value:i.dayMode,disabled:n,onChange:e=>d(e.target.value),children:[(0,W.jsx)(`option`,{value:`every`,children:`Every day`}),(0,W.jsx)(`option`,{value:`weekdays`,children:`Specific days`}),i.timeMode===`at`&&(0,W.jsx)(`option`,{value:`dayOfMonth`,children:`A day of the month`})]})]}),i.dayMode===`weekdays`&&(0,W.jsxs)(`div`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Days`}),(0,W.jsx)(`div`,{className:`routine-weekdays`,children:G.map(e=>(0,W.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,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Day of month`}),(0,W.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,W.jsx)(`option`,{value:e,children:e},e))})]})]})}function Y(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 se(e){if(e.name)return`${e.name} · ${e.label}`;let t=e.channel===`whatsapp`?Y(e.destination):e.destination;return`${e.label} · ${t}`}function ce({eventStatus:e}){let t=z(e);return(0,W.jsx)(`span`,{className:`routine-status-dot is-${t}`,"data-state":t,"aria-hidden":`true`})}function le(e){return e.agentChannel==null?e.actionPlugin==null?`trigger`:`deterministic`:e.gateTool==null?`agent-every-fire`:`checked-agent`}var ue={"checked-agent":`checks first, model only when there is work`,"agent-every-fire":`model every fire`,deterministic:`runs a tool, no model`,trigger:null};function de(e){if(!e)return[];let t;try{t=JSON.parse(e)}catch{return[]}let n=t?.checks;return Array.isArray(n)?n.flatMap(e=>{if(typeof e!=`object`||!e)return[];let t=e;return typeof t.type==`string`?[{kind:t.type,target:fe(t.type,t)}]:[]}):[]}function fe(e,t){let n=e=>typeof t[e]==`string`?t[e]:null;if(e===`mail`){let e=n(`mailbox`);if(e===null)return null;let t=n(`folder`);return t?`${e}/${t}`:e}return e===`d1`?n(`database`):e===`whatsapp`?n(`scope`):e===`calendar`?n(`connector`):null}function pe(e,t){if(!e)return`—`;let n=Date.parse(e);return Number.isFinite(n)?u(new Date(n).toISOString(),t):e}function me(e){return e?e.split(`
|
|
2
2
|
`).filter(e=>e.trim()!==``).reverse():[]}function X({routine:e,adminFetch:t,onClose:n,onSaved:r,onDeleted:o,onViewRuns:c}){let{zone:l}=y(),[u,d]=(0,O.useState)(!1),[f,h]=(0,O.useState)(!1),[_,v]=(0,O.useState)(null),[b,S]=(0,O.useState)(e),[w,T]=(0,O.useState)(!1),D=b.agentChannel!=null,k=le(b),A=de(b.gateArgs),j=ie(b.eventStatus),M=j.control===`resume`,[N,P]=(0,O.useState)(!1),[F,I]=(0,O.useState)(e.agentPrompt??``),[L,R]=(0,O.useState)(e.name??``),[z,B]=(0,O.useState)(e.description??``),[V,H]=(0,O.useState)(e.recurrence),[U,ae]=(0,O.useState)(e.agentChannel??``),[G,K]=(0,O.useState)(e.agentDestination??``),[q,J]=(0,O.useState)(null),[Y,fe]=(0,O.useState)(null),X=D||b.actionPlugin==null,Z=me(b.notes);(0,O.useEffect)(()=>{let e=e=>{e.key===`Escape`&&!f&&n()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[f,n]),(0,O.useEffect)(()=>{if(!u||!X||q!==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||J(t.destinations)}).catch(t=>{e||(J([]),fe(t instanceof Error?t.message:`Could not load destinations`))}),()=>{e=!0}},[u,X,q,t]);let he=(q??[]).filter(e=>e.channel===U),ge=U.length>0&&G.length>0,_e=L.trim().length===0&&(b.name??``).length>0||U.length>0&&G.length===0||ge&&F.trim().length===0,Q=(0,O.useCallback)(()=>{let e={},t=U.length>0&&G.length>0,n=L.trim();n!==(b.name??``)&&(e.name=n),(D||t)&&F!==(b.agentPrompt??``)&&(e.agentPrompt=F);let r=z.trim().length>0?z:null;return r!==(b.description??null)&&(e.description=r),V!=null&&V!==(b.recurrence??null)&&(e.recurrence=V),t&&(U!==(b.agentChannel??``)||G!==(b.agentDestination??``))?(e.agentChannel=U,e.agentDestination=G):!t&&U===``&&(b.agentChannel??``)!==``&&(e.agentChannel=null,e.agentDestination=null),e},[D,L,F,z,V,U,G,b]),ve=(0,O.useCallback)(async()=>{let n=Q();if(Object.keys(n).length===0){d(!1);return}h(!0),v(null);try{let i=await t(`/api/admin/routines/${encodeURIComponent(e.eventId)}`,{method:`PATCH`,headers:{"content-type":`application/json`},body:JSON.stringify(n)});if(!i.ok){let e=await i.json().catch(()=>({}));throw Error(e.error??`HTTP ${i.status}`)}let a=await i.json();S(a.routine),R(a.routine.name??``),I(a.routine.agentPrompt??``),B(a.routine.description??``),H(a.routine.recurrence),ae(a.routine.agentChannel??``),K(a.routine.agentDestination??``),r(a.routine),d(!1)}catch(e){v(e instanceof Error?e.message:`Save failed`)}finally{h(!1)}},[t,Q,e.eventId,r]),ye=(0,O.useCallback)(async()=>{if(f)return;if(!N){T(!1),P(!0);return}let n=M?`resume`:`suspend`;h(!0),v(null);try{let i=await t(`/api/admin/routines/${encodeURIComponent(e.eventId)}/${n}`,{method:`POST`});if(!i.ok){let e=await i.json().catch(()=>({}));throw Error(e.error??`HTTP ${i.status}`)}let a=await i.json();S(a.routine),r(a.routine),P(!1)}catch(e){v(e instanceof Error?e.message:`${n} failed`),P(!1)}finally{h(!1)}},[t,f,N,M,e.eventId,r]),be=(0,O.useCallback)(async()=>{if(!f){if(!w){P(!1),T(!0);return}h(!0),v(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}`)}o(e.eventId)}catch(e){v(e instanceof Error?e.message:`Delete failed`),T(!1)}finally{h(!1)}}},[t,f,w,e.eventId,o]);return(0,W.jsx)(`div`,{className:`cal-modal-overlay`,onClick:()=>{f||n()},children:(0,W.jsxs)(`div`,{className:`cal-modal ${!u||D||ge?`cal-modal-wide`:`cal-modal-dispatch`}`,role:`dialog`,"aria-modal":`true`,"aria-label":u?`Edit routine`:`Routine detail`,onClick:e=>e.stopPropagation(),children:[(0,W.jsxs)(`div`,{className:`cal-modal-header`,children:[(0,W.jsxs)(`span`,{className:`cal-modal-kind`,children:[(0,W.jsx)(x,{size:13}),` Routine`]}),(0,W.jsx)(`button`,{type:`button`,className:`cal-modal-close`,onClick:n,"aria-label":`Close`,autoFocus:!0,disabled:f,children:(0,W.jsx)(m,{size:16})})]}),!u&&(0,W.jsxs)(`div`,{className:`cal-modal-body`,children:[(0,W.jsx)(`div`,{className:`cal-modal-title`,children:b.name??`Untitled routine`}),(0,W.jsxs)(`div`,{className:`cal-modal-row`,children:[(0,W.jsx)(C,{size:14}),(0,W.jsx)(`span`,{children:b.recurrence?re(b.recurrence):`One-time`})]}),(0,W.jsxs)(`div`,{className:`cal-modal-row cal-modal-meta`,children:[(0,W.jsx)(ce,{eventStatus:b.eventStatus}),(0,W.jsxs)(`span`,{children:[`Status: `,b.eventStatus??`unknown`]})]}),(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,W.jsxs)(`span`,{children:[`Next run: `,pe(b.nextRun,l)]})}),(0,W.jsxs)(`div`,{className:`cal-modal-row cal-modal-meta`,children:[(0,W.jsx)(E,{size:14}),(0,W.jsxs)(`span`,{children:[`Last run: `,pe(b.lastTriggered,l),b.lastDispatchResult?` (${b.lastDispatchResult})`:``]})]}),b.description&&(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,W.jsx)(`span`,{children:`Description`})}),(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-row-top routine-prose`,children:(0,W.jsx)(`span`,{children:b.description})})]}),ue[k]&&(0,W.jsxs)(`div`,{className:`cal-modal-row cal-modal-meta`,"data-testid":`routine-mode`,children:[(0,W.jsx)(x,{size:14}),(0,W.jsxs)(`span`,{children:[ue[k],k===`agent-every-fire`&&b.gateWaived?`: ${b.gateWaived}`:``]})]}),D?(0,W.jsxs)(W.Fragment,{children:[(0,W.jsxs)(`div`,{className:`cal-modal-row`,children:[(0,W.jsx)(g,{channel:b.agentChannel,size:14}),(0,W.jsxs)(`span`,{children:[p[b.agentChannel]??b.agentChannel,` to `,b.agentDestination??`—`]})]}),b.gateTool!=null&&(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,W.jsx)(`span`,{children:`Checks before the agent runs`})}),(0,W.jsxs)(`div`,{className:`cal-modal-row`,children:[(0,W.jsx)(ee,{size:14}),(0,W.jsxs)(`span`,{children:[b.gatePlugin,`.`,b.gateTool]})]}),A.map((e,t)=>(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,"data-testid":`gate-check`,children:(0,W.jsxs)(`span`,{children:[e.kind,e.target?` · ${e.target}`:``]})},t))]}),(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,W.jsx)(`span`,{children:`Instruction sent to the agent`})}),(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-row-top routine-prose`,children:(0,W.jsx)(`span`,{children:b.agentPrompt??`No instruction sent to the agent.`})})]}):b.actionPlugin?(0,W.jsxs)(`div`,{className:`cal-modal-row`,children:[(0,W.jsx)(ee,{size:14}),(0,W.jsxs)(`span`,{children:[b.actionPlugin,`.`,b.actionTool,b.actionArgs?` ${b.actionArgs}`:``]})]}):(0,W.jsxs)(`div`,{className:`cal-modal-row`,children:[(0,W.jsx)(C,{size:14}),(0,W.jsx)(`span`,{children:`Scheduled trigger (no dispatch)`})]}),Z.length===0?(0,W.jsxs)(`div`,{className:`cal-modal-row cal-modal-meta`,children:[(0,W.jsx)(E,{size:14}),(0,W.jsx)(`span`,{children:`No history recorded.`})]}):(0,W.jsxs)(W.Fragment,{children:[(0,W.jsxs)(`div`,{className:`cal-modal-row cal-modal-meta`,children:[(0,W.jsx)(E,{size:14}),(0,W.jsxs)(`span`,{children:[`History (`,Z.length,` `,Z.length===1?`entry`:`entries`,`)`]})]}),(0,W.jsx)(`div`,{className:`routine-history`,children:Z.map((e,t)=>(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:e},t))})]})]}),u&&(0,W.jsxs)(`div`,{className:`cal-modal-body`,children:[(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Name`}),(0,W.jsx)(`input`,{type:`text`,value:L,onChange:e=>R(e.target.value),disabled:f,maxLength:200,placeholder:`The routine's title, shown on the card`})]}),X&&(0,W.jsxs)(W.Fragment,{children:[(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Send to`}),(0,W.jsxs)(`div`,{className:`cal-modal-field-inline`,children:[(0,W.jsxs)(`select`,{value:U,disabled:f,onChange:e=>{ae(e.target.value),K(``)},children:[(0,W.jsx)(`option`,{value:``,children:`None (no dispatch)`}),(0,W.jsx)(`option`,{value:`whatsapp`,children:`WhatsApp`}),(0,W.jsx)(`option`,{value:`telegram`,children:`Telegram`})]}),U!==``&&(0,W.jsx)(g,{channel:U,size:16})]})]}),U!==``&&(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Destination`}),(0,W.jsxs)(`select`,{value:G,disabled:f||q===null,onChange:e=>K(e.target.value),children:[(0,W.jsx)(`option`,{value:``,children:q===null?`Loading destinations`:he.length===0?`No registered destinations`:`Choose a destination`}),G!==``&&!he.some(e=>e.destination===G)&&(0,W.jsxs)(`option`,{value:G,children:[G,` (not in the current list)`]}),he.map(e=>(0,W.jsx)(`option`,{value:e.destination,children:se(e)},e.destination))]})]}),Y&&(0,W.jsxs)(`div`,{className:`cal-modal-error`,children:[`Could not load destinations: `,Y]})]}),(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Description`}),(0,W.jsx)(`input`,{type:`text`,value:z,onChange:e=>B(e.target.value),disabled:f,placeholder:`One line: what this routine is for`})]}),(D||ge)&&(0,W.jsxs)(`label`,{className:`cal-modal-field`,children:[(0,W.jsx)(`span`,{children:`Instruction sent to the agent`}),(0,W.jsx)(`textarea`,{className:`cal-modal-textarea`,value:F,onChange:e=>I(e.target.value),disabled:f,rows:16,placeholder:`What should the agent do when this routine fires?`})]}),(0,W.jsx)(oe,{recurrence:b.recurrence,onChange:H,disabled:f})]}),_&&(0,W.jsx)(`div`,{className:`cal-modal-error`,children:_}),(0,W.jsxs)(`div`,{className:`cal-modal-actions`,children:[!u&&(0,W.jsxs)(W.Fragment,{children:[(0,W.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:()=>{T(!1),P(!1),d(!0)},disabled:f,children:[(0,W.jsx)(i,{size:14}),` Edit`]}),(0,W.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:()=>c(b),disabled:f,children:[(0,W.jsx)(E,{size:14}),` Runs`]}),j.control===`none`?(0,W.jsx)(`span`,{className:`cal-modal-confirm-text`,children:j.note}):(0,W.jsxs)(W.Fragment,{children:[(0,W.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:ye,disabled:f,children:[f&&N?(0,W.jsx)(s,{size:14,className:`spin`}):M?(0,W.jsx)(ne,{size:14}):(0,W.jsx)(te,{size:14}),N?M?`Confirm resume`:`Confirm suspend`:M?`Resume`:`Suspend`]}),N&&(0,W.jsx)(`span`,{className:`cal-modal-confirm-text`,children:M?`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,W.jsxs)(`button`,{type:`button`,className:`cal-modal-btn cal-modal-btn-danger`,onClick:be,disabled:f,children:[f&&w?(0,W.jsx)(s,{size:14,className:`spin`}):(0,W.jsx)(a,{size:14}),w?`Confirm delete`:`Delete`]})]}),u&&(0,W.jsxs)(W.Fragment,{children:[(0,W.jsxs)(`button`,{type:`button`,className:`cal-modal-btn cal-modal-btn-primary`,onClick:ve,disabled:f||_e,children:[f?(0,W.jsx)(s,{size:14,className:`spin`}):null,` Save`]}),(0,W.jsx)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:()=>{d(!1),v(null)},disabled:f,children:`Cancel`})]})]})]})})}function Z(e,t){if(!e)return`—`;let n=Date.parse(e);return Number.isFinite(n)?u(new Date(n).toISOString(),t):e}function he(e){return e===null?`—`:e<1e3?`${e} ms`:`${(e/1e3).toFixed(1)} s`}function ge({run:e,routineName:t,onClose:n}){let{zone:r}=y();return(0,O.useEffect)(()=>{let e=e=>{e.key===`Escape`&&n()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[n]),(0,W.jsx)(`div`,{className:`cal-modal-overlay`,onClick:n,children:(0,W.jsxs)(`div`,{className:`cal-modal cal-modal-wide`,role:`dialog`,"aria-modal":`true`,"aria-label":`Run detail`,onClick:e=>e.stopPropagation(),children:[(0,W.jsxs)(`div`,{className:`cal-modal-header`,children:[(0,W.jsx)(`span`,{className:`cal-modal-kind`,children:`Run`}),(0,W.jsx)(`button`,{type:`button`,className:`cal-modal-close`,onClick:n,"aria-label":`Close`,autoFocus:!0,children:(0,W.jsx)(m,{size:16})})]}),(0,W.jsxs)(`div`,{className:`cal-modal-body`,children:[(0,W.jsx)(`div`,{className:`cal-modal-title`,children:t??`Untitled routine`}),e.outputExcerpt!==null&&(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-row-top routine-prose`,"data-testid":`run-output`,children:(0,W.jsx)(`span`,{children:e.outputExcerpt})}),e.outputExcerpt===null&&e.status===`finished`&&(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,"data-testid":`run-output-none`,children:(0,W.jsx)(`span`,{children:`This run finished without sending anything.`})}),(0,W.jsx)(`div`,{className:`cal-modal-row`,children:(0,W.jsx)(`span`,{children:ae(e.status)})}),(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,W.jsxs)(`span`,{children:[`Due: `,Z(e.scheduledFor,r)]})}),(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,W.jsxs)(`span`,{children:[`Started: `,Z(e.startedAt,r)]})}),(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,W.jsxs)(`span`,{children:[`Dispatch ended: `,Z(e.endedAt,r),` (`,he(e.ranMs),`)`]})}),(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,W.jsxs)(`span`,{children:[`Output seen: `,Z(e.finishedAt,r)]})}),(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,W.jsxs)(`span`,{children:[`Sent to: `,e.target,` · `,e.mode,` · `,e.kind]})}),(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,W.jsxs)(`span`,{children:[`Transport: `,e.dispatchResult??`—`,e.httpStatus===null?``:` (HTTP ${e.httpStatus})`]})}),e.error&&(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-row-top routine-prose`,children:(0,W.jsx)(`span`,{children:e.error})}),(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,W.jsxs)(`span`,{children:[`Conversation: `,e.sessionKey??`—`,e.transcriptOffset===null?``:` at byte ${e.transcriptOffset}`]})}),!e.bounded&&e.status!==`gated`&&(0,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,W.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,W.jsx)(`div`,{className:`cal-modal-row cal-modal-meta`,children:(0,W.jsxs)(`span`,{children:[`Run `,e.runId]})})]})]})})}function _e({status:e}){let t=U(e);return(0,W.jsx)(`span`,{className:`routine-status-dot is-${t}`,"data-state":t,"aria-hidden":`true`})}var Q=500;function ve(e,t){if(!e)return`—`;let n=Date.parse(e);return Number.isFinite(n)?u(new Date(n).toISOString(),t):e}function ye(e){return e===null?`—`:e<1e3?`${e} ms`:`${(e/1e3).toFixed(1)} s`}var be={channel:`a channel`,destination:`a destination`,prompt:`an instruction`};function xe(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 be)){let e=t.map(e=>be[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 Se(e){return e.status===`no-destination`?e.error?xe(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 Ce(e){let t=e.indexOf(`:`);return t<=0?{channel:null,destination:e}:{channel:e.slice(0,t),destination:e.slice(t+1)}}function we(e){return e.outputExcerpt===null?e.status===`finished`?`Finished and sent nothing.`:null:e.outputExcerpt}function Te({routine:e,adminFetch:t,cacheKey:i,from:a=`card`,onBack:o}){let{zone:l}=y(),[u,d]=(0,O.useState)([]),[f,m]=(0,O.useState)(!0),[h,_]=(0,O.useState)(null),[v,b]=(0,O.useState)(null),x=(0,O.useRef)(0),S=(0,O.useCallback)(()=>{let n=!1,r=++x.current,i=()=>n||r!==x.current;return m(!0),_(null),t(`/api/admin/routines/${encodeURIComponent(e.eventId)}/runs?limit=${Q}&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)}),()=>{n=!0}},[t,e.eventId,a]);(0,O.useEffect)(()=>S(),[S]);let C=(0,O.useCallback)(()=>{T(i,e.eventId)},[i,e.eventId]);return(0,W.jsxs)(`div`,{className:`cal-page`,children:[(0,W.jsx)(`header`,{className:`cal-header`,children:(0,W.jsxs)(`div`,{className:`cal-nav`,children:[(0,W.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:o,children:[(0,W.jsx)(c,{size:14}),` Routines`]}),(0,W.jsx)(`span`,{className:`cal-range-label runs-title`,"data-testid":`runs-title`,title:e.name??`Untitled routine`,children:e.name??`Untitled routine`}),(0,W.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,"data-testid":`runs-refresh`,onClick:S,disabled:f,title:`Refresh runs`,"aria-label":`Refresh runs`,children:[f?(0,W.jsx)(s,{size:14,className:`spin`}):(0,W.jsx)(n,{size:14}),` Refresh`]}),u.length>0&&(0,W.jsx)(`div`,{className:`routine-bulk-actions`,children:(0,W.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:C,children:[(0,W.jsx)(r,{size:14}),` Download all runs`]})})]})}),(0,W.jsxs)(`div`,{className:`cal-body`,children:[h&&(0,W.jsxs)(`div`,{className:`cal-error`,children:[`Could not load runs: `,h]}),!h&&!f&&u.length===0&&(0,W.jsxs)(`div`,{className:`cal-empty`,"data-testid":`runs-empty`,children:[(0,W.jsx)(`p`,{children:`Nothing to show for this routine.`}),(0,W.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,W.jsxs)(`p`,{children:[`For a repeating routine, the server log settles the middle one: a`,(0,W.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>=Q&&(0,W.jsxs)(`div`,{className:`cal-modal-confirm-text`,"data-testid":`runs-capped`,children:[`Showing the most recent `,Q,` runs. There may be more; the download has everything still on record.`]}),(0,W.jsx)(`div`,{className:`routine-list`,children:u.map(e=>{let t=Se(e),n=we(e),{channel:r,destination:i}=Ce(e.target);return(0,W.jsxs)(`button`,{type:`button`,className:`admin-card admin-card--padded routine-card`,"data-testid":`run-row-${e.runId}`,onClick:()=>b(e),children:[(0,W.jsxs)(`span`,{className:`admin-card-title routine-card-title run-card-title`,children:[(0,W.jsx)(_e,{status:e.status}),` `,ae(e.status)]}),(0,W.jsx)(`span`,{className:`routine-card-sched`,children:ye(e.ranMs)}),(0,W.jsx)(`span`,{className:`routine-card-target`,children:r?(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(g,{channel:r,size:13}),` `,p[r]??r,` to `,r===`whatsapp`?Y(i):i]}):i}),(0,W.jsxs)(`span`,{className:`routine-card-meta`,children:[`Due `,ve(e.scheduledFor,l)]}),n&&(0,W.jsx)(`span`,{className:`routine-card-meta run-card-output`,children:n}),t&&(0,W.jsx)(`span`,{className:`routine-card-meta run-card-detail`,children:t})]},e.runId)})})]}),v&&(0,W.jsx)(ge,{run:v,routineName:e.name,onClose:()=>b(null)})]})}t(((e,t)=>{t.exports={}}))();function Ee(e){return e.agentChannel&&e.agentDestination&&e.agentPrompt?!0:!!(e.actionPlugin&&e.actionTool)}function De(e){if(e.agentChannel||e.agentDestination||e.agentPrompt){let t=[];return e.agentChannel||t.push(`channel`),e.agentDestination||t.push(`destination`),e.agentPrompt||t.push(`prompt`),`no-${t.join(`+`)}`}return e.actionPlugin||e.actionTool?e.actionTool?`no-action-plugin`:`no-action-tool`:`no-dispatch-configured`}var $=`maxy-admin-session-key`;function Oe(e){return e?re(e):`One-time`}function ke(e,t){if(!e)return`—`;let n=Date.parse(e);return Number.isFinite(n)?u(new Date(n).toISOString(),t):e}function Ae(){let[e,t]=(0,O.useState)(null),[n,r]=(0,O.useState)(!1),[i,a]=(0,O.useState)(void 0),[s,c]=(0,O.useState)(null),[l,u]=(0,O.useState)(void 0),[d,f]=(0,O.useState)(null),[p,m]=(0,O.useState)(null);(0,O.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`&&a(e.businessName),e.sessionId!==void 0&&c(e.sessionId??null),m(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,O.useCallback)(()=>{try{sessionStorage.removeItem($)}catch{}window.location.href=`/`},[]),[_,v]=(0,O.useState)(!1),y=(0,O.useCallback)(async()=>{v(!0);try{let e=await b();if(e){try{sessionStorage.removeItem($)}catch{}window.location.href=`/`}return e}finally{v(!1)}},[]);return n?e?(0,W.jsx)(h,{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,W.jsx)(S,{cacheKey:e,businessName:i,sessionId:s,onLogout:g,onDisconnect:y,disconnecting:_,userName:l,userAvatar:d,role:p,children:(0,W.jsx)(je,{cacheKey:e})})}):(0,W.jsx)(`div`,{className:`cal-page`,children:(0,W.jsxs)(`div`,{className:`cal-empty`,children:[(0,W.jsx)(`p`,{children:`You are not signed in.`}),(0,W.jsxs)(`p`,{children:[`Open the `,(0,W.jsx)(`a`,{href:`/`,className:`cal-link`,children:`main admin page`}),` and log in, then return here.`]})]})}):(0,W.jsx)(o,{surface:`gate`})}function je({cacheKey:e}){let{zone:t}=y(),{adminFetch:r,cacheKey:i,sessionRefetchNonce:a}=d({initialCacheKey:e,surface:`routines`}),[c,l]=(0,O.useState)([]),[u,f]=(0,O.useState)(!1),[m,h]=(0,O.useState)(!1),[_,v]=(0,O.useState)(null),[b,S]=(0,O.useState)(null),[T,E]=(0,O.useState)(null),D=(0,O.useCallback)(()=>{let e=!1;return f(!0),v(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||(v(t instanceof Error?t.message:`Failed to load`),l([]))}).finally(()=>{e||(f(!1),h(!0))}),()=>{e=!0}},[r]);(0,O.useEffect)(()=>D(),[D,a]);let k=(0,O.useCallback)(e=>{l(t=>t.map(t=>t.eventId===e.eventId?e:t)),S(e)},[]),A=(0,O.useCallback)(e=>{l(t=>t.filter(t=>t.eventId!==e)),S(null)},[]),[j,M]=(0,O.useState)(!1),[re,N]=(0,O.useState)(null),P=c.filter(e=>e.eventStatus===`scheduled`).length,F=c.filter(e=>e.suspendedInBulk).length,I=(0,O.useCallback)(async e=>{M(!0),N(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;N(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.`),D()}catch(e){N(e instanceof Error?e.message:`Failed`)}finally{M(!1)}},[r,D]);return m?T?(0,W.jsx)(Te,{routine:T,adminFetch:r,cacheKey:i,from:`modal`,onBack:()=>E(null)}):(0,W.jsxs)(`div`,{className:`cal-page`,children:[(0,W.jsx)(`header`,{className:`cal-header`,children:(0,W.jsxs)(`div`,{className:`cal-nav`,children:[(0,W.jsxs)(`span`,{className:`cal-range-label`,children:[(0,W.jsx)(x,{size:16}),` Routines`]}),(0,W.jsxs)(`div`,{className:`routine-bulk-actions`,children:[(0,W.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,"data-testid":`routines-refresh`,onClick:D,disabled:u,title:`Refresh routines`,"aria-label":`Refresh routines`,children:[u?(0,W.jsx)(s,{size:14,className:`spin`}):(0,W.jsx)(n,{size:14}),` Refresh`]}),(0,W.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:()=>I(`suspend-all`),disabled:j||P===0,children:[(0,W.jsx)(te,{size:14}),` Suspend all (`,P,`)`]}),(0,W.jsxs)(`button`,{type:`button`,className:`cal-modal-btn`,onClick:()=>I(`resume-all`),disabled:j||F===0,children:[(0,W.jsx)(ne,{size:14}),` Resume all (`,F,`)`]})]})]})}),(0,W.jsxs)(`div`,{className:`cal-body`,children:[re&&(0,W.jsx)(`div`,{className:`cal-modal-confirm-text`,children:re}),_&&(0,W.jsxs)(`div`,{className:`cal-error`,children:[`Could not load routines: `,_]}),!_&&!u&&c.length===0&&(0,W.jsx)(`div`,{className:`cal-empty`,children:(0,W.jsx)(`p`,{children:`No routines yet.`})}),(0,W.jsx)(`div`,{className:`routine-list`,children:c.map(e=>(0,W.jsxs)(`div`,{role:`button`,tabIndex:0,className:`admin-card admin-card--padded routine-card`,"data-testid":`routine-card-${e.eventId}`,onClick:()=>S(e),onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),S(e))},children:[(0,W.jsx)(`span`,{className:`admin-card-title routine-card-title`,title:e.name??`Untitled routine`,children:e.name??`Untitled routine`}),(0,W.jsxs)(`span`,{className:`routine-card-sched`,children:[(0,W.jsx)(C,{size:13}),` `,Oe(e.recurrence)]}),e.description&&(0,W.jsx)(`span`,{className:`routine-card-desc`,children:e.description}),(()=>{let t=e.eventStatus===`scheduled`&&!Ee(e)?De(e):null;return t===null?(0,W.jsx)(`span`,{className:`routine-card-target`,children:e.agentChannel?(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(g,{channel:e.agentChannel,size:13}),` `,p[e.agentChannel]??e.agentChannel,` to `,e.agentDestination??`—`]}):e.actionPlugin?(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(ee,{size:13}),` `,e.actionPlugin,`.`,e.actionTool]}):(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(C,{size:13}),` Scheduled trigger`]})}):(0,W.jsxs)(`span`,{className:`routine-card-target routine-card-target--gap`,children:[(0,W.jsx)(w,{size:13}),` `,xe(t)]})})(),(()=>{let t=[],n=ue[le(e)];return n&&t.push(n),e.runs24h>0&&t.push(`24h: ${e.runs24h} ${e.runs24h===1?`fire`:`fires`}, ${e.gated24h} skipped`),t.length===0?null:(0,W.jsx)(`span`,{className:`routine-card-gate`,"data-testid":`routine-gate-${e.eventId}`,children:t.join(` · `)})})(),(0,W.jsxs)(`span`,{className:`routine-card-meta`,children:[(0,W.jsx)(ce,{eventStatus:e.eventStatus}),`Next: `,ke(e.nextRun,t),` · `,e.eventStatus??`unknown`]})]},e.eventId))})]}),b&&(0,W.jsx)(X,{routine:b,adminFetch:r,onClose:()=>S(null),onSaved:k,onDeleted:A,onViewRuns:e=>{S(null),E(e)}})]}):(0,W.jsx)(o,{surface:`gate`})}(0,D.createRoot)(document.getElementById(`root`)).render((0,W.jsx)(Ae,{}));
|
|
Binary file
|
|
Binary file
|
|
@@ -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-
|
|
8
|
+
<script type="module" crossorigin src="/assets/routines-CdqGJwyD.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/chunk-CltuBf4Z.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/useMediaQuery-DIm6yGOl.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/AdminShell-BVKfxSgh.js">
|
|
Binary file
|
|
Binary file
|