@agimon-ai/doompi-workflow 0.0.1-alpha.76 → 0.0.1-alpha.78
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/dist/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/api-contracts.cjs +7 -0
- package/dist/api-contracts.d.cts +2 -0
- package/dist/api-contracts.d.mts +2 -0
- package/dist/api-contracts.mjs +2 -0
- package/dist/extensions/pi.cjs +63 -0
- package/dist/extensions/pi.cjs.map +1 -0
- package/dist/extensions/pi.d.cts +6 -0
- package/dist/extensions/pi.d.cts.map +1 -0
- package/dist/extensions/pi.d.mts +6 -0
- package/dist/extensions/pi.d.mts.map +1 -0
- package/dist/extensions/pi.mjs +58 -0
- package/dist/extensions/pi.mjs.map +1 -0
- package/dist/extensions/server.cjs +96 -0
- package/dist/extensions/server.cjs.map +1 -0
- package/dist/extensions/server.d.cts +5 -0
- package/dist/extensions/server.d.cts.map +1 -0
- package/dist/extensions/server.d.mts +5 -0
- package/dist/extensions/server.d.mts.map +1 -0
- package/dist/extensions/server.mjs +91 -0
- package/dist/extensions/server.mjs.map +1 -0
- package/dist/extensions/web.mjs +3219 -0
- package/dist/extensions/web.mjs.map +1 -0
- package/dist/index.cjs +4 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +2 -0
- package/dist/src/constants/workflow.cjs +32 -0
- package/dist/src/constants/workflow.cjs.map +1 -0
- package/dist/src/constants/workflow.mjs +21 -0
- package/dist/src/constants/workflow.mjs.map +1 -0
- package/dist/src/extensions/(backend)/_lib/index.server.cjs +12 -0
- package/dist/src/extensions/(backend)/_lib/index.server.cjs.map +1 -0
- package/dist/src/extensions/(backend)/_lib/index.server.mjs +12 -0
- package/dist/src/extensions/(backend)/_lib/index.server.mjs.map +1 -0
- package/dist/src/extensions/(backend)/api/workflow/route.server.cjs +7 -0
- package/dist/src/extensions/(backend)/api/workflow/route.server.cjs.map +1 -0
- package/dist/src/extensions/(backend)/api/workflow/route.server.mjs +8 -0
- package/dist/src/extensions/(backend)/api/workflow/route.server.mjs.map +1 -0
- package/dist/src/extensions/(backend)/channel/workflow-catalog.server.cjs +7 -0
- package/dist/src/extensions/(backend)/channel/workflow-catalog.server.cjs.map +1 -0
- package/dist/src/extensions/(backend)/channel/workflow-catalog.server.mjs +8 -0
- package/dist/src/extensions/(backend)/channel/workflow-catalog.server.mjs.map +1 -0
- package/dist/src/extensions/(backend)/channel/workflows.server.cjs +7 -0
- package/dist/src/extensions/(backend)/channel/workflows.server.cjs.map +1 -0
- package/dist/src/extensions/(backend)/channel/workflows.server.mjs +8 -0
- package/dist/src/extensions/(backend)/channel/workflows.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.cjs +100 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.mjs +100 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.cjs +11 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.mjs +11 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/index.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.cjs +12 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.mjs +12 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/workflowSkillsResource.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/resources-discover.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/workflow-skills.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs +15 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs +16 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs +17 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs +18 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-panel.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/shortcut/workflow-view-close.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/workflow.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/workflow.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.cjs +50 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.mjs +47 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowFinishedRenderer.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.cjs +36 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.mjs +35 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/_lib/workflowStepRenderer.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-finished.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(frontend)/message/workflow-step.cli.mjs.map +1 -0
- package/dist/src/schemas/apiContracts.cjs +330 -0
- package/dist/src/schemas/apiContracts.cjs.map +1 -0
- package/dist/src/schemas/apiContracts.d.cts +53 -0
- package/dist/src/schemas/apiContracts.d.cts.map +1 -0
- package/dist/src/schemas/apiContracts.d.mts +53 -0
- package/dist/src/schemas/apiContracts.d.mts.map +1 -0
- package/dist/src/schemas/apiContracts.mjs +327 -0
- package/dist/src/schemas/apiContracts.mjs.map +1 -0
- package/dist/src/schemas/workflowPi.cjs +77 -0
- package/dist/src/schemas/workflowPi.cjs.map +1 -0
- package/dist/src/schemas/workflowPi.d.cts +1 -0
- package/dist/src/schemas/workflowPi.d.mts +1 -0
- package/dist/src/schemas/workflowPi.mjs +74 -0
- package/dist/src/schemas/workflowPi.mjs.map +1 -0
- package/dist/src/services/backgroundWork/index.cjs +61 -0
- package/dist/src/services/backgroundWork/index.cjs.map +1 -0
- package/dist/src/services/backgroundWork/index.mjs +61 -0
- package/dist/src/services/backgroundWork/index.mjs.map +1 -0
- package/dist/src/services/piToolBridge/index.cjs +205 -0
- package/dist/src/services/piToolBridge/index.cjs.map +1 -0
- package/dist/src/services/piToolBridge/index.mjs +195 -0
- package/dist/src/services/piToolBridge/index.mjs.map +1 -0
- package/dist/src/services/serverRuntime/index.cjs +387 -0
- package/dist/src/services/serverRuntime/index.cjs.map +1 -0
- package/dist/src/services/serverRuntime/index.mjs +387 -0
- package/dist/src/services/serverRuntime/index.mjs.map +1 -0
- package/dist/src/services/webWorkflowCatalog/index.cjs +53 -0
- package/dist/src/services/webWorkflowCatalog/index.cjs.map +1 -0
- package/dist/src/services/webWorkflowCatalog/index.mjs +52 -0
- package/dist/src/services/webWorkflowCatalog/index.mjs.map +1 -0
- package/dist/src/services/workflowCatalogChannel/index.cjs +74 -0
- package/dist/src/services/workflowCatalogChannel/index.cjs.map +1 -0
- package/dist/src/services/workflowCatalogChannel/index.mjs +74 -0
- package/dist/src/services/workflowCatalogChannel/index.mjs.map +1 -0
- package/dist/src/services/workflowCatalogDeps/index.cjs +25 -0
- package/dist/src/services/workflowCatalogDeps/index.cjs.map +1 -0
- package/dist/src/services/workflowCatalogDeps/index.mjs +25 -0
- package/dist/src/services/workflowCatalogDeps/index.mjs.map +1 -0
- package/dist/src/services/workflowExecution/index.cjs +205 -0
- package/dist/src/services/workflowExecution/index.cjs.map +1 -0
- package/dist/src/services/workflowExecution/index.d.cts +6 -0
- package/dist/src/services/workflowExecution/index.d.mts +6 -0
- package/dist/src/services/workflowExecution/index.mjs +200 -0
- package/dist/src/services/workflowExecution/index.mjs.map +1 -0
- package/dist/src/services/workflowFence/index.cjs +170 -0
- package/dist/src/services/workflowFence/index.cjs.map +1 -0
- package/dist/src/services/workflowFence/index.mjs +166 -0
- package/dist/src/services/workflowFence/index.mjs.map +1 -0
- package/dist/src/services/workflowHubApi/index.cjs +415 -0
- package/dist/src/services/workflowHubApi/index.cjs.map +1 -0
- package/dist/src/services/workflowHubApi/index.mjs +411 -0
- package/dist/src/services/workflowHubApi/index.mjs.map +1 -0
- package/dist/src/services/workflowLaunchCommand/index.cjs +121 -0
- package/dist/src/services/workflowLaunchCommand/index.cjs.map +1 -0
- package/dist/src/services/workflowLaunchCommand/index.d.cts +52 -0
- package/dist/src/services/workflowLaunchCommand/index.d.cts.map +1 -0
- package/dist/src/services/workflowLaunchCommand/index.d.mts +52 -0
- package/dist/src/services/workflowLaunchCommand/index.d.mts.map +1 -0
- package/dist/src/services/workflowLaunchCommand/index.mjs +118 -0
- package/dist/src/services/workflowLaunchCommand/index.mjs.map +1 -0
- package/dist/src/services/workflowLauncher/index.cjs +181 -0
- package/dist/src/services/workflowLauncher/index.cjs.map +1 -0
- package/dist/src/services/workflowLauncher/index.mjs +177 -0
- package/dist/src/services/workflowLauncher/index.mjs.map +1 -0
- package/dist/src/services/workflowNarration/index.cjs +19 -0
- package/dist/src/services/workflowNarration/index.cjs.map +1 -0
- package/dist/src/services/workflowNarration/index.mjs +19 -0
- package/dist/src/services/workflowNarration/index.mjs.map +1 -0
- package/dist/src/services/workflowResource/index.cjs +27 -0
- package/dist/src/services/workflowResource/index.cjs.map +1 -0
- package/dist/src/services/workflowResource/index.mjs +24 -0
- package/dist/src/services/workflowResource/index.mjs.map +1 -0
- package/dist/src/services/workflowRuns/index.cjs +333 -0
- package/dist/src/services/workflowRuns/index.cjs.map +1 -0
- package/dist/src/services/workflowRuns/index.mjs +319 -0
- package/dist/src/services/workflowRuns/index.mjs.map +1 -0
- package/dist/src/services/workflowTerminal/index.cjs +69 -0
- package/dist/src/services/workflowTerminal/index.cjs.map +1 -0
- package/dist/src/services/workflowTerminal/index.mjs +69 -0
- package/dist/src/services/workflowTerminal/index.mjs.map +1 -0
- package/dist/src/services/workflowTools/index.cjs +221 -0
- package/dist/src/services/workflowTools/index.cjs.map +1 -0
- package/dist/src/services/workflowTools/index.mjs +221 -0
- package/dist/src/services/workflowTools/index.mjs.map +1 -0
- package/dist/src/services/workflowWatcher/index.cjs +78 -0
- package/dist/src/services/workflowWatcher/index.cjs.map +1 -0
- package/dist/src/services/workflowWatcher/index.mjs +74 -0
- package/dist/src/services/workflowWatcher/index.mjs.map +1 -0
- package/dist/src/services/workflowsHubChannel/index.cjs +58 -0
- package/dist/src/services/workflowsHubChannel/index.cjs.map +1 -0
- package/dist/src/services/workflowsHubChannel/index.mjs +58 -0
- package/dist/src/services/workflowsHubChannel/index.mjs.map +1 -0
- package/dist/src/tui/leader.cjs +84 -0
- package/dist/src/tui/leader.cjs.map +1 -0
- package/dist/src/tui/leader.mjs +83 -0
- package/dist/src/tui/leader.mjs.map +1 -0
- package/dist/src/tui/workflow/doomOverlay.cjs +159 -0
- package/dist/src/tui/workflow/doomOverlay.cjs.map +1 -0
- package/dist/src/tui/workflow/doomOverlay.mjs +157 -0
- package/dist/src/tui/workflow/doomOverlay.mjs.map +1 -0
- package/dist/src/tui/workflow/overlayText.cjs +83 -0
- package/dist/src/tui/workflow/overlayText.cjs.map +1 -0
- package/dist/src/tui/workflow/overlayText.mjs +78 -0
- package/dist/src/tui/workflow/overlayText.mjs.map +1 -0
- package/dist/src/tui/workflow/rendering.cjs +22 -0
- package/dist/src/tui/workflow/rendering.cjs.map +1 -0
- package/dist/src/tui/workflow/rendering.mjs +20 -0
- package/dist/src/tui/workflow/rendering.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowCatalog.cjs +336 -0
- package/dist/src/tui/workflow/workflowCatalog.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowCatalog.mjs +333 -0
- package/dist/src/tui/workflow/workflowCatalog.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowFinishedMessage.cjs +50 -0
- package/dist/src/tui/workflow/workflowFinishedMessage.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowFinishedMessage.mjs +47 -0
- package/dist/src/tui/workflow/workflowFinishedMessage.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowInspector.cjs +276 -0
- package/dist/src/tui/workflow/workflowInspector.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowInspector.mjs +276 -0
- package/dist/src/tui/workflow/workflowInspector.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowOverlay.cjs +126 -0
- package/dist/src/tui/workflow/workflowOverlay.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowOverlay.mjs +125 -0
- package/dist/src/tui/workflow/workflowOverlay.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowPicker.cjs +138 -0
- package/dist/src/tui/workflow/workflowPicker.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowPicker.mjs +136 -0
- package/dist/src/tui/workflow/workflowPicker.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowProgressOverlay.cjs +197 -0
- package/dist/src/tui/workflow/workflowProgressOverlay.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowProgressOverlay.mjs +192 -0
- package/dist/src/tui/workflow/workflowProgressOverlay.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowPrompt.cjs +142 -0
- package/dist/src/tui/workflow/workflowPrompt.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowPrompt.mjs +139 -0
- package/dist/src/tui/workflow/workflowPrompt.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowRunPanel.cjs +95 -0
- package/dist/src/tui/workflow/workflowRunPanel.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowRunPanel.mjs +94 -0
- package/dist/src/tui/workflow/workflowRunPanel.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowStatusRow.cjs +20 -0
- package/dist/src/tui/workflow/workflowStatusRow.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowStatusRow.mjs +20 -0
- package/dist/src/tui/workflow/workflowStatusRow.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowStepMessage.cjs +32 -0
- package/dist/src/tui/workflow/workflowStepMessage.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowStepMessage.mjs +31 -0
- package/dist/src/tui/workflow/workflowStepMessage.mjs.map +1 -0
- package/dist/src/tui/workflow/workflowToolRender.cjs +491 -0
- package/dist/src/tui/workflow/workflowToolRender.cjs.map +1 -0
- package/dist/src/tui/workflow/workflowToolRender.mjs +490 -0
- package/dist/src/tui/workflow/workflowToolRender.mjs.map +1 -0
- package/dist/src/tui/workflowRuntime.cjs +1934 -0
- package/dist/src/tui/workflowRuntime.cjs.map +1 -0
- package/dist/src/tui/workflowRuntime.d.cts +33 -0
- package/dist/src/tui/workflowRuntime.d.cts.map +1 -0
- package/dist/src/tui/workflowRuntime.d.mts +33 -0
- package/dist/src/tui/workflowRuntime.d.mts.map +1 -0
- package/dist/src/tui/workflowRuntime.mjs +1930 -0
- package/dist/src/tui/workflowRuntime.mjs.map +1 -0
- package/dist/src/types/apiRoutes.cjs +82 -0
- package/dist/src/types/apiRoutes.cjs.map +1 -0
- package/dist/src/types/apiRoutes.mjs +80 -0
- package/dist/src/types/apiRoutes.mjs.map +1 -0
- package/dist/src/types/webWorkflowTerminal.cjs +23 -0
- package/dist/src/types/webWorkflowTerminal.cjs.map +1 -0
- package/dist/src/types/webWorkflowTerminal.mjs +22 -0
- package/dist/src/types/webWorkflowTerminal.mjs.map +1 -0
- package/dist/src/types/webWorkflows.cjs +8 -0
- package/dist/src/types/webWorkflows.cjs.map +1 -0
- package/dist/src/types/webWorkflows.mjs +7 -0
- package/dist/src/types/webWorkflows.mjs.map +1 -0
- package/package.json +8 -8
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { fitLine, frameLine, padLine } from "./rendering.mjs";
|
|
2
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
3
|
+
//#region src/tui/workflow/doomOverlay.ts
|
|
4
|
+
const DEFAULT_TERMINAL_ROWS = 24;
|
|
5
|
+
const FULL_CHROME_ROWS = 6;
|
|
6
|
+
/** Two frame columns and two gutter columns, leaving content worth framing. */
|
|
7
|
+
const MIN_FRAMED_WIDTH = 8;
|
|
8
|
+
const GUTTER = " ";
|
|
9
|
+
const GUTTER_COLUMNS = 2;
|
|
10
|
+
/** Blank columns kept between a row's left cluster and its right-aligned status. */
|
|
11
|
+
const ROW_GAP = 2;
|
|
12
|
+
/** A secondary segment thinner than this is dropped rather than shredded into a stub. */
|
|
13
|
+
const MIN_SEGMENT_WIDTH = 8;
|
|
14
|
+
const ELLIPSIS = "…";
|
|
15
|
+
const BORDER_COLOR = "borderMuted";
|
|
16
|
+
const TEXT_COLOR = "text";
|
|
17
|
+
/** Filled key caps read as pressable, matching the doom mockups' footers. */
|
|
18
|
+
const HINT_CAP_BACKGROUND = "selectedBg";
|
|
19
|
+
const HINT_SEPARATOR = " ";
|
|
20
|
+
/** A cap's two pad columns plus the space before its label. */
|
|
21
|
+
const HINT_CHROME_COLUMNS = 6;
|
|
22
|
+
const TITLE_COLOR = "accent";
|
|
23
|
+
const SECONDARY_COLOR = "dim";
|
|
24
|
+
const HORIZONTAL_BORDER = "─";
|
|
25
|
+
const VERTICAL_BORDER = "│";
|
|
26
|
+
const TOP_CORNERS = ["╭", "╮"];
|
|
27
|
+
const DIVIDER_JOINTS = ["├", "┤"];
|
|
28
|
+
const BOTTOM_CORNERS = ["╰", "╯"];
|
|
29
|
+
/**
|
|
30
|
+
* One signature colour for every doom overlay: the frame and the title badge.
|
|
31
|
+
* Per-surface colours were tried and read as arbitrary, and they also borrowed
|
|
32
|
+
* tokens that mean something else (`warning`, `syntaxNumber`), so a theme edit
|
|
33
|
+
* elsewhere would have repainted a frame. Change it here to change them all.
|
|
34
|
+
*/
|
|
35
|
+
const DOOM_OVERLAY_ACCENT = "mdHeading";
|
|
36
|
+
const DOOM_FULLSCREEN_UI_OPTIONS = {
|
|
37
|
+
overlay: true,
|
|
38
|
+
overlayOptions: {
|
|
39
|
+
anchor: "top-left",
|
|
40
|
+
width: "100%",
|
|
41
|
+
maxHeight: "100%",
|
|
42
|
+
margin: 0
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Fits a secondary segment into `budget`, or drops it entirely when too few
|
|
47
|
+
* columns remain for it to stay readable. Truncating everything to fit is what
|
|
48
|
+
* makes a tight header read as one run-on string.
|
|
49
|
+
*/
|
|
50
|
+
function fitSegment(text, budget) {
|
|
51
|
+
if (!text || budget <= 0) return "";
|
|
52
|
+
return budget < Math.min(visibleWidth(text), MIN_SEGMENT_WIDTH) ? "" : truncateToWidth(text, budget, ELLIPSIS);
|
|
53
|
+
}
|
|
54
|
+
var DoomOverlay = class {
|
|
55
|
+
tui;
|
|
56
|
+
theme;
|
|
57
|
+
constructor(tui, theme) {
|
|
58
|
+
this.tui = tui;
|
|
59
|
+
this.theme = theme;
|
|
60
|
+
}
|
|
61
|
+
invalidate() {
|
|
62
|
+
this.tui.requestRender();
|
|
63
|
+
}
|
|
64
|
+
render(width) {
|
|
65
|
+
const safeWidth = Math.max(0, Math.floor(width));
|
|
66
|
+
const height = Math.max(0, Math.floor(this.tui.terminal?.rows ?? DEFAULT_TERMINAL_ROWS));
|
|
67
|
+
if (safeWidth === 0 || height === 0) return [];
|
|
68
|
+
const chrome = this.getChrome();
|
|
69
|
+
if (height < FULL_CHROME_ROWS || safeWidth < MIN_FRAMED_WIDTH) return this.renderCompact(chrome, safeWidth, height);
|
|
70
|
+
const innerWidth = safeWidth - GUTTER_COLUMNS;
|
|
71
|
+
const contentWidth = innerWidth - GUTTER_COLUMNS;
|
|
72
|
+
const bodyHeight = height - FULL_CHROME_ROWS;
|
|
73
|
+
const body = this.renderBody(contentWidth, bodyHeight).slice(0, bodyHeight);
|
|
74
|
+
while (body.length < bodyHeight) body.push("");
|
|
75
|
+
const frame = chrome.accent ?? BORDER_COLOR;
|
|
76
|
+
return [
|
|
77
|
+
this.borderRow(TOP_CORNERS, innerWidth, frame),
|
|
78
|
+
this.contentRow(this.headerRow(chrome, contentWidth), contentWidth, safeWidth, frame),
|
|
79
|
+
this.borderRow(DIVIDER_JOINTS, innerWidth, frame, BORDER_COLOR),
|
|
80
|
+
...body.map((line) => this.contentRow(line, contentWidth, safeWidth, frame)),
|
|
81
|
+
this.borderRow(DIVIDER_JOINTS, innerWidth, frame, BORDER_COLOR),
|
|
82
|
+
this.contentRow(this.footerRow(chrome, contentWidth), contentWidth, safeWidth, frame),
|
|
83
|
+
this.borderRow(BOTTOM_CORNERS, innerWidth, frame)
|
|
84
|
+
].map((line) => padLine(line, safeWidth));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Edge glyphs and the rule between them are coloured separately: the outer
|
|
88
|
+
* rectangle carries the signature colour while an internal separator stays
|
|
89
|
+
* muted, meeting the frame at accent-coloured junctions.
|
|
90
|
+
*/
|
|
91
|
+
borderRow([left, right], innerWidth, edge = BORDER_COLOR, fill = edge) {
|
|
92
|
+
const edgeColour = edge ?? BORDER_COLOR;
|
|
93
|
+
return [
|
|
94
|
+
this.theme.fg(edgeColour, left),
|
|
95
|
+
this.theme.fg(fill ?? edgeColour, HORIZONTAL_BORDER.repeat(innerWidth)),
|
|
96
|
+
this.theme.fg(edgeColour, right)
|
|
97
|
+
].join("");
|
|
98
|
+
}
|
|
99
|
+
contentRow(content, contentWidth, width, colour = BORDER_COLOR) {
|
|
100
|
+
const edge = this.theme.fg(colour ?? BORDER_COLOR, VERTICAL_BORDER);
|
|
101
|
+
return frameLine(`${GUTTER}${padLine(content, contentWidth)}${GUTTER}`, width, edge, edge);
|
|
102
|
+
}
|
|
103
|
+
headerRow(chrome, width) {
|
|
104
|
+
const accent = chrome.accent;
|
|
105
|
+
const titleBudget = accent ? width - GUTTER_COLUMNS : width;
|
|
106
|
+
const title = truncateToWidth(chrome.title, Math.max(0, titleBudget), ELLIPSIS);
|
|
107
|
+
let left = accent ? this.theme.inverse(this.theme.bold(this.theme.fg(accent, ` ${title} `))) : this.theme.bold(this.theme.fg(TITLE_COLOR, title));
|
|
108
|
+
let leftWidth = visibleWidth(title) + (accent ? GUTTER_COLUMNS : 0);
|
|
109
|
+
const breadcrumb = fitSegment(chrome.breadcrumb, width - leftWidth - ROW_GAP);
|
|
110
|
+
if (breadcrumb) {
|
|
111
|
+
left += `${" ".repeat(ROW_GAP)}${this.theme.fg(SECONDARY_COLOR, breadcrumb)}`;
|
|
112
|
+
leftWidth += ROW_GAP + visibleWidth(breadcrumb);
|
|
113
|
+
}
|
|
114
|
+
return this.withRightStatus(left, leftWidth, chrome.headerRight, width);
|
|
115
|
+
}
|
|
116
|
+
footerRow(chrome, width) {
|
|
117
|
+
const footer = chrome.footerHints?.length ? this.hintLegend(chrome.footerHints, width) : this.theme.fg(SECONDARY_COLOR, truncateToWidth(chrome.footer, width, ELLIPSIS));
|
|
118
|
+
return this.withRightStatus(footer, visibleWidth(footer), chrome.footerRight, width);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Key legend with each key in a filled cap. Every segment sets its own colour
|
|
122
|
+
* so the caps survive: a cap's reset would otherwise strip the surrounding
|
|
123
|
+
* dim from the labels that follow it.
|
|
124
|
+
*/
|
|
125
|
+
hintLegend(hints, width) {
|
|
126
|
+
let legend = "";
|
|
127
|
+
let used = 0;
|
|
128
|
+
for (const [key, label] of hints) {
|
|
129
|
+
const segmentWidth = visibleWidth(key) + visibleWidth(label) + HINT_CHROME_COLUMNS;
|
|
130
|
+
if (used + segmentWidth > width) break;
|
|
131
|
+
const cap = this.theme.bg(HINT_CAP_BACKGROUND, this.theme.fg(TEXT_COLOR, ` ${key} `));
|
|
132
|
+
legend += `${legend ? HINT_SEPARATOR : ""}${cap}${this.theme.fg(SECONDARY_COLOR, ` ${label}`)}`;
|
|
133
|
+
used += segmentWidth;
|
|
134
|
+
}
|
|
135
|
+
return legend;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Right-aligns a status cluster, dropping it whole when the row cannot spare
|
|
139
|
+
* the columns. A clipped status reads as a stub (`doom-log…`) that carries
|
|
140
|
+
* less than the blank space it costs.
|
|
141
|
+
*/
|
|
142
|
+
withRightStatus(left, leftWidth, right, width) {
|
|
143
|
+
const statusWidth = right ? visibleWidth(right) : 0;
|
|
144
|
+
if (!right || statusWidth === 0 || leftWidth + ROW_GAP + statusWidth > width) return left;
|
|
145
|
+
return `${left}${" ".repeat(width - leftWidth - statusWidth)}${this.theme.fg(SECONDARY_COLOR, right)}`;
|
|
146
|
+
}
|
|
147
|
+
renderCompact(chrome, width, height) {
|
|
148
|
+
const lines = Array.from({ length: height }, () => "");
|
|
149
|
+
lines[0] = this.theme.bold(this.theme.fg(TITLE_COLOR, chrome.title));
|
|
150
|
+
if (height > 1) lines[height - 1] = this.theme.fg(SECONDARY_COLOR, chrome.footer);
|
|
151
|
+
return lines.map((line) => padLine(fitLine(line, width), width));
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
//#endregion
|
|
155
|
+
export { DOOM_FULLSCREEN_UI_OPTIONS, DOOM_OVERLAY_ACCENT, DoomOverlay };
|
|
156
|
+
|
|
157
|
+
//# sourceMappingURL=doomOverlay.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doomOverlay.mjs","names":[],"sources":["../../../../src/tui/workflow/doomOverlay.ts"],"sourcesContent":["import type { Theme } from '@earendil-works/pi-coding-agent';\nimport { type Component, truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nimport { fitLine, frameLine, padLine } from './rendering';\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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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
let _earendil_works_pi_tui = require("@earendil-works/pi-tui");
|
|
2
|
+
/** pi-tui brackets a truncation ellipsis with this; see `fit`. */
|
|
3
|
+
const HARD_RESET = "\x1B[0m";
|
|
4
|
+
const ESCAPE = "\x1B";
|
|
5
|
+
const FIRST_PRINTABLE_CODE_POINT = 32;
|
|
6
|
+
const DELETE_CODE_POINT = 127;
|
|
7
|
+
/**
|
|
8
|
+
* Truncates and pads to an exact column count.
|
|
9
|
+
*
|
|
10
|
+
* `truncateToWidth` wraps its ellipsis in a hard `\x1b[0m`, which would strip a
|
|
11
|
+
* row's background for everything after a clipped cell. Nothing here sets a
|
|
12
|
+
* colour that a full reset is the correct end for -- the theme closes its own
|
|
13
|
+
* with `\x1b[39m` and `\x1b[49m` -- so the injected resets are dropped.
|
|
14
|
+
*/
|
|
15
|
+
function fit(text, width) {
|
|
16
|
+
const clipped = (0, _earendil_works_pi_tui.truncateToWidth)(text, Math.max(0, width), "…").replaceAll(HARD_RESET, "");
|
|
17
|
+
return clipped + " ".repeat(Math.max(0, width - (0, _earendil_works_pi_tui.visibleWidth)(clipped)));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Fits a line that carries its own colour, keeping every escape it contains.
|
|
21
|
+
*
|
|
22
|
+
* `fit` above drops hard resets, which is right for a themed row whose
|
|
23
|
+
* background must survive a clipped cell and wrong for captured terminal
|
|
24
|
+
* output: those resets are what END the child's colour runs, and deleting them
|
|
25
|
+
* bleeds a colour through the rest of the panel. This closes the line with a
|
|
26
|
+
* reset instead, before the padding, so no attribute escapes the row.
|
|
27
|
+
*/
|
|
28
|
+
function fitTerminalLine(text, width) {
|
|
29
|
+
const safeWidth = Math.max(0, width);
|
|
30
|
+
const clipped = (0, _earendil_works_pi_tui.truncateToWidth)(text, safeWidth, "…");
|
|
31
|
+
const padding = " ".repeat(Math.max(0, safeWidth - (0, _earendil_works_pi_tui.visibleWidth)(clipped)));
|
|
32
|
+
return clipped.includes(ESCAPE) ? `${clipped}${HARD_RESET}${padding}` : `${clipped}${padding}`;
|
|
33
|
+
}
|
|
34
|
+
/** Right-aligns a trailing cluster against a left one, both clipped to fit. */
|
|
35
|
+
function rightAligned(left, right, width) {
|
|
36
|
+
const rightWidth = (0, _earendil_works_pi_tui.visibleWidth)(right);
|
|
37
|
+
const leftWidth = Math.max(0, width - rightWidth - 1);
|
|
38
|
+
return fit(left, leftWidth) + " ".repeat(Math.max(1, width - leftWidth - rightWidth)) + fit(right, rightWidth);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Trims from the front rather than the tail.
|
|
42
|
+
*
|
|
43
|
+
* For a path the file name identifies the thing, while the
|
|
44
|
+
* `automations/marketing-workflows/` prefix every entry shares does not.
|
|
45
|
+
*/
|
|
46
|
+
function pathTail(text, width) {
|
|
47
|
+
if (width <= 0) return "";
|
|
48
|
+
if ((0, _earendil_works_pi_tui.visibleWidth)(text) <= width) return text;
|
|
49
|
+
return `…${text.slice(text.length - Math.max(0, width - 1))}`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Keystrokes that carry no text: escape sequences, control keys, delete.
|
|
53
|
+
*
|
|
54
|
+
* Indexed rather than iterated so surrogate pairs stay intact; both halves sit
|
|
55
|
+
* far above the control range, so no emoji is ever mistaken for one.
|
|
56
|
+
*/
|
|
57
|
+
function isControlInput(data) {
|
|
58
|
+
for (let index = 0; index < data.length; index++) {
|
|
59
|
+
const code = data.charCodeAt(index);
|
|
60
|
+
if (code < FIRST_PRINTABLE_CODE_POINT || code === DELETE_CODE_POINT) return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Whitespace-separated terms, each of which must appear somewhere in the row's
|
|
66
|
+
* searchable text. Splitting on whitespace is what lets `short video` match a
|
|
67
|
+
* row whose words are divided between its title and its file name.
|
|
68
|
+
*/
|
|
69
|
+
function matchesQuery(haystack, query) {
|
|
70
|
+
const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
71
|
+
if (terms.length === 0) return true;
|
|
72
|
+
const lowered = haystack.toLowerCase();
|
|
73
|
+
return terms.every((term) => lowered.includes(term));
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
exports.fit = fit;
|
|
77
|
+
exports.fitTerminalLine = fitTerminalLine;
|
|
78
|
+
exports.isControlInput = isControlInput;
|
|
79
|
+
exports.matchesQuery = matchesQuery;
|
|
80
|
+
exports.pathTail = pathTail;
|
|
81
|
+
exports.rightAligned = rightAligned;
|
|
82
|
+
|
|
83
|
+
//# sourceMappingURL=overlayText.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlayText.cjs","names":["truncateToWidth","visibleWidth"],"sources":["../../../../src/tui/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 ESCAPE = '\\x1b';\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/**\n * Fits a line that carries its own colour, keeping every escape it contains.\n *\n * `fit` above drops hard resets, which is right for a themed row whose\n * background must survive a clipped cell and wrong for captured terminal\n * output: those resets are what END the child's colour runs, and deleting them\n * bleeds a colour through the rest of the panel. This closes the line with a\n * reset instead, before the padding, so no attribute escapes the row.\n */\nexport function fitTerminalLine(text: string, width: number): string {\n const safeWidth = Math.max(0, width);\n const clipped = truncateToWidth(text, safeWidth, ELLIPSIS);\n const padding = ' '.repeat(Math.max(0, safeWidth - visibleWidth(clipped)));\n return clipped.includes(ESCAPE) ? `${clipped}${HARD_RESET}${padding}` : `${clipped}${padding}`;\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":";;AAcA,MAAM,aAAa;AACnB,MAAM,SAAS;AACf,MAAM,6BAA6B;AACnC,MAAM,oBAAoB;;;;;;;;;AAU1B,SAAgB,IAAI,MAAc,OAAuB;CACvD,MAAM,WAAA,GAAUA,uBAAAA,gBAAAA,CAAgB,MAAM,KAAK,IAAI,GAAG,KAAK,GAAA,GAAW,CAAC,CAAC,WAAW,YAAY,EAAE;CAC7F,OAAO,UAAU,IAAI,OAAO,KAAK,IAAI,GAAG,SAAA,GAAQC,uBAAAA,aAAAA,CAAa,OAAO,CAAC,CAAC;AACxE;;;;;;;;;;AAWA,SAAgB,gBAAgB,MAAc,OAAuB;CACnE,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK;CACnC,MAAM,WAAA,GAAUD,uBAAAA,gBAAAA,CAAgB,MAAM,WAAA,GAAmB;CACzD,MAAM,UAAU,IAAI,OAAO,KAAK,IAAI,GAAG,aAAA,GAAYC,uBAAAA,aAAAA,CAAa,OAAO,CAAC,CAAC;CACzE,OAAO,QAAQ,SAAS,MAAM,IAAI,GAAG,UAAU,aAAa,YAAY,GAAG,UAAU;AACvF;;AAGA,SAAgB,aAAa,MAAc,OAAe,OAAuB;CAC/E,MAAM,cAAA,GAAaA,uBAAAA,aAAAA,CAAa,KAAK;CACrC,MAAM,YAAY,KAAK,IAAI,GAAG,QAAQ,aAAa,CAAC;CACpD,OAAO,IAAI,MAAM,SAAS,IAAI,IAAI,OAAO,KAAK,IAAI,GAAG,QAAQ,YAAY,UAAU,CAAC,IAAI,IAAI,OAAO,UAAU;AAC/G;;;;;;;AAQA,SAAgB,SAAS,MAAc,OAAuB;CAC5D,IAAI,SAAS,GAAG,OAAO;CACvB,KAAA,GAAIA,uBAAAA,aAAAA,CAAa,IAAI,KAAK,OAAO,OAAO;CACxC,OAAO,IAAc,KAAK,MAAM,KAAK,SAAS,KAAK,IAAI,GAAG,QAAQ,CAAC,CAAC;AACtE;;;;;;;AAQA,SAAgB,eAAe,MAAuB;CACpD,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS;EAChD,MAAM,OAAO,KAAK,WAAW,KAAK;EAClC,IAAI,OAAO,8BAA8B,SAAS,mBAAmB,OAAO;CAC9E;CACA,OAAO;AACT;;;;;;AAOA,SAAgB,aAAa,UAAkB,OAAwB;CACrE,MAAM,QAAQ,MAAM,YAAY,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;CAC7D,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,MAAM,UAAU,SAAS,YAAY;CACrC,OAAO,MAAM,OAAO,SAAS,QAAQ,SAAS,IAAI,CAAC;AACrD"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
2
|
+
/** pi-tui brackets a truncation ellipsis with this; see `fit`. */
|
|
3
|
+
const HARD_RESET = "\x1B[0m";
|
|
4
|
+
const ESCAPE = "\x1B";
|
|
5
|
+
const FIRST_PRINTABLE_CODE_POINT = 32;
|
|
6
|
+
const DELETE_CODE_POINT = 127;
|
|
7
|
+
/**
|
|
8
|
+
* Truncates and pads to an exact column count.
|
|
9
|
+
*
|
|
10
|
+
* `truncateToWidth` wraps its ellipsis in a hard `\x1b[0m`, which would strip a
|
|
11
|
+
* row's background for everything after a clipped cell. Nothing here sets a
|
|
12
|
+
* colour that a full reset is the correct end for -- the theme closes its own
|
|
13
|
+
* with `\x1b[39m` and `\x1b[49m` -- so the injected resets are dropped.
|
|
14
|
+
*/
|
|
15
|
+
function fit(text, width) {
|
|
16
|
+
const clipped = truncateToWidth(text, Math.max(0, width), "…").replaceAll(HARD_RESET, "");
|
|
17
|
+
return clipped + " ".repeat(Math.max(0, width - visibleWidth(clipped)));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Fits a line that carries its own colour, keeping every escape it contains.
|
|
21
|
+
*
|
|
22
|
+
* `fit` above drops hard resets, which is right for a themed row whose
|
|
23
|
+
* background must survive a clipped cell and wrong for captured terminal
|
|
24
|
+
* output: those resets are what END the child's colour runs, and deleting them
|
|
25
|
+
* bleeds a colour through the rest of the panel. This closes the line with a
|
|
26
|
+
* reset instead, before the padding, so no attribute escapes the row.
|
|
27
|
+
*/
|
|
28
|
+
function fitTerminalLine(text, width) {
|
|
29
|
+
const safeWidth = Math.max(0, width);
|
|
30
|
+
const clipped = truncateToWidth(text, safeWidth, "…");
|
|
31
|
+
const padding = " ".repeat(Math.max(0, safeWidth - visibleWidth(clipped)));
|
|
32
|
+
return clipped.includes(ESCAPE) ? `${clipped}${HARD_RESET}${padding}` : `${clipped}${padding}`;
|
|
33
|
+
}
|
|
34
|
+
/** Right-aligns a trailing cluster against a left one, both clipped to fit. */
|
|
35
|
+
function rightAligned(left, right, width) {
|
|
36
|
+
const rightWidth = visibleWidth(right);
|
|
37
|
+
const leftWidth = Math.max(0, width - rightWidth - 1);
|
|
38
|
+
return fit(left, leftWidth) + " ".repeat(Math.max(1, width - leftWidth - rightWidth)) + fit(right, rightWidth);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Trims from the front rather than the tail.
|
|
42
|
+
*
|
|
43
|
+
* For a path the file name identifies the thing, while the
|
|
44
|
+
* `automations/marketing-workflows/` prefix every entry shares does not.
|
|
45
|
+
*/
|
|
46
|
+
function pathTail(text, width) {
|
|
47
|
+
if (width <= 0) return "";
|
|
48
|
+
if (visibleWidth(text) <= width) return text;
|
|
49
|
+
return `…${text.slice(text.length - Math.max(0, width - 1))}`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Keystrokes that carry no text: escape sequences, control keys, delete.
|
|
53
|
+
*
|
|
54
|
+
* Indexed rather than iterated so surrogate pairs stay intact; both halves sit
|
|
55
|
+
* far above the control range, so no emoji is ever mistaken for one.
|
|
56
|
+
*/
|
|
57
|
+
function isControlInput(data) {
|
|
58
|
+
for (let index = 0; index < data.length; index++) {
|
|
59
|
+
const code = data.charCodeAt(index);
|
|
60
|
+
if (code < FIRST_PRINTABLE_CODE_POINT || code === DELETE_CODE_POINT) return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Whitespace-separated terms, each of which must appear somewhere in the row's
|
|
66
|
+
* searchable text. Splitting on whitespace is what lets `short video` match a
|
|
67
|
+
* row whose words are divided between its title and its file name.
|
|
68
|
+
*/
|
|
69
|
+
function matchesQuery(haystack, query) {
|
|
70
|
+
const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
71
|
+
if (terms.length === 0) return true;
|
|
72
|
+
const lowered = haystack.toLowerCase();
|
|
73
|
+
return terms.every((term) => lowered.includes(term));
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
export { fit, fitTerminalLine, isControlInput, matchesQuery, pathTail, rightAligned };
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=overlayText.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlayText.mjs","names":[],"sources":["../../../../src/tui/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 ESCAPE = '\\x1b';\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/**\n * Fits a line that carries its own colour, keeping every escape it contains.\n *\n * `fit` above drops hard resets, which is right for a themed row whose\n * background must survive a clipped cell and wrong for captured terminal\n * output: those resets are what END the child's colour runs, and deleting them\n * bleeds a colour through the rest of the panel. This closes the line with a\n * reset instead, before the padding, so no attribute escapes the row.\n */\nexport function fitTerminalLine(text: string, width: number): string {\n const safeWidth = Math.max(0, width);\n const clipped = truncateToWidth(text, safeWidth, ELLIPSIS);\n const padding = ' '.repeat(Math.max(0, safeWidth - visibleWidth(clipped)));\n return clipped.includes(ESCAPE) ? `${clipped}${HARD_RESET}${padding}` : `${clipped}${padding}`;\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":";;AAcA,MAAM,aAAa;AACnB,MAAM,SAAS;AACf,MAAM,6BAA6B;AACnC,MAAM,oBAAoB;;;;;;;;;AAU1B,SAAgB,IAAI,MAAc,OAAuB;CACvD,MAAM,UAAU,gBAAgB,MAAM,KAAK,IAAI,GAAG,KAAK,GAAA,GAAW,CAAC,CAAC,WAAW,YAAY,EAAE;CAC7F,OAAO,UAAU,IAAI,OAAO,KAAK,IAAI,GAAG,QAAQ,aAAa,OAAO,CAAC,CAAC;AACxE;;;;;;;;;;AAWA,SAAgB,gBAAgB,MAAc,OAAuB;CACnE,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK;CACnC,MAAM,UAAU,gBAAgB,MAAM,WAAA,GAAmB;CACzD,MAAM,UAAU,IAAI,OAAO,KAAK,IAAI,GAAG,YAAY,aAAa,OAAO,CAAC,CAAC;CACzE,OAAO,QAAQ,SAAS,MAAM,IAAI,GAAG,UAAU,aAAa,YAAY,GAAG,UAAU;AACvF;;AAGA,SAAgB,aAAa,MAAc,OAAe,OAAuB;CAC/E,MAAM,aAAa,aAAa,KAAK;CACrC,MAAM,YAAY,KAAK,IAAI,GAAG,QAAQ,aAAa,CAAC;CACpD,OAAO,IAAI,MAAM,SAAS,IAAI,IAAI,OAAO,KAAK,IAAI,GAAG,QAAQ,YAAY,UAAU,CAAC,IAAI,IAAI,OAAO,UAAU;AAC/G;;;;;;;AAQA,SAAgB,SAAS,MAAc,OAAuB;CAC5D,IAAI,SAAS,GAAG,OAAO;CACvB,IAAI,aAAa,IAAI,KAAK,OAAO,OAAO;CACxC,OAAO,IAAc,KAAK,MAAM,KAAK,SAAS,KAAK,IAAI,GAAG,QAAQ,CAAC,CAAC;AACtE;;;;;;;AAQA,SAAgB,eAAe,MAAuB;CACpD,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS;EAChD,MAAM,OAAO,KAAK,WAAW,KAAK;EAClC,IAAI,OAAO,8BAA8B,SAAS,mBAAmB,OAAO;CAC9E;CACA,OAAO;AACT;;;;;;AAOA,SAAgB,aAAa,UAAkB,OAAwB;CACrE,MAAM,QAAQ,MAAM,YAAY,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;CAC7D,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,MAAM,UAAU,SAAS,YAAY;CACrC,OAAO,MAAM,OAAO,SAAS,QAAQ,SAAS,IAAI,CAAC;AACrD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
let _earendil_works_pi_tui = require("@earendil-works/pi-tui");
|
|
2
|
+
//#region src/tui/workflow/rendering.ts
|
|
3
|
+
function fitLine(text, width) {
|
|
4
|
+
return (0, _earendil_works_pi_tui.truncateToWidth)(text, Math.max(0, width), "");
|
|
5
|
+
}
|
|
6
|
+
function padLine(text, width) {
|
|
7
|
+
const safeWidth = Math.max(0, width);
|
|
8
|
+
const fitted = fitLine(text, safeWidth);
|
|
9
|
+
return `${fitted}${" ".repeat(Math.max(0, safeWidth - (0, _earendil_works_pi_tui.visibleWidth)(fitted)))}`;
|
|
10
|
+
}
|
|
11
|
+
function frameLine(content, width, left = "│", right = "│") {
|
|
12
|
+
const safeWidth = Math.max(0, width);
|
|
13
|
+
const frameWidth = (0, _earendil_works_pi_tui.visibleWidth)(left) + (0, _earendil_works_pi_tui.visibleWidth)(right);
|
|
14
|
+
if (safeWidth <= frameWidth) return fitLine(`${left}${right}`, safeWidth);
|
|
15
|
+
return `${left}${padLine(content, safeWidth - frameWidth)}${right}`;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
exports.fitLine = fitLine;
|
|
19
|
+
exports.frameLine = frameLine;
|
|
20
|
+
exports.padLine = padLine;
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=rendering.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rendering.cjs","names":["truncateToWidth","visibleWidth"],"sources":["../../../../src/tui/workflow/rendering.ts"],"sourcesContent":["import { truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nconst THOUSAND = 1000;\nconst MILLION = 1_000_000;\n/** Below this many tokens the \"k\" form keeps a decimal, above it rounds. */\nconst K_DECIMAL_LIMIT = 10_000;\n\n/** Compact token count, e.g. `812`, `4.2k`, `186k`, `1.3M`. */\nexport function formatTokens(value: number): string {\n if (value < THOUSAND) return String(value);\n if (value < MILLION) return `${(value / THOUSAND).toFixed(value < K_DECIMAL_LIMIT ? 1 : 0)}k`;\n return `${(value / MILLION).toFixed(1)}M`;\n}\n\nexport function fitLine(text: string, width: number): string {\n return truncateToWidth(text, Math.max(0, width), '');\n}\n\nexport function padLine(text: string, width: number): string {\n const safeWidth = Math.max(0, width);\n const fitted = fitLine(text, safeWidth);\n return `${fitted}${' '.repeat(Math.max(0, safeWidth - visibleWidth(fitted)))}`;\n}\n\nexport function alignLine(left: string, right: string, width: number): string {\n const safeWidth = Math.max(0, width);\n const rightWidth = visibleWidth(right);\n if (!right || rightWidth >= safeWidth) return fitLine(right || left, safeWidth);\n\n const maxLeftWidth = Math.max(0, safeWidth - rightWidth - 1);\n const fittedLeft = fitLine(left, maxLeftWidth);\n const gap = ' '.repeat(Math.max(1, safeWidth - visibleWidth(fittedLeft) - rightWidth));\n return fitLine(`${fittedLeft}${gap}${right}`, safeWidth);\n}\n\nexport function frameLine(content: string, width: number, left = '│', right = '│'): string {\n const safeWidth = Math.max(0, width);\n const frameWidth = visibleWidth(left) + visibleWidth(right);\n if (safeWidth <= frameWidth) return fitLine(`${left}${right}`, safeWidth);\n return `${left}${padLine(content, safeWidth - frameWidth)}${right}`;\n}\n\nexport function packSegments(segments: string[], width: number, separator = ' '): string[] {\n const safeWidth = Math.max(0, width);\n if (safeWidth === 0) return [];\n\n const lines: string[] = [];\n let current = '';\n for (const segment of segments) {\n const candidate = current ? `${current}${separator}${segment}` : segment;\n if (visibleWidth(candidate) <= safeWidth) {\n current = candidate;\n continue;\n }\n if (current) lines.push(fitLine(current, safeWidth));\n current = fitLine(segment, safeWidth);\n }\n if (current) lines.push(current);\n return lines;\n}\n"],"mappings":";;AAcA,SAAgB,QAAQ,MAAc,OAAuB;CAC3D,QAAA,GAAOA,uBAAAA,gBAAAA,CAAgB,MAAM,KAAK,IAAI,GAAG,KAAK,GAAG,EAAE;AACrD;AAEA,SAAgB,QAAQ,MAAc,OAAuB;CAC3D,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK;CACnC,MAAM,SAAS,QAAQ,MAAM,SAAS;CACtC,OAAO,GAAG,SAAS,IAAI,OAAO,KAAK,IAAI,GAAG,aAAA,GAAYC,uBAAAA,aAAAA,CAAa,MAAM,CAAC,CAAC;AAC7E;AAaA,SAAgB,UAAU,SAAiB,OAAe,OAAO,KAAK,QAAQ,KAAa;CACzF,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK;CACnC,MAAM,cAAA,GAAaA,uBAAAA,aAAAA,CAAa,IAAI,KAAA,GAAIA,uBAAAA,aAAAA,CAAa,KAAK;CAC1D,IAAI,aAAa,YAAY,OAAO,QAAQ,GAAG,OAAO,SAAS,SAAS;CACxE,OAAO,GAAG,OAAO,QAAQ,SAAS,YAAY,UAAU,IAAI;AAC9D"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
2
|
+
//#region src/tui/workflow/rendering.ts
|
|
3
|
+
function fitLine(text, width) {
|
|
4
|
+
return truncateToWidth(text, Math.max(0, width), "");
|
|
5
|
+
}
|
|
6
|
+
function padLine(text, width) {
|
|
7
|
+
const safeWidth = Math.max(0, width);
|
|
8
|
+
const fitted = fitLine(text, safeWidth);
|
|
9
|
+
return `${fitted}${" ".repeat(Math.max(0, safeWidth - visibleWidth(fitted)))}`;
|
|
10
|
+
}
|
|
11
|
+
function frameLine(content, width, left = "│", right = "│") {
|
|
12
|
+
const safeWidth = Math.max(0, width);
|
|
13
|
+
const frameWidth = visibleWidth(left) + visibleWidth(right);
|
|
14
|
+
if (safeWidth <= frameWidth) return fitLine(`${left}${right}`, safeWidth);
|
|
15
|
+
return `${left}${padLine(content, safeWidth - frameWidth)}${right}`;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { fitLine, frameLine, padLine };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=rendering.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rendering.mjs","names":[],"sources":["../../../../src/tui/workflow/rendering.ts"],"sourcesContent":["import { truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nconst THOUSAND = 1000;\nconst MILLION = 1_000_000;\n/** Below this many tokens the \"k\" form keeps a decimal, above it rounds. */\nconst K_DECIMAL_LIMIT = 10_000;\n\n/** Compact token count, e.g. `812`, `4.2k`, `186k`, `1.3M`. */\nexport function formatTokens(value: number): string {\n if (value < THOUSAND) return String(value);\n if (value < MILLION) return `${(value / THOUSAND).toFixed(value < K_DECIMAL_LIMIT ? 1 : 0)}k`;\n return `${(value / MILLION).toFixed(1)}M`;\n}\n\nexport function fitLine(text: string, width: number): string {\n return truncateToWidth(text, Math.max(0, width), '');\n}\n\nexport function padLine(text: string, width: number): string {\n const safeWidth = Math.max(0, width);\n const fitted = fitLine(text, safeWidth);\n return `${fitted}${' '.repeat(Math.max(0, safeWidth - visibleWidth(fitted)))}`;\n}\n\nexport function alignLine(left: string, right: string, width: number): string {\n const safeWidth = Math.max(0, width);\n const rightWidth = visibleWidth(right);\n if (!right || rightWidth >= safeWidth) return fitLine(right || left, safeWidth);\n\n const maxLeftWidth = Math.max(0, safeWidth - rightWidth - 1);\n const fittedLeft = fitLine(left, maxLeftWidth);\n const gap = ' '.repeat(Math.max(1, safeWidth - visibleWidth(fittedLeft) - rightWidth));\n return fitLine(`${fittedLeft}${gap}${right}`, safeWidth);\n}\n\nexport function frameLine(content: string, width: number, left = '│', right = '│'): string {\n const safeWidth = Math.max(0, width);\n const frameWidth = visibleWidth(left) + visibleWidth(right);\n if (safeWidth <= frameWidth) return fitLine(`${left}${right}`, safeWidth);\n return `${left}${padLine(content, safeWidth - frameWidth)}${right}`;\n}\n\nexport function packSegments(segments: string[], width: number, separator = ' '): string[] {\n const safeWidth = Math.max(0, width);\n if (safeWidth === 0) return [];\n\n const lines: string[] = [];\n let current = '';\n for (const segment of segments) {\n const candidate = current ? `${current}${separator}${segment}` : segment;\n if (visibleWidth(candidate) <= safeWidth) {\n current = candidate;\n continue;\n }\n if (current) lines.push(fitLine(current, safeWidth));\n current = fitLine(segment, safeWidth);\n }\n if (current) lines.push(current);\n return lines;\n}\n"],"mappings":";;AAcA,SAAgB,QAAQ,MAAc,OAAuB;CAC3D,OAAO,gBAAgB,MAAM,KAAK,IAAI,GAAG,KAAK,GAAG,EAAE;AACrD;AAEA,SAAgB,QAAQ,MAAc,OAAuB;CAC3D,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK;CACnC,MAAM,SAAS,QAAQ,MAAM,SAAS;CACtC,OAAO,GAAG,SAAS,IAAI,OAAO,KAAK,IAAI,GAAG,YAAY,aAAa,MAAM,CAAC,CAAC;AAC7E;AAaA,SAAgB,UAAU,SAAiB,OAAe,OAAO,KAAK,QAAQ,KAAa;CACzF,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK;CACnC,MAAM,aAAa,aAAa,IAAI,IAAI,aAAa,KAAK;CAC1D,IAAI,aAAa,YAAY,OAAO,QAAQ,GAAG,OAAO,SAAS,SAAS;CACxE,OAAO,GAAG,OAAO,QAAQ,SAAS,YAAY,UAAU,IAAI;AAC9D"}
|