@agimon-ai/doompi-workflow 0.0.1-alpha.2 → 0.0.1-alpha.21
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.md +47 -21
- package/dist/adapters/pi/dispatcher.cjs.map +1 -0
- package/dist/{dispatcher.d.cts → adapters/pi/dispatcher.d.cts} +1 -1
- package/dist/adapters/pi/dispatcher.d.cts.map +1 -0
- package/dist/{dispatcher.d.mts → adapters/pi/dispatcher.d.mts} +1 -1
- package/dist/adapters/pi/dispatcher.d.mts.map +1 -0
- package/dist/adapters/pi/dispatcher.mjs.map +1 -0
- package/dist/adapters/pi/extension.cjs +2 -0
- package/dist/adapters/pi/extension.cjs.map +1 -0
- package/dist/{extension.d.cts → adapters/pi/extension.d.cts} +1 -1
- package/dist/adapters/pi/extension.d.cts.map +1 -0
- package/dist/{extension.d.mts → adapters/pi/extension.d.mts} +1 -1
- package/dist/adapters/pi/extension.d.mts.map +1 -0
- package/dist/adapters/pi/extension.mjs +2 -0
- package/dist/adapters/pi/extension.mjs.map +1 -0
- package/dist/adapters/pi/leader.cjs +2 -0
- package/dist/adapters/pi/leader.cjs.map +1 -0
- package/dist/adapters/pi/leader.mjs +2 -0
- package/dist/adapters/pi/leader.mjs.map +1 -0
- package/dist/adapters/pi/workflow/piExtension.cjs +11 -0
- package/dist/adapters/pi/workflow/piExtension.cjs.map +1 -0
- package/dist/adapters/pi/workflow/piExtension.mjs +11 -0
- package/dist/adapters/pi/workflow/piExtension.mjs.map +1 -0
- package/dist/{workflow → adapters/pi/workflow}/piToolBridge.cjs +1 -1
- package/dist/adapters/pi/workflow/piToolBridge.cjs.map +1 -0
- package/dist/{workflow → adapters/pi/workflow}/piToolBridge.mjs +1 -1
- package/dist/adapters/pi/workflow/piToolBridge.mjs.map +1 -0
- package/dist/adapters/pi/workflow/piTools.cjs +5 -0
- package/dist/adapters/pi/workflow/piTools.cjs.map +1 -0
- package/dist/adapters/pi/workflow/piTools.mjs +5 -0
- package/dist/adapters/pi/workflow/piTools.mjs.map +1 -0
- package/dist/adapters/pi/workflow/workflowLauncher.cjs +2 -0
- package/dist/adapters/pi/workflow/workflowLauncher.cjs.map +1 -0
- package/dist/adapters/pi/workflow/workflowLauncher.mjs +2 -0
- package/dist/adapters/pi/workflow/workflowLauncher.mjs.map +1 -0
- package/dist/extensions/dispatcher.cjs +1 -1
- package/dist/extensions/dispatcher.cjs.map +1 -1
- package/dist/extensions/dispatcher.d.cts +1 -1
- package/dist/extensions/dispatcher.d.mts +1 -1
- package/dist/extensions/dispatcher.mjs +1 -1
- package/dist/extensions/dispatcher.mjs.map +1 -1
- package/dist/extensions/pi.cjs +1 -1
- package/dist/extensions/pi.cjs.map +1 -1
- package/dist/extensions/pi.d.cts +1 -1
- package/dist/extensions/pi.d.mts +1 -1
- package/dist/extensions/pi.mjs +1 -1
- package/dist/extensions/pi.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/schemas/workflowPi.cjs +2 -0
- package/dist/schemas/workflowPi.cjs.map +1 -0
- package/dist/schemas/workflowPi.mjs +2 -0
- package/dist/schemas/workflowPi.mjs.map +1 -0
- package/dist/services/workflow/backgroundWork.cjs.map +1 -0
- package/dist/services/workflow/backgroundWork.mjs.map +1 -0
- package/dist/services/workflow/workflowNarration.cjs +2 -0
- package/dist/services/workflow/workflowNarration.cjs.map +1 -0
- package/dist/services/workflow/workflowNarration.mjs +2 -0
- package/dist/services/workflow/workflowNarration.mjs.map +1 -0
- package/dist/tui/workflow/doomOverlay.cjs.map +1 -0
- package/dist/tui/workflow/doomOverlay.mjs.map +1 -0
- package/dist/tui/workflow/overlayText.cjs.map +1 -0
- package/dist/tui/workflow/overlayText.mjs.map +1 -0
- package/dist/tui/workflow/rendering.cjs.map +1 -0
- package/dist/tui/workflow/rendering.mjs.map +1 -0
- package/dist/tui/workflow/workflowInspector.cjs +2 -0
- package/dist/{workflow/workflowInspector.mjs.map → tui/workflow/workflowInspector.cjs.map} +1 -1
- package/dist/tui/workflow/workflowInspector.mjs +2 -0
- package/dist/tui/workflow/workflowInspector.mjs.map +1 -0
- package/dist/tui/workflow/workflowOverlay.cjs.map +1 -0
- package/dist/tui/workflow/workflowOverlay.mjs.map +1 -0
- package/dist/tui/workflow/workflowPicker.cjs.map +1 -0
- package/dist/tui/workflow/workflowPicker.mjs.map +1 -0
- package/dist/tui/workflow/workflowProgressOverlay.cjs +2 -0
- package/dist/tui/workflow/workflowProgressOverlay.cjs.map +1 -0
- package/dist/tui/workflow/workflowProgressOverlay.mjs +2 -0
- package/dist/tui/workflow/workflowProgressOverlay.mjs.map +1 -0
- package/dist/tui/workflow/workflowPrompt.cjs.map +1 -0
- package/dist/tui/workflow/workflowPrompt.mjs.map +1 -0
- package/dist/tui/workflow/workflowRunPanel.cjs.map +1 -0
- package/dist/tui/workflow/workflowRunPanel.mjs.map +1 -0
- package/dist/tui/workflow/workflowStatusRow.cjs +2 -0
- package/dist/tui/workflow/workflowStatusRow.cjs.map +1 -0
- package/dist/tui/workflow/workflowStatusRow.mjs +2 -0
- package/dist/tui/workflow/workflowStatusRow.mjs.map +1 -0
- package/dist/tui/workflow/workflowStepMessage.cjs +2 -0
- package/dist/tui/workflow/workflowStepMessage.cjs.map +1 -0
- package/dist/tui/workflow/workflowStepMessage.mjs +2 -0
- package/dist/tui/workflow/workflowStepMessage.mjs.map +1 -0
- package/dist/tui/workflow/workflowToolRender.cjs +7 -0
- package/dist/tui/workflow/workflowToolRender.cjs.map +1 -0
- package/dist/tui/workflow/workflowToolRender.mjs +7 -0
- package/dist/tui/workflow/workflowToolRender.mjs.map +1 -0
- package/dist/{types.cjs → types/index.cjs} +1 -1
- package/dist/types/index.cjs.map +1 -0
- package/dist/{types.mjs → types/index.mjs} +1 -1
- package/dist/types/index.mjs.map +1 -0
- package/llms.txt +8 -0
- package/package.json +20 -11
- package/dist/dispatcher.cjs.map +0 -1
- package/dist/dispatcher.d.cts.map +0 -1
- package/dist/dispatcher.d.mts.map +0 -1
- package/dist/dispatcher.mjs.map +0 -1
- package/dist/extension.cjs +0 -2
- package/dist/extension.cjs.map +0 -1
- package/dist/extension.d.cts.map +0 -1
- package/dist/extension.d.mts.map +0 -1
- package/dist/extension.mjs +0 -2
- package/dist/extension.mjs.map +0 -1
- package/dist/leader.cjs +0 -2
- package/dist/leader.cjs.map +0 -1
- package/dist/leader.mjs +0 -2
- package/dist/leader.mjs.map +0 -1
- package/dist/types.cjs.map +0 -1
- package/dist/types.mjs.map +0 -1
- package/dist/workflow/backgroundWork.cjs.map +0 -1
- package/dist/workflow/backgroundWork.mjs.map +0 -1
- package/dist/workflow/doomOverlay.cjs.map +0 -1
- package/dist/workflow/doomOverlay.mjs.map +0 -1
- package/dist/workflow/overlayText.cjs.map +0 -1
- package/dist/workflow/overlayText.mjs.map +0 -1
- package/dist/workflow/piExtension.cjs +0 -11
- package/dist/workflow/piExtension.cjs.map +0 -1
- package/dist/workflow/piExtension.mjs +0 -11
- package/dist/workflow/piExtension.mjs.map +0 -1
- package/dist/workflow/piToolBridge.cjs.map +0 -1
- package/dist/workflow/piToolBridge.mjs.map +0 -1
- package/dist/workflow/piTools.cjs +0 -4
- package/dist/workflow/piTools.cjs.map +0 -1
- package/dist/workflow/piTools.mjs +0 -4
- package/dist/workflow/piTools.mjs.map +0 -1
- package/dist/workflow/rendering.cjs.map +0 -1
- package/dist/workflow/rendering.mjs.map +0 -1
- package/dist/workflow/workflowFooterStatus.cjs +0 -2
- package/dist/workflow/workflowFooterStatus.cjs.map +0 -1
- package/dist/workflow/workflowFooterStatus.mjs +0 -2
- package/dist/workflow/workflowFooterStatus.mjs.map +0 -1
- package/dist/workflow/workflowInspector.cjs +0 -2
- package/dist/workflow/workflowInspector.cjs.map +0 -1
- package/dist/workflow/workflowInspector.mjs +0 -2
- package/dist/workflow/workflowLauncher.cjs +0 -2
- package/dist/workflow/workflowLauncher.cjs.map +0 -1
- package/dist/workflow/workflowLauncher.mjs +0 -2
- package/dist/workflow/workflowLauncher.mjs.map +0 -1
- package/dist/workflow/workflowOverlay.cjs.map +0 -1
- package/dist/workflow/workflowOverlay.mjs.map +0 -1
- package/dist/workflow/workflowPicker.cjs.map +0 -1
- package/dist/workflow/workflowPicker.mjs.map +0 -1
- package/dist/workflow/workflowPrompt.cjs.map +0 -1
- package/dist/workflow/workflowPrompt.mjs.map +0 -1
- package/dist/workflow/workflowRunPanel.cjs.map +0 -1
- package/dist/workflow/workflowRunPanel.mjs.map +0 -1
- package/dist/workflow/workflowStatusRow.cjs +0 -2
- package/dist/workflow/workflowStatusRow.cjs.map +0 -1
- package/dist/workflow/workflowStatusRow.mjs +0 -2
- package/dist/workflow/workflowStatusRow.mjs.map +0 -1
- package/dist/workflow/workflowStepMessage.cjs +0 -2
- package/dist/workflow/workflowStepMessage.cjs.map +0 -1
- package/dist/workflow/workflowStepMessage.mjs +0 -2
- package/dist/workflow/workflowStepMessage.mjs.map +0 -1
- /package/dist/{dispatcher.cjs → adapters/pi/dispatcher.cjs} +0 -0
- /package/dist/{dispatcher.mjs → adapters/pi/dispatcher.mjs} +0 -0
- /package/dist/{workflow → services/workflow}/backgroundWork.cjs +0 -0
- /package/dist/{workflow → services/workflow}/backgroundWork.mjs +0 -0
- /package/dist/{workflow → tui/workflow}/doomOverlay.cjs +0 -0
- /package/dist/{workflow → tui/workflow}/doomOverlay.mjs +0 -0
- /package/dist/{workflow → tui/workflow}/overlayText.cjs +0 -0
- /package/dist/{workflow → tui/workflow}/overlayText.mjs +0 -0
- /package/dist/{workflow → tui/workflow}/rendering.cjs +0 -0
- /package/dist/{workflow → tui/workflow}/rendering.mjs +0 -0
- /package/dist/{workflow → tui/workflow}/workflowOverlay.cjs +0 -0
- /package/dist/{workflow → tui/workflow}/workflowOverlay.mjs +0 -0
- /package/dist/{workflow → tui/workflow}/workflowPicker.cjs +0 -0
- /package/dist/{workflow → tui/workflow}/workflowPicker.mjs +0 -0
- /package/dist/{workflow → tui/workflow}/workflowPrompt.cjs +0 -0
- /package/dist/{workflow → tui/workflow}/workflowPrompt.mjs +0 -0
- /package/dist/{workflow → tui/workflow}/workflowRunPanel.cjs +0 -0
- /package/dist/{workflow → tui/workflow}/workflowRunPanel.mjs +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
let e=require("@agimon-ai/doompi-ui/toolChrome");function t(e){if(!(!e||typeof e!=`object`||Array.isArray(e)))return e}function n(e){let t=``;for(let n of e){let e=n.codePointAt(0)??0;t+=e<=31||e===127?` `:n}return t.replace(/\s+/gu,` `).trim()}function r(e,t){let r=e?.[t];if(typeof r==`string`)return n(r)||void 0}function i(e,t){let n=e?.[t];return typeof n==`number`&&Number.isFinite(n)?n:void 0}function a(e,t){let n=e?.[t];return typeof n==`boolean`?n:void 0}function o(e,t){let n=e?.[t];return Array.isArray(n)?n.filter(e=>typeof e==`string`):[]}function s(e){if(e)try{return t(JSON.parse(e))}catch{return}}function c(e){return Array.isArray(e.content)?e.content.flatMap(e=>{let n=t(e);return n?.type===`text`&&typeof n.text==`string`?[n.text]:[]}):[]}function l(e){return c(e).flatMap(e=>e.split(`
|
|
2
|
+
`)).map(e=>e.trimEnd()).filter(e=>e.length>0)}function u(e){return s(c(e)[0])}function d(e,t,n=`${t}s`){return e===1?t:n}function f(e,t,n){return`${n.fg(`dim`,`${e} `)}${n.fg(`text`,t)}`}function p(e){let t=r(e,`runKey`);if(!t)return;let n=r(e,`workspace`);return n?`${n}/${t}`:t}function m(e,t){return e===`list_workflows`?`list`:e===`launch_workflow`?`launch`:r(t,`action`)??`run`}function h(e,t){return e===`list_workflows`?r(t,`directory`):e===`launch_workflow`?r(t,`workflowPath`):p(t)}function g(t,n,r){return new e.DoomToolResult(t,n,{wrap:r})}function _(e,t){return t.fg(`dim`,`… ${e} more · ctrl+o`)}function v(e){return e.replace(`T`,` `).replace(/\.\d{3}Z$/,`Z`)}function y(e){if(!e)return`workflow`;let t=e.split(`/`).at(-1)??e;return t.replace(/\.workflow\.ya?ml$/u,``)||t}function b(e,n,s){let c=[];if(e===`list_workflows`){let e=i(n,`page`),t=i(n,`pageSize`);e!==void 0&&c.push(`page ${e}`),t!==void 0&&c.push(`${t}/page`),r(n,`filter`)&&c.push(`filtered`);let a=o(n,`tags`);a.length>0&&c.push(`${a.length} ${d(a.length,`tag`)}`)}else if(e===`launch_workflow`){let e=r(n,`job`),i=r(n,`runner`),o=r(n,`workspace`),s=Object.keys(t(n.inputs)??{}).length,l=Object.keys(t(n.env)??{}).length;o&&c.push(`workspace ${o}`),e&&c.push(`job ${e}`),i&&c.push(`runner ${i}`),a(n,`dryRun`)&&c.push(`dry run`),r(n,`prompt`)&&c.push(`with prompt`),s>0&&c.push(`${s} ${d(s,`input`)}`),l>0&&c.push(`${l} env`)}else r(n,`expectedRunId`)&&c.push(`generation checked`),r(n,`reason`)&&c.push(`with reason`),a(n,`dryRun`)&&c.push(`dry run`),r(n,`job`)&&c.push(`job override`),r(n,`runner`)&&c.push(`runner override`);return c.map(e=>s.fg(`dim`,e))}function x(t,n,r){let i=m(t,n),a=h(t,n),o=b(t,n,r),s=[r.bold(i),a?r.fg(`muted`,a):void 0,...o].filter(e=>!!e).join(r.fg(`dim`,` · `));return new e.DoomToolCall((0,e.renderToolHeading)(`workflow`,s,r))}function S(e){if(!Array.isArray(e?.workflows))return;let n=e.workflows.flatMap(e=>{let n=t(e),i=r(n,`path`);return!n||!i?[]:[{description:r(n,`description`)??``,name:r(n,`name`)??``,path:i,tags:o(n,`tags`)}]}),a=Array.isArray(e.tags)?e.tags.flatMap(e=>{let n=t(e),a=r(n,`tag`),o=i(n,`count`);return a&&o!==void 0?[{count:o,tag:a}]:[]}):[];return{directory:r(e,`directory`),page:i(e,`page`)??1,pageSize:i(e,`pageSize`)??n.length,tags:a,total:i(e,`total`)??n.length,totalPages:i(e,`totalPages`)??+(n.length>0),workflows:n}}function C(e,t,n){let r=e.name||y(e.path),i=[`${n.fg(`accent`,`›`)} ${n.bold(r)} ${n.fg(`muted`,`· ${e.path}`)}`];return t?(e.description&&i.push(` ${n.fg(`text`,e.description)}`),e.tags.length>0&&i.push(` ${f(`tags`,e.tags.join(`, `),n)}`),i):i}function w(e,t,n){let r=S(u(e));if(!r)return;let i=`page ${r.page}/${r.totalPages}`,a=`${n.fg(r.total>0?`success`:`muted`,r.total>0?`✓`:`○`)} ${n.bold(`${r.total} ${d(r.total,`workflow`)}`)} ${n.fg(`dim`,`· ${i}`)}`,o=t.expanded?r.workflows:r.workflows.slice(0,6),s=[a,...o.flatMap(e=>C(e,t.expanded,n))],c=r.workflows.length-o.length;if(c>0&&s.push(_(c,n)),t.expanded){if(r.tags.length>0){let e=r.tags.map(({count:e,tag:t})=>`${t} (${e})`).join(`, `);s.push(f(`available tags`,e,n))}r.directory&&s.push(f(`directory`,r.directory,n)),s.push(f(`page size`,String(r.pageSize),n))}return g(s,n,t.expanded)}function T(e){let t=r(e,`effectiveStage`)??r(e,`stage`)??`unknown`,n=r(e,`effectiveOutcome`)??r(e,`outcome`),i=r(e,`executionState`);return n===`interrupted`?{color:`warning`,glyph:`!`,label:`interrupted`}:t===`error`||n===`failed`?{color:`error`,glyph:`✗`,label:`failed`}:t===`completed`&&n===`skipped`?{color:`muted`,glyph:`○`,label:`skipped`}:t===`completed`?{color:`success`,glyph:`✓`,label:`completed`}:i===`paused`?{color:`warning`,glyph:`Ⅱ`,label:`paused`}:i===`pause_requested`?{color:`warning`,glyph:`◐`,label:`pause requested`}:i===`resume_requested`?{color:`warning`,glyph:`◐`,label:`resume requested`}:t===`running`?{color:`accent`,glyph:`◐`,label:`running`}:{color:`muted`,glyph:`○`,label:t}}function E(e){let t=r(e,`runKey`)??`unknown run`,n=r(e,`workspace`);return n?`${n}/${t}`:t}function D(e,n){let i=t(e.executionCursor),a=r(i,`job`)??r(e,`job`),o=r(i,`stepName`),s=r(i,`phase`);if(!a&&!o&&!s)return;let c=a??s??`workflow`;return` ${n.fg(`muted`,`[${c}]`)} ${n.fg(`text`,o??s??`running`)}`}function O(e){let n=t(e.launcher),i=r(n,`type`);if(!i)return;let a=r(n,`sessionName`)??r(n,`workspaceId`);return a?`${i} ${a}`:i}function k(e,t,n){let o=r(e,`runKey`),s=r(e,`stage`);if(!o||!s)return;let c=T(e),l=r(e,`displayName`)??o,u=[`${n.fg(c.color,c.glyph)} ${n.bold(l)} ${n.fg(`dim`,`· ${E(e)} ·`)} ${n.fg(c.color,c.label)}`],d=D(e,n);d&&u.push(d);let p=r(e,`errorMessage`)??r(e,`failureReason`);p&&u.push(`${n.fg(`error`,`error`)} ${n.fg(`text`,p)}`);let m=r(e,`staleReason`);m&&u.push(`${n.fg(`warning`,`stale`)} ${n.fg(`text`,m)}`);let h=[r(e,`runner`)?`runner ${r(e,`runner`)}`:void 0,a(e,`dryRun`)?`dry run`:void 0,i(e,`exitCode`)===void 0?void 0:`exit ${i(e,`exitCode`)}`,r(e,`startedAt`)?`started ${v(r(e,`startedAt`)??``)}`:void 0].filter(e=>!!e);if(h.length>0&&u.push(n.fg(`dim`,h.join(` · `))),!t)return u;let g=[[`workflow`,r(e,`workflowPath`)],[`workflow id`,r(e,`workflowId`)],[`run id`,r(e,`runId`)],[`launcher`,O(e)],[`job`,r(e,`job`)],[`outcome`,r(e,`effectiveOutcome`)??r(e,`outcome`)],[`finished`,r(e,`finishedAt`)?v(r(e,`finishedAt`)??``):void 0],[`pid`,i(e,`pid`)?.toString()],[`repair`,r(e,`activeRepairId`)?`#${r(e,`activeRepairId`)}`:void 0],[`worktree`,r(e,`worktreeBranch`)??r(e,`worktreePath`)]];for(let[e,t]of g)t&&u.push(f(e,t,n));return u}function A(e,t,n){let r=u(e);if(!r)return;let i=k(r,t.expanded,n);return i?g(i,n,t.expanded):void 0}function j(e){return r(t(e?.request),`requestedAt`)??r(e,`requestedAt`)}function M(e,t,n,i,a){let o=u(n),s=p(t)??r(o,`runKey`)??`workflow`,c=r(o,`workspace`),l=c&&!s.includes(`/`)?`${c}/${s}`:s,d=[`${a.fg(`warning`,`◐`)} ${a.bold(`${e} requested`)} ${a.fg(`dim`,`· ${l}`)}`],m=j(o);return m&&d.push(f(`requested`,v(m),a)),i.expanded&&d.push(a.fg(`dim`,`verify the transition with workflow_run status`)),g(d,a,i.expanded)}function N(e,t){return e.match(t)?.[1]?.trim()}function P(e,t){let n=N(e,/^Started (.+) in workspace .+\.$/mu),i=N(e,/^Started .+ in workspace (.+)\.$/mu)??r(t,`workspace`),a=N(e,/^Run key:\s*(.+)$/mu),o=r(t,`workflowPath`),s=n??y(o),c=a?i?`${i}/${a}`:a:i??o??`workflow`;return/Workflow completed successfully/iu.test(e)?{name:s,scope:c,state:{color:`success`,glyph:`✓`,label:`completed`}}:/Workflow skipped/iu.test(e)?{name:s,scope:c,state:{color:`muted`,glyph:`○`,label:`skipped`}}:/no run was registered/iu.test(e)?{name:s,scope:c,state:{color:`warning`,glyph:`◐`,label:`starting · run key pending`}}:{name:s,scope:c,state:{color:`accent`,glyph:`◐`,label:a?`started`:`launch accepted`}}}function F(e,t,n,i){let o=P(c(t).join(`
|
|
3
|
+
`),e),s=[`${i.fg(o.state.color,o.state.glyph)} ${i.bold(o.name)} ${i.fg(`dim`,`· ${o.scope} ·`)} ${i.fg(o.state.color,o.state.label)}`],u=[r(e,`job`)?`job ${r(e,`job`)}`:void 0,r(e,`runner`)?`runner ${r(e,`runner`)}`:void 0,a(e,`dryRun`)?`dry run`:void 0].filter(e=>!!e);if(u.length>0&&s.push(i.fg(`dim`,u.join(` · `))),n.expanded){let e=l(t).filter(e=>!e.startsWith(`Next steps for the agent:`));e.length>0&&s.push(...e)}return g(s,i,n.expanded)}function I(e){let t=[],n;for(let r of e.split(`
|
|
4
|
+
`)){let e=r.match(/^--- (.+) ---$/u);if(e?.[1]){n={body:[],name:e[1]},t.push(n);continue}n?.body.push(r)}return t}function L(e){return s(e.find(e=>e.name===`run.json`)?.body.join(`
|
|
5
|
+
`))}function R(e,t,n,r){let i=I(c(t).join(`
|
|
6
|
+
`)),a=L(i),o=a?k(a,n.expanded,r):void 0,s=i.filter(e=>e.name!==`run.json`),l=p(e)??`workflow`,u=o??[`${r.fg(`success`,`✓`)} ${r.bold(`recovery evidence`)} ${r.fg(`dim`,`· ${l}`)}`],d=s.map(e=>e.name);if(u.push(d.length>0?f(`evidence`,d.join(`, `),r):r.fg(`muted`,`no durable evidence files recorded`)),n.expanded)for(let e of s)u.push(r.bold(e.name),...e.body.filter(e=>e.length>0));return g(u,r,n.expanded)}function z(e,t,n,r,i){let o=p(t)??`workflow`,s={follow:`following output`,open:`launcher opened`,recover:a(t,`dryRun`)?`recovery dry run finished`:`recovery accepted`,tail:`launcher output checked`},c=e===`recover`?{color:`accent`,glyph:`◐`,label:s[e]??e}:{color:`success`,glyph:`✓`,label:s[e]??e},u=[`${i.fg(c.color,c.glyph)} ${i.bold(c.label)} ${i.fg(`dim`,`· ${o}`)}`],d=l(n);if(e===`tail`){let e=d.find(e=>e.startsWith(`Stage:`)),t=d.find(e=>e.startsWith(`Workflow:`));t&&u.push(t),e&&u.push(e)}return r.expanded&&d.length>0&&u.push(...d),g(u,i,r.expanded)}function B(e,t,n,r,i){let a=m(e,t),o=h(e,t),s=`${i.fg(`error`,`✗`)} ${i.bold(`${a} failed`)}${o?i.fg(`dim`,` · ${o}`):``}`,c=l(n),u=r.expanded?c:c.slice(0,8),d=[s,...u.length>0?u:[i.fg(`error`,`Unknown workflow error`)]],f=c.length-u.length;return f>0&&d.push(_(f,i)),g(d,i,r.expanded)}function V(e,t,n,r,i){let a=l(n),o=a.slice(-4),s=m(e,t),c=h(e,t),u=`${i.fg(`accent`,`◐`)} ${i.bold(s)}${c?i.fg(`dim`,` · ${c}`):``}`,d=a.length-o.length,f=[u];return d>0&&f.push(i.fg(`dim`,`… ${d} earlier`)),f.push(...o),g(f,i,r.expanded)}function H(e,t,n){let r=l(e);if(r.length===0)return g([n.fg(`muted`,`No workflow output.`)],n,t.expanded);let i=t.expanded?r:r.slice(0,8),a=[...i],o=r.length-i.length;return o>0&&a.push(_(o,n)),g(a,n,t.expanded)}function U(e,t,n,i,a){if(i.isPartial)return V(e,t,n,i,a);if(i.isError===!0||n.isError===!0)return B(e,t,n,i,a);if(e===`list_workflows`)return w(n,i,a)??H(n,i,a);if(e===`launch_workflow`)return F(t,n,i,a);let o=r(t,`action`);return o===`status`?A(n,i,a)??H(n,i,a):o===`pause`||o===`resume`||o===`stop`?M(o,t,n,i,a):o===`recovery-evidence`?R(t,n,i,a):o===`follow`||o===`open`||o===`recover`||o===`tail`?z(o,t,n,i,a):H(n,i,a)}exports.renderWorkflowToolCall=x,exports.renderWorkflowToolResult=U;
|
|
7
|
+
//# sourceMappingURL=workflowToolRender.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflowToolRender.cjs","names":["DoomToolResult","DoomToolCall","renderToolHeading"],"sources":["../../../src/tui/workflow/workflowToolRender.ts"],"sourcesContent":["import { DoomToolCall, DoomToolResult, renderToolHeading } from '@agimon-ai/doompi-ui/toolChrome';\nimport type { Theme, ThemeColor } from '@earendil-works/pi-coding-agent';\nimport type { Component } from '@earendil-works/pi-tui';\n\nexport type WorkflowToolName = 'launch_workflow' | 'list_workflows' | 'workflow_run';\nexport type WorkflowPiToolName = WorkflowToolName;\n\ninterface WorkflowToolResultLike {\n content?: unknown;\n isError?: boolean;\n}\n\ninterface WorkflowToolRenderOptions {\n expanded: boolean;\n isError?: boolean;\n isPartial?: boolean;\n}\n\ntype JsonRecord = Record<string, unknown>;\n\ntype WorkflowState = {\n color: ThemeColor;\n glyph: string;\n label: string;\n};\n\ninterface WorkflowCatalogItem {\n description: string;\n name: string;\n path: string;\n tags: string[];\n}\n\ninterface WorkflowCatalog {\n directory?: string;\n page: number;\n pageSize: number;\n tags: Array<{ count: number; tag: string }>;\n total: number;\n totalPages: number;\n workflows: WorkflowCatalogItem[];\n}\n\ninterface EvidenceSection {\n body: string[];\n name: string;\n}\n\nconst COLLAPSED_CATALOG_ROWS = 6;\nconst COLLAPSED_DETAIL_LINES = 8;\nconst PARTIAL_DETAIL_LINES = 4;\n\nfunction asRecord(value: unknown): JsonRecord | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined;\n return value as JsonRecord;\n}\n\nfunction inlineText(value: string): string {\n let normalized = '';\n for (const character of value) {\n const code = character.codePointAt(0) ?? 0;\n normalized += code <= 31 || code === 127 ? ' ' : character;\n }\n return normalized.replace(/\\s+/gu, ' ').trim();\n}\n\nfunction readString(record: JsonRecord | undefined, key: string): string | undefined {\n const value = record?.[key];\n if (typeof value !== 'string') return undefined;\n return inlineText(value) || undefined;\n}\n\nfunction readNumber(record: JsonRecord | undefined, key: string): number | undefined {\n const value = record?.[key];\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction readBoolean(record: JsonRecord | undefined, key: string): boolean | undefined {\n const value = record?.[key];\n return typeof value === 'boolean' ? value : undefined;\n}\n\nfunction readStringArray(record: JsonRecord | undefined, key: string): string[] {\n const value = record?.[key];\n if (!Array.isArray(value)) return [];\n return value.filter((item): item is string => typeof item === 'string');\n}\n\nfunction parseJsonRecord(text: string | undefined): JsonRecord | undefined {\n if (!text) return undefined;\n try {\n return asRecord(JSON.parse(text));\n } catch {\n return undefined;\n }\n}\n\nfunction textBlocks(result: WorkflowToolResultLike): string[] {\n if (!Array.isArray(result.content)) return [];\n return result.content.flatMap((item) => {\n const record = asRecord(item);\n return record?.type === 'text' && typeof record.text === 'string' ? [record.text] : [];\n });\n}\n\nfunction detailLines(result: WorkflowToolResultLike): string[] {\n return textBlocks(result)\n .flatMap((block) => block.split('\\n'))\n .map((line) => line.trimEnd())\n .filter((line) => line.length > 0);\n}\n\nfunction firstPayload(result: WorkflowToolResultLike): JsonRecord | undefined {\n return parseJsonRecord(textBlocks(result)[0]);\n}\n\nfunction plural(count: number, singular: string, pluralForm = `${singular}s`): string {\n return count === 1 ? singular : pluralForm;\n}\n\nfunction labelValue(label: string, value: string, theme: Theme): string {\n return `${theme.fg('dim', `${label} `)}${theme.fg('text', value)}`;\n}\n\nfunction targetScope(args: Record<string, unknown>): string | undefined {\n const runKey = readString(args, 'runKey');\n if (!runKey) return undefined;\n const workspace = readString(args, 'workspace');\n return workspace ? `${workspace}/${runKey}` : runKey;\n}\n\nfunction toolAction(toolName: WorkflowPiToolName, args: Record<string, unknown>): string {\n if (toolName === 'list_workflows') return 'list';\n if (toolName === 'launch_workflow') return 'launch';\n return readString(args, 'action') ?? 'run';\n}\n\nfunction toolTarget(toolName: WorkflowPiToolName, args: Record<string, unknown>): string | undefined {\n if (toolName === 'list_workflows') return readString(args, 'directory');\n if (toolName === 'launch_workflow') return readString(args, 'workflowPath');\n return targetScope(args);\n}\n\nfunction renderResult(lines: readonly string[], theme: Theme, expanded: boolean): Component {\n return new DoomToolResult(lines, theme, { wrap: expanded });\n}\n\nfunction hiddenDetailLine(hidden: number, theme: Theme): string {\n return theme.fg('dim', `… ${hidden} more · ctrl+o`);\n}\n\nfunction statusTimestamp(value: string): string {\n return value.replace('T', ' ').replace(/\\.\\d{3}Z$/, 'Z');\n}\n\nfunction workflowNameFromPath(path: string | undefined): string {\n if (!path) return 'workflow';\n const filename = path.split('/').at(-1) ?? path;\n return filename.replace(/\\.workflow\\.ya?ml$/u, '') || filename;\n}\n\nfunction callMetadata(toolName: WorkflowPiToolName, args: Record<string, unknown>, theme: Theme): string[] {\n const values: string[] = [];\n\n if (toolName === 'list_workflows') {\n const page = readNumber(args, 'page');\n const pageSize = readNumber(args, 'pageSize');\n if (page !== undefined) values.push(`page ${page}`);\n if (pageSize !== undefined) values.push(`${pageSize}/page`);\n if (readString(args, 'filter')) values.push('filtered');\n const tags = readStringArray(args, 'tags');\n if (tags.length > 0) values.push(`${tags.length} ${plural(tags.length, 'tag')}`);\n } else if (toolName === 'launch_workflow') {\n const job = readString(args, 'job');\n const runner = readString(args, 'runner');\n const workspace = readString(args, 'workspace');\n const inputCount = Object.keys(asRecord(args.inputs) ?? {}).length;\n const environmentCount = Object.keys(asRecord(args.env) ?? {}).length;\n if (workspace) values.push(`workspace ${workspace}`);\n if (job) values.push(`job ${job}`);\n if (runner) values.push(`runner ${runner}`);\n if (readBoolean(args, 'dryRun')) values.push('dry run');\n if (readString(args, 'prompt')) values.push('with prompt');\n if (inputCount > 0) values.push(`${inputCount} ${plural(inputCount, 'input')}`);\n if (environmentCount > 0) values.push(`${environmentCount} env`);\n } else {\n const expectedRunId = readString(args, 'expectedRunId');\n if (expectedRunId) values.push('generation checked');\n if (readString(args, 'reason')) values.push('with reason');\n if (readBoolean(args, 'dryRun')) values.push('dry run');\n if (readString(args, 'job')) values.push('job override');\n if (readString(args, 'runner')) values.push('runner override');\n }\n\n return values.map((value) => theme.fg('dim', value));\n}\n\nexport function renderWorkflowToolCall(\n toolName: WorkflowPiToolName,\n args: Record<string, unknown>,\n theme: Theme,\n): Component {\n const action = toolAction(toolName, args);\n const target = toolTarget(toolName, args);\n const metadata = callMetadata(toolName, args, theme);\n const purpose = [theme.bold(action), target ? theme.fg('muted', target) : undefined, ...metadata]\n .filter((part): part is string => !!part)\n .join(theme.fg('dim', ' · '));\n return new DoomToolCall(renderToolHeading('workflow', purpose, theme));\n}\n\nfunction parseCatalog(payload: JsonRecord | undefined): WorkflowCatalog | undefined {\n if (!Array.isArray(payload?.workflows)) return undefined;\n\n const workflows = payload.workflows.flatMap((value) => {\n const record = asRecord(value);\n const path = readString(record, 'path');\n if (!record || !path) return [];\n return [\n {\n description: readString(record, 'description') ?? '',\n name: readString(record, 'name') ?? '',\n path,\n tags: readStringArray(record, 'tags'),\n },\n ];\n });\n const tags = Array.isArray(payload.tags)\n ? payload.tags.flatMap((value) => {\n const record = asRecord(value);\n const tag = readString(record, 'tag');\n const count = readNumber(record, 'count');\n return tag && count !== undefined ? [{ count, tag }] : [];\n })\n : [];\n\n return {\n directory: readString(payload, 'directory'),\n page: readNumber(payload, 'page') ?? 1,\n pageSize: readNumber(payload, 'pageSize') ?? workflows.length,\n tags,\n total: readNumber(payload, 'total') ?? workflows.length,\n totalPages: readNumber(payload, 'totalPages') ?? (workflows.length > 0 ? 1 : 0),\n workflows,\n };\n}\n\nfunction catalogItemLines(item: WorkflowCatalogItem, expanded: boolean, theme: Theme): string[] {\n const name = item.name || workflowNameFromPath(item.path);\n const lines = [`${theme.fg('accent', '›')} ${theme.bold(name)} ${theme.fg('muted', `· ${item.path}`)}`];\n if (!expanded) return lines;\n if (item.description) lines.push(` ${theme.fg('text', item.description)}`);\n if (item.tags.length > 0) lines.push(` ${labelValue('tags', item.tags.join(', '), theme)}`);\n return lines;\n}\n\nfunction renderCatalogResult(\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component | undefined {\n const catalog = parseCatalog(firstPayload(result));\n if (!catalog) return undefined;\n\n const pageLabel = `page ${catalog.page}/${catalog.totalPages}`;\n const summary = `${theme.fg(catalog.total > 0 ? 'success' : 'muted', catalog.total > 0 ? '✓' : '○')} ${theme.bold(\n `${catalog.total} ${plural(catalog.total, 'workflow')}`,\n )} ${theme.fg('dim', `· ${pageLabel}`)}`;\n const shown = options.expanded ? catalog.workflows : catalog.workflows.slice(0, COLLAPSED_CATALOG_ROWS);\n const lines = [summary, ...shown.flatMap((item) => catalogItemLines(item, options.expanded, theme))];\n const hidden = catalog.workflows.length - shown.length;\n if (hidden > 0) lines.push(hiddenDetailLine(hidden, theme));\n\n if (options.expanded) {\n if (catalog.tags.length > 0) {\n const tags = catalog.tags.map(({ count, tag }) => `${tag} (${count})`).join(', ');\n lines.push(labelValue('available tags', tags, theme));\n }\n if (catalog.directory) lines.push(labelValue('directory', catalog.directory, theme));\n lines.push(labelValue('page size', String(catalog.pageSize), theme));\n }\n\n return renderResult(lines, theme, options.expanded);\n}\n\nfunction readWorkflowState(record: JsonRecord): WorkflowState {\n const stage = readString(record, 'effectiveStage') ?? readString(record, 'stage') ?? 'unknown';\n const outcome = readString(record, 'effectiveOutcome') ?? readString(record, 'outcome');\n const executionState = readString(record, 'executionState');\n\n if (outcome === 'interrupted') return { color: 'warning', glyph: '!', label: 'interrupted' };\n if (stage === 'error' || outcome === 'failed') return { color: 'error', glyph: '✗', label: 'failed' };\n if (stage === 'completed' && outcome === 'skipped') return { color: 'muted', glyph: '○', label: 'skipped' };\n if (stage === 'completed') return { color: 'success', glyph: '✓', label: 'completed' };\n if (executionState === 'paused') return { color: 'warning', glyph: 'Ⅱ', label: 'paused' };\n if (executionState === 'pause_requested') return { color: 'warning', glyph: '◐', label: 'pause requested' };\n if (executionState === 'resume_requested') return { color: 'warning', glyph: '◐', label: 'resume requested' };\n if (stage === 'running') return { color: 'accent', glyph: '◐', label: 'running' };\n return { color: 'muted', glyph: '○', label: stage };\n}\n\nfunction recordScope(record: JsonRecord): string {\n const runKey = readString(record, 'runKey') ?? 'unknown run';\n const workspace = readString(record, 'workspace');\n return workspace ? `${workspace}/${runKey}` : runKey;\n}\n\nfunction currentActivity(record: JsonRecord, theme: Theme): string | undefined {\n const cursor = asRecord(record.executionCursor);\n const job = readString(cursor, 'job') ?? readString(record, 'job');\n const step = readString(cursor, 'stepName');\n const phase = readString(cursor, 'phase');\n if (!job && !step && !phase) return undefined;\n const context = job ?? phase ?? 'workflow';\n return ` ${theme.fg('muted', `[${context}]`)} ${theme.fg('text', step ?? phase ?? 'running')}`;\n}\n\nfunction launcherLabel(record: JsonRecord): string | undefined {\n const launcher = asRecord(record.launcher);\n const type = readString(launcher, 'type');\n if (!type) return undefined;\n const identity = readString(launcher, 'sessionName') ?? readString(launcher, 'workspaceId');\n return identity ? `${type} ${identity}` : type;\n}\n\nfunction workflowRecordLines(record: JsonRecord, expanded: boolean, theme: Theme): string[] | undefined {\n const runKey = readString(record, 'runKey');\n const stage = readString(record, 'stage');\n if (!runKey || !stage) return undefined;\n\n const state = readWorkflowState(record);\n const displayName = readString(record, 'displayName') ?? runKey;\n const heading = `${theme.fg(state.color, state.glyph)} ${theme.bold(displayName)} ${theme.fg(\n 'dim',\n `· ${recordScope(record)} ·`,\n )} ${theme.fg(state.color, state.label)}`;\n const lines = [heading];\n const activity = currentActivity(record, theme);\n if (activity) lines.push(activity);\n\n const failure = readString(record, 'errorMessage') ?? readString(record, 'failureReason');\n if (failure) lines.push(`${theme.fg('error', 'error')} ${theme.fg('text', failure)}`);\n const staleReason = readString(record, 'staleReason');\n if (staleReason) lines.push(`${theme.fg('warning', 'stale')} ${theme.fg('text', staleReason)}`);\n\n const conciseMetadata = [\n readString(record, 'runner') ? `runner ${readString(record, 'runner')}` : undefined,\n readBoolean(record, 'dryRun') ? 'dry run' : undefined,\n readNumber(record, 'exitCode') !== undefined ? `exit ${readNumber(record, 'exitCode')}` : undefined,\n readString(record, 'startedAt') ? `started ${statusTimestamp(readString(record, 'startedAt') ?? '')}` : undefined,\n ].filter((value): value is string => !!value);\n if (conciseMetadata.length > 0) lines.push(theme.fg('dim', conciseMetadata.join(' · ')));\n\n if (!expanded) return lines;\n\n const detailedValues: Array<[string, string | undefined]> = [\n ['workflow', readString(record, 'workflowPath')],\n ['workflow id', readString(record, 'workflowId')],\n ['run id', readString(record, 'runId')],\n ['launcher', launcherLabel(record)],\n ['job', readString(record, 'job')],\n ['outcome', readString(record, 'effectiveOutcome') ?? readString(record, 'outcome')],\n [\n 'finished',\n readString(record, 'finishedAt') ? statusTimestamp(readString(record, 'finishedAt') ?? '') : undefined,\n ],\n ['pid', readNumber(record, 'pid')?.toString()],\n ['repair', readString(record, 'activeRepairId') ? `#${readString(record, 'activeRepairId')}` : undefined],\n ['worktree', readString(record, 'worktreeBranch') ?? readString(record, 'worktreePath')],\n ];\n for (const [label, value] of detailedValues) {\n if (value) lines.push(labelValue(label, value, theme));\n }\n return lines;\n}\n\nfunction renderStatusResult(\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component | undefined {\n const payload = firstPayload(result);\n if (!payload) return undefined;\n const lines = workflowRecordLines(payload, options.expanded, theme);\n return lines ? renderResult(lines, theme, options.expanded) : undefined;\n}\n\nfunction nestedRequestedAt(payload: JsonRecord | undefined): string | undefined {\n return readString(asRecord(payload?.request), 'requestedAt') ?? readString(payload, 'requestedAt');\n}\n\nfunction renderControlResult(\n action: string,\n args: Record<string, unknown>,\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component {\n const payload = firstPayload(result);\n const scope = targetScope(args) ?? readString(payload, 'runKey') ?? 'workflow';\n const payloadWorkspace = readString(payload, 'workspace');\n const resolvedScope = payloadWorkspace && !scope.includes('/') ? `${payloadWorkspace}/${scope}` : scope;\n const lines = [\n `${theme.fg('warning', '◐')} ${theme.bold(`${action} requested`)} ${theme.fg('dim', `· ${resolvedScope}`)}`,\n ];\n const requestedAt = nestedRequestedAt(payload);\n if (requestedAt) lines.push(labelValue('requested', statusTimestamp(requestedAt), theme));\n if (options.expanded) lines.push(theme.fg('dim', 'verify the transition with workflow_run status'));\n return renderResult(lines, theme, options.expanded);\n}\n\nfunction matchLine(text: string, pattern: RegExp): string | undefined {\n return text.match(pattern)?.[1]?.trim();\n}\n\nfunction launchSummary(\n text: string,\n args: Record<string, unknown>,\n): { name: string; scope: string; state: WorkflowState } {\n const startedName = matchLine(text, /^Started (.+) in workspace .+\\.$/mu);\n const workspace = matchLine(text, /^Started .+ in workspace (.+)\\.$/mu) ?? readString(args, 'workspace');\n const runKey = matchLine(text, /^Run key:\\s*(.+)$/mu);\n const path = readString(args, 'workflowPath');\n const name = startedName ?? workflowNameFromPath(path);\n const scope = runKey ? (workspace ? `${workspace}/${runKey}` : runKey) : (workspace ?? path ?? 'workflow');\n\n if (/Workflow completed successfully/iu.test(text)) {\n return { name, scope, state: { color: 'success', glyph: '✓', label: 'completed' } };\n }\n if (/Workflow skipped/iu.test(text)) {\n return { name, scope, state: { color: 'muted', glyph: '○', label: 'skipped' } };\n }\n if (/no run was registered/iu.test(text)) {\n return { name, scope, state: { color: 'warning', glyph: '◐', label: 'starting · run key pending' } };\n }\n return { name, scope, state: { color: 'accent', glyph: '◐', label: runKey ? 'started' : 'launch accepted' } };\n}\n\nfunction renderLaunchResult(\n args: Record<string, unknown>,\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component {\n const blocks = textBlocks(result);\n const text = blocks.join('\\n');\n const summary = launchSummary(text, args);\n const lines = [\n `${theme.fg(summary.state.color, summary.state.glyph)} ${theme.bold(summary.name)} ${theme.fg(\n 'dim',\n `· ${summary.scope} ·`,\n )} ${theme.fg(summary.state.color, summary.state.label)}`,\n ];\n const metadata = [\n readString(args, 'job') ? `job ${readString(args, 'job')}` : undefined,\n readString(args, 'runner') ? `runner ${readString(args, 'runner')}` : undefined,\n readBoolean(args, 'dryRun') ? 'dry run' : undefined,\n ].filter((value): value is string => !!value);\n if (metadata.length > 0) lines.push(theme.fg('dim', metadata.join(' · ')));\n if (options.expanded) {\n const details = detailLines(result).filter((line) => !line.startsWith('Next steps for the agent:'));\n if (details.length > 0) lines.push(...details);\n }\n return renderResult(lines, theme, options.expanded);\n}\n\nfunction splitEvidence(text: string): EvidenceSection[] {\n const sections: EvidenceSection[] = [];\n let current: EvidenceSection | undefined;\n for (const line of text.split('\\n')) {\n const match = line.match(/^--- (.+) ---$/u);\n if (match?.[1]) {\n current = { body: [], name: match[1] };\n sections.push(current);\n continue;\n }\n current?.body.push(line);\n }\n return sections;\n}\n\nfunction recoveryRecord(sections: EvidenceSection[]): JsonRecord | undefined {\n const runSection = sections.find((section) => section.name === 'run.json');\n return parseJsonRecord(runSection?.body.join('\\n'));\n}\n\nfunction renderRecoveryEvidenceResult(\n args: Record<string, unknown>,\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component {\n const text = textBlocks(result).join('\\n');\n const sections = splitEvidence(text);\n const record = recoveryRecord(sections);\n const recordLines = record ? workflowRecordLines(record, options.expanded, theme) : undefined;\n const evidenceSections = sections.filter((section) => section.name !== 'run.json');\n const scope = targetScope(args) ?? 'workflow';\n const lines = recordLines ?? [\n `${theme.fg('success', '✓')} ${theme.bold('recovery evidence')} ${theme.fg('dim', `· ${scope}`)}`,\n ];\n const names = evidenceSections.map((section) => section.name);\n lines.push(\n names.length > 0\n ? labelValue('evidence', names.join(', '), theme)\n : theme.fg('muted', 'no durable evidence files recorded'),\n );\n\n if (options.expanded) {\n for (const section of evidenceSections) {\n lines.push(theme.bold(section.name), ...section.body.filter((line) => line.length > 0));\n }\n }\n return renderResult(lines, theme, options.expanded);\n}\n\nfunction renderSimpleActionResult(\n action: string,\n args: Record<string, unknown>,\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component {\n const scope = targetScope(args) ?? 'workflow';\n const actionLabel: Record<string, string> = {\n follow: 'following output',\n open: 'launcher opened',\n recover: readBoolean(args, 'dryRun') ? 'recovery dry run finished' : 'recovery accepted',\n tail: 'launcher output checked',\n };\n const state: WorkflowState =\n action === 'recover'\n ? { color: 'accent', glyph: '◐', label: actionLabel[action] ?? action }\n : { color: 'success', glyph: '✓', label: actionLabel[action] ?? action };\n const lines = [`${theme.fg(state.color, state.glyph)} ${theme.bold(state.label)} ${theme.fg('dim', `· ${scope}`)}`];\n const details = detailLines(result);\n if (action === 'tail') {\n const stageLine = details.find((line) => line.startsWith('Stage:'));\n const workflowLine = details.find((line) => line.startsWith('Workflow:'));\n if (workflowLine) lines.push(workflowLine);\n if (stageLine) lines.push(stageLine);\n }\n if (options.expanded && details.length > 0) lines.push(...details);\n return renderResult(lines, theme, options.expanded);\n}\n\nfunction renderFailure(\n toolName: WorkflowPiToolName,\n args: Record<string, unknown>,\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component {\n const action = toolAction(toolName, args);\n const target = toolTarget(toolName, args);\n const summary = `${theme.fg('error', '✗')} ${theme.bold(`${action} failed`)}${\n target ? theme.fg('dim', ` · ${target}`) : ''\n }`;\n const details = detailLines(result);\n const shown = options.expanded ? details : details.slice(0, COLLAPSED_DETAIL_LINES);\n const lines = [summary, ...(shown.length > 0 ? shown : [theme.fg('error', 'Unknown workflow error')])];\n const hidden = details.length - shown.length;\n if (hidden > 0) lines.push(hiddenDetailLine(hidden, theme));\n return renderResult(lines, theme, options.expanded);\n}\n\nfunction renderPartial(\n toolName: WorkflowPiToolName,\n args: Record<string, unknown>,\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component {\n const details = detailLines(result);\n const shown = details.slice(-PARTIAL_DETAIL_LINES);\n const action = toolAction(toolName, args);\n const target = toolTarget(toolName, args);\n const summary = `${theme.fg('accent', '◐')} ${theme.bold(action)}${target ? theme.fg('dim', ` · ${target}`) : ''}`;\n const hidden = details.length - shown.length;\n const lines = [summary];\n if (hidden > 0) lines.push(theme.fg('dim', `… ${hidden} earlier`));\n lines.push(...shown);\n return renderResult(lines, theme, options.expanded);\n}\n\nfunction renderFallback(result: WorkflowToolResultLike, options: WorkflowToolRenderOptions, theme: Theme): Component {\n const details = detailLines(result);\n if (details.length === 0) return renderResult([theme.fg('muted', 'No workflow output.')], theme, options.expanded);\n const shown = options.expanded ? details : details.slice(0, COLLAPSED_DETAIL_LINES);\n const lines = [...shown];\n const hidden = details.length - shown.length;\n if (hidden > 0) lines.push(hiddenDetailLine(hidden, theme));\n return renderResult(lines, theme, options.expanded);\n}\n\nexport function renderWorkflowToolResult(\n toolName: WorkflowPiToolName,\n args: Record<string, unknown>,\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component {\n if (options.isPartial) return renderPartial(toolName, args, result, options, theme);\n if (options.isError === true || result.isError === true) {\n return renderFailure(toolName, args, result, options, theme);\n }\n\n if (toolName === 'list_workflows') {\n return renderCatalogResult(result, options, theme) ?? renderFallback(result, options, theme);\n }\n if (toolName === 'launch_workflow') return renderLaunchResult(args, result, options, theme);\n\n const action = readString(args, 'action');\n if (action === 'status') {\n return renderStatusResult(result, options, theme) ?? renderFallback(result, options, theme);\n }\n if (action === 'pause' || action === 'resume' || action === 'stop') {\n return renderControlResult(action, args, result, options, theme);\n }\n if (action === 'recovery-evidence') {\n return renderRecoveryEvidenceResult(args, result, options, theme);\n }\n if (action === 'follow' || action === 'open' || action === 'recover' || action === 'tail') {\n return renderSimpleActionResult(action, args, result, options, theme);\n }\n return renderFallback(result, options, theme);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{DoomToolCall as e,DoomToolResult as t,renderToolHeading as n}from"@agimon-ai/doompi-ui/toolChrome";function r(e){if(!(!e||typeof e!=`object`||Array.isArray(e)))return e}function i(e){let t=``;for(let n of e){let e=n.codePointAt(0)??0;t+=e<=31||e===127?` `:n}return t.replace(/\s+/gu,` `).trim()}function a(e,t){let n=e?.[t];if(typeof n==`string`)return i(n)||void 0}function o(e,t){let n=e?.[t];return typeof n==`number`&&Number.isFinite(n)?n:void 0}function s(e,t){let n=e?.[t];return typeof n==`boolean`?n:void 0}function c(e,t){let n=e?.[t];return Array.isArray(n)?n.filter(e=>typeof e==`string`):[]}function l(e){if(e)try{return r(JSON.parse(e))}catch{return}}function u(e){return Array.isArray(e.content)?e.content.flatMap(e=>{let t=r(e);return t?.type===`text`&&typeof t.text==`string`?[t.text]:[]}):[]}function d(e){return u(e).flatMap(e=>e.split(`
|
|
2
|
+
`)).map(e=>e.trimEnd()).filter(e=>e.length>0)}function f(e){return l(u(e)[0])}function p(e,t,n=`${t}s`){return e===1?t:n}function m(e,t,n){return`${n.fg(`dim`,`${e} `)}${n.fg(`text`,t)}`}function h(e){let t=a(e,`runKey`);if(!t)return;let n=a(e,`workspace`);return n?`${n}/${t}`:t}function g(e,t){return e===`list_workflows`?`list`:e===`launch_workflow`?`launch`:a(t,`action`)??`run`}function _(e,t){return e===`list_workflows`?a(t,`directory`):e===`launch_workflow`?a(t,`workflowPath`):h(t)}function v(e,n,r){return new t(e,n,{wrap:r})}function y(e,t){return t.fg(`dim`,`… ${e} more · ctrl+o`)}function b(e){return e.replace(`T`,` `).replace(/\.\d{3}Z$/,`Z`)}function x(e){if(!e)return`workflow`;let t=e.split(`/`).at(-1)??e;return t.replace(/\.workflow\.ya?ml$/u,``)||t}function S(e,t,n){let i=[];if(e===`list_workflows`){let e=o(t,`page`),n=o(t,`pageSize`);e!==void 0&&i.push(`page ${e}`),n!==void 0&&i.push(`${n}/page`),a(t,`filter`)&&i.push(`filtered`);let r=c(t,`tags`);r.length>0&&i.push(`${r.length} ${p(r.length,`tag`)}`)}else if(e===`launch_workflow`){let e=a(t,`job`),n=a(t,`runner`),o=a(t,`workspace`),c=Object.keys(r(t.inputs)??{}).length,l=Object.keys(r(t.env)??{}).length;o&&i.push(`workspace ${o}`),e&&i.push(`job ${e}`),n&&i.push(`runner ${n}`),s(t,`dryRun`)&&i.push(`dry run`),a(t,`prompt`)&&i.push(`with prompt`),c>0&&i.push(`${c} ${p(c,`input`)}`),l>0&&i.push(`${l} env`)}else a(t,`expectedRunId`)&&i.push(`generation checked`),a(t,`reason`)&&i.push(`with reason`),s(t,`dryRun`)&&i.push(`dry run`),a(t,`job`)&&i.push(`job override`),a(t,`runner`)&&i.push(`runner override`);return i.map(e=>n.fg(`dim`,e))}function C(t,r,i){let a=g(t,r),o=_(t,r),s=S(t,r,i),c=[i.bold(a),o?i.fg(`muted`,o):void 0,...s].filter(e=>!!e).join(i.fg(`dim`,` · `));return new e(n(`workflow`,c,i))}function w(e){if(!Array.isArray(e?.workflows))return;let t=e.workflows.flatMap(e=>{let t=r(e),n=a(t,`path`);return!t||!n?[]:[{description:a(t,`description`)??``,name:a(t,`name`)??``,path:n,tags:c(t,`tags`)}]}),n=Array.isArray(e.tags)?e.tags.flatMap(e=>{let t=r(e),n=a(t,`tag`),i=o(t,`count`);return n&&i!==void 0?[{count:i,tag:n}]:[]}):[];return{directory:a(e,`directory`),page:o(e,`page`)??1,pageSize:o(e,`pageSize`)??t.length,tags:n,total:o(e,`total`)??t.length,totalPages:o(e,`totalPages`)??+(t.length>0),workflows:t}}function T(e,t,n){let r=e.name||x(e.path),i=[`${n.fg(`accent`,`›`)} ${n.bold(r)} ${n.fg(`muted`,`· ${e.path}`)}`];return t?(e.description&&i.push(` ${n.fg(`text`,e.description)}`),e.tags.length>0&&i.push(` ${m(`tags`,e.tags.join(`, `),n)}`),i):i}function E(e,t,n){let r=w(f(e));if(!r)return;let i=`page ${r.page}/${r.totalPages}`,a=`${n.fg(r.total>0?`success`:`muted`,r.total>0?`✓`:`○`)} ${n.bold(`${r.total} ${p(r.total,`workflow`)}`)} ${n.fg(`dim`,`· ${i}`)}`,o=t.expanded?r.workflows:r.workflows.slice(0,6),s=[a,...o.flatMap(e=>T(e,t.expanded,n))],c=r.workflows.length-o.length;if(c>0&&s.push(y(c,n)),t.expanded){if(r.tags.length>0){let e=r.tags.map(({count:e,tag:t})=>`${t} (${e})`).join(`, `);s.push(m(`available tags`,e,n))}r.directory&&s.push(m(`directory`,r.directory,n)),s.push(m(`page size`,String(r.pageSize),n))}return v(s,n,t.expanded)}function D(e){let t=a(e,`effectiveStage`)??a(e,`stage`)??`unknown`,n=a(e,`effectiveOutcome`)??a(e,`outcome`),r=a(e,`executionState`);return n===`interrupted`?{color:`warning`,glyph:`!`,label:`interrupted`}:t===`error`||n===`failed`?{color:`error`,glyph:`✗`,label:`failed`}:t===`completed`&&n===`skipped`?{color:`muted`,glyph:`○`,label:`skipped`}:t===`completed`?{color:`success`,glyph:`✓`,label:`completed`}:r===`paused`?{color:`warning`,glyph:`Ⅱ`,label:`paused`}:r===`pause_requested`?{color:`warning`,glyph:`◐`,label:`pause requested`}:r===`resume_requested`?{color:`warning`,glyph:`◐`,label:`resume requested`}:t===`running`?{color:`accent`,glyph:`◐`,label:`running`}:{color:`muted`,glyph:`○`,label:t}}function O(e){let t=a(e,`runKey`)??`unknown run`,n=a(e,`workspace`);return n?`${n}/${t}`:t}function k(e,t){let n=r(e.executionCursor),i=a(n,`job`)??a(e,`job`),o=a(n,`stepName`),s=a(n,`phase`);if(!i&&!o&&!s)return;let c=i??s??`workflow`;return` ${t.fg(`muted`,`[${c}]`)} ${t.fg(`text`,o??s??`running`)}`}function A(e){let t=r(e.launcher),n=a(t,`type`);if(!n)return;let i=a(t,`sessionName`)??a(t,`workspaceId`);return i?`${n} ${i}`:n}function j(e,t,n){let r=a(e,`runKey`),i=a(e,`stage`);if(!r||!i)return;let c=D(e),l=a(e,`displayName`)??r,u=[`${n.fg(c.color,c.glyph)} ${n.bold(l)} ${n.fg(`dim`,`· ${O(e)} ·`)} ${n.fg(c.color,c.label)}`],d=k(e,n);d&&u.push(d);let f=a(e,`errorMessage`)??a(e,`failureReason`);f&&u.push(`${n.fg(`error`,`error`)} ${n.fg(`text`,f)}`);let p=a(e,`staleReason`);p&&u.push(`${n.fg(`warning`,`stale`)} ${n.fg(`text`,p)}`);let h=[a(e,`runner`)?`runner ${a(e,`runner`)}`:void 0,s(e,`dryRun`)?`dry run`:void 0,o(e,`exitCode`)===void 0?void 0:`exit ${o(e,`exitCode`)}`,a(e,`startedAt`)?`started ${b(a(e,`startedAt`)??``)}`:void 0].filter(e=>!!e);if(h.length>0&&u.push(n.fg(`dim`,h.join(` · `))),!t)return u;let g=[[`workflow`,a(e,`workflowPath`)],[`workflow id`,a(e,`workflowId`)],[`run id`,a(e,`runId`)],[`launcher`,A(e)],[`job`,a(e,`job`)],[`outcome`,a(e,`effectiveOutcome`)??a(e,`outcome`)],[`finished`,a(e,`finishedAt`)?b(a(e,`finishedAt`)??``):void 0],[`pid`,o(e,`pid`)?.toString()],[`repair`,a(e,`activeRepairId`)?`#${a(e,`activeRepairId`)}`:void 0],[`worktree`,a(e,`worktreeBranch`)??a(e,`worktreePath`)]];for(let[e,t]of g)t&&u.push(m(e,t,n));return u}function M(e,t,n){let r=f(e);if(!r)return;let i=j(r,t.expanded,n);return i?v(i,n,t.expanded):void 0}function N(e){return a(r(e?.request),`requestedAt`)??a(e,`requestedAt`)}function P(e,t,n,r,i){let o=f(n),s=h(t)??a(o,`runKey`)??`workflow`,c=a(o,`workspace`),l=c&&!s.includes(`/`)?`${c}/${s}`:s,u=[`${i.fg(`warning`,`◐`)} ${i.bold(`${e} requested`)} ${i.fg(`dim`,`· ${l}`)}`],d=N(o);return d&&u.push(m(`requested`,b(d),i)),r.expanded&&u.push(i.fg(`dim`,`verify the transition with workflow_run status`)),v(u,i,r.expanded)}function F(e,t){return e.match(t)?.[1]?.trim()}function I(e,t){let n=F(e,/^Started (.+) in workspace .+\.$/mu),r=F(e,/^Started .+ in workspace (.+)\.$/mu)??a(t,`workspace`),i=F(e,/^Run key:\s*(.+)$/mu),o=a(t,`workflowPath`),s=n??x(o),c=i?r?`${r}/${i}`:i:r??o??`workflow`;return/Workflow completed successfully/iu.test(e)?{name:s,scope:c,state:{color:`success`,glyph:`✓`,label:`completed`}}:/Workflow skipped/iu.test(e)?{name:s,scope:c,state:{color:`muted`,glyph:`○`,label:`skipped`}}:/no run was registered/iu.test(e)?{name:s,scope:c,state:{color:`warning`,glyph:`◐`,label:`starting · run key pending`}}:{name:s,scope:c,state:{color:`accent`,glyph:`◐`,label:i?`started`:`launch accepted`}}}function L(e,t,n,r){let i=I(u(t).join(`
|
|
3
|
+
`),e),o=[`${r.fg(i.state.color,i.state.glyph)} ${r.bold(i.name)} ${r.fg(`dim`,`· ${i.scope} ·`)} ${r.fg(i.state.color,i.state.label)}`],c=[a(e,`job`)?`job ${a(e,`job`)}`:void 0,a(e,`runner`)?`runner ${a(e,`runner`)}`:void 0,s(e,`dryRun`)?`dry run`:void 0].filter(e=>!!e);if(c.length>0&&o.push(r.fg(`dim`,c.join(` · `))),n.expanded){let e=d(t).filter(e=>!e.startsWith(`Next steps for the agent:`));e.length>0&&o.push(...e)}return v(o,r,n.expanded)}function R(e){let t=[],n;for(let r of e.split(`
|
|
4
|
+
`)){let e=r.match(/^--- (.+) ---$/u);if(e?.[1]){n={body:[],name:e[1]},t.push(n);continue}n?.body.push(r)}return t}function z(e){return l(e.find(e=>e.name===`run.json`)?.body.join(`
|
|
5
|
+
`))}function B(e,t,n,r){let i=R(u(t).join(`
|
|
6
|
+
`)),a=z(i),o=a?j(a,n.expanded,r):void 0,s=i.filter(e=>e.name!==`run.json`),c=h(e)??`workflow`,l=o??[`${r.fg(`success`,`✓`)} ${r.bold(`recovery evidence`)} ${r.fg(`dim`,`· ${c}`)}`],d=s.map(e=>e.name);if(l.push(d.length>0?m(`evidence`,d.join(`, `),r):r.fg(`muted`,`no durable evidence files recorded`)),n.expanded)for(let e of s)l.push(r.bold(e.name),...e.body.filter(e=>e.length>0));return v(l,r,n.expanded)}function V(e,t,n,r,i){let a=h(t)??`workflow`,o={follow:`following output`,open:`launcher opened`,recover:s(t,`dryRun`)?`recovery dry run finished`:`recovery accepted`,tail:`launcher output checked`},c=e===`recover`?{color:`accent`,glyph:`◐`,label:o[e]??e}:{color:`success`,glyph:`✓`,label:o[e]??e},l=[`${i.fg(c.color,c.glyph)} ${i.bold(c.label)} ${i.fg(`dim`,`· ${a}`)}`],u=d(n);if(e===`tail`){let e=u.find(e=>e.startsWith(`Stage:`)),t=u.find(e=>e.startsWith(`Workflow:`));t&&l.push(t),e&&l.push(e)}return r.expanded&&u.length>0&&l.push(...u),v(l,i,r.expanded)}function H(e,t,n,r,i){let a=g(e,t),o=_(e,t),s=`${i.fg(`error`,`✗`)} ${i.bold(`${a} failed`)}${o?i.fg(`dim`,` · ${o}`):``}`,c=d(n),l=r.expanded?c:c.slice(0,8),u=[s,...l.length>0?l:[i.fg(`error`,`Unknown workflow error`)]],f=c.length-l.length;return f>0&&u.push(y(f,i)),v(u,i,r.expanded)}function U(e,t,n,r,i){let a=d(n),o=a.slice(-4),s=g(e,t),c=_(e,t),l=`${i.fg(`accent`,`◐`)} ${i.bold(s)}${c?i.fg(`dim`,` · ${c}`):``}`,u=a.length-o.length,f=[l];return u>0&&f.push(i.fg(`dim`,`… ${u} earlier`)),f.push(...o),v(f,i,r.expanded)}function W(e,t,n){let r=d(e);if(r.length===0)return v([n.fg(`muted`,`No workflow output.`)],n,t.expanded);let i=t.expanded?r:r.slice(0,8),a=[...i],o=r.length-i.length;return o>0&&a.push(y(o,n)),v(a,n,t.expanded)}function G(e,t,n,r,i){if(r.isPartial)return U(e,t,n,r,i);if(r.isError===!0||n.isError===!0)return H(e,t,n,r,i);if(e===`list_workflows`)return E(n,r,i)??W(n,r,i);if(e===`launch_workflow`)return L(t,n,r,i);let o=a(t,`action`);return o===`status`?M(n,r,i)??W(n,r,i):o===`pause`||o===`resume`||o===`stop`?P(o,t,n,r,i):o===`recovery-evidence`?B(t,n,r,i):o===`follow`||o===`open`||o===`recover`||o===`tail`?V(o,t,n,r,i):W(n,r,i)}export{C as renderWorkflowToolCall,G as renderWorkflowToolResult};
|
|
7
|
+
//# sourceMappingURL=workflowToolRender.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflowToolRender.mjs","names":[],"sources":["../../../src/tui/workflow/workflowToolRender.ts"],"sourcesContent":["import { DoomToolCall, DoomToolResult, renderToolHeading } from '@agimon-ai/doompi-ui/toolChrome';\nimport type { Theme, ThemeColor } from '@earendil-works/pi-coding-agent';\nimport type { Component } from '@earendil-works/pi-tui';\n\nexport type WorkflowToolName = 'launch_workflow' | 'list_workflows' | 'workflow_run';\nexport type WorkflowPiToolName = WorkflowToolName;\n\ninterface WorkflowToolResultLike {\n content?: unknown;\n isError?: boolean;\n}\n\ninterface WorkflowToolRenderOptions {\n expanded: boolean;\n isError?: boolean;\n isPartial?: boolean;\n}\n\ntype JsonRecord = Record<string, unknown>;\n\ntype WorkflowState = {\n color: ThemeColor;\n glyph: string;\n label: string;\n};\n\ninterface WorkflowCatalogItem {\n description: string;\n name: string;\n path: string;\n tags: string[];\n}\n\ninterface WorkflowCatalog {\n directory?: string;\n page: number;\n pageSize: number;\n tags: Array<{ count: number; tag: string }>;\n total: number;\n totalPages: number;\n workflows: WorkflowCatalogItem[];\n}\n\ninterface EvidenceSection {\n body: string[];\n name: string;\n}\n\nconst COLLAPSED_CATALOG_ROWS = 6;\nconst COLLAPSED_DETAIL_LINES = 8;\nconst PARTIAL_DETAIL_LINES = 4;\n\nfunction asRecord(value: unknown): JsonRecord | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined;\n return value as JsonRecord;\n}\n\nfunction inlineText(value: string): string {\n let normalized = '';\n for (const character of value) {\n const code = character.codePointAt(0) ?? 0;\n normalized += code <= 31 || code === 127 ? ' ' : character;\n }\n return normalized.replace(/\\s+/gu, ' ').trim();\n}\n\nfunction readString(record: JsonRecord | undefined, key: string): string | undefined {\n const value = record?.[key];\n if (typeof value !== 'string') return undefined;\n return inlineText(value) || undefined;\n}\n\nfunction readNumber(record: JsonRecord | undefined, key: string): number | undefined {\n const value = record?.[key];\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction readBoolean(record: JsonRecord | undefined, key: string): boolean | undefined {\n const value = record?.[key];\n return typeof value === 'boolean' ? value : undefined;\n}\n\nfunction readStringArray(record: JsonRecord | undefined, key: string): string[] {\n const value = record?.[key];\n if (!Array.isArray(value)) return [];\n return value.filter((item): item is string => typeof item === 'string');\n}\n\nfunction parseJsonRecord(text: string | undefined): JsonRecord | undefined {\n if (!text) return undefined;\n try {\n return asRecord(JSON.parse(text));\n } catch {\n return undefined;\n }\n}\n\nfunction textBlocks(result: WorkflowToolResultLike): string[] {\n if (!Array.isArray(result.content)) return [];\n return result.content.flatMap((item) => {\n const record = asRecord(item);\n return record?.type === 'text' && typeof record.text === 'string' ? [record.text] : [];\n });\n}\n\nfunction detailLines(result: WorkflowToolResultLike): string[] {\n return textBlocks(result)\n .flatMap((block) => block.split('\\n'))\n .map((line) => line.trimEnd())\n .filter((line) => line.length > 0);\n}\n\nfunction firstPayload(result: WorkflowToolResultLike): JsonRecord | undefined {\n return parseJsonRecord(textBlocks(result)[0]);\n}\n\nfunction plural(count: number, singular: string, pluralForm = `${singular}s`): string {\n return count === 1 ? singular : pluralForm;\n}\n\nfunction labelValue(label: string, value: string, theme: Theme): string {\n return `${theme.fg('dim', `${label} `)}${theme.fg('text', value)}`;\n}\n\nfunction targetScope(args: Record<string, unknown>): string | undefined {\n const runKey = readString(args, 'runKey');\n if (!runKey) return undefined;\n const workspace = readString(args, 'workspace');\n return workspace ? `${workspace}/${runKey}` : runKey;\n}\n\nfunction toolAction(toolName: WorkflowPiToolName, args: Record<string, unknown>): string {\n if (toolName === 'list_workflows') return 'list';\n if (toolName === 'launch_workflow') return 'launch';\n return readString(args, 'action') ?? 'run';\n}\n\nfunction toolTarget(toolName: WorkflowPiToolName, args: Record<string, unknown>): string | undefined {\n if (toolName === 'list_workflows') return readString(args, 'directory');\n if (toolName === 'launch_workflow') return readString(args, 'workflowPath');\n return targetScope(args);\n}\n\nfunction renderResult(lines: readonly string[], theme: Theme, expanded: boolean): Component {\n return new DoomToolResult(lines, theme, { wrap: expanded });\n}\n\nfunction hiddenDetailLine(hidden: number, theme: Theme): string {\n return theme.fg('dim', `… ${hidden} more · ctrl+o`);\n}\n\nfunction statusTimestamp(value: string): string {\n return value.replace('T', ' ').replace(/\\.\\d{3}Z$/, 'Z');\n}\n\nfunction workflowNameFromPath(path: string | undefined): string {\n if (!path) return 'workflow';\n const filename = path.split('/').at(-1) ?? path;\n return filename.replace(/\\.workflow\\.ya?ml$/u, '') || filename;\n}\n\nfunction callMetadata(toolName: WorkflowPiToolName, args: Record<string, unknown>, theme: Theme): string[] {\n const values: string[] = [];\n\n if (toolName === 'list_workflows') {\n const page = readNumber(args, 'page');\n const pageSize = readNumber(args, 'pageSize');\n if (page !== undefined) values.push(`page ${page}`);\n if (pageSize !== undefined) values.push(`${pageSize}/page`);\n if (readString(args, 'filter')) values.push('filtered');\n const tags = readStringArray(args, 'tags');\n if (tags.length > 0) values.push(`${tags.length} ${plural(tags.length, 'tag')}`);\n } else if (toolName === 'launch_workflow') {\n const job = readString(args, 'job');\n const runner = readString(args, 'runner');\n const workspace = readString(args, 'workspace');\n const inputCount = Object.keys(asRecord(args.inputs) ?? {}).length;\n const environmentCount = Object.keys(asRecord(args.env) ?? {}).length;\n if (workspace) values.push(`workspace ${workspace}`);\n if (job) values.push(`job ${job}`);\n if (runner) values.push(`runner ${runner}`);\n if (readBoolean(args, 'dryRun')) values.push('dry run');\n if (readString(args, 'prompt')) values.push('with prompt');\n if (inputCount > 0) values.push(`${inputCount} ${plural(inputCount, 'input')}`);\n if (environmentCount > 0) values.push(`${environmentCount} env`);\n } else {\n const expectedRunId = readString(args, 'expectedRunId');\n if (expectedRunId) values.push('generation checked');\n if (readString(args, 'reason')) values.push('with reason');\n if (readBoolean(args, 'dryRun')) values.push('dry run');\n if (readString(args, 'job')) values.push('job override');\n if (readString(args, 'runner')) values.push('runner override');\n }\n\n return values.map((value) => theme.fg('dim', value));\n}\n\nexport function renderWorkflowToolCall(\n toolName: WorkflowPiToolName,\n args: Record<string, unknown>,\n theme: Theme,\n): Component {\n const action = toolAction(toolName, args);\n const target = toolTarget(toolName, args);\n const metadata = callMetadata(toolName, args, theme);\n const purpose = [theme.bold(action), target ? theme.fg('muted', target) : undefined, ...metadata]\n .filter((part): part is string => !!part)\n .join(theme.fg('dim', ' · '));\n return new DoomToolCall(renderToolHeading('workflow', purpose, theme));\n}\n\nfunction parseCatalog(payload: JsonRecord | undefined): WorkflowCatalog | undefined {\n if (!Array.isArray(payload?.workflows)) return undefined;\n\n const workflows = payload.workflows.flatMap((value) => {\n const record = asRecord(value);\n const path = readString(record, 'path');\n if (!record || !path) return [];\n return [\n {\n description: readString(record, 'description') ?? '',\n name: readString(record, 'name') ?? '',\n path,\n tags: readStringArray(record, 'tags'),\n },\n ];\n });\n const tags = Array.isArray(payload.tags)\n ? payload.tags.flatMap((value) => {\n const record = asRecord(value);\n const tag = readString(record, 'tag');\n const count = readNumber(record, 'count');\n return tag && count !== undefined ? [{ count, tag }] : [];\n })\n : [];\n\n return {\n directory: readString(payload, 'directory'),\n page: readNumber(payload, 'page') ?? 1,\n pageSize: readNumber(payload, 'pageSize') ?? workflows.length,\n tags,\n total: readNumber(payload, 'total') ?? workflows.length,\n totalPages: readNumber(payload, 'totalPages') ?? (workflows.length > 0 ? 1 : 0),\n workflows,\n };\n}\n\nfunction catalogItemLines(item: WorkflowCatalogItem, expanded: boolean, theme: Theme): string[] {\n const name = item.name || workflowNameFromPath(item.path);\n const lines = [`${theme.fg('accent', '›')} ${theme.bold(name)} ${theme.fg('muted', `· ${item.path}`)}`];\n if (!expanded) return lines;\n if (item.description) lines.push(` ${theme.fg('text', item.description)}`);\n if (item.tags.length > 0) lines.push(` ${labelValue('tags', item.tags.join(', '), theme)}`);\n return lines;\n}\n\nfunction renderCatalogResult(\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component | undefined {\n const catalog = parseCatalog(firstPayload(result));\n if (!catalog) return undefined;\n\n const pageLabel = `page ${catalog.page}/${catalog.totalPages}`;\n const summary = `${theme.fg(catalog.total > 0 ? 'success' : 'muted', catalog.total > 0 ? '✓' : '○')} ${theme.bold(\n `${catalog.total} ${plural(catalog.total, 'workflow')}`,\n )} ${theme.fg('dim', `· ${pageLabel}`)}`;\n const shown = options.expanded ? catalog.workflows : catalog.workflows.slice(0, COLLAPSED_CATALOG_ROWS);\n const lines = [summary, ...shown.flatMap((item) => catalogItemLines(item, options.expanded, theme))];\n const hidden = catalog.workflows.length - shown.length;\n if (hidden > 0) lines.push(hiddenDetailLine(hidden, theme));\n\n if (options.expanded) {\n if (catalog.tags.length > 0) {\n const tags = catalog.tags.map(({ count, tag }) => `${tag} (${count})`).join(', ');\n lines.push(labelValue('available tags', tags, theme));\n }\n if (catalog.directory) lines.push(labelValue('directory', catalog.directory, theme));\n lines.push(labelValue('page size', String(catalog.pageSize), theme));\n }\n\n return renderResult(lines, theme, options.expanded);\n}\n\nfunction readWorkflowState(record: JsonRecord): WorkflowState {\n const stage = readString(record, 'effectiveStage') ?? readString(record, 'stage') ?? 'unknown';\n const outcome = readString(record, 'effectiveOutcome') ?? readString(record, 'outcome');\n const executionState = readString(record, 'executionState');\n\n if (outcome === 'interrupted') return { color: 'warning', glyph: '!', label: 'interrupted' };\n if (stage === 'error' || outcome === 'failed') return { color: 'error', glyph: '✗', label: 'failed' };\n if (stage === 'completed' && outcome === 'skipped') return { color: 'muted', glyph: '○', label: 'skipped' };\n if (stage === 'completed') return { color: 'success', glyph: '✓', label: 'completed' };\n if (executionState === 'paused') return { color: 'warning', glyph: 'Ⅱ', label: 'paused' };\n if (executionState === 'pause_requested') return { color: 'warning', glyph: '◐', label: 'pause requested' };\n if (executionState === 'resume_requested') return { color: 'warning', glyph: '◐', label: 'resume requested' };\n if (stage === 'running') return { color: 'accent', glyph: '◐', label: 'running' };\n return { color: 'muted', glyph: '○', label: stage };\n}\n\nfunction recordScope(record: JsonRecord): string {\n const runKey = readString(record, 'runKey') ?? 'unknown run';\n const workspace = readString(record, 'workspace');\n return workspace ? `${workspace}/${runKey}` : runKey;\n}\n\nfunction currentActivity(record: JsonRecord, theme: Theme): string | undefined {\n const cursor = asRecord(record.executionCursor);\n const job = readString(cursor, 'job') ?? readString(record, 'job');\n const step = readString(cursor, 'stepName');\n const phase = readString(cursor, 'phase');\n if (!job && !step && !phase) return undefined;\n const context = job ?? phase ?? 'workflow';\n return ` ${theme.fg('muted', `[${context}]`)} ${theme.fg('text', step ?? phase ?? 'running')}`;\n}\n\nfunction launcherLabel(record: JsonRecord): string | undefined {\n const launcher = asRecord(record.launcher);\n const type = readString(launcher, 'type');\n if (!type) return undefined;\n const identity = readString(launcher, 'sessionName') ?? readString(launcher, 'workspaceId');\n return identity ? `${type} ${identity}` : type;\n}\n\nfunction workflowRecordLines(record: JsonRecord, expanded: boolean, theme: Theme): string[] | undefined {\n const runKey = readString(record, 'runKey');\n const stage = readString(record, 'stage');\n if (!runKey || !stage) return undefined;\n\n const state = readWorkflowState(record);\n const displayName = readString(record, 'displayName') ?? runKey;\n const heading = `${theme.fg(state.color, state.glyph)} ${theme.bold(displayName)} ${theme.fg(\n 'dim',\n `· ${recordScope(record)} ·`,\n )} ${theme.fg(state.color, state.label)}`;\n const lines = [heading];\n const activity = currentActivity(record, theme);\n if (activity) lines.push(activity);\n\n const failure = readString(record, 'errorMessage') ?? readString(record, 'failureReason');\n if (failure) lines.push(`${theme.fg('error', 'error')} ${theme.fg('text', failure)}`);\n const staleReason = readString(record, 'staleReason');\n if (staleReason) lines.push(`${theme.fg('warning', 'stale')} ${theme.fg('text', staleReason)}`);\n\n const conciseMetadata = [\n readString(record, 'runner') ? `runner ${readString(record, 'runner')}` : undefined,\n readBoolean(record, 'dryRun') ? 'dry run' : undefined,\n readNumber(record, 'exitCode') !== undefined ? `exit ${readNumber(record, 'exitCode')}` : undefined,\n readString(record, 'startedAt') ? `started ${statusTimestamp(readString(record, 'startedAt') ?? '')}` : undefined,\n ].filter((value): value is string => !!value);\n if (conciseMetadata.length > 0) lines.push(theme.fg('dim', conciseMetadata.join(' · ')));\n\n if (!expanded) return lines;\n\n const detailedValues: Array<[string, string | undefined]> = [\n ['workflow', readString(record, 'workflowPath')],\n ['workflow id', readString(record, 'workflowId')],\n ['run id', readString(record, 'runId')],\n ['launcher', launcherLabel(record)],\n ['job', readString(record, 'job')],\n ['outcome', readString(record, 'effectiveOutcome') ?? readString(record, 'outcome')],\n [\n 'finished',\n readString(record, 'finishedAt') ? statusTimestamp(readString(record, 'finishedAt') ?? '') : undefined,\n ],\n ['pid', readNumber(record, 'pid')?.toString()],\n ['repair', readString(record, 'activeRepairId') ? `#${readString(record, 'activeRepairId')}` : undefined],\n ['worktree', readString(record, 'worktreeBranch') ?? readString(record, 'worktreePath')],\n ];\n for (const [label, value] of detailedValues) {\n if (value) lines.push(labelValue(label, value, theme));\n }\n return lines;\n}\n\nfunction renderStatusResult(\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component | undefined {\n const payload = firstPayload(result);\n if (!payload) return undefined;\n const lines = workflowRecordLines(payload, options.expanded, theme);\n return lines ? renderResult(lines, theme, options.expanded) : undefined;\n}\n\nfunction nestedRequestedAt(payload: JsonRecord | undefined): string | undefined {\n return readString(asRecord(payload?.request), 'requestedAt') ?? readString(payload, 'requestedAt');\n}\n\nfunction renderControlResult(\n action: string,\n args: Record<string, unknown>,\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component {\n const payload = firstPayload(result);\n const scope = targetScope(args) ?? readString(payload, 'runKey') ?? 'workflow';\n const payloadWorkspace = readString(payload, 'workspace');\n const resolvedScope = payloadWorkspace && !scope.includes('/') ? `${payloadWorkspace}/${scope}` : scope;\n const lines = [\n `${theme.fg('warning', '◐')} ${theme.bold(`${action} requested`)} ${theme.fg('dim', `· ${resolvedScope}`)}`,\n ];\n const requestedAt = nestedRequestedAt(payload);\n if (requestedAt) lines.push(labelValue('requested', statusTimestamp(requestedAt), theme));\n if (options.expanded) lines.push(theme.fg('dim', 'verify the transition with workflow_run status'));\n return renderResult(lines, theme, options.expanded);\n}\n\nfunction matchLine(text: string, pattern: RegExp): string | undefined {\n return text.match(pattern)?.[1]?.trim();\n}\n\nfunction launchSummary(\n text: string,\n args: Record<string, unknown>,\n): { name: string; scope: string; state: WorkflowState } {\n const startedName = matchLine(text, /^Started (.+) in workspace .+\\.$/mu);\n const workspace = matchLine(text, /^Started .+ in workspace (.+)\\.$/mu) ?? readString(args, 'workspace');\n const runKey = matchLine(text, /^Run key:\\s*(.+)$/mu);\n const path = readString(args, 'workflowPath');\n const name = startedName ?? workflowNameFromPath(path);\n const scope = runKey ? (workspace ? `${workspace}/${runKey}` : runKey) : (workspace ?? path ?? 'workflow');\n\n if (/Workflow completed successfully/iu.test(text)) {\n return { name, scope, state: { color: 'success', glyph: '✓', label: 'completed' } };\n }\n if (/Workflow skipped/iu.test(text)) {\n return { name, scope, state: { color: 'muted', glyph: '○', label: 'skipped' } };\n }\n if (/no run was registered/iu.test(text)) {\n return { name, scope, state: { color: 'warning', glyph: '◐', label: 'starting · run key pending' } };\n }\n return { name, scope, state: { color: 'accent', glyph: '◐', label: runKey ? 'started' : 'launch accepted' } };\n}\n\nfunction renderLaunchResult(\n args: Record<string, unknown>,\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component {\n const blocks = textBlocks(result);\n const text = blocks.join('\\n');\n const summary = launchSummary(text, args);\n const lines = [\n `${theme.fg(summary.state.color, summary.state.glyph)} ${theme.bold(summary.name)} ${theme.fg(\n 'dim',\n `· ${summary.scope} ·`,\n )} ${theme.fg(summary.state.color, summary.state.label)}`,\n ];\n const metadata = [\n readString(args, 'job') ? `job ${readString(args, 'job')}` : undefined,\n readString(args, 'runner') ? `runner ${readString(args, 'runner')}` : undefined,\n readBoolean(args, 'dryRun') ? 'dry run' : undefined,\n ].filter((value): value is string => !!value);\n if (metadata.length > 0) lines.push(theme.fg('dim', metadata.join(' · ')));\n if (options.expanded) {\n const details = detailLines(result).filter((line) => !line.startsWith('Next steps for the agent:'));\n if (details.length > 0) lines.push(...details);\n }\n return renderResult(lines, theme, options.expanded);\n}\n\nfunction splitEvidence(text: string): EvidenceSection[] {\n const sections: EvidenceSection[] = [];\n let current: EvidenceSection | undefined;\n for (const line of text.split('\\n')) {\n const match = line.match(/^--- (.+) ---$/u);\n if (match?.[1]) {\n current = { body: [], name: match[1] };\n sections.push(current);\n continue;\n }\n current?.body.push(line);\n }\n return sections;\n}\n\nfunction recoveryRecord(sections: EvidenceSection[]): JsonRecord | undefined {\n const runSection = sections.find((section) => section.name === 'run.json');\n return parseJsonRecord(runSection?.body.join('\\n'));\n}\n\nfunction renderRecoveryEvidenceResult(\n args: Record<string, unknown>,\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component {\n const text = textBlocks(result).join('\\n');\n const sections = splitEvidence(text);\n const record = recoveryRecord(sections);\n const recordLines = record ? workflowRecordLines(record, options.expanded, theme) : undefined;\n const evidenceSections = sections.filter((section) => section.name !== 'run.json');\n const scope = targetScope(args) ?? 'workflow';\n const lines = recordLines ?? [\n `${theme.fg('success', '✓')} ${theme.bold('recovery evidence')} ${theme.fg('dim', `· ${scope}`)}`,\n ];\n const names = evidenceSections.map((section) => section.name);\n lines.push(\n names.length > 0\n ? labelValue('evidence', names.join(', '), theme)\n : theme.fg('muted', 'no durable evidence files recorded'),\n );\n\n if (options.expanded) {\n for (const section of evidenceSections) {\n lines.push(theme.bold(section.name), ...section.body.filter((line) => line.length > 0));\n }\n }\n return renderResult(lines, theme, options.expanded);\n}\n\nfunction renderSimpleActionResult(\n action: string,\n args: Record<string, unknown>,\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component {\n const scope = targetScope(args) ?? 'workflow';\n const actionLabel: Record<string, string> = {\n follow: 'following output',\n open: 'launcher opened',\n recover: readBoolean(args, 'dryRun') ? 'recovery dry run finished' : 'recovery accepted',\n tail: 'launcher output checked',\n };\n const state: WorkflowState =\n action === 'recover'\n ? { color: 'accent', glyph: '◐', label: actionLabel[action] ?? action }\n : { color: 'success', glyph: '✓', label: actionLabel[action] ?? action };\n const lines = [`${theme.fg(state.color, state.glyph)} ${theme.bold(state.label)} ${theme.fg('dim', `· ${scope}`)}`];\n const details = detailLines(result);\n if (action === 'tail') {\n const stageLine = details.find((line) => line.startsWith('Stage:'));\n const workflowLine = details.find((line) => line.startsWith('Workflow:'));\n if (workflowLine) lines.push(workflowLine);\n if (stageLine) lines.push(stageLine);\n }\n if (options.expanded && details.length > 0) lines.push(...details);\n return renderResult(lines, theme, options.expanded);\n}\n\nfunction renderFailure(\n toolName: WorkflowPiToolName,\n args: Record<string, unknown>,\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component {\n const action = toolAction(toolName, args);\n const target = toolTarget(toolName, args);\n const summary = `${theme.fg('error', '✗')} ${theme.bold(`${action} failed`)}${\n target ? theme.fg('dim', ` · ${target}`) : ''\n }`;\n const details = detailLines(result);\n const shown = options.expanded ? details : details.slice(0, COLLAPSED_DETAIL_LINES);\n const lines = [summary, ...(shown.length > 0 ? shown : [theme.fg('error', 'Unknown workflow error')])];\n const hidden = details.length - shown.length;\n if (hidden > 0) lines.push(hiddenDetailLine(hidden, theme));\n return renderResult(lines, theme, options.expanded);\n}\n\nfunction renderPartial(\n toolName: WorkflowPiToolName,\n args: Record<string, unknown>,\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component {\n const details = detailLines(result);\n const shown = details.slice(-PARTIAL_DETAIL_LINES);\n const action = toolAction(toolName, args);\n const target = toolTarget(toolName, args);\n const summary = `${theme.fg('accent', '◐')} ${theme.bold(action)}${target ? theme.fg('dim', ` · ${target}`) : ''}`;\n const hidden = details.length - shown.length;\n const lines = [summary];\n if (hidden > 0) lines.push(theme.fg('dim', `… ${hidden} earlier`));\n lines.push(...shown);\n return renderResult(lines, theme, options.expanded);\n}\n\nfunction renderFallback(result: WorkflowToolResultLike, options: WorkflowToolRenderOptions, theme: Theme): Component {\n const details = detailLines(result);\n if (details.length === 0) return renderResult([theme.fg('muted', 'No workflow output.')], theme, options.expanded);\n const shown = options.expanded ? details : details.slice(0, COLLAPSED_DETAIL_LINES);\n const lines = [...shown];\n const hidden = details.length - shown.length;\n if (hidden > 0) lines.push(hiddenDetailLine(hidden, theme));\n return renderResult(lines, theme, options.expanded);\n}\n\nexport function renderWorkflowToolResult(\n toolName: WorkflowPiToolName,\n args: Record<string, unknown>,\n result: WorkflowToolResultLike,\n options: WorkflowToolRenderOptions,\n theme: Theme,\n): Component {\n if (options.isPartial) return renderPartial(toolName, args, result, options, theme);\n if (options.isError === true || result.isError === true) {\n return renderFailure(toolName, args, result, options, theme);\n }\n\n if (toolName === 'list_workflows') {\n return renderCatalogResult(result, options, theme) ?? renderFallback(result, options, theme);\n }\n if (toolName === 'launch_workflow') return renderLaunchResult(args, result, options, theme);\n\n const action = readString(args, 'action');\n if (action === 'status') {\n return renderStatusResult(result, options, theme) ?? renderFallback(result, options, theme);\n }\n if (action === 'pause' || action === 'resume' || action === 'stop') {\n return renderControlResult(action, args, result, options, theme);\n }\n if (action === 'recovery-evidence') {\n return renderRecoveryEvidenceResult(args, result, options, theme);\n }\n if (action === 'follow' || action === 'open' || action === 'recover' || action === 'tail') {\n return renderSimpleActionResult(action, args, result, options, theme);\n }\n return renderFallback(result, options, theme);\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
exports.LEADER_DISABLE_ACTION=`workflow.disable`,exports.LEADER_ENABLE_ACTION=`workflow.enable`,exports.LEADER_LABEL=`workflows`,exports.LEADER_LAUNCH_ACTION=`workflow.launch`,exports.LEADER_MANAGE_ACTION=`workflow.manage`,exports.LEADER_RECOVER_ACTION=`workflow.recover`,exports.PACKAGE_SOURCE=`@agimon-ai/doompi-workflow`;
|
|
2
|
-
//# sourceMappingURL=
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/types/index.ts"],"sourcesContent":["export const PACKAGE_SOURCE = '@agimon-ai/doompi-workflow';\nexport const COMMAND_DESCRIPTION = 'Doom Pi workflow execution and monitoring integration';\nexport const LEADER_KEY = 'w';\nexport const LEADER_LABEL = 'workflows';\nexport const LEADER_ORDER = 50;\nexport const LEADER_ENABLE_ACTION = 'workflow.enable';\nexport const LEADER_DISABLE_ACTION = 'workflow.disable';\nexport const LEADER_MANAGE_ACTION = 'workflow.manage';\nexport const LEADER_LAUNCH_ACTION = 'workflow.launch';\nexport const LEADER_RECOVER_ACTION = 'workflow.recover';\n"],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
const e=`@agimon-ai/doompi-workflow`,t=`workflows`,n=`workflow.enable`,r=`workflow.disable`,i=`workflow.manage`,a=`workflow.launch`,o=`workflow.recover`;export{r as LEADER_DISABLE_ACTION,n as LEADER_ENABLE_ACTION,t as LEADER_LABEL,a as LEADER_LAUNCH_ACTION,i as LEADER_MANAGE_ACTION,o as LEADER_RECOVER_ACTION,e as PACKAGE_SOURCE};
|
|
2
|
-
//# sourceMappingURL=
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/types/index.ts"],"sourcesContent":["export const PACKAGE_SOURCE = '@agimon-ai/doompi-workflow';\nexport const COMMAND_DESCRIPTION = 'Doom Pi workflow execution and monitoring integration';\nexport const LEADER_KEY = 'w';\nexport const LEADER_LABEL = 'workflows';\nexport const LEADER_ORDER = 50;\nexport const LEADER_ENABLE_ACTION = 'workflow.enable';\nexport const LEADER_DISABLE_ACTION = 'workflow.disable';\nexport const LEADER_MANAGE_ACTION = 'workflow.manage';\nexport const LEADER_LAUNCH_ACTION = 'workflow.launch';\nexport const LEADER_RECOVER_ACTION = 'workflow.recover';\n"],"mappings":"AAAA,MAAa,EAAiB,6BAGjB,EAAe,YAEf,EAAuB,kBACvB,EAAwB,mBACxB,EAAuB,kBACvB,EAAuB,kBACvB,EAAwB"}
|
package/llms.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Doom Pi Workflow
|
|
2
|
+
|
|
3
|
+
Package-owned guidance for launching, monitoring, and recovering Doom Pi workflows.
|
|
4
|
+
|
|
5
|
+
## Resources
|
|
6
|
+
|
|
7
|
+
- [Package README](./README.md): Workflow mode, leader bindings, execution model, monitoring, and public entrypoints.
|
|
8
|
+
- [Workflow recovery skill](./skills/workflow-recovery/SKILL.md): Evidence-first recovery of failed or interrupted workflow runs.
|
package/package.json
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/doompi-workflow",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.21",
|
|
4
4
|
"description": "Doompi workflow execution and monitoring integration",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai",
|
|
7
|
+
"coding-agent",
|
|
8
|
+
"developer-tools",
|
|
9
|
+
"doompi",
|
|
10
|
+
"pi-package"
|
|
11
|
+
],
|
|
5
12
|
"homepage": "https://agimon.ai",
|
|
6
13
|
"license": "MIT",
|
|
7
14
|
"author": "Vuong Ngo",
|
|
8
15
|
"files": [
|
|
9
16
|
"dist",
|
|
10
|
-
"
|
|
17
|
+
"llms.txt",
|
|
18
|
+
"README.md",
|
|
19
|
+
"skills/workflow-recovery/SKILL.md"
|
|
11
20
|
],
|
|
12
21
|
"type": "module",
|
|
13
22
|
"main": "./dist/index.cjs",
|
|
@@ -38,23 +47,23 @@
|
|
|
38
47
|
"dependencies": {
|
|
39
48
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
40
49
|
"zod": "4.4.3",
|
|
41
|
-
"@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.
|
|
42
|
-
"@agimon-ai/doompi-telemetry": "0.0.1-alpha.
|
|
43
|
-
"@agimon-ai/workflow-mcp": "0.
|
|
50
|
+
"@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.21",
|
|
51
|
+
"@agimon-ai/doompi-telemetry": "0.0.1-alpha.21",
|
|
52
|
+
"@agimon-ai/workflow-mcp": "0.23.11",
|
|
53
|
+
"@agimon-ai/doompi-ui": "0.0.1-alpha.21"
|
|
44
54
|
},
|
|
45
55
|
"devDependencies": {
|
|
46
|
-
"@earendil-works/pi-coding-agent": "0.84.
|
|
47
|
-
"@earendil-works/pi-tui": "0.84.
|
|
56
|
+
"@earendil-works/pi-coding-agent": "0.84.2",
|
|
57
|
+
"@earendil-works/pi-tui": "0.84.2",
|
|
48
58
|
"@types/node": "26.1.1",
|
|
49
59
|
"@vitest/coverage-v8": "4.1.10",
|
|
50
60
|
"tsdown": "0.22.14",
|
|
51
61
|
"typescript": "6.0.3",
|
|
52
|
-
"vitest": "4.1.10"
|
|
53
|
-
"@agimon-ai/doompi-ui": "0.0.1-alpha.2"
|
|
62
|
+
"vitest": "4.1.10"
|
|
54
63
|
},
|
|
55
64
|
"peerDependencies": {
|
|
56
|
-
"@earendil-works/pi-coding-agent": "0.84.
|
|
57
|
-
"@earendil-works/pi-tui": "0.84.
|
|
65
|
+
"@earendil-works/pi-coding-agent": "0.84.2",
|
|
66
|
+
"@earendil-works/pi-tui": "0.84.2"
|
|
58
67
|
},
|
|
59
68
|
"peerDependenciesMeta": {
|
|
60
69
|
"@earendil-works/pi-coding-agent": {
|
package/dist/dispatcher.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.cjs","names":["resolveRootSessionId","readChildProcessContext","SUBAGENT_PARENT_SESSION_ENV","WorkflowModeChanged"],"sources":["../src/dispatcher.ts"],"sourcesContent":["import {\n readChildProcessContext,\n resolveRootSessionId,\n SUBAGENT_PARENT_SESSION_ENV,\n} from '@agimon-ai/doompi-extension-contracts/child-process';\nimport { createProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\nimport { WorkflowModeChanged } from '@agimon-ai/doompi-extension-contracts/workflow';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport { createWorkflowPiExtension } from './workflow/piExtension.ts';\n\ntype RegisteredTool = Parameters<ExtensionAPI['registerTool']>[0];\nconst DISPATCHER_TOOL_NAMES = new Set(['list_workflows', 'launch_workflow']);\nconst ROOT_SCOPED_TOOL_NAMES = new Set(['launch_workflow']);\n\nfunction boundValue(target: object, property: PropertyKey): unknown {\n const value = Reflect.get(target, property, target);\n return typeof value === 'function' ? value.bind(target) : value;\n}\n\nfunction withParentSession(ctx: ExtensionContext, parentSessionId: string): ExtensionContext {\n const sessionManager = new Proxy(ctx.sessionManager, {\n get(target, property) {\n if (property === 'getSessionId') return () => parentSessionId;\n return boundValue(target, property);\n },\n });\n return new Proxy(ctx, {\n get(target, property) {\n if (property === 'sessionManager') return sessionManager;\n return boundValue(target, property);\n },\n });\n}\n\nexport function createDispatcherBridge(\n pi: ExtensionAPI,\n parentSessionId: string | undefined,\n environment: Readonly<Record<string, string | undefined>> = process.env,\n): ExtensionAPI {\n const rootSessionId = parentSessionId ? resolveRootSessionId(parentSessionId, environment) : undefined;\n return new Proxy(pi, {\n get(target, property) {\n if (property === 'setActiveTools') {\n return (names: string[]): void => target.setActiveTools(names.filter((name) => name !== 'workflow_run'));\n }\n if (property !== 'registerTool') return boundValue(target, property);\n return (tool: RegisteredTool): void => {\n if (!DISPATCHER_TOOL_NAMES.has(tool.name)) return;\n if (!rootSessionId || !ROOT_SCOPED_TOOL_NAMES.has(tool.name)) {\n target.registerTool(tool);\n return;\n }\n target.registerTool({\n ...tool,\n execute: (toolCallId, params, signal, onUpdate, ctx) =>\n tool.execute(toolCallId, params, signal, onUpdate, withParentSession(ctx, rootSessionId)),\n });\n };\n },\n });\n}\n\nexport function resolveDispatcherParentSession(\n environment: Readonly<Record<string, string | undefined>>,\n): string | undefined {\n const childContext = readChildProcessContext(environment);\n return childContext?.parentSessionId ?? (environment[SUBAGENT_PARENT_SESSION_ENV]?.trim() || undefined);\n}\n\nexport function registerWorkflowDispatcherExtension(pi: ExtensionAPI): void {\n const parentSessionId = resolveDispatcherParentSession(process.env);\n const rootSessionId = parentSessionId ? resolveRootSessionId(parentSessionId) : undefined;\n createWorkflowPiExtension()(createDispatcherBridge(pi, rootSessionId));\n\n pi.on('session_start', (_event, ctx) => {\n const sessionId = resolveRootSessionId(ctx.sessionManager.getSessionId());\n createProtocolRuntime({\n bus: pi.events,\n source: '@agimon-ai/doompi-workflow/dispatcher',\n sessionId,\n }).notify(WorkflowModeChanged, { mode: 'on', ...(rootSessionId ? { parentSessionId: rootSessionId } : {}) });\n });\n}\n"],"mappings":"2OAWA,MAAM,EAAwB,IAAI,IAAI,CAAC,iBAAkB,iBAAiB,CAAC,EACrE,EAAyB,IAAI,IAAI,CAAC,iBAAiB,CAAC,EAE1D,SAAS,EAAW,EAAgB,EAAgC,CAClE,IAAM,EAAQ,QAAQ,IAAI,EAAQ,EAAU,CAAM,EAClD,OAAO,OAAO,GAAU,WAAa,EAAM,KAAK,CAAM,EAAI,CAC5D,CAEA,SAAS,EAAkB,EAAuB,EAA2C,CAC3F,IAAM,EAAiB,IAAI,MAAM,EAAI,eAAgB,CACnD,IAAI,EAAQ,EAAU,CAEpB,OADI,IAAa,mBAA6B,EACvC,EAAW,EAAQ,CAAQ,CACpC,CACF,CAAC,EACD,OAAO,IAAI,MAAM,EAAK,CACpB,IAAI,EAAQ,EAAU,CAEpB,OADI,IAAa,iBAAyB,EACnC,EAAW,EAAQ,CAAQ,CACpC,CACF,CAAC,CACH,CAEA,SAAgB,EACd,EACA,EACA,EAA4D,QAAQ,IACtD,CACd,IAAM,EAAgB,GAAA,EAAkBA,EAAAA,qBAAAA,CAAqB,EAAiB,CAAW,EAAI,IAAA,GAC7F,OAAO,IAAI,MAAM,EAAI,CACnB,IAAI,EAAQ,EAAU,CAKpB,OAJI,IAAa,iBACP,GAA0B,EAAO,eAAe,EAAM,OAAQ,GAAS,IAAS,cAAc,CAAC,EAErG,IAAa,eACT,GAA+B,CAChC,KAAsB,IAAI,EAAK,IAAI,EACxC,IAAI,CAAC,GAAiB,CAAC,EAAuB,IAAI,EAAK,IAAI,EAAG,CAC5D,EAAO,aAAa,CAAI,EACxB,MACF,CACA,EAAO,aAAa,CAClB,GAAG,EACH,SAAU,EAAY,EAAQ,EAAQ,EAAU,IAC9C,EAAK,QAAQ,EAAY,EAAQ,EAAQ,EAAU,EAAkB,EAAK,CAAa,CAAC,CAC5F,CAAC,CALD,CAMF,EAZwC,EAAW,EAAQ,CAAQ,CAarE,CACF,CAAC,CACH,CAEA,SAAgB,EACd,EACoB,CAEpB,OAAA,EADqBC,EAAAA,wBAAAA,CAAwB,CAC3B,CAAC,EAAE,kBAAoB,EAAYC,EAAAA,4BAA4B,EAAE,KAAK,GAAK,IAAA,GAC/F,CAEA,SAAgB,EAAoC,EAAwB,CAC1E,IAAM,EAAkB,EAA+B,QAAQ,GAAG,EAC5D,EAAgB,GAAA,EAAkBF,EAAAA,qBAAAA,CAAqB,CAAe,EAAI,IAAA,GAChF,EAAA,0BAA0B,CAAC,CAAC,EAAuB,EAAI,CAAa,CAAC,EAErE,EAAG,GAAG,iBAAkB,EAAQ,IAAQ,CACtC,IAAM,GAAA,EAAYA,EAAAA,qBAAAA,CAAqB,EAAI,eAAe,aAAa,CAAC,GACxE,EAAA,EAAA,sBAAA,CAAsB,CACpB,IAAK,EAAG,OACR,OAAQ,wCACR,WACF,CAAC,CAAC,CAAC,OAAOG,EAAAA,oBAAqB,CAAE,KAAM,KAAM,GAAI,EAAgB,CAAE,gBAAiB,CAAc,EAAI,CAAC,CAAG,CAAC,CAC7G,CAAC,CACH"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.d.cts","names":[],"sources":["../src/dispatcher.ts"],"mappings":";;iBAqEgB,oCAAoC,IAAI"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.d.mts","names":[],"sources":["../src/dispatcher.ts"],"mappings":";;iBAqEgB,oCAAoC,IAAI"}
|
package/dist/dispatcher.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.mjs","names":[],"sources":["../src/dispatcher.ts"],"sourcesContent":["import {\n readChildProcessContext,\n resolveRootSessionId,\n SUBAGENT_PARENT_SESSION_ENV,\n} from '@agimon-ai/doompi-extension-contracts/child-process';\nimport { createProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\nimport { WorkflowModeChanged } from '@agimon-ai/doompi-extension-contracts/workflow';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport { createWorkflowPiExtension } from './workflow/piExtension.ts';\n\ntype RegisteredTool = Parameters<ExtensionAPI['registerTool']>[0];\nconst DISPATCHER_TOOL_NAMES = new Set(['list_workflows', 'launch_workflow']);\nconst ROOT_SCOPED_TOOL_NAMES = new Set(['launch_workflow']);\n\nfunction boundValue(target: object, property: PropertyKey): unknown {\n const value = Reflect.get(target, property, target);\n return typeof value === 'function' ? value.bind(target) : value;\n}\n\nfunction withParentSession(ctx: ExtensionContext, parentSessionId: string): ExtensionContext {\n const sessionManager = new Proxy(ctx.sessionManager, {\n get(target, property) {\n if (property === 'getSessionId') return () => parentSessionId;\n return boundValue(target, property);\n },\n });\n return new Proxy(ctx, {\n get(target, property) {\n if (property === 'sessionManager') return sessionManager;\n return boundValue(target, property);\n },\n });\n}\n\nexport function createDispatcherBridge(\n pi: ExtensionAPI,\n parentSessionId: string | undefined,\n environment: Readonly<Record<string, string | undefined>> = process.env,\n): ExtensionAPI {\n const rootSessionId = parentSessionId ? resolveRootSessionId(parentSessionId, environment) : undefined;\n return new Proxy(pi, {\n get(target, property) {\n if (property === 'setActiveTools') {\n return (names: string[]): void => target.setActiveTools(names.filter((name) => name !== 'workflow_run'));\n }\n if (property !== 'registerTool') return boundValue(target, property);\n return (tool: RegisteredTool): void => {\n if (!DISPATCHER_TOOL_NAMES.has(tool.name)) return;\n if (!rootSessionId || !ROOT_SCOPED_TOOL_NAMES.has(tool.name)) {\n target.registerTool(tool);\n return;\n }\n target.registerTool({\n ...tool,\n execute: (toolCallId, params, signal, onUpdate, ctx) =>\n tool.execute(toolCallId, params, signal, onUpdate, withParentSession(ctx, rootSessionId)),\n });\n };\n },\n });\n}\n\nexport function resolveDispatcherParentSession(\n environment: Readonly<Record<string, string | undefined>>,\n): string | undefined {\n const childContext = readChildProcessContext(environment);\n return childContext?.parentSessionId ?? (environment[SUBAGENT_PARENT_SESSION_ENV]?.trim() || undefined);\n}\n\nexport function registerWorkflowDispatcherExtension(pi: ExtensionAPI): void {\n const parentSessionId = resolveDispatcherParentSession(process.env);\n const rootSessionId = parentSessionId ? resolveRootSessionId(parentSessionId) : undefined;\n createWorkflowPiExtension()(createDispatcherBridge(pi, rootSessionId));\n\n pi.on('session_start', (_event, ctx) => {\n const sessionId = resolveRootSessionId(ctx.sessionManager.getSessionId());\n createProtocolRuntime({\n bus: pi.events,\n source: '@agimon-ai/doompi-workflow/dispatcher',\n sessionId,\n }).notify(WorkflowModeChanged, { mode: 'on', ...(rootSessionId ? { parentSessionId: rootSessionId } : {}) });\n });\n}\n"],"mappings":"4YAWA,MAAM,EAAwB,IAAI,IAAI,CAAC,iBAAkB,iBAAiB,CAAC,EACrE,EAAyB,IAAI,IAAI,CAAC,iBAAiB,CAAC,EAE1D,SAAS,EAAW,EAAgB,EAAgC,CAClE,IAAM,EAAQ,QAAQ,IAAI,EAAQ,EAAU,CAAM,EAClD,OAAO,OAAO,GAAU,WAAa,EAAM,KAAK,CAAM,EAAI,CAC5D,CAEA,SAAS,EAAkB,EAAuB,EAA2C,CAC3F,IAAM,EAAiB,IAAI,MAAM,EAAI,eAAgB,CACnD,IAAI,EAAQ,EAAU,CAEpB,OADI,IAAa,mBAA6B,EACvC,EAAW,EAAQ,CAAQ,CACpC,CACF,CAAC,EACD,OAAO,IAAI,MAAM,EAAK,CACpB,IAAI,EAAQ,EAAU,CAEpB,OADI,IAAa,iBAAyB,EACnC,EAAW,EAAQ,CAAQ,CACpC,CACF,CAAC,CACH,CAEA,SAAgB,EACd,EACA,EACA,EAA4D,QAAQ,IACtD,CACd,IAAM,EAAgB,EAAkB,EAAqB,EAAiB,CAAW,EAAI,IAAA,GAC7F,OAAO,IAAI,MAAM,EAAI,CACnB,IAAI,EAAQ,EAAU,CAKpB,OAJI,IAAa,iBACP,GAA0B,EAAO,eAAe,EAAM,OAAQ,GAAS,IAAS,cAAc,CAAC,EAErG,IAAa,eACT,GAA+B,CAChC,KAAsB,IAAI,EAAK,IAAI,EACxC,IAAI,CAAC,GAAiB,CAAC,EAAuB,IAAI,EAAK,IAAI,EAAG,CAC5D,EAAO,aAAa,CAAI,EACxB,MACF,CACA,EAAO,aAAa,CAClB,GAAG,EACH,SAAU,EAAY,EAAQ,EAAQ,EAAU,IAC9C,EAAK,QAAQ,EAAY,EAAQ,EAAQ,EAAU,EAAkB,EAAK,CAAa,CAAC,CAC5F,CAAC,CALD,CAMF,EAZwC,EAAW,EAAQ,CAAQ,CAarE,CACF,CAAC,CACH,CAEA,SAAgB,EACd,EACoB,CAEpB,OADqB,EAAwB,CAC3B,CAAC,EAAE,kBAAoB,EAAY,EAA4B,EAAE,KAAK,GAAK,IAAA,GAC/F,CAEA,SAAgB,EAAoC,EAAwB,CAC1E,IAAM,EAAkB,EAA+B,QAAQ,GAAG,EAC5D,EAAgB,EAAkB,EAAqB,CAAe,EAAI,IAAA,GAChF,EAA0B,CAAC,CAAC,EAAuB,EAAI,CAAa,CAAC,EAErE,EAAG,GAAG,iBAAkB,EAAQ,IAAQ,CACtC,IAAM,EAAY,EAAqB,EAAI,eAAe,aAAa,CAAC,EACxE,EAAsB,CACpB,IAAK,EAAG,OACR,OAAQ,wCACR,WACF,CAAC,CAAC,CAAC,OAAO,EAAqB,CAAE,KAAM,KAAM,GAAI,EAAgB,CAAE,gBAAiB,CAAc,EAAI,CAAC,CAAG,CAAC,CAC7G,CAAC,CACH"}
|
package/dist/extension.cjs
DELETED
package/dist/extension.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"extension.cjs","names":["registerLeaderContribution"],"sources":["../src/extension.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { registerLeaderContribution } from './leader.ts';\nimport { createWorkflowPiExtension } from './workflow/piExtension.ts';\n\nexport function registerWorkflowExtension(pi: ExtensionAPI): void {\n const leader = registerLeaderContribution(pi);\n createWorkflowPiExtension({ onModeChange: (enabled) => leader.setMode(enabled) })(pi);\n}\n"],"mappings":"wEAIA,SAAgB,EAA0B,EAAwB,CAChE,IAAM,EAASA,EAAAA,2BAA2B,CAAE,EAC5C,EAAA,0BAA0B,CAAE,aAAe,GAAY,EAAO,QAAQ,CAAO,CAAE,CAAC,CAAC,CAAC,CAAE,CACtF"}
|
package/dist/extension.d.cts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.cts","names":[],"sources":["../src/extension.ts"],"mappings":";;iBAIgB,0BAA0B,IAAI"}
|
package/dist/extension.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.mts","names":[],"sources":["../src/extension.ts"],"mappings":";;iBAIgB,0BAA0B,IAAI"}
|
package/dist/extension.mjs
DELETED
package/dist/extension.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"extension.mjs","names":[],"sources":["../src/extension.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { registerLeaderContribution } from './leader.ts';\nimport { createWorkflowPiExtension } from './workflow/piExtension.ts';\n\nexport function registerWorkflowExtension(pi: ExtensionAPI): void {\n const leader = registerLeaderContribution(pi);\n createWorkflowPiExtension({ onModeChange: (enabled) => leader.setMode(enabled) })(pi);\n}\n"],"mappings":"iIAIA,SAAgB,EAA0B,EAAwB,CAChE,IAAM,EAAS,EAA2B,CAAE,EAC5C,EAA0B,CAAE,aAAe,GAAY,EAAO,QAAQ,CAAO,CAAE,CAAC,CAAC,CAAC,CAAE,CACtF"}
|
package/dist/leader.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("./types.cjs");let t=require("@agimon-ai/doompi-extension-contracts/leader");const n=`doom-workflow`,r={key:`w`,label:e.LEADER_LABEL,order:50};function i(t){return[{id:`${n}.manage`,path:[r,{key:`l`,label:`manage`,detail:`running workflows`}],action:{name:e.LEADER_MANAGE_ACTION}},{id:`${n}.launch`,path:[r,{key:`w`,label:`launch`,detail:`start a workflow`}],action:{name:e.LEADER_LAUNCH_ACTION}},t?{id:`${n}.disable`,path:[r,{key:`e`,label:`exit`,detail:`take back workflow tools`}],action:{name:e.LEADER_DISABLE_ACTION}}:{id:`${n}.enable`,path:[r,{key:`e`,label:`enter`,detail:`give the agent workflow tools`}],action:{name:e.LEADER_ENABLE_ACTION}},{id:`${n}.recover`,path:[r,{key:`r`,label:`recover`,detail:`failed workflow`}],action:{name:e.LEADER_RECOVER_ACTION}}]}function a(n){let r=(0,t.createDoomLeaderContribution)(n,{source:e.PACKAGE_SOURCE,bindings:i(!1)});return{setMode(e){r.update(i(e))},dispose(){r.dispose()}}}exports.registerLeaderContribution=a,exports.workflowLeaderBindings=i;
|
|
2
|
-
//# sourceMappingURL=leader.cjs.map
|
package/dist/leader.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"leader.cjs","names":["LEADER_LABEL","LEADER_MANAGE_ACTION","LEADER_LAUNCH_ACTION","LEADER_DISABLE_ACTION","LEADER_ENABLE_ACTION","LEADER_RECOVER_ACTION","createDoomLeaderContribution","PACKAGE_SOURCE"],"sources":["../src/leader.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { createDoomLeaderContribution, type LeaderBinding } from '@agimon-ai/doompi-extension-contracts/leader';\nimport {\n LEADER_DISABLE_ACTION,\n LEADER_ENABLE_ACTION,\n LEADER_KEY,\n LEADER_LABEL,\n LEADER_LAUNCH_ACTION,\n LEADER_MANAGE_ACTION,\n LEADER_ORDER,\n LEADER_RECOVER_ACTION,\n PACKAGE_SOURCE,\n} from './types.ts';\n\nconst LEADER_BINDING_PREFIX = 'doom-workflow';\nconst GROUP_SEGMENT = { key: LEADER_KEY, label: LEADER_LABEL, order: LEADER_ORDER } as const;\n\nexport interface WorkflowLeaderHandle {\n /** Republish the menu for the mode's current state. */\n setMode(enabled: boolean): void;\n dispose(): void;\n}\n\n/**\n * The menu as it stands with the mode on or off.\n *\n * One entry on `e` rather than an enable row beside a disable row: only one of\n * the two ever does anything, and a menu that prints both makes the reader\n * check the mode line to find out which. The label says which way it flips.\n */\nexport function workflowLeaderBindings(mode: boolean): LeaderBinding[] {\n return [\n {\n id: `${LEADER_BINDING_PREFIX}.manage`,\n path: [GROUP_SEGMENT, { key: 'l', label: 'manage', detail: 'running workflows' }],\n action: { name: LEADER_MANAGE_ACTION },\n },\n {\n id: `${LEADER_BINDING_PREFIX}.launch`,\n path: [GROUP_SEGMENT, { key: 'w', label: 'launch', detail: 'start a workflow' }],\n action: { name: LEADER_LAUNCH_ACTION },\n },\n mode\n ? {\n id: `${LEADER_BINDING_PREFIX}.disable`,\n path: [GROUP_SEGMENT, { key: 'e', label: 'exit', detail: 'take back workflow tools' }],\n action: { name: LEADER_DISABLE_ACTION },\n }\n : {\n id: `${LEADER_BINDING_PREFIX}.enable`,\n path: [GROUP_SEGMENT, { key: 'e', label: 'enter', detail: 'give the agent workflow tools' }],\n action: { name: LEADER_ENABLE_ACTION },\n },\n {\n id: `${LEADER_BINDING_PREFIX}.recover`,\n path: [GROUP_SEGMENT, { key: 'r', label: 'recover', detail: 'failed workflow' }],\n action: { name: LEADER_RECOVER_ACTION },\n },\n ];\n}\n\nexport function registerLeaderContribution(pi: Pick<ExtensionAPI, 'events' | 'on'>): WorkflowLeaderHandle {\n const contribution = createDoomLeaderContribution(pi, {\n source: PACKAGE_SOURCE,\n bindings: workflowLeaderBindings(false),\n });\n return {\n setMode(enabled) {\n contribution.update(workflowLeaderBindings(enabled));\n },\n dispose() {\n contribution.dispose();\n },\n };\n}\n"],"mappings":"6FAcA,MAAM,EAAwB,gBACxB,EAAgB,CAAE,IAAA,IAAiB,MAAOA,EAAAA,aAAc,MAAA,EAAoB,EAelF,SAAgB,EAAuB,EAAgC,CACrE,MAAO,CACL,CACE,GAAI,GAAG,EAAsB,SAC7B,KAAM,CAAC,EAAe,CAAE,IAAK,IAAK,MAAO,SAAU,OAAQ,mBAAoB,CAAC,EAChF,OAAQ,CAAE,KAAMC,EAAAA,oBAAqB,CACvC,EACA,CACE,GAAI,GAAG,EAAsB,SAC7B,KAAM,CAAC,EAAe,CAAE,IAAK,IAAK,MAAO,SAAU,OAAQ,kBAAmB,CAAC,EAC/E,OAAQ,CAAE,KAAMC,EAAAA,oBAAqB,CACvC,EACA,EACI,CACE,GAAI,GAAG,EAAsB,UAC7B,KAAM,CAAC,EAAe,CAAE,IAAK,IAAK,MAAO,OAAQ,OAAQ,0BAA2B,CAAC,EACrF,OAAQ,CAAE,KAAMC,EAAAA,qBAAsB,CACxC,EACA,CACE,GAAI,GAAG,EAAsB,SAC7B,KAAM,CAAC,EAAe,CAAE,IAAK,IAAK,MAAO,QAAS,OAAQ,+BAAgC,CAAC,EAC3F,OAAQ,CAAE,KAAMC,EAAAA,oBAAqB,CACvC,EACJ,CACE,GAAI,GAAG,EAAsB,UAC7B,KAAM,CAAC,EAAe,CAAE,IAAK,IAAK,MAAO,UAAW,OAAQ,iBAAkB,CAAC,EAC/E,OAAQ,CAAE,KAAMC,EAAAA,qBAAsB,CACxC,CACF,CACF,CAEA,SAAgB,EAA2B,EAA+D,CACxG,IAAM,GAAA,EAAeC,EAAAA,6BAAAA,CAA6B,EAAI,CACpD,OAAQC,EAAAA,eACR,SAAU,EAAuB,EAAK,CACxC,CAAC,EACD,MAAO,CACL,QAAQ,EAAS,CACf,EAAa,OAAO,EAAuB,CAAO,CAAC,CACrD,EACA,SAAU,CACR,EAAa,QAAQ,CACvB,CACF,CACF"}
|
package/dist/leader.mjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{LEADER_DISABLE_ACTION as e,LEADER_ENABLE_ACTION as t,LEADER_LABEL as n,LEADER_LAUNCH_ACTION as r,LEADER_MANAGE_ACTION as i,LEADER_RECOVER_ACTION as a,PACKAGE_SOURCE as o}from"./types.mjs";import{createDoomLeaderContribution as s}from"@agimon-ai/doompi-extension-contracts/leader";const c=`doom-workflow`,l={key:`w`,label:n,order:50};function u(n){return[{id:`${c}.manage`,path:[l,{key:`l`,label:`manage`,detail:`running workflows`}],action:{name:i}},{id:`${c}.launch`,path:[l,{key:`w`,label:`launch`,detail:`start a workflow`}],action:{name:r}},n?{id:`${c}.disable`,path:[l,{key:`e`,label:`exit`,detail:`take back workflow tools`}],action:{name:e}}:{id:`${c}.enable`,path:[l,{key:`e`,label:`enter`,detail:`give the agent workflow tools`}],action:{name:t}},{id:`${c}.recover`,path:[l,{key:`r`,label:`recover`,detail:`failed workflow`}],action:{name:a}}]}function d(e){let t=s(e,{source:o,bindings:u(!1)});return{setMode(e){t.update(u(e))},dispose(){t.dispose()}}}export{d as registerLeaderContribution,u as workflowLeaderBindings};
|
|
2
|
-
//# sourceMappingURL=leader.mjs.map
|
package/dist/leader.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"leader.mjs","names":[],"sources":["../src/leader.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { createDoomLeaderContribution, type LeaderBinding } from '@agimon-ai/doompi-extension-contracts/leader';\nimport {\n LEADER_DISABLE_ACTION,\n LEADER_ENABLE_ACTION,\n LEADER_KEY,\n LEADER_LABEL,\n LEADER_LAUNCH_ACTION,\n LEADER_MANAGE_ACTION,\n LEADER_ORDER,\n LEADER_RECOVER_ACTION,\n PACKAGE_SOURCE,\n} from './types.ts';\n\nconst LEADER_BINDING_PREFIX = 'doom-workflow';\nconst GROUP_SEGMENT = { key: LEADER_KEY, label: LEADER_LABEL, order: LEADER_ORDER } as const;\n\nexport interface WorkflowLeaderHandle {\n /** Republish the menu for the mode's current state. */\n setMode(enabled: boolean): void;\n dispose(): void;\n}\n\n/**\n * The menu as it stands with the mode on or off.\n *\n * One entry on `e` rather than an enable row beside a disable row: only one of\n * the two ever does anything, and a menu that prints both makes the reader\n * check the mode line to find out which. The label says which way it flips.\n */\nexport function workflowLeaderBindings(mode: boolean): LeaderBinding[] {\n return [\n {\n id: `${LEADER_BINDING_PREFIX}.manage`,\n path: [GROUP_SEGMENT, { key: 'l', label: 'manage', detail: 'running workflows' }],\n action: { name: LEADER_MANAGE_ACTION },\n },\n {\n id: `${LEADER_BINDING_PREFIX}.launch`,\n path: [GROUP_SEGMENT, { key: 'w', label: 'launch', detail: 'start a workflow' }],\n action: { name: LEADER_LAUNCH_ACTION },\n },\n mode\n ? {\n id: `${LEADER_BINDING_PREFIX}.disable`,\n path: [GROUP_SEGMENT, { key: 'e', label: 'exit', detail: 'take back workflow tools' }],\n action: { name: LEADER_DISABLE_ACTION },\n }\n : {\n id: `${LEADER_BINDING_PREFIX}.enable`,\n path: [GROUP_SEGMENT, { key: 'e', label: 'enter', detail: 'give the agent workflow tools' }],\n action: { name: LEADER_ENABLE_ACTION },\n },\n {\n id: `${LEADER_BINDING_PREFIX}.recover`,\n path: [GROUP_SEGMENT, { key: 'r', label: 'recover', detail: 'failed workflow' }],\n action: { name: LEADER_RECOVER_ACTION },\n },\n ];\n}\n\nexport function registerLeaderContribution(pi: Pick<ExtensionAPI, 'events' | 'on'>): WorkflowLeaderHandle {\n const contribution = createDoomLeaderContribution(pi, {\n source: PACKAGE_SOURCE,\n bindings: workflowLeaderBindings(false),\n });\n return {\n setMode(enabled) {\n contribution.update(workflowLeaderBindings(enabled));\n },\n dispose() {\n contribution.dispose();\n },\n };\n}\n"],"mappings":"+RAcA,MAAM,EAAwB,gBACxB,EAAgB,CAAE,IAAA,IAAiB,MAAO,EAAc,MAAA,EAAoB,EAelF,SAAgB,EAAuB,EAAgC,CACrE,MAAO,CACL,CACE,GAAI,GAAG,EAAsB,SAC7B,KAAM,CAAC,EAAe,CAAE,IAAK,IAAK,MAAO,SAAU,OAAQ,mBAAoB,CAAC,EAChF,OAAQ,CAAE,KAAM,CAAqB,CACvC,EACA,CACE,GAAI,GAAG,EAAsB,SAC7B,KAAM,CAAC,EAAe,CAAE,IAAK,IAAK,MAAO,SAAU,OAAQ,kBAAmB,CAAC,EAC/E,OAAQ,CAAE,KAAM,CAAqB,CACvC,EACA,EACI,CACE,GAAI,GAAG,EAAsB,UAC7B,KAAM,CAAC,EAAe,CAAE,IAAK,IAAK,MAAO,OAAQ,OAAQ,0BAA2B,CAAC,EACrF,OAAQ,CAAE,KAAM,CAAsB,CACxC,EACA,CACE,GAAI,GAAG,EAAsB,SAC7B,KAAM,CAAC,EAAe,CAAE,IAAK,IAAK,MAAO,QAAS,OAAQ,+BAAgC,CAAC,EAC3F,OAAQ,CAAE,KAAM,CAAqB,CACvC,EACJ,CACE,GAAI,GAAG,EAAsB,UAC7B,KAAM,CAAC,EAAe,CAAE,IAAK,IAAK,MAAO,UAAW,OAAQ,iBAAkB,CAAC,EAC/E,OAAQ,CAAE,KAAM,CAAsB,CACxC,CACF,CACF,CAEA,SAAgB,EAA2B,EAA+D,CACxG,IAAM,EAAe,EAA6B,EAAI,CACpD,OAAQ,EACR,SAAU,EAAuB,EAAK,CACxC,CAAC,EACD,MAAO,CACL,QAAQ,EAAS,CACf,EAAa,OAAO,EAAuB,CAAO,CAAC,CACrD,EACA,SAAU,CACR,EAAa,QAAQ,CACvB,CACF,CACF"}
|
package/dist/types.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.cjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["export const PACKAGE_SOURCE = '@agimon-ai/doompi-workflow';\nexport const COMMAND_DESCRIPTION = 'Doom Pi workflow execution and monitoring integration';\nexport const LEADER_KEY = 'w';\nexport const LEADER_LABEL = 'workflows';\nexport const LEADER_ORDER = 50;\nexport const LEADER_ENABLE_ACTION = 'workflow.enable';\nexport const LEADER_DISABLE_ACTION = 'workflow.disable';\nexport const LEADER_MANAGE_ACTION = 'workflow.manage';\nexport const LEADER_LAUNCH_ACTION = 'workflow.launch';\nexport const LEADER_RECOVER_ACTION = 'workflow.recover';\n"],"mappings":""}
|
package/dist/types.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.mjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["export const PACKAGE_SOURCE = '@agimon-ai/doompi-workflow';\nexport const COMMAND_DESCRIPTION = 'Doom Pi workflow execution and monitoring integration';\nexport const LEADER_KEY = 'w';\nexport const LEADER_LABEL = 'workflows';\nexport const LEADER_ORDER = 50;\nexport const LEADER_ENABLE_ACTION = 'workflow.enable';\nexport const LEADER_DISABLE_ACTION = 'workflow.disable';\nexport const LEADER_MANAGE_ACTION = 'workflow.manage';\nexport const LEADER_LAUNCH_ACTION = 'workflow.launch';\nexport const LEADER_RECOVER_ACTION = 'workflow.recover';\n"],"mappings":"AAAA,MAAa,EAAiB,6BAGjB,EAAe,YAEf,EAAuB,kBACvB,EAAwB,mBACxB,EAAuB,kBACvB,EAAuB,kBACvB,EAAwB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"backgroundWork.cjs","names":["registerBackgroundWorkProvider"],"sources":["../../src/workflow/backgroundWork.ts"],"sourcesContent":["/**\n * Background-work registration for workflow runs.\n *\n * DESIGN PATTERNS:\n * - Pi event-bus integration through the shared typed protocol\n * - Snapshot pattern: the extension pushes the current run set, the provider\n * only reads it\n *\n * CODING STANDARDS:\n * - Named exports only\n * - Explicit return types on exported functions\n *\n * AVOID:\n * - Process-global symbols or dynamic imports for extension communication\n * - Reporting runs owned by another Pi session\n */\n\nimport {\n registerBackgroundWorkProvider,\n type BackgroundWorkProviderHandle,\n} from '@agimon-ai/doompi-extension-contracts/background-work';\nimport type { ProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\n\nexport interface RunProviderItem {\n id: string;\n sessionId: string;\n}\n\nexport interface RunProviderHandle {\n /** Replace the reported run set. */\n update(items: RunProviderItem[]): void;\n /** Remove the registration. Safe to call when registration never happened. */\n dispose(): void;\n}\n\nconst PROVIDER_NAME = 'workflow-mcp';\n\n/**\n * Register a background-work provider for this session's workflow runs.\n *\n * The runtime pins all announcements to the active Pi session and validates\n * each snapshot before it reaches another extension.\n */\nexport function registerRunProvider(runtime: ProtocolRuntime): RunProviderHandle {\n let items: RunProviderItem[] = [];\n const provider: BackgroundWorkProviderHandle = registerBackgroundWorkProvider(runtime, {\n provider: PROVIDER_NAME,\n listActiveWork: () => items,\n });\n const handle: RunProviderHandle = {\n update(next) {\n items = next;\n provider.update();\n },\n dispose() {\n items = [];\n provider.dispose();\n },\n };\n return handle;\n}\n"],"mappings":"uEA2CA,SAAgB,EAAoB,EAA6C,CAC/E,IAAI,EAA2B,CAAC,EAC1B,GAAA,EAAyCA,EAAAA,+BAAAA,CAA+B,EAAS,CACrF,SAAU,eACV,mBAAsB,CACxB,CAAC,EAWD,MAAO,CATL,OAAO,EAAM,CACX,EAAQ,EACR,EAAS,OAAO,CAClB,EACA,SAAU,CACR,EAAQ,CAAC,EACT,EAAS,QAAQ,CACnB,CAEU,CACd"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"backgroundWork.mjs","names":[],"sources":["../../src/workflow/backgroundWork.ts"],"sourcesContent":["/**\n * Background-work registration for workflow runs.\n *\n * DESIGN PATTERNS:\n * - Pi event-bus integration through the shared typed protocol\n * - Snapshot pattern: the extension pushes the current run set, the provider\n * only reads it\n *\n * CODING STANDARDS:\n * - Named exports only\n * - Explicit return types on exported functions\n *\n * AVOID:\n * - Process-global symbols or dynamic imports for extension communication\n * - Reporting runs owned by another Pi session\n */\n\nimport {\n registerBackgroundWorkProvider,\n type BackgroundWorkProviderHandle,\n} from '@agimon-ai/doompi-extension-contracts/background-work';\nimport type { ProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\n\nexport interface RunProviderItem {\n id: string;\n sessionId: string;\n}\n\nexport interface RunProviderHandle {\n /** Replace the reported run set. */\n update(items: RunProviderItem[]): void;\n /** Remove the registration. Safe to call when registration never happened. */\n dispose(): void;\n}\n\nconst PROVIDER_NAME = 'workflow-mcp';\n\n/**\n * Register a background-work provider for this session's workflow runs.\n *\n * The runtime pins all announcements to the active Pi session and validates\n * each snapshot before it reaches another extension.\n */\nexport function registerRunProvider(runtime: ProtocolRuntime): RunProviderHandle {\n let items: RunProviderItem[] = [];\n const provider: BackgroundWorkProviderHandle = registerBackgroundWorkProvider(runtime, {\n provider: PROVIDER_NAME,\n listActiveWork: () => items,\n });\n const handle: RunProviderHandle = {\n update(next) {\n items = next;\n provider.update();\n },\n dispose() {\n items = [];\n provider.dispose();\n },\n };\n return handle;\n}\n"],"mappings":"uGA2CA,SAAgB,EAAoB,EAA6C,CAC/E,IAAI,EAA2B,CAAC,EAC1B,EAAyC,EAA+B,EAAS,CACrF,SAAU,eACV,mBAAsB,CACxB,CAAC,EAWD,MAAO,CATL,OAAO,EAAM,CACX,EAAQ,EACR,EAAS,OAAO,CAClB,EACA,SAAU,CACR,EAAQ,CAAC,EACT,EAAS,QAAQ,CACnB,CAEU,CACd"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"doomOverlay.cjs","names":["visibleWidth","truncateToWidth","padLine","frameLine","fitLine"],"sources":["../../src/workflow/doomOverlay.ts"],"sourcesContent":["import type { Theme } from '@earendil-works/pi-coding-agent';\nimport { type Component, truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\nimport { fitLine, frameLine, padLine } from './rendering.ts';\n\nconst DEFAULT_TERMINAL_ROWS = 24;\nconst FULL_CHROME_ROWS = 6;\n/** Two frame columns and two gutter columns, leaving content worth framing. */\nconst MIN_FRAMED_WIDTH = 8;\nconst GUTTER = ' ';\nconst GUTTER_COLUMNS = 2;\n/** Blank columns kept between a row's left cluster and its right-aligned status. */\nconst ROW_GAP = 2;\n/** A secondary segment thinner than this is dropped rather than shredded into a stub. */\nconst MIN_SEGMENT_WIDTH = 8;\nconst ELLIPSIS = '…';\nconst BORDER_COLOR = 'borderMuted';\nconst TEXT_COLOR = 'text';\n/** Filled key caps read as pressable, matching the doom mockups' footers. */\nconst HINT_CAP_BACKGROUND = 'selectedBg';\nconst HINT_SEPARATOR = ' ';\n/** A cap's two pad columns plus the space before its label. */\nconst HINT_CHROME_COLUMNS = 6;\nconst TITLE_COLOR = 'accent';\nconst SECONDARY_COLOR = 'dim';\nconst HORIZONTAL_BORDER = '─';\nconst VERTICAL_BORDER = '│';\nconst TOP_CORNERS = ['╭', '╮'] as const;\nconst DIVIDER_JOINTS = ['├', '┤'] as const;\nconst BOTTOM_CORNERS = ['╰', '╯'] as const;\n\nexport interface DoomOverlayTui {\n terminal?: {\n rows: number;\n columns?: number;\n };\n requestRender(force?: boolean): void;\n}\n\nexport interface DoomOverlayChrome {\n title: string;\n breadcrumb?: string;\n headerRight?: string;\n footer: string;\n footerRight?: string;\n /**\n * Key/label pairs rendered as filled caps, e.g. `[ enter ] edit subject`.\n * Takes precedence over `footer`, which stays for surfaces that want a plain\n * sentence rather than a key legend.\n */\n footerHints?: readonly (readonly [string, string])[];\n /**\n * Signature colour for the surface. When set, the frame takes it and the\n * title renders as a filled badge rather than plain accent text, matching the\n * doom mockups. Left unset, the frame stays muted and the title plain.\n */\n accent?: Parameters<Theme['fg']>[0];\n}\n\n/**\n * One signature colour for every doom overlay: the frame and the title badge.\n * Per-surface colours were tried and read as arbitrary, and they also borrowed\n * tokens that mean something else (`warning`, `syntaxNumber`), so a theme edit\n * elsewhere would have repainted a frame. Change it here to change them all.\n */\nexport const DOOM_OVERLAY_ACCENT = 'mdHeading' satisfies DoomOverlayChrome['accent'];\n\nexport const DOOM_FULLSCREEN_UI_OPTIONS = {\n overlay: true,\n overlayOptions: {\n anchor: 'top-left',\n width: '100%',\n maxHeight: '100%',\n margin: 0,\n },\n} as const;\n\n/**\n * Fits a secondary segment into `budget`, or drops it entirely when too few\n * columns remain for it to stay readable. Truncating everything to fit is what\n * makes a tight header read as one run-on string.\n */\nfunction fitSegment(text: string | undefined, budget: number): string {\n if (!text || budget <= 0) return '';\n return budget < Math.min(visibleWidth(text), MIN_SEGMENT_WIDTH) ? '' : truncateToWidth(text, budget, ELLIPSIS);\n}\n\nexport abstract class DoomOverlay implements Component {\n protected constructor(\n protected readonly tui: DoomOverlayTui,\n protected readonly theme: Theme,\n ) {}\n\n invalidate(): void {\n this.tui.requestRender();\n }\n\n render(width: number): string[] {\n const safeWidth = Math.max(0, Math.floor(width));\n const height = Math.max(0, Math.floor(this.tui.terminal?.rows ?? DEFAULT_TERMINAL_ROWS));\n if (safeWidth === 0 || height === 0) return [];\n\n const chrome = this.getChrome();\n if (height < FULL_CHROME_ROWS || safeWidth < MIN_FRAMED_WIDTH) {\n return this.renderCompact(chrome, safeWidth, height);\n }\n\n const innerWidth = safeWidth - GUTTER_COLUMNS;\n const contentWidth = innerWidth - GUTTER_COLUMNS;\n const bodyHeight = height - FULL_CHROME_ROWS;\n const body = this.renderBody(contentWidth, bodyHeight).slice(0, bodyHeight);\n while (body.length < bodyHeight) body.push('');\n\n const frame = chrome.accent ?? BORDER_COLOR;\n return [\n this.borderRow(TOP_CORNERS, innerWidth, frame),\n this.contentRow(this.headerRow(chrome, contentWidth), contentWidth, safeWidth, frame),\n this.borderRow(DIVIDER_JOINTS, innerWidth, frame, BORDER_COLOR),\n ...body.map((line) => this.contentRow(line, contentWidth, safeWidth, frame)),\n this.borderRow(DIVIDER_JOINTS, innerWidth, frame, BORDER_COLOR),\n this.contentRow(this.footerRow(chrome, contentWidth), contentWidth, safeWidth, frame),\n this.borderRow(BOTTOM_CORNERS, innerWidth, frame),\n ].map((line) => padLine(line, safeWidth));\n }\n\n protected abstract getChrome(): DoomOverlayChrome;\n\n protected abstract renderBody(width: number, height: number): string[];\n\n /**\n * Edge glyphs and the rule between them are coloured separately: the outer\n * rectangle carries the signature colour while an internal separator stays\n * muted, meeting the frame at accent-coloured junctions.\n */\n private borderRow(\n [left, right]: readonly [string, string],\n innerWidth: number,\n edge: DoomOverlayChrome['accent'] = BORDER_COLOR,\n fill: DoomOverlayChrome['accent'] = edge,\n ): string {\n const edgeColour = edge ?? BORDER_COLOR;\n return [\n this.theme.fg(edgeColour, left),\n this.theme.fg(fill ?? edgeColour, HORIZONTAL_BORDER.repeat(innerWidth)),\n this.theme.fg(edgeColour, right),\n ].join('');\n }\n\n private contentRow(\n content: string,\n contentWidth: number,\n width: number,\n colour: DoomOverlayChrome['accent'] = BORDER_COLOR,\n ): string {\n const edge = this.theme.fg(colour ?? BORDER_COLOR, VERTICAL_BORDER);\n return frameLine(`${GUTTER}${padLine(content, contentWidth)}${GUTTER}`, width, edge, edge);\n }\n\n private headerRow(chrome: DoomOverlayChrome, width: number): string {\n // A signature colour turns the title into a filled badge, as the mockups\n // show; without one it stays plain accent text.\n const accent = chrome.accent;\n const titleBudget = accent ? width - GUTTER_COLUMNS : width;\n const title = truncateToWidth(chrome.title, Math.max(0, titleBudget), ELLIPSIS);\n let left = accent\n ? this.theme.inverse(this.theme.bold(this.theme.fg(accent, ` ${title} `)))\n : this.theme.bold(this.theme.fg(TITLE_COLOR, title));\n let leftWidth = visibleWidth(title) + (accent ? GUTTER_COLUMNS : 0);\n\n // The breadcrumb claims room before the right status: it says where you are,\n // which outranks ambient context when the terminal is narrow.\n const breadcrumb = fitSegment(chrome.breadcrumb, width - leftWidth - ROW_GAP);\n if (breadcrumb) {\n left += `${' '.repeat(ROW_GAP)}${this.theme.fg(SECONDARY_COLOR, breadcrumb)}`;\n leftWidth += ROW_GAP + visibleWidth(breadcrumb);\n }\n return this.withRightStatus(left, leftWidth, chrome.headerRight, width);\n }\n\n private footerRow(chrome: DoomOverlayChrome, width: number): string {\n const footer = chrome.footerHints?.length\n ? this.hintLegend(chrome.footerHints, width)\n : this.theme.fg(SECONDARY_COLOR, truncateToWidth(chrome.footer, width, ELLIPSIS));\n return this.withRightStatus(footer, visibleWidth(footer), chrome.footerRight, width);\n }\n\n /**\n * Key legend with each key in a filled cap. Every segment sets its own colour\n * so the caps survive: a cap's reset would otherwise strip the surrounding\n * dim from the labels that follow it.\n */\n private hintLegend(hints: readonly (readonly [string, string])[], width: number): string {\n let legend = '';\n let used = 0;\n for (const [key, label] of hints) {\n const segmentWidth = visibleWidth(key) + visibleWidth(label) + HINT_CHROME_COLUMNS;\n if (used + segmentWidth > width) break;\n const cap = this.theme.bg(HINT_CAP_BACKGROUND, this.theme.fg(TEXT_COLOR, ` ${key} `));\n legend += `${legend ? HINT_SEPARATOR : ''}${cap}${this.theme.fg(SECONDARY_COLOR, ` ${label}`)}`;\n used += segmentWidth;\n }\n return legend;\n }\n\n /**\n * Right-aligns a status cluster, dropping it whole when the row cannot spare\n * the columns. A clipped status reads as a stub (`doom-log…`) that carries\n * less than the blank space it costs.\n */\n private withRightStatus(left: string, leftWidth: number, right: string | undefined, width: number): string {\n const statusWidth = right ? visibleWidth(right) : 0;\n if (!right || statusWidth === 0 || leftWidth + ROW_GAP + statusWidth > width) return left;\n return `${left}${' '.repeat(width - leftWidth - statusWidth)}${this.theme.fg(SECONDARY_COLOR, right)}`;\n }\n\n private renderCompact(chrome: DoomOverlayChrome, width: number, height: number): string[] {\n const lines = Array.from({ length: height }, () => '');\n lines[0] = this.theme.bold(this.theme.fg(TITLE_COLOR, chrome.title));\n if (height > 1) lines[height - 1] = this.theme.fg(SECONDARY_COLOR, chrome.footer);\n return lines.map((line) => padLine(fitLine(line, width), width));\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"doomOverlay.mjs","names":[],"sources":["../../src/workflow/doomOverlay.ts"],"sourcesContent":["import type { Theme } from '@earendil-works/pi-coding-agent';\nimport { type Component, truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\nimport { fitLine, frameLine, padLine } from './rendering.ts';\n\nconst DEFAULT_TERMINAL_ROWS = 24;\nconst FULL_CHROME_ROWS = 6;\n/** Two frame columns and two gutter columns, leaving content worth framing. */\nconst MIN_FRAMED_WIDTH = 8;\nconst GUTTER = ' ';\nconst GUTTER_COLUMNS = 2;\n/** Blank columns kept between a row's left cluster and its right-aligned status. */\nconst ROW_GAP = 2;\n/** A secondary segment thinner than this is dropped rather than shredded into a stub. */\nconst MIN_SEGMENT_WIDTH = 8;\nconst ELLIPSIS = '…';\nconst BORDER_COLOR = 'borderMuted';\nconst TEXT_COLOR = 'text';\n/** Filled key caps read as pressable, matching the doom mockups' footers. */\nconst HINT_CAP_BACKGROUND = 'selectedBg';\nconst HINT_SEPARATOR = ' ';\n/** A cap's two pad columns plus the space before its label. */\nconst HINT_CHROME_COLUMNS = 6;\nconst TITLE_COLOR = 'accent';\nconst SECONDARY_COLOR = 'dim';\nconst HORIZONTAL_BORDER = '─';\nconst VERTICAL_BORDER = '│';\nconst TOP_CORNERS = ['╭', '╮'] as const;\nconst DIVIDER_JOINTS = ['├', '┤'] as const;\nconst BOTTOM_CORNERS = ['╰', '╯'] as const;\n\nexport interface DoomOverlayTui {\n terminal?: {\n rows: number;\n columns?: number;\n };\n requestRender(force?: boolean): void;\n}\n\nexport interface DoomOverlayChrome {\n title: string;\n breadcrumb?: string;\n headerRight?: string;\n footer: string;\n footerRight?: string;\n /**\n * Key/label pairs rendered as filled caps, e.g. `[ enter ] edit subject`.\n * Takes precedence over `footer`, which stays for surfaces that want a plain\n * sentence rather than a key legend.\n */\n footerHints?: readonly (readonly [string, string])[];\n /**\n * Signature colour for the surface. When set, the frame takes it and the\n * title renders as a filled badge rather than plain accent text, matching the\n * doom mockups. Left unset, the frame stays muted and the title plain.\n */\n accent?: Parameters<Theme['fg']>[0];\n}\n\n/**\n * One signature colour for every doom overlay: the frame and the title badge.\n * Per-surface colours were tried and read as arbitrary, and they also borrowed\n * tokens that mean something else (`warning`, `syntaxNumber`), so a theme edit\n * elsewhere would have repainted a frame. Change it here to change them all.\n */\nexport const DOOM_OVERLAY_ACCENT = 'mdHeading' satisfies DoomOverlayChrome['accent'];\n\nexport const DOOM_FULLSCREEN_UI_OPTIONS = {\n overlay: true,\n overlayOptions: {\n anchor: 'top-left',\n width: '100%',\n maxHeight: '100%',\n margin: 0,\n },\n} as const;\n\n/**\n * Fits a secondary segment into `budget`, or drops it entirely when too few\n * columns remain for it to stay readable. Truncating everything to fit is what\n * makes a tight header read as one run-on string.\n */\nfunction fitSegment(text: string | undefined, budget: number): string {\n if (!text || budget <= 0) return '';\n return budget < Math.min(visibleWidth(text), MIN_SEGMENT_WIDTH) ? '' : truncateToWidth(text, budget, ELLIPSIS);\n}\n\nexport abstract class DoomOverlay implements Component {\n protected constructor(\n protected readonly tui: DoomOverlayTui,\n protected readonly theme: Theme,\n ) {}\n\n invalidate(): void {\n this.tui.requestRender();\n }\n\n render(width: number): string[] {\n const safeWidth = Math.max(0, Math.floor(width));\n const height = Math.max(0, Math.floor(this.tui.terminal?.rows ?? DEFAULT_TERMINAL_ROWS));\n if (safeWidth === 0 || height === 0) return [];\n\n const chrome = this.getChrome();\n if (height < FULL_CHROME_ROWS || safeWidth < MIN_FRAMED_WIDTH) {\n return this.renderCompact(chrome, safeWidth, height);\n }\n\n const innerWidth = safeWidth - GUTTER_COLUMNS;\n const contentWidth = innerWidth - GUTTER_COLUMNS;\n const bodyHeight = height - FULL_CHROME_ROWS;\n const body = this.renderBody(contentWidth, bodyHeight).slice(0, bodyHeight);\n while (body.length < bodyHeight) body.push('');\n\n const frame = chrome.accent ?? BORDER_COLOR;\n return [\n this.borderRow(TOP_CORNERS, innerWidth, frame),\n this.contentRow(this.headerRow(chrome, contentWidth), contentWidth, safeWidth, frame),\n this.borderRow(DIVIDER_JOINTS, innerWidth, frame, BORDER_COLOR),\n ...body.map((line) => this.contentRow(line, contentWidth, safeWidth, frame)),\n this.borderRow(DIVIDER_JOINTS, innerWidth, frame, BORDER_COLOR),\n this.contentRow(this.footerRow(chrome, contentWidth), contentWidth, safeWidth, frame),\n this.borderRow(BOTTOM_CORNERS, innerWidth, frame),\n ].map((line) => padLine(line, safeWidth));\n }\n\n protected abstract getChrome(): DoomOverlayChrome;\n\n protected abstract renderBody(width: number, height: number): string[];\n\n /**\n * Edge glyphs and the rule between them are coloured separately: the outer\n * rectangle carries the signature colour while an internal separator stays\n * muted, meeting the frame at accent-coloured junctions.\n */\n private borderRow(\n [left, right]: readonly [string, string],\n innerWidth: number,\n edge: DoomOverlayChrome['accent'] = BORDER_COLOR,\n fill: DoomOverlayChrome['accent'] = edge,\n ): string {\n const edgeColour = edge ?? BORDER_COLOR;\n return [\n this.theme.fg(edgeColour, left),\n this.theme.fg(fill ?? edgeColour, HORIZONTAL_BORDER.repeat(innerWidth)),\n this.theme.fg(edgeColour, right),\n ].join('');\n }\n\n private contentRow(\n content: string,\n contentWidth: number,\n width: number,\n colour: DoomOverlayChrome['accent'] = BORDER_COLOR,\n ): string {\n const edge = this.theme.fg(colour ?? BORDER_COLOR, VERTICAL_BORDER);\n return frameLine(`${GUTTER}${padLine(content, contentWidth)}${GUTTER}`, width, edge, edge);\n }\n\n private headerRow(chrome: DoomOverlayChrome, width: number): string {\n // A signature colour turns the title into a filled badge, as the mockups\n // show; without one it stays plain accent text.\n const accent = chrome.accent;\n const titleBudget = accent ? width - GUTTER_COLUMNS : width;\n const title = truncateToWidth(chrome.title, Math.max(0, titleBudget), ELLIPSIS);\n let left = accent\n ? this.theme.inverse(this.theme.bold(this.theme.fg(accent, ` ${title} `)))\n : this.theme.bold(this.theme.fg(TITLE_COLOR, title));\n let leftWidth = visibleWidth(title) + (accent ? GUTTER_COLUMNS : 0);\n\n // The breadcrumb claims room before the right status: it says where you are,\n // which outranks ambient context when the terminal is narrow.\n const breadcrumb = fitSegment(chrome.breadcrumb, width - leftWidth - ROW_GAP);\n if (breadcrumb) {\n left += `${' '.repeat(ROW_GAP)}${this.theme.fg(SECONDARY_COLOR, breadcrumb)}`;\n leftWidth += ROW_GAP + visibleWidth(breadcrumb);\n }\n return this.withRightStatus(left, leftWidth, chrome.headerRight, width);\n }\n\n private footerRow(chrome: DoomOverlayChrome, width: number): string {\n const footer = chrome.footerHints?.length\n ? this.hintLegend(chrome.footerHints, width)\n : this.theme.fg(SECONDARY_COLOR, truncateToWidth(chrome.footer, width, ELLIPSIS));\n return this.withRightStatus(footer, visibleWidth(footer), chrome.footerRight, width);\n }\n\n /**\n * Key legend with each key in a filled cap. Every segment sets its own colour\n * so the caps survive: a cap's reset would otherwise strip the surrounding\n * dim from the labels that follow it.\n */\n private hintLegend(hints: readonly (readonly [string, string])[], width: number): string {\n let legend = '';\n let used = 0;\n for (const [key, label] of hints) {\n const segmentWidth = visibleWidth(key) + visibleWidth(label) + HINT_CHROME_COLUMNS;\n if (used + segmentWidth > width) break;\n const cap = this.theme.bg(HINT_CAP_BACKGROUND, this.theme.fg(TEXT_COLOR, ` ${key} `));\n legend += `${legend ? HINT_SEPARATOR : ''}${cap}${this.theme.fg(SECONDARY_COLOR, ` ${label}`)}`;\n used += segmentWidth;\n }\n return legend;\n }\n\n /**\n * Right-aligns a status cluster, dropping it whole when the row cannot spare\n * the columns. A clipped status reads as a stub (`doom-log…`) that carries\n * less than the blank space it costs.\n */\n private withRightStatus(left: string, leftWidth: number, right: string | undefined, width: number): string {\n const statusWidth = right ? visibleWidth(right) : 0;\n if (!right || statusWidth === 0 || leftWidth + ROW_GAP + statusWidth > width) return left;\n return `${left}${' '.repeat(width - leftWidth - statusWidth)}${this.theme.fg(SECONDARY_COLOR, right)}`;\n }\n\n private renderCompact(chrome: DoomOverlayChrome, width: number, height: number): string[] {\n const lines = Array.from({ length: height }, () => '');\n lines[0] = this.theme.bold(this.theme.fg(TITLE_COLOR, chrome.title));\n if (height > 1) lines[height - 1] = this.theme.fg(SECONDARY_COLOR, chrome.footer);\n return lines.map((line) => padLine(fitLine(line, width), width));\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"overlayText.cjs","names":["truncateToWidth","visibleWidth"],"sources":["../../src/workflow/overlayText.ts"],"sourcesContent":["/**\n * Text primitives shared by every doom overlay in this extension.\n *\n * Kept in one place because each of them encodes a decision that has to hold on\n * every surface: how a cell is clipped, which end of a path survives, and what\n * counts as a keystroke that carries text.\n */\n\nimport { truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nexport const ELLIPSIS = '…';\nexport const CURSOR_BLOCK = '█';\nexport const SELECTION_MARKER = '›';\n/** pi-tui brackets a truncation ellipsis with this; see `fit`. */\nconst HARD_RESET = '\\x1b[0m';\nconst FIRST_PRINTABLE_CODE_POINT = 0x20;\nconst DELETE_CODE_POINT = 0x7f;\n\n/**\n * Truncates and pads to an exact column count.\n *\n * `truncateToWidth` wraps its ellipsis in a hard `\\x1b[0m`, which would strip a\n * row's background for everything after a clipped cell. Nothing here sets a\n * colour that a full reset is the correct end for -- the theme closes its own\n * with `\\x1b[39m` and `\\x1b[49m` -- so the injected resets are dropped.\n */\nexport function fit(text: string, width: number): string {\n const clipped = truncateToWidth(text, Math.max(0, width), ELLIPSIS).replaceAll(HARD_RESET, '');\n return clipped + ' '.repeat(Math.max(0, width - visibleWidth(clipped)));\n}\n\n/** Right-aligns a trailing cluster against a left one, both clipped to fit. */\nexport function rightAligned(left: string, right: string, width: number): string {\n const rightWidth = visibleWidth(right);\n const leftWidth = Math.max(0, width - rightWidth - 1);\n return fit(left, leftWidth) + ' '.repeat(Math.max(1, width - leftWidth - rightWidth)) + fit(right, rightWidth);\n}\n\n/**\n * Trims from the front rather than the tail.\n *\n * For a path the file name identifies the thing, while the\n * `automations/marketing-workflows/` prefix every entry shares does not.\n */\nexport function pathTail(text: string, width: number): string {\n if (width <= 0) return '';\n if (visibleWidth(text) <= width) return text;\n return `${ELLIPSIS}${text.slice(text.length - Math.max(0, width - 1))}`;\n}\n\n/**\n * Keystrokes that carry no text: escape sequences, control keys, delete.\n *\n * Indexed rather than iterated so surrogate pairs stay intact; both halves sit\n * far above the control range, so no emoji is ever mistaken for one.\n */\nexport function isControlInput(data: string): boolean {\n for (let index = 0; index < data.length; index++) {\n const code = data.charCodeAt(index);\n if (code < FIRST_PRINTABLE_CODE_POINT || code === DELETE_CODE_POINT) return true;\n }\n return false;\n}\n\n/**\n * Whitespace-separated terms, each of which must appear somewhere in the row's\n * searchable text. Splitting on whitespace is what lets `short video` match a\n * row whose words are divided between its title and its file name.\n */\nexport function matchesQuery(haystack: string, query: string): boolean {\n const terms = query.toLowerCase().split(/\\s+/).filter(Boolean);\n if (terms.length === 0) return true;\n const lowered = haystack.toLowerCase();\n return terms.every((term) => lowered.includes(term));\n}\n"],"mappings":"wCA0BA,SAAgB,EAAI,EAAc,EAAuB,CACvD,IAAM,GAAA,EAAUA,EAAAA,gBAAAA,CAAgB,EAAM,KAAK,IAAI,EAAG,CAAK,EAAA,GAAW,CAAC,CAAC,WAAW,UAAY,EAAE,EAC7F,OAAO,EAAU,IAAI,OAAO,KAAK,IAAI,EAAG,GAAA,EAAQC,EAAAA,aAAAA,CAAa,CAAO,CAAC,CAAC,CACxE,CAGA,SAAgB,EAAa,EAAc,EAAe,EAAuB,CAC/E,IAAM,GAAA,EAAaA,EAAAA,aAAAA,CAAa,CAAK,EAC/B,EAAY,KAAK,IAAI,EAAG,EAAQ,EAAa,CAAC,EACpD,OAAO,EAAI,EAAM,CAAS,EAAI,IAAI,OAAO,KAAK,IAAI,EAAG,EAAQ,EAAY,CAAU,CAAC,EAAI,EAAI,EAAO,CAAU,CAC/G,CAQA,SAAgB,EAAS,EAAc,EAAuB,CAG5D,OAFI,GAAS,EAAU,IACvB,EAAIA,EAAAA,aAAAA,CAAa,CAAI,GAAK,EAAc,EACjC,IAAc,EAAK,MAAM,EAAK,OAAS,KAAK,IAAI,EAAG,EAAQ,CAAC,CAAC,GACtE,CAQA,SAAgB,EAAe,EAAuB,CACpD,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAK,OAAQ,IAAS,CAChD,IAAM,EAAO,EAAK,WAAW,CAAK,EAClC,GAAI,EAAO,IAA8B,IAAS,IAAmB,MAAO,EAC9E,CACA,MAAO,EACT,CAOA,SAAgB,EAAa,EAAkB,EAAwB,CACrE,IAAM,EAAQ,EAAM,YAAY,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO,EAC7D,GAAI,EAAM,SAAW,EAAG,MAAO,GAC/B,IAAM,EAAU,EAAS,YAAY,EACrC,OAAO,EAAM,MAAO,GAAS,EAAQ,SAAS,CAAI,CAAC,CACrD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"overlayText.mjs","names":[],"sources":["../../src/workflow/overlayText.ts"],"sourcesContent":["/**\n * Text primitives shared by every doom overlay in this extension.\n *\n * Kept in one place because each of them encodes a decision that has to hold on\n * every surface: how a cell is clipped, which end of a path survives, and what\n * counts as a keystroke that carries text.\n */\n\nimport { truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nexport const ELLIPSIS = '…';\nexport const CURSOR_BLOCK = '█';\nexport const SELECTION_MARKER = '›';\n/** pi-tui brackets a truncation ellipsis with this; see `fit`. */\nconst HARD_RESET = '\\x1b[0m';\nconst FIRST_PRINTABLE_CODE_POINT = 0x20;\nconst DELETE_CODE_POINT = 0x7f;\n\n/**\n * Truncates and pads to an exact column count.\n *\n * `truncateToWidth` wraps its ellipsis in a hard `\\x1b[0m`, which would strip a\n * row's background for everything after a clipped cell. Nothing here sets a\n * colour that a full reset is the correct end for -- the theme closes its own\n * with `\\x1b[39m` and `\\x1b[49m` -- so the injected resets are dropped.\n */\nexport function fit(text: string, width: number): string {\n const clipped = truncateToWidth(text, Math.max(0, width), ELLIPSIS).replaceAll(HARD_RESET, '');\n return clipped + ' '.repeat(Math.max(0, width - visibleWidth(clipped)));\n}\n\n/** Right-aligns a trailing cluster against a left one, both clipped to fit. */\nexport function rightAligned(left: string, right: string, width: number): string {\n const rightWidth = visibleWidth(right);\n const leftWidth = Math.max(0, width - rightWidth - 1);\n return fit(left, leftWidth) + ' '.repeat(Math.max(1, width - leftWidth - rightWidth)) + fit(right, rightWidth);\n}\n\n/**\n * Trims from the front rather than the tail.\n *\n * For a path the file name identifies the thing, while the\n * `automations/marketing-workflows/` prefix every entry shares does not.\n */\nexport function pathTail(text: string, width: number): string {\n if (width <= 0) return '';\n if (visibleWidth(text) <= width) return text;\n return `${ELLIPSIS}${text.slice(text.length - Math.max(0, width - 1))}`;\n}\n\n/**\n * Keystrokes that carry no text: escape sequences, control keys, delete.\n *\n * Indexed rather than iterated so surrogate pairs stay intact; both halves sit\n * far above the control range, so no emoji is ever mistaken for one.\n */\nexport function isControlInput(data: string): boolean {\n for (let index = 0; index < data.length; index++) {\n const code = data.charCodeAt(index);\n if (code < FIRST_PRINTABLE_CODE_POINT || code === DELETE_CODE_POINT) return true;\n }\n return false;\n}\n\n/**\n * Whitespace-separated terms, each of which must appear somewhere in the row's\n * searchable text. Splitting on whitespace is what lets `short video` match a\n * row whose words are divided between its title and its file name.\n */\nexport function matchesQuery(haystack: string, query: string): boolean {\n const terms = query.toLowerCase().split(/\\s+/).filter(Boolean);\n if (terms.length === 0) return true;\n const lowered = haystack.toLowerCase();\n return terms.every((term) => lowered.includes(term));\n}\n"],"mappings":"2EA0BA,SAAgB,EAAI,EAAc,EAAuB,CACvD,IAAM,EAAU,EAAgB,EAAM,KAAK,IAAI,EAAG,CAAK,EAAA,GAAW,CAAC,CAAC,WAAW,UAAY,EAAE,EAC7F,OAAO,EAAU,IAAI,OAAO,KAAK,IAAI,EAAG,EAAQ,EAAa,CAAO,CAAC,CAAC,CACxE,CAGA,SAAgB,EAAa,EAAc,EAAe,EAAuB,CAC/E,IAAM,EAAa,EAAa,CAAK,EAC/B,EAAY,KAAK,IAAI,EAAG,EAAQ,EAAa,CAAC,EACpD,OAAO,EAAI,EAAM,CAAS,EAAI,IAAI,OAAO,KAAK,IAAI,EAAG,EAAQ,EAAY,CAAU,CAAC,EAAI,EAAI,EAAO,CAAU,CAC/G,CAQA,SAAgB,EAAS,EAAc,EAAuB,CAG5D,OAFI,GAAS,EAAU,GACnB,EAAa,CAAI,GAAK,EAAc,EACjC,IAAc,EAAK,MAAM,EAAK,OAAS,KAAK,IAAI,EAAG,EAAQ,CAAC,CAAC,GACtE,CAQA,SAAgB,EAAe,EAAuB,CACpD,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAK,OAAQ,IAAS,CAChD,IAAM,EAAO,EAAK,WAAW,CAAK,EAClC,GAAI,EAAO,IAA8B,IAAS,IAAmB,MAAO,EAC9E,CACA,MAAO,EACT,CAOA,SAAgB,EAAa,EAAkB,EAAwB,CACrE,IAAM,EAAQ,EAAM,YAAY,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO,EAC7D,GAAI,EAAM,SAAW,EAAG,MAAO,GAC/B,IAAM,EAAU,EAAS,YAAY,EACrC,OAAO,EAAM,MAAO,GAAS,EAAQ,SAAS,CAAI,CAAC,CACrD"}
|