botmux 2.98.4-canary.2 → 2.99.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +2 -2
- package/README.md +2 -2
- package/dist/adapters/cli/genius.d.ts +4 -0
- package/dist/adapters/cli/genius.d.ts.map +1 -0
- package/dist/adapters/cli/genius.js +216 -0
- package/dist/adapters/cli/genius.js.map +1 -0
- package/dist/adapters/cli/registry.d.ts +2 -1
- package/dist/adapters/cli/registry.d.ts.map +1 -1
- package/dist/adapters/cli/registry.js +3 -1
- package/dist/adapters/cli/registry.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +1 -1
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/core/dashboard-rows.d.ts +1 -1
- package/dist/core/dashboard-rows.d.ts.map +1 -1
- package/dist/core/dashboard-rows.js +2 -1
- package/dist/core/dashboard-rows.js.map +1 -1
- package/dist/dashboard/session-card-model.d.ts +2 -2
- package/dist/dashboard/session-card-model.d.ts.map +1 -1
- package/dist/dashboard/session-card-model.js +5 -2
- package/dist/dashboard/session-card-model.js.map +1 -1
- package/dist/dashboard/web/app.d.ts.map +1 -1
- package/dist/dashboard/web/app.js +28 -63
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts +3 -0
- package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -0
- package/dist/dashboard/web/bot-defaults-page.js +23 -0
- package/dist/dashboard/web/bot-defaults-page.js.map +1 -0
- package/dist/dashboard/web/bot-defaults.d.ts +2 -1
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js +30 -30
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/connectors-page.d.ts +14 -0
- package/dist/dashboard/web/connectors-page.d.ts.map +1 -0
- package/dist/dashboard/web/connectors-page.js +303 -0
- package/dist/dashboard/web/connectors-page.js.map +1 -0
- package/dist/dashboard/web/connectors.d.ts +1 -12
- package/dist/dashboard/web/connectors.d.ts.map +1 -1
- package/dist/dashboard/web/connectors.js +1 -325
- package/dist/dashboard/web/connectors.js.map +1 -1
- package/dist/dashboard/web/dashboard-routes.d.ts +14 -0
- package/dist/dashboard/web/dashboard-routes.d.ts.map +1 -0
- package/dist/dashboard/web/dashboard-routes.js +176 -0
- package/dist/dashboard/web/dashboard-routes.js.map +1 -0
- package/dist/dashboard/web/groups-page.d.ts +3 -0
- package/dist/dashboard/web/groups-page.d.ts.map +1 -0
- package/dist/dashboard/web/groups-page.js +26 -0
- package/dist/dashboard/web/groups-page.js.map +1 -0
- package/dist/dashboard/web/groups.d.ts +1 -1
- package/dist/dashboard/web/groups.d.ts.map +1 -1
- package/dist/dashboard/web/groups.js +113 -52
- package/dist/dashboard/web/groups.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +18 -0
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/insights-page.d.ts +3 -0
- package/dist/dashboard/web/insights-page.d.ts.map +1 -0
- package/dist/dashboard/web/insights-page.js +26 -0
- package/dist/dashboard/web/insights-page.js.map +1 -0
- package/dist/dashboard/web/insights.d.ts +18 -1
- package/dist/dashboard/web/insights.d.ts.map +1 -1
- package/dist/dashboard/web/insights.js +25 -61
- package/dist/dashboard/web/insights.js.map +1 -1
- package/dist/dashboard/web/office-page.d.ts +3 -0
- package/dist/dashboard/web/office-page.d.ts.map +1 -0
- package/dist/dashboard/web/office-page.js +149 -0
- package/dist/dashboard/web/office-page.js.map +1 -0
- package/dist/dashboard/web/office.d.ts +1 -1
- package/dist/dashboard/web/office.d.ts.map +1 -1
- package/dist/dashboard/web/office.js +1 -139
- package/dist/dashboard/web/office.js.map +1 -1
- package/dist/dashboard/web/overview-page.d.ts +3 -0
- package/dist/dashboard/web/overview-page.d.ts.map +1 -0
- package/dist/dashboard/web/overview-page.js +149 -0
- package/dist/dashboard/web/overview-page.js.map +1 -0
- package/dist/dashboard/web/overview.d.ts +2 -2
- package/dist/dashboard/web/overview.d.ts.map +1 -1
- package/dist/dashboard/web/overview.js +14 -3
- package/dist/dashboard/web/overview.js.map +1 -1
- package/dist/dashboard/web/react-hooks.d.ts +8 -0
- package/dist/dashboard/web/react-hooks.d.ts.map +1 -0
- package/dist/dashboard/web/react-hooks.js +43 -0
- package/dist/dashboard/web/react-hooks.js.map +1 -0
- package/dist/dashboard/web/react-mount.d.ts +4 -0
- package/dist/dashboard/web/react-mount.d.ts.map +1 -0
- package/dist/dashboard/web/react-mount.js +7 -0
- package/dist/dashboard/web/react-mount.js.map +1 -0
- package/dist/dashboard/web/roles-page.d.ts +4 -0
- package/dist/dashboard/web/roles-page.d.ts.map +1 -0
- package/dist/dashboard/web/roles-page.js +26 -0
- package/dist/dashboard/web/roles-page.js.map +1 -0
- package/dist/dashboard/web/roles.d.ts +1 -2
- package/dist/dashboard/web/roles.d.ts.map +1 -1
- package/dist/dashboard/web/roles.js +189 -135
- package/dist/dashboard/web/roles.js.map +1 -1
- package/dist/dashboard/web/route-lifecycle.d.ts +14 -0
- package/dist/dashboard/web/route-lifecycle.d.ts.map +1 -0
- package/dist/dashboard/web/route-lifecycle.js +29 -0
- package/dist/dashboard/web/route-lifecycle.js.map +1 -0
- package/dist/dashboard/web/schedules-page.d.ts +14 -0
- package/dist/dashboard/web/schedules-page.d.ts.map +1 -0
- package/dist/dashboard/web/schedules-page.js +84 -0
- package/dist/dashboard/web/schedules-page.js.map +1 -0
- package/dist/dashboard/web/schedules.d.ts +1 -1
- package/dist/dashboard/web/schedules.d.ts.map +1 -1
- package/dist/dashboard/web/schedules.js +1 -115
- package/dist/dashboard/web/schedules.js.map +1 -1
- package/dist/dashboard/web/sessions-page.d.ts +3 -0
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -0
- package/dist/dashboard/web/sessions-page.js +28 -0
- package/dist/dashboard/web/sessions-page.js.map +1 -0
- package/dist/dashboard/web/sessions.d.ts +4 -1
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +43 -10
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/settings-page.d.ts +3 -0
- package/dist/dashboard/web/settings-page.d.ts.map +1 -0
- package/dist/dashboard/web/settings-page.js +387 -0
- package/dist/dashboard/web/settings-page.js.map +1 -0
- package/dist/dashboard/web/settings.d.ts +1 -1
- package/dist/dashboard/web/settings.d.ts.map +1 -1
- package/dist/dashboard/web/settings.js +1 -534
- package/dist/dashboard/web/settings.js.map +1 -1
- package/dist/dashboard/web/skills-page.d.ts +33 -0
- package/dist/dashboard/web/skills-page.d.ts.map +1 -0
- package/dist/dashboard/web/skills-page.js +515 -0
- package/dist/dashboard/web/skills-page.js.map +1 -0
- package/dist/dashboard/web/skills.d.ts +1 -1
- package/dist/dashboard/web/skills.d.ts.map +1 -1
- package/dist/dashboard/web/skills.js +1 -711
- package/dist/dashboard/web/skills.js.map +1 -1
- package/dist/dashboard/web/store.d.ts +9 -0
- package/dist/dashboard/web/store.d.ts.map +1 -1
- package/dist/dashboard/web/store.js +19 -2
- package/dist/dashboard/web/store.js.map +1 -1
- package/dist/dashboard/web/team-federation-page.d.ts +4 -0
- package/dist/dashboard/web/team-federation-page.d.ts.map +1 -0
- package/dist/dashboard/web/team-federation-page.js +47 -0
- package/dist/dashboard/web/team-federation-page.js.map +1 -0
- package/dist/dashboard/web/team-federation.d.ts +2 -2
- package/dist/dashboard/web/team-federation.d.ts.map +1 -1
- package/dist/dashboard/web/team-federation.js +104 -97
- package/dist/dashboard/web/team-federation.js.map +1 -1
- package/dist/dashboard/web/v3-page.d.ts +3 -0
- package/dist/dashboard/web/v3-page.d.ts.map +1 -0
- package/dist/dashboard/web/v3-page.js +27 -0
- package/dist/dashboard/web/v3-page.js.map +1 -0
- package/dist/dashboard/web/v3.d.ts +2 -1
- package/dist/dashboard/web/v3.d.ts.map +1 -1
- package/dist/dashboard/web/v3.js +18 -43
- package/dist/dashboard/web/v3.js.map +1 -1
- package/dist/dashboard/web/whiteboards-page.d.ts +3 -0
- package/dist/dashboard/web/whiteboards-page.d.ts.map +1 -0
- package/dist/dashboard/web/whiteboards-page.js +203 -0
- package/dist/dashboard/web/whiteboards-page.js.map +1 -0
- package/dist/dashboard/web/whiteboards.d.ts +1 -1
- package/dist/dashboard/web/whiteboards.d.ts.map +1 -1
- package/dist/dashboard/web/whiteboards.js +1 -275
- package/dist/dashboard/web/whiteboards.js.map +1 -1
- package/dist/dashboard-web/app.js +36 -2550
- package/dist/dashboard-web/chunks/bot-defaults-page-3EV7K6LJ.js +358 -0
- package/dist/dashboard-web/chunks/chunk-5E3MJJL4.js +1 -0
- package/dist/dashboard-web/chunks/chunk-76J7PNZI.js +1 -0
- package/dist/dashboard-web/chunks/chunk-7SZRL6FY.js +1 -0
- package/dist/dashboard-web/chunks/chunk-JTSE5VP6.js +54 -0
- package/dist/dashboard-web/chunks/chunk-JXLHRRJD.js +31 -0
- package/dist/dashboard-web/chunks/chunk-NASYW5FD.js +1 -0
- package/dist/dashboard-web/chunks/connectors-XPZKEHF6.js +1 -0
- package/dist/dashboard-web/chunks/groups-page-C54PVKYP.js +207 -0
- package/dist/dashboard-web/chunks/insights-page-BBQYR7WY.js +309 -0
- package/dist/dashboard-web/chunks/office-page-6DXYOG55.js +1 -0
- package/dist/dashboard-web/chunks/overview-page-5PJCAMID.js +1 -0
- package/dist/dashboard-web/chunks/roles-page-APUDLPVM.js +98 -0
- package/dist/dashboard-web/chunks/schedules-WG2UKHSO.js +1 -0
- package/dist/dashboard-web/chunks/sessions-page-F3U5NFPD.js +238 -0
- package/dist/dashboard-web/chunks/settings-page-OSBZNCXL.js +2 -0
- package/dist/dashboard-web/chunks/skills-page-Y3VUAOYG.js +2 -0
- package/dist/dashboard-web/chunks/team-federation-page-CRH3WZPH.js +10 -0
- package/dist/dashboard-web/chunks/v3-page-FVPUL665.js +149 -0
- package/dist/dashboard-web/chunks/whiteboards-page-HLCTYSSV.js +1 -0
- package/dist/dashboard-web/chunks/workflows-UB7OPYGI.js +184 -0
- package/dist/dashboard-web/index.html +1 -1
- package/dist/dashboard-web/style.css +82 -1
- package/dist/dashboard.js +5 -6
- package/dist/dashboard.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +1 -0
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +1 -0
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +1 -0
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +7 -0
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/sessions-card.d.ts.map +1 -1
- package/dist/im/lark/sessions-card.js +4 -1
- package/dist/im/lark/sessions-card.js.map +1 -1
- package/dist/setup/bot-config-editor.d.ts.map +1 -1
- package/dist/setup/bot-config-editor.js +16 -14
- package/dist/setup/bot-config-editor.js.map +1 -1
- package/dist/worker.js +1 -1
- package/dist/worker.js.map +1 -1
- package/package.json +8 -2
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import{m as i}from"./chunk-JXLHRRJD.js";import"./chunk-7SZRL6FY.js";function Rt(){let t=[["",i("workflow.filter.nonTerminal")],["all",i("workflow.filter.all")],["pending",C("pending")],["running",C("running")],["waiting",C("waiting")],["succeeded",C("succeeded")],["failed",C("failed")],["cancelled",C("cancelled")]];return`
|
|
2
|
+
<nav class="wf-subnav">
|
|
3
|
+
<a href="#/legacy-workflow" class="active" data-i18n="workflow.subnav.runs">${r(i("workflow.subnav.runs"))}</a>
|
|
4
|
+
<a href="#/workflows" data-i18n="workflow.subnav.v3">${r(i("workflow.subnav.v3"))}</a>
|
|
5
|
+
</nav>
|
|
6
|
+
<form id="wf-filters" class="filters">
|
|
7
|
+
<input type="search" name="q" placeholder="${r(i("workflow.searchPlaceholder"))}" />
|
|
8
|
+
<select name="status">
|
|
9
|
+
${t.map(([e,n])=>`<option value="${r(e)}">${r(n)}</option>`).join("")}
|
|
10
|
+
</select>
|
|
11
|
+
<span id="wf-last-load" class="muted"></span>
|
|
12
|
+
</form>
|
|
13
|
+
<table>
|
|
14
|
+
<thead><tr>
|
|
15
|
+
<th>${r(i("workflow.table.run"))}</th><th>${r(i("workflow.table.workflow"))}</th><th>${r(i("workflow.table.status"))}</th>
|
|
16
|
+
<th>${r(i("workflow.table.lastSeq"))}</th><th>${r(i("workflow.table.dangling"))}</th><th>${r(i("workflow.table.updated"))}</th>
|
|
17
|
+
<th>${r(i("workflow.table.chatApp"))}</th>
|
|
18
|
+
</tr></thead>
|
|
19
|
+
<tbody id="wf-tbody"></tbody>
|
|
20
|
+
</table>
|
|
21
|
+
`}var Ct=5e3,Ht=2e3,B=new Set(["succeeded","failed","cancelled"]);function r(t){return t.replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}function qt(t){let e=new Date(t),a=Date.now()-t;return a<6e4?i("time.secondsAgo",{value:Math.max(1,Math.floor(a/1e3))}):a<36e5?i("time.minutesAgo",{value:Math.floor(a/6e4)}):a<864e5?i("time.hoursAgo",{value:Math.floor(a/36e5)}):e.toISOString().slice(0,19).replace("T"," ")}function M(t){return`<span class="${B.has(t)?"wf-status terminal":"wf-status live"} wf-status-${r(t)}">${r(C(t))}</span>`}function C(t){let e=`workflow.status.${t}`,n=i(e);return n===e?t:n}function Te(t){let e=location.hash.match(/^#\/legacy-workflow\/([^?#]+)(?:\?([^#]*))?$/);if(e){let n=new URLSearchParams(e[2]??"");return Ot(t,decodeURIComponent(e[1]),{focusAttemptId:n.get("attempt")??void 0})}return Pt(t)}function Pt(t){t.innerHTML=Rt();let e=t.querySelector("#wf-tbody"),n=t.querySelector("#wf-filters"),a=t.querySelector("#wf-last-load"),o=[],s=null,d=!1,c=null,f=!1;function h($){let I=(new FormData(n).get("q")??"").trim().toLowerCase();return I?$.filter(g=>g.runId.toLowerCase().includes(I)||g.workflowId.toLowerCase().includes(I)||(g.chatId??"").toLowerCase().includes(I)):$}function v(){let $=h(o);if($.length===0){e.innerHTML=`<tr><td colspan="7" class="empty">${c?r(i("workflow.list.failedLoad",{error:c})):o.length===0?r(i("workflow.list.noRuns")):r(i("workflow.list.noFilterMatch"))}</td></tr>`;return}e.innerHTML=$.map(m=>{let I=`${m.dEf}/${m.dAct}/${m.dWait}`,g=m.dEf+m.dAct+m.dWait>0?"wf-dangling has":"wf-dangling none",b=[];m.chatId&&b.push(r(m.chatId)),m.larkAppId&&b.push(`<span class="muted">${r(m.larkAppId)}</span>`);let O=b.length>0?b.join("<br/>"):"\u2014",L=xt(m);return`<tr data-runid="${r(m.runId)}">
|
|
22
|
+
<td><a href="#/legacy-workflow/${encodeURIComponent(m.runId)}"><code>${r(m.runId)}</code></a></td>
|
|
23
|
+
<td>${r(m.workflowId)}</td>
|
|
24
|
+
<td>${M(m.status)}${m.failedNodeId?` <span class="muted">(${r(m.failedNodeId)})</span>`:""}${L}</td>
|
|
25
|
+
<td>${m.lastSeq}</td>
|
|
26
|
+
<td class="${g}">${I}</td>
|
|
27
|
+
<td title="${r(new Date(m.updatedAt).toISOString())}">${qt(m.updatedAt)}</td>
|
|
28
|
+
<td>${O}</td>
|
|
29
|
+
</tr>`}).join("")}function k(){c?(a.textContent=i("workflow.list.error",{error:c}),a.classList.add("error")):(a.textContent=i("workflow.list.loaded",{count:o.length,time:new Date().toLocaleTimeString()}),a.classList.remove("error"))}async function u(){if(!(f||d)&&!document.hidden){d=!0;try{let $=n.elements.namedItem("status")?.value??"",m=new URLSearchParams;$==="all"?m.set("all","1"):$&&m.set("status",$);let I="/api/workflows/runs"+(m.toString()?`?${m}`:""),g=await fetch(I);g.ok?(o=(await g.json()).runs??[],c=null):(c=`HTTP ${g.status}`,o=[])}catch($){c=$?.message??String($),o=[]}finally{d=!1,f||(v(),k())}}}function y(){s!==null&&window.clearTimeout(s),s=window.setTimeout(async()=>{await u(),f||y()},Ct)}function P(){document.hidden||u()}return n.addEventListener("input",()=>{v()}),n.addEventListener("change",$=>{$.target.getAttribute("name")==="status"&&u()}),document.addEventListener("visibilitychange",P),u().then(()=>{f||y()}),()=>{f=!0,s!==null&&window.clearTimeout(s),document.removeEventListener("visibilitychange",P)}}function Ot(t,e,n={}){t.innerHTML=`
|
|
30
|
+
<div class="wf-detail-head">
|
|
31
|
+
<a class="btn-link" href="#/legacy-workflow">${r(i("workflow.detail.back"))}</a>
|
|
32
|
+
<div>
|
|
33
|
+
<h2><code>${r(e)}</code></h2>
|
|
34
|
+
<div id="wf-detail-subtitle" class="muted">${r(i("workflow.detail.loading"))}</div>
|
|
35
|
+
</div>
|
|
36
|
+
<button id="wf-cancel-run" type="button" class="contrast" hidden>${r(i("workflow.detail.cancel"))}</button>
|
|
37
|
+
<span id="wf-detail-refresh" class="muted"></span>
|
|
38
|
+
</div>
|
|
39
|
+
<section id="wf-detail-error" class="hint-warn" hidden></section>
|
|
40
|
+
<section id="wf-cancel-status" class="hint-ok" hidden></section>
|
|
41
|
+
<section id="wf-summary" class="wf-summary-grid"></section>
|
|
42
|
+
<section id="wf-dangling-panel"></section>
|
|
43
|
+
<section class="wf-panel">
|
|
44
|
+
<div class="wf-panel-title">
|
|
45
|
+
<h3>${r(i("workflow.detail.parallel"))}</h3>
|
|
46
|
+
<span id="wf-parallel-meta" class="muted"></span>
|
|
47
|
+
</div>
|
|
48
|
+
<div id="wf-parallel-view"></div>
|
|
49
|
+
</section>
|
|
50
|
+
<section class="wf-panel">
|
|
51
|
+
<div class="wf-panel-title">
|
|
52
|
+
<h3>${r(i("workflow.detail.nodes"))}</h3>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="wf-table-scroll">
|
|
55
|
+
<table>
|
|
56
|
+
<thead><tr>
|
|
57
|
+
<th>${r(i("workflow.detail.node"))}</th><th>${r(i("workflow.detail.nodeStatus"))}</th><th>${r(i("workflow.detail.activity"))}</th><th>${r(i("workflow.detail.activityStatus"))}</th>
|
|
58
|
+
<th>${r(i("workflow.detail.attempts"))}</th><th>${r(i("workflow.detail.current"))}</th><th>${r(i("workflow.detail.detail"))}</th>
|
|
59
|
+
</tr></thead>
|
|
60
|
+
<tbody id="wf-node-tbody"></tbody>
|
|
61
|
+
</table>
|
|
62
|
+
</div>
|
|
63
|
+
</section>
|
|
64
|
+
<section class="wf-panel">
|
|
65
|
+
<div class="wf-panel-title">
|
|
66
|
+
<h3>${r(i("workflow.detail.nodeIO"))}</h3>
|
|
67
|
+
</div>
|
|
68
|
+
<div id="wf-io-list" class="wf-io-list"></div>
|
|
69
|
+
</section>
|
|
70
|
+
<section class="wf-panel">
|
|
71
|
+
<div class="wf-panel-title">
|
|
72
|
+
<h3>${r(i("workflow.detail.timeline"))}</h3>
|
|
73
|
+
<button id="wf-load-older" type="button" hidden>${r(i("workflow.detail.loadOlder"))}</button>
|
|
74
|
+
</div>
|
|
75
|
+
<div class="wf-table-scroll wf-timeline-scroll">
|
|
76
|
+
<table>
|
|
77
|
+
<thead><tr>
|
|
78
|
+
<th>${r(i("workflow.detail.seq"))}</th><th>${r(i("workflow.detail.event"))}</th><th>${r(i("workflow.detail.actor"))}</th><th>${r(i("workflow.detail.node"))}</th><th>${r(i("workflow.detail.activity"))}</th><th>${r(i("workflow.detail.error"))}</th><th>${r(i("workflow.detail.time"))}</th>
|
|
79
|
+
</tr></thead>
|
|
80
|
+
<tbody id="wf-event-tbody"></tbody>
|
|
81
|
+
</table>
|
|
82
|
+
</div>
|
|
83
|
+
<div id="wf-event-meta" class="muted"></div>
|
|
84
|
+
</section>
|
|
85
|
+
`;let a=t.querySelector("#wf-detail-subtitle"),o=t.querySelector("#wf-detail-refresh"),s=t.querySelector("#wf-detail-error"),d=t.querySelector("#wf-cancel-status"),c=t.querySelector("#wf-summary"),f=t.querySelector("#wf-dangling-panel"),h=t.querySelector("#wf-parallel-view"),v=t.querySelector("#wf-parallel-meta"),k=t.querySelector("#wf-node-tbody"),u=t.querySelector("#wf-io-list"),y=t.querySelector(".wf-timeline-scroll"),P=t.querySelector("#wf-event-tbody"),$=t.querySelector("#wf-event-meta"),m=t.querySelector("#wf-cancel-run"),I=t.querySelector("#wf-load-older"),g=null,b=[],O=new Set,L=null,N=null,x=!1,U=0,H=null,j=!1,Z=!1,_=!1,St=new Set,$t=new Map,rt=new Map,F=new Map,K=new Set,V=new Map,q=new Set,D=new Map,bt=new Map,it=0,ot=n.focusAttemptId;function T(l){if(!l){s.hidden=!0,s.textContent="";return}s.hidden=!1,s.textContent=l}function at(l){if(!l){d.hidden=!0,d.textContent="";return}d.hidden=!1,d.textContent=l}async function st(){let l=await fetch(`/api/workflows/runs/${encodeURIComponent(e)}/snapshot`);if(l.status===404)throw new Error(i("workflow.detail.unknownRun"));if(!l.ok)throw new Error(i("workflow.detail.snapshotHttp",{status:l.status}));g=await l.json()}async function J(l){let S=await fetch(`/api/workflows/runs/${encodeURIComponent(e)}/events?${l}`);if(S.status===404)throw new Error(i("workflow.detail.unknownRun"));if(!S.ok)throw new Error(i("workflow.detail.eventsHttp",{status:S.status}));return await S.json()}function z(l,S){let p=l.filter(w=>O.has(w.eventId)?!1:(O.add(w.eventId),!0));p.length!==0&&(b=S==="prepend"?[...p,...b]:[...b,...p],b.sort((w,R)=>W(w.eventId)-W(R.eventId)))}async function It(){await st();let l=await J(new URLSearchParams({tail:"100"}));b=[],O=new Set,z(l.events,"append"),L=l.oldestSeq,N=l.newestSeq,x=l.hasOlder,U=l.totalCount,A()}async function G(){if(!(j||Z||document.hidden)){Z=!0;try{if(await st(),N!==null){let l=await J(new URLSearchParams({afterSeq:String(N),limit:"200"}));z(l.events,"append"),l.newestSeq!==null&&(N=l.newestSeq),L===null&&l.oldestSeq!==null&&(L=l.oldestSeq),U=l.totalCount}else{let l=await J(new URLSearchParams({tail:"1"}));z(l.events,"append"),L=l.oldestSeq,N=l.newestSeq,x=l.hasOlder,U=l.totalCount}T(null),A()}catch(l){T(l?.message??String(l))}finally{Z=!1}}}async function Tt(){if(!(L===null||!x)){I.disabled=!0;try{let l=await J(new URLSearchParams({beforeSeq:String(L),limit:"100"}));z(l.events,"prepend"),l.oldestSeq!==null&&(L=l.oldestSeq),x=l.hasOlder,U=l.totalCount,T(null),A()}catch(l){T(l?.message??String(l))}finally{I.disabled=!1}}}async function At(){if(!g||B.has(g.run.status)||_)return;if(!g.chatBinding?.larkAppId){T(i("workflow.detail.cancelUnavailable",{runId:e}));return}let l=Ut(g),S=i("workflow.detail.cancelConfirm",{runId:e,...l});if(window.confirm(S)){_=!0,m.disabled=!0;try{let p=await fetch(`/api/workflows/runs/${encodeURIComponent(e)}/cancel`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({reason:"cancelled via dashboard"})});if(p.status===401)throw new Error(i("workflow.detail.writeAccessCancel"));let w=await p.json().catch(()=>({}));if(!p.ok||!w.ok)throw new Error(w.hint??w.error??i("workflow.detail.cancelHttp",{status:p.status}));at(w.pending?i("workflow.detail.cancelPending"):null),T(null),await G()}catch(p){T(p?.message??String(p))}finally{_=!1,m.disabled=!1,A()}}}async function Et(l,S){if(!q.has(l)){q.add(l),D.delete(l),A();try{let p=await fetch(`/api/workflows/runs/${encodeURIComponent(e)}/attempts/${encodeURIComponent(S)}/${encodeURIComponent(l)}/resume`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({})});if(p.status===401)throw new Error(i("workflow.detail.writeAccessResume"));let w=await p.json().catch(()=>({}));if(!p.ok||!w.ok||!w.resumeId||!w.url)throw new Error(w.hint??w.message??w.error??i("workflow.detail.resumeStartFailed",{status:p.status}));V.set(l,{resumeId:w.resumeId,url:w.url})}catch(p){let w=p?.message??String(p);D.set(l,w)}finally{q.delete(l),A()}}}async function Lt(l,S){if(!q.has(l)){q.add(l),D.delete(l),A();try{let p=await fetch(`/api/workflows/runs/${encodeURIComponent(e)}/attempts/${encodeURIComponent(S)}/${encodeURIComponent(l)}/resume/end`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({reason:"ended_by_dashboard"})});if(p.status===401)throw new Error(i("workflow.detail.writeAccessResume"));let w=await p.json().catch(()=>({}));if(!p.ok||!w.ok)if(w.error==="resume_not_running")V.delete(l);else throw new Error(w.hint??w.message??w.error??i("workflow.detail.resumeEndFailed",{status:p.status}));else V.delete(l)}catch(p){let w=p?.message??String(p);D.set(l,w)}finally{q.delete(l),A()}}}async function Mt(l,S){if(!K.has(l)){K.add(l),F.delete(l),A();try{let p=rt.get(l)?.trim()||void 0,w=await fetch(`/api/workflows/runs/${encodeURIComponent(e)}/${S}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({comment:p})});if(w.status===401)throw new Error(i("workflow.detail.writeAccessApproval"));let R=await w.json().catch(()=>({}));if(!w.ok||!R.ok)throw new Error(R.hint??R.message??R.error??i("workflow.detail.actionHttp",{action:S,status:w.status}));let et=S==="approve"?i("workflow.detail.approved"):i("workflow.detail.rejected");F.set(l,{kind:"ok",text:R.alreadyTerminal?i("workflow.detail.alreadyTerminal",{label:et}):R.pending?i("workflow.detail.workflowContinue",{label:et}):i("workflow.detail.workflowRefreshing",{label:et})}),T(null),await G()}catch(p){let w=p?.message??String(p);F.set(l,{kind:"error",text:w}),T(w)}finally{K.delete(l),A()}}}function A(){if(!g)return;it=y.scrollTop;let l=g.run;B.has(l.status)&&at(null),a.innerHTML=`${r(l.workflowId??"?")} \xB7 ${M(l.status)} \xB7 lastSeq ${g.lastSeq}`,o.textContent=i("workflow.detail.refreshed",{time:new Date().toLocaleTimeString()}),m.hidden=B.has(l.status),m.disabled=_||!g.chatBinding?.larkAppId,m.textContent=g.chatBinding?.larkAppId?i("workflow.detail.cancel"):i("workflow.detail.cliCancelOnly"),m.title=g.chatBinding?.larkAppId?i("workflow.detail.cancelTitle"):i("workflow.detail.cliCancelTitle",{runId:e}),Nt(c,g),jt(f,g),Dt(h,v,g,b),Vt(k,g),Jt(u,g,St,$t,{comments:rt,statuses:F,resolving:K,onResolve:Mt},{sessions:V,pending:q,errors:D,onStart:Et,onEnd:Lt},ot,bt)&&(ot=void 0),he(P,b),y.scrollTop=it,I.hidden=!x,$.textContent=i("workflow.detail.eventsLoaded",{loaded:b.length,total:U})}function tt(){if(H!==null&&window.clearTimeout(H),g&&B.has(g.run.status)){H=null;return}H=window.setTimeout(async()=>{await G(),j||tt()},Ht)}function lt(){document.hidden||G().then(()=>{!j&&H===null&&tt()})}return I.addEventListener("click",()=>{Tt()}),m.addEventListener("click",()=>{At()}),document.addEventListener("visibilitychange",lt),It().then(()=>{T(null),j||tt()}).catch(l=>{T(l?.message??String(l)),a.textContent=i("workflow.detail.loadFailed")}),()=>{j=!0,H!==null&&window.clearTimeout(H),document.removeEventListener("visibilitychange",lt)}}function Nt(t,e){let n=e.run,a=[[i("workflow.summary.workflow"),r(n.workflowId??"?")],[i("workflow.summary.status"),M(n.status)],[i("workflow.summary.lastSeq"),String(e.lastSeq)],[i("workflow.summary.updated"),r(new Date(e.updatedAt).toLocaleString())],[i("workflow.summary.revision"),r(Y(n.revisionId))],[i("workflow.summary.initiator"),r(n.initiator??"-")]];n.failedNodeId&&a.push([i("workflow.summary.failedNode"),r(n.failedNodeId)]),n.cancelOriginEventId&&a.push([i("workflow.summary.cancelOrigin"),r(n.cancelOriginEventId)]),e.chatBinding&&(a.push([i("workflow.summary.chat"),`<code>${r(e.chatBinding.chatId)}</code>`]),a.push([i("workflow.summary.app"),`<code>${r(e.chatBinding.larkAppId)}</code>`])),t.innerHTML=a.map(([o,s])=>`<div class="wf-summary-item"><span>${o}</span><strong>${s}</strong></div>`).join("")}function xt(t){if(!t.errorCode)return"";let e=t.errorMessage?` \u2014 ${be(t.errorMessage,96)}`:"";return`<div class="wf-run-error">
|
|
86
|
+
<span class="muted error">${r(t.errorCode)}</span>${r(e)}
|
|
87
|
+
</div>`}function Ut(t){let e=t.dangling;return{total:new Set([...e.activities,...e.effectAttempted,...e.waits,...e.cancels]).size,effects:e.effectAttempted.length,activities:e.activities.length,waits:e.waits.length,cancels:e.cancels.length}}function jt(t,e){let n=e.dangling,a=[[i("workflow.dangling.activities"),n.activities],[i("workflow.dangling.effects"),n.effectAttempted],[i("workflow.dangling.waits"),n.waits],[i("workflow.dangling.cancels"),n.cancels]],o=new Set(a.flatMap(([,s])=>s)).size;if(t.className=o>0?"wf-panel wf-dangling-panel has":"wf-panel wf-dangling-panel",o===0){t.innerHTML=`<div class="wf-panel-title"><h3>${r(i("workflow.detail.dangling"))}</h3></div><div class="muted">${r(i("workflow.detail.noDangling"))}</div>`;return}t.innerHTML=`<div class="wf-panel-title"><h3>${r(i("workflow.detail.dangling"))}</h3><span class="wf-dangling has">${o}</span></div>
|
|
88
|
+
<div class="wf-dangling-grid">
|
|
89
|
+
${a.map(([s,d])=>`<div><strong>${s}</strong>${d.length===0?`<div class="muted">${r(i("workflow.detail.none"))}</div>`:`<ul>${d.map(c=>`<li><code>${r(c)}</code></li>`).join("")}</ul>`}</div>`).join("")}
|
|
90
|
+
</div>`}function Dt(t,e,n,a){let o=Bt(a,n);if(o.length===0){e.textContent="",t.innerHTML=`<div class="empty">${r(i("workflow.detail.noParallelData"))}</div>`;return}let s=Date.now(),d=Math.min(...o.map(u=>u.startedAt)),c=Math.max(...o.map(u=>u.endedAt??s),d+1e3),f=Math.max(1,c-d),h=_t(o,s),v=o.filter(u=>!u.endedAt&&(u.status==="running"||u.status==="effectAttempting")).length;e.textContent=i("workflow.detail.parallelMeta",{count:o.length,max:h,running:v});let k=o.sort((u,y)=>u.startedAt-y.startedAt||u.activityId.localeCompare(y.activityId)).map(u=>Wt(u,d,f,s)).join("");t.innerHTML=`<div class="wf-parallel-axis">
|
|
91
|
+
<span title="${r(new Date(d).toISOString())}">${r(X(d))}</span>
|
|
92
|
+
<span title="${r(new Date(c).toISOString())}">${r(X(c))}</span>
|
|
93
|
+
</div>
|
|
94
|
+
<div class="wf-parallel-list">${k}</div>`}function Bt(t,e){let n=new Map,a=new Map(e.activities.map(o=>[o.activityId,o.ownerNodeId]));for(let o of[...t].sort((s,d)=>W(s.eventId)-W(d.eventId))){let s=$e(o);if(!s)continue;let d=typeof s.activityId=="string"?s.activityId:void 0,c=typeof s.attemptId=="string"?s.attemptId:void 0;if(!d||!c)continue;let f=n.get(c);if(o.type==="attemptCreated"){let h=typeof s.attemptNumber=="number"?s.attemptNumber:void 0;f={nodeId:typeof s.nodeId=="string"?s.nodeId:a.get(d),activityId:d,attemptId:c,attemptNumber:h,status:"pending",startedAt:o.timestamp},n.set(c,f);continue}f||(f={nodeId:a.get(d),activityId:d,attemptId:c,status:"pending",startedAt:o.timestamp},n.set(c,f)),o.type==="activityRunning"?(f.status="running",f.runningAt=o.timestamp):o.type==="effectAttempted"?f.status="effectAttempting":o.type==="activityWaiting"||o.type==="waitCreated"?f.status="waiting":Ft(o.type)&&(f.status=Kt(o.type),f.endedAt=o.timestamp,f.endType=o.type)}return[...n.values()]}function Wt(t,e,n,a){let o=t.endedAt??a,s=ut((t.startedAt-e)/n*100,0,100),d=ut((Math.max(o,t.startedAt+1)-t.startedAt)/n*100,.7,100-s),c=t.nodeId??t.activityId,f=t.attemptNumber!==void 0?`#${t.attemptNumber}`:Y(t.attemptId),h=[`${c} ${t.status}`,`${new Date(t.startedAt).toISOString()} \u2192 ${t.endedAt?new Date(t.endedAt).toISOString():i("workflow.detail.parallelNow")}`,t.endType?`end: ${t.endType}`:void 0].filter(Boolean).join(`
|
|
95
|
+
`);return`<div class="wf-parallel-row">
|
|
96
|
+
<div class="wf-parallel-label">
|
|
97
|
+
<code>${r(c)}</code>
|
|
98
|
+
<span class="muted">${r(t.activityId)} \xB7 ${r(f)}</span>
|
|
99
|
+
</div>
|
|
100
|
+
<div class="wf-parallel-track">
|
|
101
|
+
<div class="wf-parallel-bar wf-parallel-${r(t.status)}" style="left:${s.toFixed(3)}%;width:${d.toFixed(3)}%;" title="${r(h)}">
|
|
102
|
+
<span>${r(C(t.status))}</span>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
</div>`}function _t(t,e){let n=[];for(let s of t)n.push({time:s.startedAt,delta:1}),n.push({time:s.endedAt??e,delta:-1});n.sort((s,d)=>s.time-d.time||d.delta-s.delta);let a=0,o=0;for(let s of n)a+=s.delta,o=Math.max(o,a);return o}function Ft(t){return t==="activitySucceeded"||t==="activityFailed"||t==="activityTimedOut"||t==="activityCanceled"}function Kt(t){return t==="activitySucceeded"?"succeeded":t==="activityCanceled"?"cancelled":t==="activityTimedOut"?"timedOut":"failed"}function Vt(t,e){let n=new Map(e.activities.map(s=>[s.activityId,s])),a=new Set,o=[];for(let s of e.nodes){let d=(s.activityId?n.get(s.activityId):void 0)??e.activities.find(c=>c.ownerNodeId===s.nodeId);d&&a.add(d.activityId),o.push(dt(s,d))}for(let s of e.activities)a.has(s.activityId)||o.push(dt(void 0,s));t.innerHTML=o.length>0?o.join(""):`<tr><td colspan="7" class="empty">${r(i("workflow.detail.noNodes"))}</td></tr>`}function dt(t,e){let n=e?.attempts[e.attempts.length-1];return`<tr>
|
|
106
|
+
<td>${t?`<code>${r(t.nodeId)}</code>`:'<span class="muted">-</span>'}</td>
|
|
107
|
+
<td>${t?M(t.status):'<span class="muted">-</span>'}</td>
|
|
108
|
+
<td>${e?`<code>${r(e.activityId)}</code>`:'<span class="muted">-</span>'}</td>
|
|
109
|
+
<td>${e?M(e.status):'<span class="muted">-</span>'}</td>
|
|
110
|
+
<td>${e?.attempts.length??0}</td>
|
|
111
|
+
<td>${n?`<code>${r(n.attemptId)}</code>`:'<span class="muted">-</span>'}</td>
|
|
112
|
+
<td>${n?ye(n):`<span class="muted">${r(i("workflow.detail.idle"))}</span>`}</td>
|
|
113
|
+
</tr>`}function Jt(t,e,n,a,o,s,d,c){fe(t,n,a),le(t,o.comments);let f=!!(d&&e.attemptIO?.[d]?.terminal);f&&d&&n.add(nt(d,i("workflow.detail.liveTerminal")));let h=zt(e),v=new Set;if(c){for(let u of h){v.add(u.key);let y=c.get(u.key);y||(y=Gt(u.key),c.set(u.key,y),t.appendChild(y.article)),Qt(y,u,n,o,s,d)}for(let[u,y]of Array.from(c))v.has(u)||(y.article.remove(),c.delete(u));if(h.length===0){if(!t.querySelector(".wf-io-empty-placeholder")){let u=document.createElement("div");u.className="empty wf-io-empty-placeholder",u.textContent=i("workflow.detail.noNodeIO"),t.appendChild(u)}}else t.querySelector(".wf-io-empty-placeholder")?.remove()}else{let u=[];for(let y of h)u.push(ee(y,n,o,s,d));t.innerHTML=u.length>0?u.join(""):`<div class="empty">${r(i("workflow.detail.noNodeIO"))}</div>`}me(t,a);let k=ue(t,d);return we(t,n),pe(t,a),ce(t,o),kt(t,s),k&&f}function zt(t){let e=new Map(t.activities.map(o=>[o.activityId,o])),n=new Set,a=[];for(let o of t.nodes){let s=(o.activityId?e.get(o.activityId):void 0)??t.activities.find(d=>d.ownerNodeId===o.nodeId);if(!s){a.push({key:`node:${o.nodeId}`,node:o});continue}n.add(s.activityId),a.push({key:`activity:${s.activityId}`,node:o,activity:s,io:t.attemptIO?.[Q(s)?.attemptId??""]})}for(let o of t.activities)n.has(o.activityId)||a.push({key:`activity:${o.activityId}`,activity:o,io:t.attemptIO?.[Q(o)?.attemptId??""]});return a}function Gt(t){let e=document.createElement("article");e.className="wf-io-card",e.dataset.wfCardKey=t;let n=document.createElement("div");n.className="wf-io-card-head";let a=document.createElement("div");a.className="wf-io-terminal-slot";let o=document.createElement("div");return o.className="wf-io-grid",e.appendChild(n),e.appendChild(a),e.appendChild(o),{article:e,head:n,terminalSlot:a,grid:o,currentTerminalUrl:null}}function Qt(t,e,n,a,o,s){let d=Q(e.activity),c=e.node?.nodeId??e.activity?.ownerNodeId??e.activity?.activityId??"unknown",f=!!(d&&d.attemptId===s);t.article.classList.toggle("is-focused",f),d?t.article.dataset.wfAttemptCard=d.attemptId:delete t.article.dataset.wfAttemptCard;let h=ht(d,a);t.head.innerHTML=`
|
|
114
|
+
<header>
|
|
115
|
+
<div>
|
|
116
|
+
<strong><code>${r(c)}</code></strong>
|
|
117
|
+
<span class="muted">${e.activity?r(e.activity.activityId):r(i("workflow.detail.notDispatched"))}</span>
|
|
118
|
+
</div>
|
|
119
|
+
<div>${e.node?M(e.node.status):""} ${e.activity?M(e.activity.status):""}</div>
|
|
120
|
+
</header>
|
|
121
|
+
<div class="wf-io-meta">
|
|
122
|
+
${d?`${r(i("workflow.detail.attempt"))} <code>${r(d.attemptId)}</code>`:r(i("workflow.detail.noAttempt"))}
|
|
123
|
+
</div>
|
|
124
|
+
${h}
|
|
125
|
+
`;let v=ft(d,e.activity,e.io?.terminal,o),k=v?.url??null;if(k!==t.currentTerminalUrl)v===null?t.terminalSlot.innerHTML="":t.terminalSlot.innerHTML=wt(e.key,d,e.activity,e.io?.terminal,v,n,o),t.currentTerminalUrl=k;else if(v!==null&&e.io?.terminal){let y=t.terminalSlot.querySelector("details.wf-terminal-block > summary");if(y){let P=mt(v.kind);y.innerHTML=`${r(P)} ${yt(d,e.io.terminal)}`}d&&de(t.terminalSlot,d,e.activity,e.io.terminal,v,o)}let u=d?.attemptId??e.activity?.activityId??e.node?.nodeId??"unknown";t.grid.innerHTML=`
|
|
126
|
+
${E(u,i("workflow.detail.authoredInput"),e.io?.input,n)}
|
|
127
|
+
${E(u,i("workflow.detail.resolvedInput"),e.io?.resolvedInput,n)}
|
|
128
|
+
${E(u,i("workflow.detail.output"),e.io?.output,n)}
|
|
129
|
+
${E(u,i("workflow.detail.executionLog"),e.io?.log,n)}
|
|
130
|
+
${e.io?.waitPrompt?E(u,i("workflow.detail.waitPrompt"),e.io.waitPrompt,n):""}
|
|
131
|
+
`}function ft(t,e,n,a){if(!n||n.error)return null;if(ne(t,n))return{kind:"live",url:ie(n)};if(!t||!e||!re(t,n))return null;let o=ae();if(!o)return null;let s=a?.sessions.get(t.attemptId);return s?{kind:"resume",url:s.url,resumeId:s.resumeId,downloadUrl:ct(o,e.activityId,t.attemptId)}:{kind:"replay",url:oe(o,e.activityId,t.attemptId,!!n.hasPtyLog),downloadUrl:ct(o,e.activityId,t.attemptId)}}function wt(t,e,n,a,o,s,d){if(!a)return"";let c=mt(o.kind),f=nt(t,c),h=yt(e,a),v=Xt(o.kind),k=o.kind==="replay"||o.kind==="resume"?`<a class="btn-link" href="${r(o.downloadUrl)}" download>${r(i("workflow.detail.downloadFullLog"))}</a>`:"",u=e?gt(e,n,a,o,d):"",y=e?vt(e.attemptId,d):"";return`<details class="wf-io-block wf-terminal-block" data-io-key="${r(f)}"${s.has(f)?" open":""}>
|
|
132
|
+
<summary>${r(c)} ${h}</summary>
|
|
133
|
+
<div class="wf-terminal-actions">
|
|
134
|
+
<a class="btn-link" href="${r(o.url)}" target="_blank" rel="noreferrer">${r(v)}</a>
|
|
135
|
+
${k}
|
|
136
|
+
${u}
|
|
137
|
+
</div>
|
|
138
|
+
${y}
|
|
139
|
+
<iframe class="wf-terminal-frame" src="${r(o.url)}" title="${r(c)}" loading="lazy"></iframe>
|
|
140
|
+
</details>`}function mt(t){return t==="live"?i("workflow.detail.liveTerminal"):t==="resume"?i("workflow.detail.terminalResume"):i("workflow.detail.terminalReplay")}function Xt(t){return t==="live"?i("workflow.detail.openTerminalNewTab"):t==="resume"?i("workflow.detail.openResumeNewTab"):i("workflow.detail.openReplayNewTab")}var pt=new Set(["antigravity","codex-app","cursor","mira"]),Yt=new Set(["aiden","coco","claude-code","seed","relay","codex","mtr","hermes","pi","mir"]);function Zt(t){return!!t&&(Yt.has(t)||pt.has(t))}function te(t){return!!t&&pt.has(t)}function gt(t,e,n,a,o){if(!o||a.kind==="live"||!e)return"";let s=a.kind==="resume",d=o.pending.has(t.attemptId),c=`data-wf-resume-attempt="${r(t.attemptId)}" data-wf-resume-activity="${r(e.activityId)}"`;return s?`<button type="button" class="btn-link" data-wf-resume-button="1" data-wf-resume-action="end" ${c}${d?" disabled":""}>${r(d?i("workflow.detail.resumeEnding"):i("workflow.detail.endResumeSession"))}</button>`:Zt(n.cliId)?te(n.cliId)&&!n.cliSessionId?`<button type="button" class="btn-link" data-wf-resume-button="1" disabled title="${r(i("workflow.detail.resumeMissingCliSession"))}">${r(i("workflow.detail.resumeSession"))}</button>`:`<button type="button" class="btn-link" data-wf-resume-button="1" data-wf-resume-action="start" ${c}${d?" disabled":""}>${r(d?i("workflow.detail.resumeStarting"):i("workflow.detail.resumeSession"))}</button>`:`<button type="button" class="btn-link" data-wf-resume-button="1" disabled title="${r(i("workflow.detail.resumeUnsupportedCli",{cliId:n.cliId??"?"}))}">${r(i("workflow.detail.resumeSession"))}</button>`}function vt(t,e){if(!e)return"";let n=e.errors.get(t);return n?`<div class="hint-warn wf-resume-status" data-wf-resume-status="${r(t)}">${r(n)}</div>`:""}function ee(t,e,n,a,o){let s=Q(t.activity),d=t.node?.nodeId??t.activity?.ownerNodeId??t.activity?.activityId??"unknown",c=s?.attemptId??t.activity?.activityId??t.node?.nodeId??"unknown",f=ht(s,n),h=s?.attemptId===o?" is-focused":"",v=s?` data-wf-attempt-card="${r(s.attemptId)}"`:"",k=ft(s,t.activity,t.io?.terminal,a),u=k?wt(c,s,t.activity,t.io?.terminal,k,e,a):"";return`<article class="wf-io-card${h}" data-wf-card-key="${r(t.key)}"${v}>
|
|
141
|
+
<div class="wf-io-card-head">
|
|
142
|
+
<header>
|
|
143
|
+
<div>
|
|
144
|
+
<strong><code>${r(d)}</code></strong>
|
|
145
|
+
<span class="muted">${t.activity?r(t.activity.activityId):r(i("workflow.detail.notDispatched"))}</span>
|
|
146
|
+
</div>
|
|
147
|
+
<div>${t.node?M(t.node.status):""} ${t.activity?M(t.activity.status):""}</div>
|
|
148
|
+
</header>
|
|
149
|
+
<div class="wf-io-meta">
|
|
150
|
+
${s?`${r(i("workflow.detail.attempt"))} <code>${r(s.attemptId)}</code>`:r(i("workflow.detail.noAttempt"))}
|
|
151
|
+
</div>
|
|
152
|
+
${f}
|
|
153
|
+
</div>
|
|
154
|
+
<div class="wf-io-terminal-slot">${u}</div>
|
|
155
|
+
<div class="wf-io-grid">
|
|
156
|
+
${E(c,i("workflow.detail.authoredInput"),t.io?.input,e)}
|
|
157
|
+
${E(c,i("workflow.detail.resolvedInput"),t.io?.resolvedInput,e)}
|
|
158
|
+
${E(c,i("workflow.detail.output"),t.io?.output,e)}
|
|
159
|
+
${E(c,i("workflow.detail.executionLog"),t.io?.log,e)}
|
|
160
|
+
${t.io?.waitPrompt?E(c,i("workflow.detail.waitPrompt"),t.io.waitPrompt,e):""}
|
|
161
|
+
</div>
|
|
162
|
+
</article>`}function Q(t){return t?.attempts[t.attempts.length-1]}function yt(t,e){let n=[];return e.error?n.push(i("workflow.detail.error")):n.push(e.status==="live"?i("workflow.detail.terminalLive"):i("workflow.detail.terminalClosedShort")),t?.status&&n.push(t.status),e.webPort>0&&n.push(`:${e.webPort}`),`<span class="muted">${r(n.join(" \xB7 "))}</span>`}function ne(t,e){return e.status==="live"&&e.webPort>0&&(t?.status==="pending"||t?.status==="running"||t?.status==="effectAttempting")}function re(t,e){return t.status==="succeeded"||t.status==="failed"||t.status==="cancelled"||t.status==="timedOut"?!!(e.sessionId||e.startedAt):!1}function ie(t){return`http://${window.location.hostname||"127.0.0.1"}:${t.webPort}`}function oe(t,e,n,a){let o=new URLSearchParams({runId:t,activityId:e,attemptId:n});return a&&o.set("hasPtyLog","1"),`/assets/terminal-replay.html?${o.toString()}`}function ct(t,e,n){return`/api/workflows/runs/${encodeURIComponent(t)}/attempts/${encodeURIComponent(e)}/${encodeURIComponent(n)}/terminal-log/raw?download=1`}function ae(){let t=window.location.hash.match(/^#\/legacy-workflow\/([^/?#]+)/);if(!t)return null;try{return decodeURIComponent(t[1])}catch{return null}}function ht(t,e){if(!se(t))return"";let n=t.attemptId,a=e.comments.get(n)??"",o=e.resolving.has(n),s=e.statuses.get(n),d=s?.kind==="error"?"hint-warn":"hint-ok";return`<div class="wf-approval-box" data-wf-approval="${r(n)}">
|
|
163
|
+
<label>
|
|
164
|
+
<span>${r(i("workflow.detail.approvalComment"))}</span>
|
|
165
|
+
<textarea class="wf-approval-comment" data-wf-approval-comment="${r(n)}" rows="2" placeholder="${r(i("workflow.detail.optionalComment"))}"${o?" disabled":""}>${r(a)}</textarea>
|
|
166
|
+
</label>
|
|
167
|
+
<div class="wf-approval-actions">
|
|
168
|
+
<button type="button" class="primary" data-wf-approval-action="approve" data-wf-attempt-id="${r(n)}"${o?" disabled":""}>${r(i("workflow.detail.approve"))}</button>
|
|
169
|
+
<button type="button" data-wf-approval-action="reject" data-wf-attempt-id="${r(n)}"${o?" disabled":""}>${r(i("workflow.detail.reject"))}</button>
|
|
170
|
+
${o?`<span class="muted">${r(i("workflow.detail.submitting"))}</span>`:""}
|
|
171
|
+
</div>
|
|
172
|
+
${s?`<div class="${d} wf-approval-status">${r(s.text)}</div>`:""}
|
|
173
|
+
</div>`}function se(t){return!!t&&t.status==="waiting"&&t.wait?.waitKind==="human-gate"&&!t.wait.resolution}function le(t,e){t.querySelectorAll("textarea[data-wf-approval-comment]").forEach(n=>{let a=n.dataset.wfApprovalComment;a&&e.set(a,n.value)})}function kt(t,e){t.querySelectorAll("button[data-wf-resume-action][data-wf-resume-attempt][data-wf-resume-activity]").forEach(n=>{n.dataset.wfResumeBound!=="1"&&(n.dataset.wfResumeBound="1",n.addEventListener("click",()=>{let a=n.dataset.wfResumeAttempt,o=n.dataset.wfResumeActivity,s=n.dataset.wfResumeAction;!a||!o||(s==="start"?e.onStart(a,o):s==="end"&&e.onEnd(a,o))}))})}function de(t,e,n,a,o,s){let d=t.querySelector(".wf-terminal-actions");if(!d)return;let c=d.querySelector('button[data-wf-resume-button="1"]'),f=gt(e,n,a,o,s);c?c.outerHTML=f:f&&d.insertAdjacentHTML("beforeend",f);let h=t.querySelector("details.wf-terminal-block");if(h){let v=h.querySelector(".wf-resume-status"),k=vt(e.attemptId,s);v?v.outerHTML=k:k&&d.insertAdjacentHTML("afterend",k)}kt(t,s)}function ce(t,e){t.querySelectorAll("textarea[data-wf-approval-comment]").forEach(n=>{let a=n.dataset.wfApprovalComment;a&&n.addEventListener("input",()=>{e.comments.set(a,n.value)})}),t.querySelectorAll("button[data-wf-approval-action][data-wf-attempt-id]").forEach(n=>{n.addEventListener("click",()=>{let a=n.dataset.wfAttemptId,o=n.dataset.wfApprovalAction;!a||o!=="approve"&&o!=="reject"||e.onResolve(a,o)})})}function E(t,e,n,a){let o=nt(t,e);return`<details class="wf-io-block" data-io-key="${r(o)}"${a.has(o)?" open":""}>
|
|
174
|
+
<summary>${r(e)} ${ge(n)}</summary>
|
|
175
|
+
${ve(n)}
|
|
176
|
+
</details>`}function nt(t,e){return`${t}:${e}`}function ue(t,e){if(!e)return!1;for(let n of t.querySelectorAll("[data-wf-attempt-card]"))if(n.dataset.wfAttemptCard===e)return n.scrollIntoView({block:"center"}),!0;return!1}function fe(t,e,n){t.querySelectorAll("details.wf-io-block[data-io-key]").forEach(a=>{let o=a.dataset.ioKey;if(!o)return;a.open?e.add(o):e.delete(o);let s=a.querySelector(".wf-io-pre");s&&n.set(o,s.scrollTop)})}function we(t,e){t.querySelectorAll("details.wf-io-block[data-io-key]").forEach(n=>{n.dataset.ioToggleBound!=="1"&&(n.dataset.ioToggleBound="1",n.addEventListener("toggle",()=>{let a=n.dataset.ioKey;a&&(n.open?e.add(a):e.delete(a))}))})}function me(t,e){t.querySelectorAll("details.wf-io-block[data-io-key]").forEach(n=>{let a=n.dataset.ioKey;if(!a)return;let o=e.get(a);if(o===void 0)return;let s=n.querySelector(".wf-io-pre");s&&(s.scrollTop=o)})}function pe(t,e){t.querySelectorAll("details.wf-io-block[data-io-key]").forEach(n=>{let a=n.dataset.ioKey;if(!a)return;let o=n.querySelector(".wf-io-pre");o&&o.dataset.ioScrollBound!=="1"&&(o.dataset.ioScrollBound="1",o.addEventListener("scroll",()=>{e.set(a,o.scrollTop)}))})}function ge(t){if(!t)return`<span class="muted">${r(i("workflow.detail.empty"))}</span>`;let e=[];return t.outputBytes!==void 0&&e.push(`${t.outputBytes}B`),t.truncated&&e.push(i("workflow.detail.truncated")),t.error&&e.push(i("workflow.detail.error")),t.outputHash&&e.push(Y(t.outputHash)),e.length?`<span class="muted">${r(e.join(" \xB7 "))}</span>`:""}function ve(t){if(!t)return`<div class="muted wf-io-empty">${r(i("workflow.detail.noData"))}</div>`;let e=t.value!==void 0?JSON.stringify(t.value,null,2):t.text??"",n=t.error?`<div class="muted error">${r(t.error)}</div>`:"";return e?`${n}<pre class="wf-io-pre">${r(e)}</pre>`:`${n}<div class="muted wf-io-empty">${r(i("workflow.detail.noPreview"))}</div>`}function ye(t){let e=[];if(t.effectAttempted&&e.push(`${r(i("workflow.detail.effect"))} ${r(t.effectAttempted.provider)}`),t.wait){let n=t.wait.resolution?`${t.wait.resolution.kind}${t.wait.resolution.resolution?":"+t.wait.resolution.resolution:""}`:i("workflow.detail.open");e.push(`${r(i("workflow.detail.wait"))} ${r(t.wait.waitKind)} ${r(n)}`),t.wait.deadlineAt!==void 0&&e.push(`${r(i("workflow.detail.deadline"))} ${r(X(t.wait.deadlineAt))}`)}if(t.error){let n=`${t.error.errorCode}${t.error.errorClass?` \xB7 ${t.error.errorClass}`:""}`;e.push(`<span class="muted error">${r(n)}</span>`),t.error.errorMessage&&e.push(`<span class="error wf-error-msg">${r(t.error.errorMessage)}</span>`)}return t.output&&e.push(`${r(i("workflow.detail.output"))} ${r(Y(t.output.outputHash))}`),t.runningMs!==void 0&&e.push(`${t.runningMs}ms`),e.length>0?e.join("<br/>"):'<span class="muted">-</span>'}function he(t,e){t.innerHTML=e.length>0?e.map(ke).join(""):`<tr><td colspan="7" class="empty">${r(i("workflow.detail.noEvents"))}</td></tr>`}function ke(t){let e=Se(t.payload);return`<tr>
|
|
177
|
+
<td>${W(t.eventId)}</td>
|
|
178
|
+
<td><code>${r(t.type)}</code></td>
|
|
179
|
+
<td>${r(t.actor)}</td>
|
|
180
|
+
<td>${e.nodeId?`<code>${r(e.nodeId)}</code>`:"-"}</td>
|
|
181
|
+
<td>${e.activityId?`<code>${r(e.activityId)}</code>`:"-"}</td>
|
|
182
|
+
<td>${e.errorCode?`<span class="muted error">${r(e.errorCode)}</span>`:"-"}</td>
|
|
183
|
+
<td title="${r(new Date(t.timestamp).toISOString())}">${r(X(t.timestamp))}</td>
|
|
184
|
+
</tr>`}function W(t){let e=t.lastIndexOf("-");if(e<0)return 0;let n=Number(t.slice(e+1));return Number.isFinite(n)?n:0}function Se(t){if(!t||typeof t!="object"||"ref"in t)return{};let e=t,n={};typeof e.nodeId=="string"&&(n.nodeId=e.nodeId),typeof e.activityId=="string"&&(n.activityId=e.activityId),typeof e.failedNodeId=="string"&&(n.nodeId=e.failedNodeId);let a=e.error;return a&&typeof a=="object"&&"errorCode"in a&&(n.errorCode=String(a.errorCode)),n}function $e(t){return!t.payload||typeof t.payload!="object"||"ref"in t.payload?null:t.payload}function ut(t,e,n){return Math.min(n,Math.max(e,t))}function Y(t){return t?t.length>18?t.slice(0,10)+"..."+t.slice(-6):t:"-"}function be(t,e){return t.length>e?t.slice(0,e-1)+"\u2026":t}function X(t){return new Date(t).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"})}export{Te as renderWorkflowsPage};
|
|
@@ -773,6 +773,12 @@ th {
|
|
|
773
773
|
|
|
774
774
|
tbody tr:last-child td { border-bottom: 0; }
|
|
775
775
|
|
|
776
|
+
.schedules-table .schedule-actions {
|
|
777
|
+
display: flex;
|
|
778
|
+
gap: 6px;
|
|
779
|
+
flex-wrap: wrap;
|
|
780
|
+
}
|
|
781
|
+
|
|
776
782
|
/* ── 首尾列固定的横向滚动矩阵(群组与 Bot)─────────────────────────────
|
|
777
783
|
bot 一多中间的成员列就溢出视口,操作按钮被顶出屏幕。把圆角/阴影挪到
|
|
778
784
|
滚动容器上,表格本体放开宽度横向滚,首列(群)和尾列(操作)sticky 钉住。 */
|
|
@@ -969,6 +975,7 @@ button.primary {
|
|
|
969
975
|
.status-working,
|
|
970
976
|
.status-active { background: var(--accent-soft); color: var(--accent-strong); }
|
|
971
977
|
.status-idle { background: var(--surface-muted); color: var(--muted); }
|
|
978
|
+
.status-dormant { background: var(--surface-muted); color: var(--muted); }
|
|
972
979
|
.status-closed { background: var(--danger-soft); color: var(--danger); }
|
|
973
980
|
.status-analyzing { background: var(--warning-soft); color: var(--warning); }
|
|
974
981
|
.status-starting { background: var(--success-soft); color: var(--success); }
|
|
@@ -1572,6 +1579,14 @@ button.primary {
|
|
|
1572
1579
|
background: var(--danger);
|
|
1573
1580
|
}
|
|
1574
1581
|
|
|
1582
|
+
.kanban-card-dot[data-status="idle"] {
|
|
1583
|
+
background: var(--success);
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
.kanban-card-dot[data-status="dormant"] {
|
|
1587
|
+
background: var(--muted);
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1575
1590
|
.kanban-card-dot[data-status="closed"] {
|
|
1576
1591
|
background: var(--border);
|
|
1577
1592
|
}
|
|
@@ -2111,6 +2126,9 @@ fieldset legend {
|
|
|
2111
2126
|
}
|
|
2112
2127
|
|
|
2113
2128
|
.bulk-bar[hidden] { display: none; }
|
|
2129
|
+
/* Mobile table rules are author-level and can override the UA hidden style;
|
|
2130
|
+
keep hidden tables invisible across view toggles such as sessions board/table. */
|
|
2131
|
+
table[hidden] { display: none !important; }
|
|
2114
2132
|
.bulk-bar #bulk-count { font-weight: 800; margin-right: 4px; }
|
|
2115
2133
|
.idle-cleanup-bar {
|
|
2116
2134
|
display: grid;
|
|
@@ -2601,6 +2619,66 @@ input.row-select,
|
|
|
2601
2619
|
display: block;
|
|
2602
2620
|
overflow-x: auto;
|
|
2603
2621
|
}
|
|
2622
|
+
.schedules-table {
|
|
2623
|
+
display: block;
|
|
2624
|
+
overflow: visible;
|
|
2625
|
+
border: 0;
|
|
2626
|
+
border-radius: 0;
|
|
2627
|
+
background: transparent;
|
|
2628
|
+
box-shadow: none;
|
|
2629
|
+
}
|
|
2630
|
+
.schedules-table thead {
|
|
2631
|
+
display: none;
|
|
2632
|
+
}
|
|
2633
|
+
.schedules-table tbody {
|
|
2634
|
+
display: grid;
|
|
2635
|
+
gap: 10px;
|
|
2636
|
+
}
|
|
2637
|
+
.schedules-table tr {
|
|
2638
|
+
display: grid;
|
|
2639
|
+
gap: 8px;
|
|
2640
|
+
padding: 14px;
|
|
2641
|
+
border: 1px solid var(--border-soft);
|
|
2642
|
+
border-radius: var(--radius);
|
|
2643
|
+
background: var(--surface);
|
|
2644
|
+
box-shadow: var(--shadow);
|
|
2645
|
+
}
|
|
2646
|
+
.schedules-table td {
|
|
2647
|
+
display: grid;
|
|
2648
|
+
grid-template-columns: minmax(84px, 0.36fr) minmax(0, 1fr);
|
|
2649
|
+
gap: 10px;
|
|
2650
|
+
align-items: baseline;
|
|
2651
|
+
min-width: 0;
|
|
2652
|
+
padding: 0;
|
|
2653
|
+
border-bottom: 0;
|
|
2654
|
+
white-space: normal;
|
|
2655
|
+
overflow-wrap: anywhere;
|
|
2656
|
+
}
|
|
2657
|
+
.schedules-table td[data-label]::before {
|
|
2658
|
+
content: attr(data-label);
|
|
2659
|
+
color: var(--muted);
|
|
2660
|
+
font-size: 11px;
|
|
2661
|
+
font-weight: 800;
|
|
2662
|
+
line-height: 1.35;
|
|
2663
|
+
text-transform: uppercase;
|
|
2664
|
+
}
|
|
2665
|
+
.schedules-table td.actions-cell {
|
|
2666
|
+
grid-template-columns: 1fr;
|
|
2667
|
+
}
|
|
2668
|
+
.schedules-table .schedule-actions {
|
|
2669
|
+
gap: 8px;
|
|
2670
|
+
}
|
|
2671
|
+
.schedules-table .schedule-actions button {
|
|
2672
|
+
flex: 1 1 120px;
|
|
2673
|
+
}
|
|
2674
|
+
.schedules-table tr.schedule-empty-row {
|
|
2675
|
+
padding: 0;
|
|
2676
|
+
}
|
|
2677
|
+
.schedules-table tr.schedule-empty-row td {
|
|
2678
|
+
display: block;
|
|
2679
|
+
padding: 18px;
|
|
2680
|
+
text-align: center;
|
|
2681
|
+
}
|
|
2604
2682
|
}
|
|
2605
2683
|
|
|
2606
2684
|
/* ─── Roles Page ─── */
|
|
@@ -3414,6 +3492,7 @@ button.contrast:hover { background: var(--danger-soft); border-color: var(--dang
|
|
|
3414
3492
|
.status-analyzing { background: var(--accent-soft); color: var(--accent); }
|
|
3415
3493
|
.status-starting { background: var(--info-soft); color: var(--info); }
|
|
3416
3494
|
.status-idle { background: var(--success-soft); color: var(--success); }
|
|
3495
|
+
.status-dormant { background: var(--surface-muted); color: var(--muted); }
|
|
3417
3496
|
.status-limited { background: var(--danger-soft); color: var(--danger); }
|
|
3418
3497
|
|
|
3419
3498
|
/* ── 玻璃面板(dark 下生效;light 保持实底)─────────────────────────────── */
|
|
@@ -4388,6 +4467,7 @@ button.contrast:hover { background: var(--danger-soft); border-color: var(--dang
|
|
|
4388
4467
|
}
|
|
4389
4468
|
|
|
4390
4469
|
.skills-install-grid label:first-child,
|
|
4470
|
+
.skills-install-grid .skills-source-label,
|
|
4391
4471
|
.skills-install-field-wide,
|
|
4392
4472
|
.skills-install-note {
|
|
4393
4473
|
grid-column: 1 / -1;
|
|
@@ -4408,7 +4488,8 @@ button.contrast:hover { background: var(--danger-soft); border-color: var(--dang
|
|
|
4408
4488
|
font-weight: 700;
|
|
4409
4489
|
}
|
|
4410
4490
|
|
|
4411
|
-
.skills-install-grid label
|
|
4491
|
+
.skills-install-grid label,
|
|
4492
|
+
.skills-install-grid .skills-source-label {
|
|
4412
4493
|
display: grid;
|
|
4413
4494
|
gap: 5px;
|
|
4414
4495
|
color: var(--muted);
|
package/dist/dashboard.js
CHANGED
|
@@ -421,15 +421,14 @@ function serveStatic(req, res, pathname) {
|
|
|
421
421
|
const st = statSync(fp);
|
|
422
422
|
if (!st.isFile())
|
|
423
423
|
return false;
|
|
424
|
-
//
|
|
425
|
-
//
|
|
426
|
-
//
|
|
427
|
-
|
|
428
|
-
// when the build changed. No manual hard-refresh needed after deploy.
|
|
424
|
+
// Fixed entry filenames (index.html/app.js/style.css) need revalidation so
|
|
425
|
+
// a deploy never serves new JS with old CSS. Lazy chunks are content-hashed
|
|
426
|
+
// and can be cached immutably once the current app.js points at them.
|
|
427
|
+
const immutableChunk = relToRoot.startsWith('chunks/') || relToRoot.startsWith('chunks\\');
|
|
429
428
|
const etag = `W/"${st.size.toString(16)}-${Math.floor(st.mtimeMs).toString(16)}"`;
|
|
430
429
|
const headers = {
|
|
431
430
|
'content-type': MIME[extname(fp)] ?? 'application/octet-stream',
|
|
432
|
-
'cache-control': 'no-cache',
|
|
431
|
+
'cache-control': immutableChunk ? 'public, max-age=31536000, immutable' : 'no-cache',
|
|
433
432
|
etag,
|
|
434
433
|
};
|
|
435
434
|
if (req.headers['if-none-match'] === etag) {
|