@astralyn/pi 0.84.11 → 0.84.13
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/CHANGELOG.md +31 -0
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +2 -1
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/core/agent-session.d.ts +62 -8
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +395 -78
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +4 -3
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +5 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +19 -5
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +5 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +44 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +18 -10
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +4 -2
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +8 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +17 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/bash.d.ts +5 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +5 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/extensions/background/actions.d.ts +21 -0
- package/dist/extensions/background/actions.d.ts.map +1 -0
- package/dist/extensions/background/actions.js +264 -0
- package/dist/extensions/background/actions.js.map +1 -0
- package/dist/extensions/background/constants.d.ts +24 -0
- package/dist/extensions/background/constants.d.ts.map +1 -0
- package/dist/extensions/background/constants.js +24 -0
- package/dist/extensions/background/constants.js.map +1 -0
- package/dist/extensions/background/index.d.ts +6 -115
- package/dist/extensions/background/index.d.ts.map +1 -1
- package/dist/extensions/background/index.js +38 -509
- package/dist/extensions/background/index.js.map +1 -1
- package/dist/extensions/background/manager.d.ts +2 -1
- package/dist/extensions/background/manager.d.ts.map +1 -1
- package/dist/extensions/background/manager.js +8 -10
- package/dist/extensions/background/manager.js.map +1 -1
- package/dist/extensions/background/notify.d.ts +16 -0
- package/dist/extensions/background/notify.d.ts.map +1 -0
- package/dist/extensions/background/notify.js +114 -0
- package/dist/extensions/background/notify.js.map +1 -0
- package/dist/extensions/background/output-file.d.ts +58 -0
- package/dist/extensions/background/output-file.d.ts.map +1 -0
- package/dist/extensions/background/output-file.js +122 -0
- package/dist/extensions/background/output-file.js.map +1 -0
- package/dist/extensions/background/registry.d.ts +40 -72
- package/dist/extensions/background/registry.d.ts.map +1 -1
- package/dist/extensions/background/registry.js +71 -184
- package/dist/extensions/background/registry.js.map +1 -1
- package/dist/extensions/background/render.d.ts +3 -10
- package/dist/extensions/background/render.d.ts.map +1 -1
- package/dist/extensions/background/render.js +20 -60
- package/dist/extensions/background/render.js.map +1 -1
- package/dist/extensions/background/schema.d.ts +34 -0
- package/dist/extensions/background/schema.d.ts.map +1 -0
- package/dist/extensions/background/schema.js +89 -0
- package/dist/extensions/background/schema.js.map +1 -0
- package/dist/extensions/background/task-view.d.ts +48 -0
- package/dist/extensions/background/task-view.d.ts.map +1 -0
- package/dist/extensions/background/task-view.js +90 -0
- package/dist/extensions/background/task-view.js.map +1 -0
- package/dist/extensions/background/text.d.ts +15 -0
- package/dist/extensions/background/text.d.ts.map +1 -0
- package/dist/extensions/background/text.js +31 -0
- package/dist/extensions/background/text.js.map +1 -0
- package/dist/extensions/background/types.d.ts +74 -0
- package/dist/extensions/background/types.d.ts.map +1 -0
- package/dist/extensions/background/types.js +17 -0
- package/dist/extensions/background/types.js.map +1 -0
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +2 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/llama/client.d.ts +6 -0
- package/dist/extensions/llama/client.d.ts.map +1 -1
- package/dist/extensions/llama/client.js +7 -0
- package/dist/extensions/llama/client.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts +3 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +27 -6
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/extensions/subagent/activity.d.ts +5 -0
- package/dist/extensions/subagent/activity.d.ts.map +1 -1
- package/dist/extensions/subagent/activity.js +5 -0
- package/dist/extensions/subagent/activity.js.map +1 -1
- package/dist/extensions/subagent/agents-command.d.ts.map +1 -1
- package/dist/extensions/subagent/agents-command.js +6 -391
- package/dist/extensions/subagent/agents-command.js.map +1 -1
- package/dist/extensions/subagent/constants.d.ts.map +1 -1
- package/dist/extensions/subagent/constants.js +1 -0
- package/dist/extensions/subagent/constants.js.map +1 -1
- package/dist/extensions/subagent/render.d.ts.map +1 -1
- package/dist/extensions/subagent/render.js +15 -1
- package/dist/extensions/subagent/render.js.map +1 -1
- package/dist/extensions/subagent/resolve.d.ts.map +1 -1
- package/dist/extensions/subagent/resolve.js +2 -4
- package/dist/extensions/subagent/resolve.js.map +1 -1
- package/dist/extensions/subagent/runner.d.ts +1 -1
- package/dist/extensions/subagent/runner.d.ts.map +1 -1
- package/dist/extensions/subagent/runner.js +8 -8
- package/dist/extensions/subagent/runner.js.map +1 -1
- package/dist/extensions/subagent/sdk-runner.d.ts +11 -0
- package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
- package/dist/extensions/subagent/sdk-runner.js +90 -79
- package/dist/extensions/subagent/sdk-runner.js.map +1 -1
- package/dist/extensions/subagent/state.d.ts.map +1 -1
- package/dist/extensions/subagent/state.js +145 -126
- package/dist/extensions/subagent/state.js.map +1 -1
- package/dist/extensions/subagent/text.d.ts.map +1 -1
- package/dist/extensions/subagent/text.js +4 -0
- package/dist/extensions/subagent/text.js.map +1 -1
- package/dist/extensions/subagent/ui/agents-dialog.d.ts +4 -0
- package/dist/extensions/subagent/ui/agents-dialog.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/agents-dialog.js +84 -0
- package/dist/extensions/subagent/ui/agents-dialog.js.map +1 -0
- package/dist/extensions/subagent/ui/choice-menu.d.ts +39 -0
- package/dist/extensions/subagent/ui/choice-menu.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/choice-menu.js +93 -0
- package/dist/extensions/subagent/ui/choice-menu.js.map +1 -0
- package/dist/extensions/subagent/ui/model-picker.d.ts +47 -0
- package/dist/extensions/subagent/ui/model-picker.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/model-picker.js +142 -0
- package/dist/extensions/subagent/ui/model-picker.js.map +1 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.d.ts +41 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.js +98 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.js.map +1 -0
- package/dist/extensions/web-search/auth.d.ts +12 -0
- package/dist/extensions/web-search/auth.d.ts.map +1 -0
- package/dist/extensions/web-search/auth.js +90 -0
- package/dist/extensions/web-search/auth.js.map +1 -0
- package/dist/extensions/web-search/constants.d.ts +13 -0
- package/dist/extensions/web-search/constants.d.ts.map +1 -0
- package/dist/extensions/web-search/constants.js +27 -0
- package/dist/extensions/web-search/constants.js.map +1 -0
- package/dist/extensions/web-search/fusion.d.ts +36 -0
- package/dist/extensions/web-search/fusion.d.ts.map +1 -0
- package/dist/extensions/web-search/fusion.js +272 -0
- package/dist/extensions/web-search/fusion.js.map +1 -0
- package/dist/extensions/web-search/index.d.ts +6 -0
- package/dist/extensions/web-search/index.d.ts.map +1 -0
- package/dist/extensions/web-search/index.js +70 -0
- package/dist/extensions/web-search/index.js.map +1 -0
- package/dist/extensions/web-search/providers/deepseek.d.ts +15 -0
- package/dist/extensions/web-search/providers/deepseek.d.ts.map +1 -0
- package/dist/extensions/web-search/providers/deepseek.js +63 -0
- package/dist/extensions/web-search/providers/deepseek.js.map +1 -0
- package/dist/extensions/web-search/providers/http.d.ts +9 -0
- package/dist/extensions/web-search/providers/http.d.ts.map +1 -0
- package/dist/extensions/web-search/providers/http.js +25 -0
- package/dist/extensions/web-search/providers/http.js.map +1 -0
- package/dist/extensions/web-search/providers/minimax.d.ts +14 -0
- package/dist/extensions/web-search/providers/minimax.d.ts.map +1 -0
- package/dist/extensions/web-search/providers/minimax.js +69 -0
- package/dist/extensions/web-search/providers/minimax.js.map +1 -0
- package/dist/extensions/web-search/render.d.ts +11 -0
- package/dist/extensions/web-search/render.d.ts.map +1 -0
- package/dist/extensions/web-search/render.js +109 -0
- package/dist/extensions/web-search/render.js.map +1 -0
- package/dist/extensions/web-search/schema.d.ts +12 -0
- package/dist/extensions/web-search/schema.d.ts.map +1 -0
- package/dist/extensions/web-search/schema.js +57 -0
- package/dist/extensions/web-search/schema.js.map +1 -0
- package/dist/extensions/web-search/types.d.ts +111 -0
- package/dist/extensions/web-search/types.d.ts.map +1 -0
- package/dist/extensions/web-search/types.js +5 -0
- package/dist/extensions/web-search/types.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +10 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +71 -58
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +7 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +7 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +3 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +12 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +6 -4
- package/dist/utils/shell.js.map +1 -1
- package/docs/bundled/README.md +1 -0
- package/docs/bundled/extensions/web-search.md +50 -0
- package/docs/compaction.md +5 -12
- package/docs/environment-variables.md +3 -0
- package/docs/extensions.md +21 -5
- package/docs/keybindings.md +1 -1
- package/docs/quickstart.md +1 -1
- package/docs/rpc.md +23 -0
- package/docs/settings.md +7 -0
- package/docs/terminal-setup.md +12 -0
- package/docs/usage.md +4 -3
- package/npm-shrinkwrap.json +29 -29
- package/package.json +6 -6
- package/dist/core/compaction-controller.d.ts +0 -90
- package/dist/core/compaction-controller.d.ts.map +0 -1
- package/dist/core/compaction-controller.js +0 -471
- package/dist/core/compaction-controller.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/background/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAO9C,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAEN,yBAAyB,EACzB,mBAAmB,EACnB,mBAAmB,GACnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EACN,sBAAsB,EACtB,kBAAkB,EAClB,cAAc,EACd,cAAc,EAKd,gBAAgB,EAChB,cAAc,EAEd,eAAe,EACf,eAAe,GACf,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,YAAY,EACZ,4BAA4B,EAC5B,YAAY,EACZ,cAAc,GAEd,MAAM,aAAa,CAAC;AAErB,MAAM,CAAC,MAAM,oBAAoB,GAAG,iBAAiB,CAAC;AACtD,MAAM,qBAAqB,GAAG,CAAC,GAAG,IAAI,CAAC;AACvC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAC9B,MAAM,sBAAsB,GAAG,CAAC,CAAC;AACjC,0DAA0D;AAC1D,MAAM,mBAAmB,GAAG,EAAE,GAAG,IAAI,CAAC;AACtC,6EAA6E;AAC7E,MAAM,kBAAkB,GAAG,CAAC,GAAG,IAAI,CAAC;AAEpC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC;IAC5B,MAAM,EAAE,IAAI,CAAC,KAAK,CACjB,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAChH,EAAE,WAAW,EAAE,4CAA4C,EAAE,CAC7D;IACD,aAAa;IACb,OAAO,EAAE,IAAI,CAAC,QAAQ,CACrB,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,mEAAmE,EAAE,CAAC,CACjG;IACD,WAAW,EAAE,IAAI,CAAC,QAAQ,CACzB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,sFAAsF;KACnG,CAAC,CACF;IACD,OAAO,EAAE,IAAI,CAAC,QAAQ,CACrB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,qFAAqF;KAClG,CAAC,CACF;IACD,yBAAyB;IACzB,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,6EAA6E,EAAE,CAAC,CAC3G;IACD,WAAW;IACX,IAAI,EAAE,IAAI,CAAC,QAAQ,CAClB,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE;QACxD,WAAW,EAAE,+DAA+D;KAC5E,CAAC,CACF;IACD,KAAK,EAAE,IAAI,CAAC,QAAQ,CACnB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,sCAAsC,UAAU,CAAC,qBAAqB,CAAC,SAAS,UAAU,CAAC,iBAAiB,CAAC,GAAG;KAC7H,CAAC,CACF;IACD,WAAW;IACX,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,mCAAmC,kBAAkB,SAAS,cAAc,SAAS;KAClG,CAAC,CACF;IACD,UAAU,EAAE,IAAI,CAAC,QAAQ,CACxB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EACV,qGAAqG;KACtG,CAAC,CACF;CACD,CAAC,CAAC;AA0EH,MAAM,UAAU,SAAS,CAAC,IAAY;IACrC,OAAO,IAAI;SACT,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC/C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtC,IACC,IAAI,KAAK,IAAI;YACb,IAAI,KAAK,IAAI;YACb,IAAI,KAAK,IAAI;YACb,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,MAAM,CAAC;YAChC,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC;YAClC,IAAI,IAAI,OAAO,EACd,CAAC;YACF,MAAM,IAAI,IAAI,CAAC;QAChB,CAAC;IACF,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,SAAS,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;AAEvE,qFAAqF;AACrF,SAAS,gBAAgB,CAAC,YAAgC;IACzD,IAAI,YAAY,CAAC,SAAS,EAAE,CAAC;QAC5B,OAAO,CAAC,6BAA6B,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC5E,CAAC;IACD,MAAM,KAAK,GAAG;QACb,UAAU,YAAY,CAAC,SAAS,GAAG;QACnC,eAAe,YAAY,CAAC,UAAU,GAAG;QACzC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE;QACpD,YAAY,CAAC,iBAAiB,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE;KAC5D;SACC,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IACZ,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;IAC/F,OAAO,CAAC,gBAAgB,KAAK,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,gBAAgB,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,YAAgC;IACxE,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC;IAC/B,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IAClF,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,QAAQ,GAAG,CAAC;IAC7G,MAAM,KAAK,GAAG;QACb,wBAAwB,IAAI,CAAC,EAAE,aAAa,IAAI,CAAC,MAAM,IAAI,QAAQ,aAAa,OAAO,IAAI;QAC3F,YAAY,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY;KAC7C,CAAC;IACF,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,gBAAgB,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;IACvE,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,gBAAgB,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;IACrE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,UAAU,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACrD,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC,CAAC;IAC9C,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACjC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAA4D;IAC5F,IAAI,MAAM,CAAC,KAAK,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACzC,gFAAgF;IAChF,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IACzC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC;IAC5C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,OAAO,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,UAAU,CAAC,CAAC;IAClD,IAAI,OAAO,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,oBAAoB,CAAC,CAAC;IAC5D,IAAI,KAAK,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC;IAC3C,OAAO,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,YAAiC;IAClE,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC;IAC/B,uEAAuE;IACvE,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG;QACb,wBAAwB,IAAI,CAAC,EAAE,wDAAwD,OAAO,IAAI;QAClG,YAAY,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY;KAC7C,CAAC;IACF,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,gBAAgB,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;IACvE,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,gBAAgB,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;IACrE,KAAK,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC,CAAC;IAC9C,KAAK,CAAC,IAAI,CACT,kGAAkG;QACjG,wGAAwG;QACxG,6CAA6C,CAC9C,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACjC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,cAAc,CAAC,YAAiC;IACxD,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC;IAC/B,OAAO;QACN,MAAM,EAAE,IAAI,CAAC,EAAE;QACf,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,MAAM,EAAE,SAAS;QACjB,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,SAAS;QACnB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS;QACtC,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,UAAU,EAAE,YAAY,CAAC,UAAU;QACnC,QAAQ,EAAE,YAAY,CAAC,QAAQ;QAC/B,aAAa,EAAE,YAAY,CAAC,aAAa;QACzC,SAAS,EAAE,YAAY,CAAC,SAAS;KACjC,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAa,EAAE,MAAyC;IACvF,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAClC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,MAAM,MAAM,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAC/E,CAAC;QACF,OAAO,YAAY,KAAK,gCAAgC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAC5E,CAAC;IACD,OAAO,+BAA+B,KAAK,qEAAqE,CAAC;AAClH,CAAC;AAED,kFAAkF;AAClF,SAAS,gBAAgB,CAAC,IAAY,EAAE,GAAW;IAClD,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IACxE,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACnG,OAAO,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,QAAQ,KAAK,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AACjG,CAAC;AAED,sFAAsF;AACtF,SAAS,SAAS,CAAC,IAAY;IAC9B,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,MAAM,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACtH,CAAC;AAED,SAAS,qBAAqB,CAAC,YAAgC;IAC9D,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC;IAC/B,OAAO;QACN,MAAM,EAAE,IAAI,CAAC,EAAE;QACf,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,SAAS,EAAE,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,SAAS;QAC5D,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,UAAU,EAAE,YAAY,CAAC,UAAU;QACnC,QAAQ,EAAE,YAAY,CAAC,QAAQ;QAC/B,aAAa,EAAE,YAAY,CAAC,aAAa;QACzC,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,SAAS,EAAE,YAAY,CAAC,SAAS;KACjC,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,UAA0B,EAAE,MAA0B;IAC1F,IAAI,CAAC,MAAM;QAAE,OAAO,UAAU,CAAC;IAC/B,OAAO;QACN,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,MAAM,KAAK,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC;KACvF,CAAC;AACH,CAAC;AAUD,0GAA0G;AAC1G,MAAM,UAAU,mBAAmB,CAClC,GAAqB,EACrB,gBAAuE;IAEvE,OAAO,GAAG,CAAC,gBAAgB,EAAE,EAAE,IAAI,gBAAgB,EAAE,EAAE,IAAI,EAAE,CAAC;AAC/D,CAAC;AAED,+FAA+F;AAC/F,SAAS,2BAA2B,CAAC,GAAqB;IACzD,MAAM,KAAK,GAAG,mBAAmB,CAAC,GAAG,EAAE,GAAG,EAAE;QAC3C,yEAAyE;QACzE,qEAAqE;QACrE,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE;YAC/D,cAAc,EAAE,GAAG,CAAC,gBAAgB,EAAE;SACtC,CAAC,CAAC;QACH,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,YAAY,EAAE,EAAE,aAAa,EAAE,QAAQ,CAAC,qBAAqB,EAAE,EAAE,CAAC;IAChG,CAAC,CAAC,CAAC;IACH,OAAO,oBAAoB,CAAC,yBAAyB,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;AAC7G,CAAC;AAED,8EAA8E;AAC9E,SAAS,cAAc,CAAC,KAAc;IACrC,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,QAAQ;YACZ,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzD,MAAM,IAAI,KAAK,CAAC,sFAAsF,CAAC,CAAC;YACzG,CAAC;YACD,MAAM;QACP,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM;YACV,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvD,MAAM,IAAI,KAAK,CACd,WAAW,KAAK,CAAC,MAAM,wFAAwF,CAC/G,CAAC;YACH,CAAC;YACD,MAAM;QACP,KAAK,MAAM;YACV,MAAM;IACR,CAAC;AACF,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,yBAAyB,CAAC,SAAwC;IACjF,OAAO,CAAC,EAAgB,EAAE,EAAE;QAC3B,IAAI,QAA4C,CAAC;QACjD,IAAI,UAAwC,CAAC;QAE7C,MAAM,eAAe,GAAG,GAA2B,EAAE;YACpD,IAAI,CAAC,QAAQ;gBAAE,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;YAC9F,OAAO,QAAQ,CAAC;QACjB,CAAC,CAAC;QAEF,MAAM,kBAAkB,GAAG,CAAC,MAAc,EAAU,EAAE;YACrD,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YACvD,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC5E,OAAO,QAAQ,CAAC,IAAI,CAAC;QACtB,CAAC,CAAC;QAEF,uEAAuE;QACvE,MAAM,aAAa,GAAkB,CAAC,MAAM,EAAE,EAAE;YAC/C,IAAI,CAAC,QAAQ;gBAAE,OAAO,SAAS,CAAC;YAChC,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YAC9C,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3G,CAAC,CAAC;QAEF,MAAM,YAAY,GAAG,GAAG,EAAE;YACzB,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,cAAc;gBAAE,OAAO;YACjD,UAAU,EAAE,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,gBAAgB,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC7E,CAAC,CAAC;QAEF,0FAA0F;QAC1F,MAAM,MAAM,GAAG,CAAC,OAAe,EAAE,OAA8B,EAAE,EAAE;YAClE,EAAE,CAAC,WAAW,CACb,EAAE,UAAU,EAAE,oBAAoB,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EACrE,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,CAC5C,CAAC;QACH,CAAC,CAAC;QAEF,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;YACtC,UAAU,GAAG,GAAG,CAAC;YACjB,sFAAsF;YACtF,IAAI,QAAQ;gBAAE,KAAK,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACvC,QAAQ,GAAG,IAAI,sBAAsB,CAAC;gBACrC,UAAU,EAAE,SAAS,EAAE,UAAU,IAAI,2BAA2B,CAAC,GAAG,CAAC;gBACrE,SAAS,EAAE,SAAS,EAAE,SAAS;gBAC/B,cAAc,EAAE,SAAS,EAAE,cAAc;gBACzC,KAAK,EAAE,SAAS,EAAE,KAAK;gBACvB,QAAQ,EAAE,CAAC,YAAY,EAAE,EAAE,CAC1B,MAAM,CAAC,wBAAwB,CAAC,YAAY,CAAC,EAAE,qBAAqB,CAAC,YAAY,CAAC,CAAC;gBACpF,sEAAsE;gBACtE,qEAAqE;gBACrE,2BAA2B;gBAC3B,OAAO,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,YAAY,CAAC,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC;gBAChG,QAAQ,EAAE,YAAY;aACtB,CAAC,CAAC;YACH,YAAY,EAAE,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,EAAE,CAAC,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;YAC/C,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;YAC1C,UAAU,GAAG,SAAS,CAAC;YACvB,MAAM,MAAM,GAAG,QAAQ,CAAC;YACxB,QAAQ,GAAG,SAAS,CAAC;YACrB,MAAM,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,KAAK,EACtB,MAAqB,EACrB,GAAqB,EACuB,EAAE;YAC9C,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC;gBAC/F,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;YAC3E,CAAC;YACD,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,GAAG,mBAAmB,EAAE,CAAC;gBAC1E,MAAM,IAAI,KAAK,CAAC,+BAA+B,mBAAmB,UAAU,CAAC,CAAC;YAC/E,CAAC;YACD,+EAA+E;YAC/E,MAAM,YAAY,GAAG,mBAAmB,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YACxF,sEAAsE;YACtE,kEAAkE;YAClE,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC,SAAS,CAAC;gBACxC,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,cAAc,EAAE,MAAM,CAAC,OAAO;gBAC9B,GAAG,EAAE,YAAY,CAAC,GAAG;aACrB,CAAC,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,MAAM,IAAI,GAAG;gBACZ,2BAA2B,IAAI,CAAC,EAAE,GAAG,KAAK,GAAG;gBAC7C,gBAAgB,IAAI,CAAC,UAAU,EAAE;gBACjC,EAAE;gBACF,uGAAuG;oBACtG,6FAA6F;oBAC7F,+EAA+E;aAChF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACb,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;gBACjC,OAAO,EAAE;oBACR,MAAM,EAAE,QAAQ;oBAChB,MAAM,EAAE,IAAI,CAAC,EAAE;oBACf,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,WAAW,EAAE,MAAM,CAAC,WAAW;iBAC/B;aACD,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,OAAO,GAAG,KAAK,EAAE,MAAmB,EAA2C,EAAE;YACtF,MAAM,IAAI,GAAG,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC;YACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CACxB,iBAAiB,EACjB,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,qBAAqB,CAAC,CAAC,CAC9E,CAAC;YACF,IAAI,KAAkD,CAAC;YACvD,IAAI,CAAC;gBACJ,KAAK,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YACpE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,MAAM,IAAI,KAAK,CACd,6BAA6B,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,MAAM,MAAM,OAAO,kBAAkB,IAAI,CAAC,UAAU,EAAE,CACpG,CAAC;YACH,CAAC;YACD,MAAM,IAAI,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,MAAM,WAAW,GAAG,KAAK,CAAC,SAAS;gBAClC,CAAC,CAAC;oBACA,GAAG,IAAI,IAAI,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE;oBAC5E,QAAQ,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE;oBAChC,GAAG,OAAO;oBACV,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC7D,gBAAgB,IAAI,CAAC,UAAU,EAAE;iBACjC;gBACF,CAAC,CAAC;oBACA,QAAQ,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE;oBAChC,GAAG,OAAO;oBACV,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ;oBACvC,WAAW,IAAI,CAAC,UAAU,EAAE;iBAC5B,CAAC;YACJ,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC;YACxD,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;gBAC1E,OAAO,EAAE;oBACR,MAAM,EAAE,MAAM;oBACd,MAAM,EAAE,IAAI,CAAC,EAAE;oBACf,IAAI;oBACJ,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,UAAU,EAAE,IAAI,CAAC,UAAU;iBAC3B;aACD,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,OAAO,GAAG,KAAK,EAAE,MAAmB,EAAE,MAAoB,EAA2C,EAAE;YAC5G,MAAM,IAAI,GAAG,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACtB,cAAc,EACd,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,IAAI,kBAAkB,CAAC,CAAC,CACzE,CAAC;YACF,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YAC9E,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC;YAC1C,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC;YAC9B,MAAM,UAAU,GACf,SAAS,CAAC,QAAQ,KAAK,SAAS,IAAI,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxG,MAAM,GAAG,GAAG,cAAc,CAAC,CAAC,SAAS,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;YAEpF,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBAClC,iEAAiE;gBACjE,IAAI,QAAQ,GAAG,EAAE,CAAC;gBAClB,IAAI,QAAQ,GAAG,EAAE,CAAC;gBAClB,IAAI,UAAU,GAAG,SAAS,CAAC,WAAW,CAAC;gBACvC,IAAI,CAAC;oBACJ,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CAAC,CAAC;oBACzG,QAAQ,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAC3C,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;oBAC7B,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3E,CAAC;gBAAC,MAAM,CAAC;oBACR,QAAQ,GAAG,uBAAuB,CAAC;gBACpC,CAAC;gBACD,MAAM,KAAK,GAAG;oBACb,IAAI,SAAS,CAAC,EAAE,2BAA2B,cAAc,CAAC,QAAQ,CAAC,MAAM,UAAU,CAAC,UAAU,CAAC,SAAS;iBACxG,CAAC;gBACF,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACnC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,cAAc,QAAQ,MAAM,OAAO,EAAE,CAAC,CAAC;gBAC1E,KAAK,CAAC,IAAI,CACT,wGAAwG;oBACvG,mFAAmF,CACpF,CAAC;gBACF,OAAO;oBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;oBACrD,OAAO,EAAE;wBACR,MAAM,EAAE,MAAM;wBACd,MAAM,EAAE,SAAS,CAAC,EAAE;wBACpB,QAAQ,EAAE,IAAI;wBACd,MAAM,EAAE,SAAS,CAAC,MAAM;wBACxB,QAAQ,EAAE,SAAS,CAAC,QAAQ;wBAC5B,QAAQ;wBACR,UAAU,EAAE,CAAC;wBACb,UAAU;wBACV,cAAc,EAAE,KAAK;wBACrB,UAAU,EAAE,SAAS,CAAC,UAAU;qBAChC;iBACD,CAAC;YACH,CAAC;YAED,kEAAkE;YAClE,mEAAmE;YACnE,wDAAwD;YACxD,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACvG,IAAI,KAAkD,CAAC;YACvD,IAAI,UAA8B,CAAC;YACnC,IAAI,CAAC;gBACJ,KAAK,GAAG,MAAM,eAAe,CAAC,SAAS,CAAC,UAAU,EAAE,KAAK,IAAI,CAAC,EAAE,mBAAmB,CAAC,CAAC;gBACrF,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC;oBACrD,mEAAmE;oBACnE,iEAAiE;oBACjE,iEAAiE;oBACjE,KAAK,GAAG,MAAM,eAAe,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC,EAAE,mBAAmB,CAAC,CAAC;oBAC5E,UAAU,GAAG,SAAS,CAAC,eAAe;wBACrC,CAAC,CAAC,oFAAoF;wBACtF,CAAC,CAAC,gDAAgD,CAAC;gBACrD,CAAC;YACF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,wEAAwE;gBACxE,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,OAAO;oBACN,OAAO,EAAE;wBACR;4BACC,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,IAAI,SAAS,CAAC,EAAE,IAAI,SAAS,CAAC,MAAM,GAAG,UAAU,UAAU,GAAG,aAAa,cAAc,CAAC,QAAQ,CAAC,4BAA4B,OAAO,EAAE;yBAC9I;qBACD;oBACD,OAAO,EAAE;wBACR,MAAM,EAAE,MAAM;wBACd,MAAM,EAAE,SAAS,CAAC,EAAE;wBACpB,QAAQ,EAAE,KAAK;wBACf,MAAM,EAAE,SAAS,CAAC,MAAM;wBACxB,QAAQ,EAAE,SAAS,CAAC,QAAQ;wBAC5B,QAAQ;wBACR,UAAU,EAAE,CAAC;wBACb,UAAU,EAAE,SAAS,CAAC,WAAW;wBACjC,cAAc,EAAE,KAAK;wBACrB,UAAU,EAAE,SAAS,CAAC,UAAU;qBAChC;iBACD,CAAC;YACH,CAAC;YAED,MAAM,KAAK,GAAG;gBACb,IAAI,SAAS,CAAC,EAAE,IAAI,SAAS,CAAC,MAAM,GAAG,UAAU,UAAU,GAAG,aAAa,cAAc,CAAC,QAAQ,CAAC,OAAO,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,uBAAuB,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG;aAC5L,CAAC;YACF,IAAI,UAAU;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,GAAG,CAAC,CAAC;YAC9C,IAAI,SAAS,CAAC,KAAK;gBAAE,KAAK,CAAC,IAAI,CAAC,UAAU,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;YAC7D,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;gBACrB,KAAK,CAAC,IAAI,CACT,YAAY,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,kBAAkB,SAAS,CAAC,UAAU,GAAG,CACpH,CAAC;YACH,CAAC;YACD,MAAM,IAAI,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YACxD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;YACvD,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,OAAO,EAAE;oBACR,MAAM,EAAE,MAAM;oBACd,MAAM,EAAE,SAAS,CAAC,EAAE;oBACpB,QAAQ,EAAE,KAAK;oBACf,MAAM,EAAE,SAAS,CAAC,MAAM;oBACxB,QAAQ,EAAE,SAAS,CAAC,QAAQ;oBAC5B,QAAQ;oBACR,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,cAAc,EAAE,KAAK,CAAC,SAAS;oBAC/B,UAAU,EAAE,SAAS,CAAC,UAAU;iBAChC;aACD,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,OAAO,GAAG,CAAC,MAAmB,EAAkC,EAAE;YACvE,MAAM,IAAI,GAAG,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACpB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpG,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,4BAA4B,IAAI,CAAC,MAAM,GAAG,IAAI,IAAI,CAAC,CAAC;YACpF,CAAC;YACD,OAAO;gBACN,OAAO,EAAE;oBACR;wBACC,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,eAAe,IAAI,CAAC,EAAE,6JAA6J;qBACzL;iBACD;gBACD,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;aACnE,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,OAAO,GAAG,GAAmC,EAAE;YACpD,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC,SAAS,EAAE,CAAC;YAC5C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO;oBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iEAAiE,EAAE,CAAC;oBACpG,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;iBACzE,CAAC;YACH,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;YAClE,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;YACnE,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC;YAChE,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC;YACtD,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,cAAc,QAAQ,CAAC,MAAM,WAAW,CAAC,CAAC;YAC1E,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,OAAO,EAAE,GAAG,aAAa,CAAC,EAAE,CAAC;gBACnD,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;YACzC,CAAC;YACD,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChB,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,kEAAkE,CAAC,CAAC;YAC3F,CAAC;YACD,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,OAAO,EAAE;oBACR,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,OAAO,CAAC,MAAM;oBACvB,QAAQ,EAAE,QAAQ,CAAC,MAAM;oBACzB,KAAK,EAAE,OAAO,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM;oBAC5C,MAAM;iBACN;aACD,CAAC;QACH,CAAC,CAAC;QAEF,EAAE,CAAC,YAAY,CAA6B;YAC3C,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,IAAI;YACX,WAAW,EACV,2CAA2C;gBAC3C,yFAAyF;gBACzF,6FAA6F;gBAC7F,2FAA2F;gBAC3F,eAAe;gBACf,yEAAyE;gBACzE,yFAAyF;gBACzF,4FAA4F;gBAC5F,0EAA0E;gBAC1E,qDAAqD;gBACrD,0CAA0C;YAC3C,aAAa,EAAE,gEAAgE;YAC/E,gBAAgB,EAAE;gBACjB,iNAAiN;gBACjN,8HAA8H;aAC9H;YACD,UAAU,EAAE,QAAQ;YACpB,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG;gBACxD,cAAc,CAAC,MAAM,CAAC,CAAC;gBACvB,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;oBACvB,KAAK,QAAQ;wBACZ,OAAO,SAAS,CAAC,MAAuB,EAAE,GAAG,CAAC,CAAC;oBAChD,KAAK,MAAM;wBACV,OAAO,OAAO,CAAC,MAAqB,CAAC,CAAC;oBACvC,KAAK,MAAM;wBACV,OAAO,OAAO,CAAC,MAAqB,EAAE,MAAM,CAAC,CAAC;oBAC/C,KAAK,MAAM;wBACV,OAAO,OAAO,CAAC,MAAqB,CAAC,CAAC;oBACvC,KAAK,MAAM;wBACV,OAAO,OAAO,EAAE,CAAC;gBACnB,CAAC;YACF,CAAC;YACD,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO;gBAC9B,OAAO,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;YAC1D,CAAC;YACD,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO;gBAC3C,OAAO,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YACxD,CAAC;SACD,CAAC,CAAC;QAEH,EAAE,CAAC,uBAAuB,CAAwB,oBAAoB,EAAE,4BAA4B,CAAC,CAAC;QAEtG,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE;YACxB,WAAW,EAAE,kCAAkC;YAC/C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAA4B,EAAE,EAAE;gBACtD,MAAM,MAAM,GAAG,QAAQ,CAAC;gBACxB,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;oBAC5C,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC;oBAC9C,OAAO;gBACR,CAAC;gBACD,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;oBACxB,oEAAoE;oBACpE,MAAM,KAAK,GAAG,MAAM;yBAClB,SAAS,EAAE;yBACX,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;yBACZ,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;oBACpD,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,sBAAsB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,iDAAiD,EACvF,MAAM,CACN,CAAC;oBACF,OAAO;gBACR,CAAC;gBACD,MAAM,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAC1C,CAAC;SACD,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,qBAAqB,CAAC,GAA4B,EAAE,QAAgC;IAClG,mFAAmF;IACnF,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAClB,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,CACjC,IAAI,mBAAmB,CAAC;QACvB,GAAG;QACH,KAAK;QACL,WAAW;QACX,IAAI,EAAE;YACL,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE;YACrC,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvC,SAAS,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC;SACpE;QACD,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;KAC9B,CAAC,CACH,CAAC;AACH,CAAC;AAED,eAAe,yBAAyB,EAAE,CAAC","sourcesContent":["/**\n * background — run bash commands in the background.\n *\n * Tools: a single `bg` tool with five actions. create starts a task and\n * returns immediately; the result arrives as a <background-task> notification\n * (queued behind the current run while streaming, waking the agent when\n * idle). read returns a bounded slice of a task's output file; wait blocks\n * (bounded) for a task's completion and delivers it inline — the followUp\n * notification is suppressed so the completion is delivered exactly once;\n * kill stops a single task; list enumerates known tasks. /bg opens the\n * interactive task manager. Running counts surface in the footer via\n * ctx.ui.setStatus.\n */\n\nimport { type Static, Type } from \"typebox\";\nimport { getAgentDir } from \"../../config.ts\";\nimport type {\n\tAgentToolResult,\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n} from \"../../core/extensions/types.ts\";\nimport { SettingsManager } from \"../../core/settings-manager.ts\";\nimport {\n\ttype BashOperations,\n\tcreateLocalBashOperations,\n\tMAX_TIMEOUT_SECONDS,\n\tresolveSpawnContext,\n} from \"../../core/tools/bash.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize } from \"../../core/tools/truncate.ts\";\nimport { sanitizeBinaryOutput } from \"../../utils/shell.ts\";\nimport { BackgroundTasksMenu } from \"./manager.ts\";\nimport {\n\tBackgroundTaskRegistry,\n\tBG_WAIT_DEFAULT_MS,\n\tBG_WAIT_MAX_MS,\n\tBG_WAIT_MIN_MS,\n\ttype BgStallNotification,\n\ttype BgTask,\n\ttype BgTaskNotification,\n\ttype BgTaskStatus,\n\tfirstCommandLine,\n\tformatDuration,\n\ttype ResolveTaskResult,\n\treadOutputSince,\n\treadOutputSlice,\n} from \"./registry.ts\";\nimport {\n\tcommandLabel,\n\trenderBackgroundNotification,\n\trenderBgCall,\n\trenderBgResult,\n\ttype WaitLiveProbe,\n} from \"./render.ts\";\n\nexport const BG_NOTIFICATION_TYPE = \"background-task\";\nconst BG_LOGS_DEFAULT_BYTES = 8 * 1024;\nconst BG_LOGS_MIN_BYTES = 256;\nconst BG_LIST_FINISHED_SHOWN = 5;\n/** Bounded output delta returned by a successful wait. */\nconst BG_WAIT_DELTA_BYTES = 32 * 1024;\n/** Tail peek included in a wait timeout result so progress stays visible. */\nconst BG_WAIT_PEEK_BYTES = 2 * 1024;\n\nconst bgSchema = Type.Object({\n\taction: Type.Union(\n\t\t[Type.Literal(\"create\"), Type.Literal(\"read\"), Type.Literal(\"wait\"), Type.Literal(\"kill\"), Type.Literal(\"list\")],\n\t\t{ description: \"Which background-task operation to perform\" },\n\t),\n\t// — create —\n\tcommand: Type.Optional(\n\t\tType.String({ description: \"Bash command to run in the background (create). Do not append '&'\" }),\n\t),\n\tdescription: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Short label for the task, shown in /bg and notifications, e.g. 'dev server' (create)\",\n\t\t}),\n\t),\n\ttimeout: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription: \"Kill the task after this many seconds; on expiry it is reported as timeout (create)\",\n\t\t}),\n\t),\n\t// — read / wait / kill —\n\ttaskId: Type.Optional(\n\t\tType.String({ description: \"Task id; a unique prefix is accepted, e.g. 'bg-3f' or '3f' (read/wait/kill)\" }),\n\t),\n\t// — read —\n\tmode: Type.Optional(\n\t\tType.Union([Type.Literal(\"tail\"), Type.Literal(\"head\")], {\n\t\t\tdescription: \"Read from the end (default) or the start of the output (read)\",\n\t\t}),\n\t),\n\tbytes: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription: `Max bytes to return (read, default ${formatSize(BG_LOGS_DEFAULT_BYTES)}, max ${formatSize(DEFAULT_MAX_BYTES)})`,\n\t\t}),\n\t),\n\t// — wait —\n\twaitMs: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription: `Max time to wait in ms, default ${BG_WAIT_DEFAULT_MS}, max ${BG_WAIT_MAX_MS} (wait)`,\n\t\t}),\n\t),\n\tsinceBytes: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription:\n\t\t\t\t\"Only return output written after this byte offset — take it from a previous read/wait result (wait)\",\n\t\t}),\n\t),\n});\n\nexport type BgInput = Static<typeof bgSchema>;\n\n/** Per-action inputs: validateAction guarantees the required fields before the cast. */\nexport type BgCreateInput = BgInput & { action: \"create\"; command: string };\nexport type BgReadInput = BgInput & { action: \"read\"; taskId: string };\nexport type BgWaitInput = BgInput & { action: \"wait\"; taskId: string };\nexport type BgKillInput = BgInput & { action: \"kill\"; taskId: string };\n\nexport interface BgCreateDetails {\n\taction: \"create\";\n\ttaskId: string;\n\toutputPath: string;\n\tcommand: string;\n\tdescription?: string;\n}\n\nexport interface BgReadDetails {\n\taction: \"read\";\n\ttaskId: string;\n\tmode: \"head\" | \"tail\";\n\tsliceBytes: number;\n\ttotalBytes: number;\n\toutputPath: string;\n}\n\nexport interface BgWaitDetails {\n\taction: \"wait\";\n\ttaskId: string;\n\t/** True when the wait window expired and the task is still running. */\n\ttimedOut: boolean;\n\tstatus: BgTaskStatus;\n\texitCode: number | null | undefined;\n\twaitedMs: number;\n\tdeltaBytes: number;\n\ttotalBytes: number;\n\tdeltaTruncated: boolean;\n\toutputPath: string;\n}\n\nexport interface BgKillDetails {\n\taction: \"kill\";\n\ttaskId: string;\n\tcommand: string;\n}\n\nexport interface BgListDetails {\n\taction: \"list\";\n\trunning: number;\n\tfinished: number;\n\tshown: number;\n\thidden: number;\n}\n\nexport type BgDetails = BgCreateDetails | BgReadDetails | BgWaitDetails | BgKillDetails | BgListDetails;\n\nexport interface BgNotificationDetails {\n\ttaskId: string;\n\tcommand: string;\n\tdescription?: string;\n\tstatus: BgTaskStatus;\n\t/** True for the one-shot \"waiting for interactive input\" signal; the task keeps running. */\n\tstalled?: true;\n\texitCode: number | null | undefined;\n\truntimeMs: number;\n\toutputPath: string;\n\ttotalBytes: number;\n\ttailText: string;\n\ttailTruncated: boolean;\n\terror?: string;\n\ttailError?: string;\n}\n\nexport function escapeXml(text: string): string {\n\treturn text\n\t\t.replaceAll(\"&\", \"&\")\n\t\t.replaceAll(\"<\", \"<\")\n\t\t.replaceAll(\">\", \">\")\n\t\t.replaceAll('\"', \""\")\n\t\t.replaceAll(\"'\", \"'\");\n}\n\n/**\n * Strip characters XML 1.0 forbids: C0 controls (except \\t \\n \\r), lone\n * surrogates (U+D800–U+DFFF), and the non-characters U+FFFE/U+FFFF.\n * sanitizeBinaryOutput does not remove the latter two classes, so this filter\n * is the authority for every text field in the notification XML.\n */\nexport function filterXmlCharacters(text: string): string {\n\tlet result = \"\";\n\tfor (const char of text) {\n\t\tconst code = char.codePointAt(0) ?? 0;\n\t\tif (\n\t\t\tcode === 0x09 ||\n\t\t\tcode === 0x0a ||\n\t\t\tcode === 0x0d ||\n\t\t\t(code >= 0x20 && code <= 0xd7ff) ||\n\t\t\t(code >= 0xe000 && code <= 0xfffd) ||\n\t\t\tcode >= 0x10000\n\t\t) {\n\t\t\tresult += char;\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * filterXmlCharacters keeps \\t \\n \\r and every other XML-legal codepoint, so\n * every field built with this is valid XML 1.0 after escaping.\n */\nconst xmlText = (text: string) => escapeXml(filterXmlCharacters(text));\n\n/** The `<output-tail>` element, shared by the completion and stall notifications. */\nfunction renderOutputTail(notification: BgTaskNotification): string[] {\n\tif (notification.tailError) {\n\t\treturn [`<output-tail unavailable=\"${xmlText(notification.tailError)}\"/>`];\n\t}\n\tconst attrs = [\n\t\t`bytes=\"${notification.tailBytes}\"`,\n\t\t`totalBytes=\"${notification.totalBytes}\"`,\n\t\tnotification.tailTruncated ? 'truncated=\"true\"' : \"\",\n\t\tnotification.tailStartsMidLine ? 'startsMidLine=\"true\"' : \"\",\n\t]\n\t\t.filter(Boolean)\n\t\t.join(\" \");\n\tconst tail = notification.tailText.length > 0 ? xmlText(notification.tailText) : \"(no output)\";\n\treturn [`<output-tail ${attrs}>`, tail.trimEnd(), \"</output-tail>\"];\n}\n\nexport function buildNotificationContent(notification: BgTaskNotification): string {\n\tconst task = notification.task;\n\tconst runtime = formatDuration((task.endedAt ?? task.startedAt) - task.startedAt);\n\tconst exitCode = task.exitCode === undefined || task.exitCode === null ? \"\" : ` exitCode=\"${task.exitCode}\"`;\n\tconst lines = [\n\t\t`<background-task id=\"${task.id}\" status=\"${task.status}\"${exitCode} runtime=\"${runtime}\">`,\n\t\t`<command>${xmlText(task.command)}</command>`,\n\t];\n\tif (task.description) {\n\t\tlines.push(`<description>${xmlText(task.description)}</description>`);\n\t}\n\tlines.push(`<output-file>${xmlText(task.outputPath)}</output-file>`);\n\tif (task.error) {\n\t\tlines.push(`<error>${xmlText(task.error)}</error>`);\n\t}\n\tlines.push(...renderOutputTail(notification));\n\tlines.push(\"</background-task>\");\n\treturn lines.join(\"\\n\");\n}\n\nexport function formatStatusline(counts: { running: number; total: number; stalled?: number }): string | undefined {\n\tif (counts.total === 0) return undefined;\n\t// Stalled tasks are running tasks: report them separately so the counts add up.\n\tconst waiting = counts.stalled ?? 0;\n\tconst running = counts.running - waiting;\n\tconst ended = counts.total - counts.running;\n\tconst parts: string[] = [];\n\tif (running > 0) parts.push(`${running} running`);\n\tif (waiting > 0) parts.push(`${waiting} waiting for input`);\n\tif (ended > 0) parts.push(`${ended} done`);\n\treturn `bg ${parts.join(\" · \")}`;\n}\n\nexport function buildStallContent(notification: BgStallNotification): string {\n\tconst task = notification.task;\n\t// A stalled task is by definition still running, so it has no endedAt.\n\tconst runtime = formatDuration(Date.now() - task.startedAt);\n\tconst lines = [\n\t\t`<background-task id=\"${task.id}\" status=\"running\" waiting-for-input=\"true\" runtime=\"${runtime}\">`,\n\t\t`<command>${xmlText(task.command)}</command>`,\n\t];\n\tif (task.description) {\n\t\tlines.push(`<description>${xmlText(task.description)}</description>`);\n\t}\n\tlines.push(`<output-file>${xmlText(task.outputPath)}</output-file>`);\n\tlines.push(...renderOutputTail(notification));\n\tlines.push(\n\t\t\"<advice>The command appears blocked waiting for interactive input. Kill it (bg action kill) and \" +\n\t\t\t\"re-run with piped input (e.g. echo y | command) or a non-interactive flag if one exists (e.g. --yes). \" +\n\t\t\t\"The task keeps running until then.</advice>\",\n\t);\n\tlines.push(\"</background-task>\");\n\treturn lines.join(\"\\n\");\n}\n\nfunction toStallDetails(notification: BgStallNotification): BgNotificationDetails {\n\tconst task = notification.task;\n\treturn {\n\t\ttaskId: task.id,\n\t\tcommand: task.command,\n\t\tdescription: task.description,\n\t\tstatus: \"running\",\n\t\tstalled: true,\n\t\texitCode: undefined,\n\t\truntimeMs: Date.now() - task.startedAt,\n\t\toutputPath: task.outputPath,\n\t\ttotalBytes: notification.totalBytes,\n\t\ttailText: notification.tailText,\n\t\ttailTruncated: notification.tailTruncated,\n\t\ttailError: notification.tailError,\n\t};\n}\n\nfunction describeResolveFailure(input: string, result: ResolveTaskResult & { ok: false }): string {\n\tif (result.reason === \"ambiguous\") {\n\t\tconst lines = result.candidates.map(\n\t\t\t(task) => ` ${task.id} (${task.status}) ${commandLabel(taskLabel(task), 60)}`,\n\t\t);\n\t\treturn `Task id \"${input}\" is ambiguous. Candidates:\\n${lines.join(\"\\n\")}`;\n\t}\n\treturn `No background task matches \"${input}\". Check the id returned by bg (action create), or run action list.`;\n}\n\n/** One row of a bounded task listing: the model-facing list and /bg summaries. */\nfunction describeTaskLine(task: BgTask, now: number): string {\n\tconst duration = formatDuration((task.endedAt ?? now) - task.startedAt);\n\tconst exit = task.exitCode !== undefined && task.exitCode !== null ? ` exit ${task.exitCode}` : \"\";\n\treturn ` ${task.id} ${task.status}${exit} ${duration} ${commandLabel(taskLabel(task), 60)}`;\n}\n\n/** Label for listings: the model-provided description over the first command line. */\nfunction taskLabel(task: BgTask): string {\n\treturn task.description ? `${task.description} — ${firstCommandLine(task.command)}` : firstCommandLine(task.command);\n}\n\nfunction toNotificationDetails(notification: BgTaskNotification): BgNotificationDetails {\n\tconst task = notification.task;\n\treturn {\n\t\ttaskId: task.id,\n\t\tcommand: task.command,\n\t\tdescription: task.description,\n\t\tstatus: task.status,\n\t\texitCode: task.exitCode,\n\t\truntimeMs: (task.endedAt ?? task.startedAt) - task.startedAt,\n\t\toutputPath: task.outputPath,\n\t\ttotalBytes: notification.totalBytes,\n\t\ttailText: notification.tailText,\n\t\ttailTruncated: notification.tailTruncated,\n\t\terror: task.error,\n\t\ttailError: notification.tailError,\n\t};\n}\n\n/**\n * Wrap operations so every executed command carries the prefix, mirroring the\n * built-in bash tool. The prefix never reaches task labels or notifications:\n * `BgTask.command` stays the user's original input.\n */\nexport function prependCommandPrefix(operations: BashOperations, prefix: string | undefined): BashOperations {\n\tif (!prefix) return operations;\n\treturn {\n\t\texec: (command, cwd, options) => operations.exec(`${prefix}\\n${command}`, cwd, options),\n\t};\n}\n\nexport interface BackgroundExtensionOverrides {\n\toperations?: BashOperations;\n\toutputDir?: string;\n\tmaxOutputBytes?: number;\n\t/** Stall watchdog tuning; defaults follow Claude Code's CC-1175 (5s/45s/1KB). */\n\tstall?: { pollIntervalMs?: number; thresholdMs?: number; tailBytes?: number };\n}\n\n/** Shell configuration for one bg session: the session's settings win, disk settings are the fallback. */\nexport function resolveSessionShell(\n\tctx: ExtensionContext,\n\treadDiskSettings?: () => { shellPath?: string; commandPrefix?: string },\n): { shellPath?: string; commandPrefix?: string } {\n\treturn ctx.getShellSettings?.() ?? readDiskSettings?.() ?? {};\n}\n\n/** Local shell operations honoring the session's shell settings (shellPath, commandPrefix). */\nfunction createSessionBashOperations(ctx: ExtensionContext): BashOperations {\n\tconst shell = resolveSessionShell(ctx, () => {\n\t\t// Hosts without getShellSettings (older SDK hosts): fall back to reading\n\t\t// settings from disk, matching what the session was configured with.\n\t\tconst settings = SettingsManager.create(ctx.cwd, getAgentDir(), {\n\t\t\tprojectTrusted: ctx.isProjectTrusted(),\n\t\t});\n\t\treturn { shellPath: settings.getShellPath(), commandPrefix: settings.getShellCommandPrefix() };\n\t});\n\treturn prependCommandPrefix(createLocalBashOperations({ shellPath: shell.shellPath }), shell.commandPrefix);\n}\n\n/** Validate per-action required fields; every message names the next step. */\nfunction validateAction(input: BgInput): void {\n\tswitch (input.action) {\n\t\tcase \"create\":\n\t\t\tif (!input.command || input.command.trim().length === 0) {\n\t\t\t\tthrow new Error(\"action 'create' requires 'command' — pass the bash command to run in the background.\");\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"read\":\n\t\tcase \"wait\":\n\t\tcase \"kill\":\n\t\t\tif (!input.taskId || input.taskId.trim().length === 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`action '${input.action}' requires 'taskId' — use the id returned by action create, or action list to find it.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"list\":\n\t\t\tbreak;\n\t}\n}\n\n/** Factory with injectable seams for tests; the default export uses production wiring. */\nexport function createBackgroundExtension(overrides?: BackgroundExtensionOverrides): (pi: ExtensionAPI) => void {\n\treturn (pi: ExtensionAPI) => {\n\t\tlet registry: BackgroundTaskRegistry | undefined;\n\t\tlet sessionCtx: ExtensionContext | undefined;\n\n\t\tconst requireRegistry = (): BackgroundTaskRegistry => {\n\t\t\tif (!registry) throw new Error(\"Background tasks are not available yet (no active session).\");\n\t\t\treturn registry;\n\t\t};\n\n\t\tconst resolveTaskOrThrow = (taskId: string): BgTask => {\n\t\t\tconst resolved = requireRegistry().resolveTask(taskId);\n\t\t\tif (!resolved.ok) throw new Error(describeResolveFailure(taskId, resolved));\n\t\t\treturn resolved.task;\n\t\t};\n\n\t\t/** Read-only live peek for the pending wait renderer; never throws. */\n\t\tconst waitLiveProbe: WaitLiveProbe = (taskId) => {\n\t\t\tif (!registry) return undefined;\n\t\t\tconst resolved = registry.resolveTask(taskId);\n\t\t\treturn resolved.ok ? { status: resolved.task.status, outputBytes: resolved.task.outputBytes } : undefined;\n\t\t};\n\n\t\tconst updateStatus = () => {\n\t\t\tif (!registry || registry.isShuttingDown) return;\n\t\t\tsessionCtx?.ui.setStatus(\"background\", formatStatusline(registry.counts()));\n\t\t};\n\n\t\t/** Both background messages reach the model the same way; that choice lives here only. */\n\t\tconst notify = (content: string, details: BgNotificationDetails) => {\n\t\t\tpi.sendMessage(\n\t\t\t\t{ customType: BG_NOTIFICATION_TYPE, content, display: true, details },\n\t\t\t\t{ deliverAs: \"followUp\", triggerTurn: true },\n\t\t\t);\n\t\t};\n\n\t\tpi.on(\"session_start\", (_event, ctx) => {\n\t\t\tsessionCtx = ctx;\n\t\t\t// Defensive: a leftover registry (session_shutdown not seen) must not leak processes.\n\t\t\tif (registry) void registry.shutdown();\n\t\t\tregistry = new BackgroundTaskRegistry({\n\t\t\t\toperations: overrides?.operations ?? createSessionBashOperations(ctx),\n\t\t\t\toutputDir: overrides?.outputDir,\n\t\t\t\tmaxOutputBytes: overrides?.maxOutputBytes,\n\t\t\t\tstall: overrides?.stall,\n\t\t\t\tonNotify: (notification) =>\n\t\t\t\t\tnotify(buildNotificationContent(notification), toNotificationDetails(notification)),\n\t\t\t\t// Informational one-shot signal: not a terminal state, so it bypasses\n\t\t\t\t// the claim protocol (a waiting model needs to know it is blocked on\n\t\t\t\t// input, not merely slow).\n\t\t\t\tonStall: (notification) => notify(buildStallContent(notification), toStallDetails(notification)),\n\t\t\t\tonChange: updateStatus,\n\t\t\t});\n\t\t\tupdateStatus();\n\t\t});\n\n\t\tpi.on(\"session_shutdown\", async (_event, ctx) => {\n\t\t\tctx.ui.setStatus(\"background\", undefined);\n\t\t\tsessionCtx = undefined;\n\t\t\tconst active = registry;\n\t\t\tregistry = undefined;\n\t\t\tawait active?.shutdown();\n\t\t});\n\n\t\tconst runCreate = async (\n\t\t\tparams: BgCreateInput,\n\t\t\tctx: ExtensionContext,\n\t\t): Promise<AgentToolResult<BgCreateDetails>> => {\n\t\t\tif (params.timeout !== undefined && (!Number.isFinite(params.timeout) || params.timeout <= 0)) {\n\t\t\t\tthrow new Error(\"Invalid timeout: must be a positive number of seconds.\");\n\t\t\t}\n\t\t\tif (params.timeout !== undefined && params.timeout > MAX_TIMEOUT_SECONDS) {\n\t\t\t\tthrow new Error(`Invalid timeout: maximum is ${MAX_TIMEOUT_SECONDS} seconds`);\n\t\t\t}\n\t\t\t// Same PI_* session variables as the built-in bash tool, snapshotted at start.\n\t\t\tconst spawnContext = resolveSpawnContext(params.command, ctx.cwd, undefined, true, ctx);\n\t\t\t// Deliberately ignore the turn signal: aborting the current turn must\n\t\t\t// not kill the background task (that is what action kill is for).\n\t\t\tconst task = requireRegistry().startTask({\n\t\t\t\tcommand: params.command,\n\t\t\t\tcwd: ctx.cwd,\n\t\t\t\tdescription: params.description,\n\t\t\t\ttimeoutSeconds: params.timeout,\n\t\t\t\tenv: spawnContext.env,\n\t\t\t});\n\t\t\tconst label = task.description ? ` (${task.description})` : \"\";\n\t\t\tconst text = [\n\t\t\t\t`Started background task ${task.id}${label}.`,\n\t\t\t\t`Output file: ${task.outputPath}`,\n\t\t\t\t\"\",\n\t\t\t\t\"A <background-task> notification with the result and output tail arrives automatically when the task \" +\n\t\t\t\t\t\"ends — do NOT poll (no sleep loops, no repeated reads). Use action read for an early peek, \" +\n\t\t\t\t\t\"action wait when the next step depends on the result, action kill to stop it.\",\n\t\t\t].join(\"\\n\");\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text }],\n\t\t\t\tdetails: {\n\t\t\t\t\taction: \"create\",\n\t\t\t\t\ttaskId: task.id,\n\t\t\t\t\toutputPath: task.outputPath,\n\t\t\t\t\tcommand: params.command,\n\t\t\t\t\tdescription: params.description,\n\t\t\t\t},\n\t\t\t};\n\t\t};\n\n\t\tconst runRead = async (params: BgReadInput): Promise<AgentToolResult<BgReadDetails>> => {\n\t\t\tconst task = resolveTaskOrThrow(params.taskId);\n\t\t\tconst mode = params.mode ?? \"tail\";\n\t\t\tconst maxBytes = Math.min(\n\t\t\t\tDEFAULT_MAX_BYTES,\n\t\t\t\tMath.max(BG_LOGS_MIN_BYTES, Math.floor(params.bytes ?? BG_LOGS_DEFAULT_BYTES)),\n\t\t\t);\n\t\t\tlet slice: Awaited<ReturnType<typeof readOutputSlice>>;\n\t\t\ttry {\n\t\t\t\tslice = await readOutputSlice(task.outputPath, { mode, maxBytes });\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Could not read output for ${task.id} (${task.status}): ${message}\\nOutput file: ${task.outputPath}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst text = sanitizeBinaryOutput(slice.text);\n\t\t\tconst running = task.status === \"running\" ? [\"still running\"] : [];\n\t\t\tconst noticeParts = slice.truncated\n\t\t\t\t? [\n\t\t\t\t\t\t`${mode} ${formatSize(slice.sliceBytes)} of ${formatSize(slice.totalBytes)}`,\n\t\t\t\t\t\t`task ${task.id} ${task.status}`,\n\t\t\t\t\t\t...running,\n\t\t\t\t\t\t...(slice.startsMidLine ? [\"first line may be partial\"] : []),\n\t\t\t\t\t\t`full output: ${task.outputPath}`,\n\t\t\t\t\t]\n\t\t\t\t: [\n\t\t\t\t\t\t`task ${task.id} ${task.status}`,\n\t\t\t\t\t\t...running,\n\t\t\t\t\t\t`${formatSize(slice.totalBytes)} total`,\n\t\t\t\t\t\t`output: ${task.outputPath}`,\n\t\t\t\t\t];\n\t\t\tconst body = text.length > 0 ? text : \"(no output yet)\";\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `[${noticeParts.join(\" · \")}]\\n${body}` }],\n\t\t\t\tdetails: {\n\t\t\t\t\taction: \"read\",\n\t\t\t\t\ttaskId: task.id,\n\t\t\t\t\tmode,\n\t\t\t\t\tsliceBytes: slice.sliceBytes,\n\t\t\t\t\ttotalBytes: slice.totalBytes,\n\t\t\t\t\toutputPath: task.outputPath,\n\t\t\t\t},\n\t\t\t};\n\t\t};\n\n\t\tconst runWait = async (params: BgWaitInput, signal?: AbortSignal): Promise<AgentToolResult<BgWaitDetails>> => {\n\t\t\tconst task = resolveTaskOrThrow(params.taskId);\n\t\t\tconst waitMs = Math.min(\n\t\t\t\tBG_WAIT_MAX_MS,\n\t\t\t\tMath.max(BG_WAIT_MIN_MS, Math.floor(params.waitMs ?? BG_WAIT_DEFAULT_MS)),\n\t\t\t);\n\t\t\tconst startedWait = Date.now();\n\t\t\tconst result = await requireRegistry().waitForResult(task.id, waitMs, signal);\n\t\t\tconst waitedMs = Date.now() - startedWait;\n\t\t\tconst finalTask = result.task;\n\t\t\tconst exitSuffix =\n\t\t\t\tfinalTask.exitCode !== undefined && finalTask.exitCode !== null ? ` · exit ${finalTask.exitCode}` : \"\";\n\t\t\tconst ran = formatDuration((finalTask.endedAt ?? Date.now()) - finalTask.startedAt);\n\n\t\t\tif (result.outcome === \"timeout\") {\n\t\t\t\t// Still running: keep progress visible with a bounded tail peek.\n\t\t\t\tlet peekText = \"\";\n\t\t\t\tlet peekNote = \"\";\n\t\t\t\tlet totalBytes = finalTask.outputBytes;\n\t\t\t\ttry {\n\t\t\t\t\tconst peek = await readOutputSlice(finalTask.outputPath, { mode: \"tail\", maxBytes: BG_WAIT_PEEK_BYTES });\n\t\t\t\t\tpeekText = sanitizeBinaryOutput(peek.text);\n\t\t\t\t\ttotalBytes = peek.totalBytes;\n\t\t\t\t\tpeekNote = peek.truncated ? ` (last ${formatSize(peek.sliceBytes)})` : \"\";\n\t\t\t\t} catch {\n\t\t\t\t\tpeekNote = \" (output unavailable)\";\n\t\t\t\t}\n\t\t\t\tconst lines = [\n\t\t\t\t\t`[${finalTask.id} still running · waited ${formatDuration(waitedMs)} · ${formatSize(totalBytes)} total]`,\n\t\t\t\t];\n\t\t\t\tconst trimmed = peekText.trimEnd();\n\t\t\t\tif (trimmed.length > 0) lines.push(`Last output${peekNote}:\\n${trimmed}`);\n\t\t\t\tlines.push(\n\t\t\t\t\t\"The task keeps running. Wait again (action wait), peek with action read, or stop it with action kill; \" +\n\t\t\t\t\t\t\"the <background-task> notification still arrives when it ends. Do not sleep-poll.\",\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: lines.join(\"\\n\\n\") }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\taction: \"wait\",\n\t\t\t\t\t\ttaskId: finalTask.id,\n\t\t\t\t\t\ttimedOut: true,\n\t\t\t\t\t\tstatus: finalTask.status,\n\t\t\t\t\t\texitCode: finalTask.exitCode,\n\t\t\t\t\t\twaitedMs,\n\t\t\t\t\t\tdeltaBytes: 0,\n\t\t\t\t\t\ttotalBytes,\n\t\t\t\t\t\tdeltaTruncated: false,\n\t\t\t\t\t\toutputPath: finalTask.outputPath,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Terminal: deliver the bounded delta since the requested offset.\n\t\t\t// The followUp notification was suppressed by the claim protocol —\n\t\t\t// this result is the single delivery of the completion.\n\t\t\tconst since = params.sinceBytes !== undefined ? Math.max(0, Math.floor(params.sinceBytes)) : undefined;\n\t\t\tlet delta: Awaited<ReturnType<typeof readOutputSince>>;\n\t\t\tlet offsetNote: string | undefined;\n\t\t\ttry {\n\t\t\t\tdelta = await readOutputSince(finalTask.outputPath, since ?? 0, BG_WAIT_DELTA_BYTES);\n\t\t\t\tif (since !== undefined && since > delta.totalBytes) {\n\t\t\t\t\t// A stale offset past EOF (the output was truncated at the cap, or\n\t\t\t\t\t// the model is reusing an id from an earlier read): fall back to\n\t\t\t\t\t// the tail and say so. Never an error — the offset is not a bug.\n\t\t\t\t\tdelta = await readOutputSince(finalTask.outputPath, 0, BG_WAIT_DELTA_BYTES);\n\t\t\t\t\toffsetNote = finalTask.outputTruncated\n\t\t\t\t\t\t? \"the given offset is past EOF — output was truncated at the limit; showing the tail\"\n\t\t\t\t\t\t: \"the given offset is past EOF; showing the tail\";\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\t// Deliver the terminal status even when the output file cannot be read.\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: `[${finalTask.id} ${finalTask.status}${exitSuffix} · ran ${ran} · waited ${formatDuration(waitedMs)}]\\nerror reading output: ${message}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\taction: \"wait\",\n\t\t\t\t\t\ttaskId: finalTask.id,\n\t\t\t\t\t\ttimedOut: false,\n\t\t\t\t\t\tstatus: finalTask.status,\n\t\t\t\t\t\texitCode: finalTask.exitCode,\n\t\t\t\t\t\twaitedMs,\n\t\t\t\t\t\tdeltaBytes: 0,\n\t\t\t\t\t\ttotalBytes: finalTask.outputBytes,\n\t\t\t\t\t\tdeltaTruncated: false,\n\t\t\t\t\t\toutputPath: finalTask.outputPath,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst lines = [\n\t\t\t\t`[${finalTask.id} ${finalTask.status}${exitSuffix} · ran ${ran} · waited ${formatDuration(waitedMs)} · +${formatSize(delta.sliceBytes)} new output · total ${formatSize(delta.totalBytes)}]`,\n\t\t\t];\n\t\t\tif (offsetNote) lines.push(`[${offsetNote}]`);\n\t\t\tif (finalTask.error) lines.push(`error: ${finalTask.error}`);\n\t\t\tif (delta.truncated) {\n\t\t\t\tlines.push(\n\t\t\t\t\t`[showing ${formatSize(delta.sliceBytes)} of ${formatSize(delta.totalBytes)}; full output: ${finalTask.outputPath}]`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst body = sanitizeBinaryOutput(delta.text).trimEnd();\n\t\t\tlines.push(body.length > 0 ? body : \"(no new output)\");\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: lines.join(\"\\n\") }],\n\t\t\t\tdetails: {\n\t\t\t\t\taction: \"wait\",\n\t\t\t\t\ttaskId: finalTask.id,\n\t\t\t\t\ttimedOut: false,\n\t\t\t\t\tstatus: finalTask.status,\n\t\t\t\t\texitCode: finalTask.exitCode,\n\t\t\t\t\twaitedMs,\n\t\t\t\t\tdeltaBytes: delta.sliceBytes,\n\t\t\t\t\ttotalBytes: delta.totalBytes,\n\t\t\t\t\tdeltaTruncated: delta.truncated,\n\t\t\t\t\toutputPath: finalTask.outputPath,\n\t\t\t\t},\n\t\t\t};\n\t\t};\n\n\t\tconst runKill = (params: BgKillInput): AgentToolResult<BgKillDetails> => {\n\t\t\tconst task = resolveTaskOrThrow(params.taskId);\n\t\t\tconst result = requireRegistry().killTask(task.id);\n\t\t\tif (!result.killed) {\n\t\t\t\tconst exit = task.exitCode !== undefined && task.exitCode !== null ? `, exit ${task.exitCode}` : \"\";\n\t\t\t\tthrow new Error(`Task ${task.id} is not running (status: ${task.status}${exit}).`);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `Killed task ${task.id}. If you are waiting on it (action wait) the killed status is delivered there; otherwise a completion notification follows once the process tree is reaped.`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdetails: { action: \"kill\", taskId: task.id, command: task.command },\n\t\t\t};\n\t\t};\n\n\t\tconst runList = (): AgentToolResult<BgListDetails> => {\n\t\t\tconst tasks = requireRegistry().listTasks();\n\t\t\tif (tasks.length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"No background tasks this session. Start one with action create.\" }],\n\t\t\t\t\tdetails: { action: \"list\", running: 0, finished: 0, shown: 0, hidden: 0 },\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst now = Date.now();\n\t\t\tconst running = tasks.filter((task) => task.status === \"running\");\n\t\t\tconst finished = tasks.filter((task) => task.status !== \"running\");\n\t\t\tconst shownFinished = finished.slice(0, BG_LIST_FINISHED_SHOWN);\n\t\t\tconst hidden = finished.length - shownFinished.length;\n\t\t\tconst lines = [`${running.length} running · ${finished.length} finished`];\n\t\t\tfor (const task of [...running, ...shownFinished]) {\n\t\t\t\tlines.push(describeTaskLine(task, now));\n\t\t\t}\n\t\t\tif (hidden > 0) {\n\t\t\t\tlines.push(`(+${hidden} more finished, not shown — action read shows any task's output)`);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: lines.join(\"\\n\") }],\n\t\t\t\tdetails: {\n\t\t\t\t\taction: \"list\",\n\t\t\t\t\trunning: running.length,\n\t\t\t\t\tfinished: finished.length,\n\t\t\t\t\tshown: running.length + shownFinished.length,\n\t\t\t\t\thidden,\n\t\t\t\t},\n\t\t\t};\n\t\t};\n\n\t\tpi.registerTool<typeof bgSchema, BgDetails>({\n\t\t\tname: \"bg\",\n\t\t\tlabel: \"bg\",\n\t\t\tdescription:\n\t\t\t\t\"Run and manage background bash tasks.\\n\\n\" +\n\t\t\t\t\"create: start a command in the background and return immediately with a task id and an \" +\n\t\t\t\t\"output file path. A <background-task> notification with status, exit code, and output tail \" +\n\t\t\t\t\"arrives automatically when it ends. Do NOT append '&' to the command; bg already runs it \" +\n\t\t\t\t\"detached.\\n\\n\" +\n\t\t\t\t\"read: bounded slice of a task's output; works while the task runs. The \" +\n\t\t\t\t\"output file is a plain file — the read tool also works on it for line-based paging.\\n\\n\" +\n\t\t\t\t\"wait: block until a task finishes and return its status plus output written since a given \" +\n\t\t\t\t\"offset. On timeout the task is still running and you may wait again.\\n\\n\" +\n\t\t\t\t\"kill: stop a running task (whole process tree).\\n\\n\" +\n\t\t\t\t\"list: currently known tasks with status.\",\n\t\t\tpromptSnippet: \"Manage background shell tasks (create, read, wait, kill, list)\",\n\t\t\tpromptGuidelines: [\n\t\t\t\t\"Use `bg` action create for long-running commands (dev servers, watch builds, slow tests) instead of regular bash; the completion notification arrives on its own, so continue independent work or end the turn.\",\n\t\t\t\t\"Never wait on a `bg` task with sleep loops or repeated reads; use `bg` action wait when the next step depends on its result.\",\n\t\t\t],\n\t\t\tparameters: bgSchema,\n\t\t\tasync execute(_toolCallId, params, signal, _onUpdate, ctx): Promise<AgentToolResult<BgDetails>> {\n\t\t\t\tvalidateAction(params);\n\t\t\t\tswitch (params.action) {\n\t\t\t\t\tcase \"create\":\n\t\t\t\t\t\treturn runCreate(params as BgCreateInput, ctx);\n\t\t\t\t\tcase \"read\":\n\t\t\t\t\t\treturn runRead(params as BgReadInput);\n\t\t\t\t\tcase \"wait\":\n\t\t\t\t\t\treturn runWait(params as BgWaitInput, signal);\n\t\t\t\t\tcase \"kill\":\n\t\t\t\t\t\treturn runKill(params as BgKillInput);\n\t\t\t\t\tcase \"list\":\n\t\t\t\t\t\treturn runList();\n\t\t\t\t}\n\t\t\t},\n\t\t\trenderCall(args, theme, context) {\n\t\t\t\treturn renderBgCall(args, theme, context, waitLiveProbe);\n\t\t\t},\n\t\t\trenderResult(result, options, theme, context) {\n\t\t\t\treturn renderBgResult(result, options, theme, context);\n\t\t\t},\n\t\t});\n\n\t\tpi.registerMessageRenderer<BgNotificationDetails>(BG_NOTIFICATION_TYPE, renderBackgroundNotification);\n\n\t\tpi.registerCommand(\"bg\", {\n\t\t\tdescription: \"View and manage background tasks\",\n\t\t\thandler: async (_args, ctx: ExtensionCommandContext) => {\n\t\t\t\tconst active = registry;\n\t\t\t\tif (!active || active.counts().total === 0) {\n\t\t\t\t\tctx.ui.notify(\"No background tasks.\", \"info\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (ctx.mode !== \"tui\") {\n\t\t\t\t\t// RPC/print: ctx.ui.custom is unavailable — show a bounded summary.\n\t\t\t\t\tconst lines = active\n\t\t\t\t\t\t.listTasks()\n\t\t\t\t\t\t.slice(0, 10)\n\t\t\t\t\t\t.map((task) => describeTaskLine(task, Date.now()));\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t`Background tasks:\\n${lines.join(\"\\n\")}\\nUse the bg tool (action kill) to stop a task.`,\n\t\t\t\t\t\t\"info\",\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tawait showBackgroundManager(ctx, active);\n\t\t\t},\n\t\t});\n\t};\n}\n\nasync function showBackgroundManager(ctx: ExtensionCommandContext, registry: BackgroundTaskRegistry): Promise<void> {\n\t// No overlay options: the component mounts inline in the editor slot, like /model.\n\tawait ctx.ui.custom(\n\t\t(tui, theme, keybindings, done) =>\n\t\t\tnew BackgroundTasksMenu({\n\t\t\t\ttui,\n\t\t\t\ttheme,\n\t\t\t\tkeybindings,\n\t\t\t\thost: {\n\t\t\t\t\tlistTasks: () => registry.listTasks(),\n\t\t\t\t\tkillTask: (id) => registry.killTask(id),\n\t\t\t\t\treadSlice: (filePath, options) => readOutputSlice(filePath, options),\n\t\t\t\t},\n\t\t\t\tonClose: () => done(undefined),\n\t\t\t}),\n\t);\n}\n\nexport default createBackgroundExtension();\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/background/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * background — run bash commands in the background.\n *\n * Tools: a single `bg` tool with five actions. create starts a task and\n * returns immediately; the result arrives as a <background-task> notification\n * (queued behind the current run while streaming, waking the agent when\n * idle). read returns a bounded slice of a task's output file; wait blocks\n * (bounded) for a task's completion and delivers it inline — the followUp\n * notification is suppressed so the completion is delivered exactly once;\n * kill stops a single task; list enumerates known tasks. /bg opens the\n * interactive task manager. Running counts surface in the footer via\n * ctx.ui.setStatus.\n *\n * This file is wiring only: the actions live in actions.ts, the notification\n * in notify.ts, the transcript rows in render.ts, and the menu in manager.ts.\n */\n\nimport { getAgentDir } from \"../../config.ts\";\nimport type {\n\tAgentToolResult,\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n} from \"../../core/extensions/types.ts\";\nimport { SettingsManager } from \"../../core/settings-manager.ts\";\nimport { type BashOperations, createLocalBashOperations } from \"../../core/tools/bash.ts\";\nimport { describeTaskLine, runCreate, runKill, runList, runRead, runWait } from \"./actions.ts\";\nimport { BG_NOTIFICATION_TYPE } from \"./constants.ts\";\nimport { BackgroundTasksMenu } from \"./manager.ts\";\nimport { buildNotificationContent, toNotificationDetails } from \"./notify.ts\";\nimport { readOutputSlice } from \"./output-file.ts\";\nimport { BackgroundTaskRegistry } from \"./registry.ts\";\nimport {\n\ttype BgRenderState,\n\trenderBackgroundNotification,\n\trenderBgCall,\n\trenderBgResult,\n\ttype WaitLiveProbe,\n} from \"./render.ts\";\nimport { BG_PROMPT_GUIDELINES, BG_PROMPT_SNIPPET, BG_TOOL_DESCRIPTION, bgSchema } from \"./schema.ts\";\nimport { formatStatusline } from \"./task-view.ts\";\nimport type { BgDetails, BgNotificationDetails } from \"./types.ts\";\n\n/** Tasks shown by the non-TUI `/bg` fallback summary. */\nconst BG_COMMAND_SUMMARY_SHOWN = 10;\n\n/**\n * Wrap operations so every executed command carries the prefix, mirroring the\n * built-in bash tool. The prefix never reaches task labels or notifications:\n * `BgTask.command` stays the user's original input.\n */\nexport function prependCommandPrefix(operations: BashOperations, prefix: string | undefined): BashOperations {\n\tif (!prefix) return operations;\n\treturn {\n\t\texec: (command, cwd, options) => operations.exec(`${prefix}\\n${command}`, cwd, options),\n\t};\n}\n\n/** Hosts without getShellSettings (older SDK hosts): read what the session was configured with. */\nfunction readDiskShellSettings(ctx: ExtensionContext): { shellPath?: string; commandPrefix?: string } {\n\tconst settings = SettingsManager.create(ctx.cwd, getAgentDir(), { projectTrusted: ctx.isProjectTrusted() });\n\treturn { shellPath: settings.getShellPath(), commandPrefix: settings.getShellCommandPrefix() };\n}\n\n/** Local shell operations honoring the session's shell settings (shellPath, commandPrefix). */\nfunction createSessionBashOperations(ctx: ExtensionContext): BashOperations {\n\tconst shell = ctx.getShellSettings?.() ?? readDiskShellSettings(ctx);\n\treturn prependCommandPrefix(createLocalBashOperations({ shellPath: shell.shellPath }), shell.commandPrefix);\n}\n\nexport interface BackgroundExtensionOverrides {\n\toperations?: BashOperations;\n\toutputDir?: string;\n\tmaxOutputBytes?: number;\n\t/** Stall watchdog tuning, or false to disable it; defaults follow Claude Code's CC-1175 (5s/45s/1KB). */\n\tstall?: { pollIntervalMs?: number; thresholdMs?: number; tailBytes?: number } | false;\n}\n\n/** Factory with injectable seams for tests; the default export uses production wiring. */\nexport function createBackgroundExtension(overrides?: BackgroundExtensionOverrides): (pi: ExtensionAPI) => void {\n\treturn (pi: ExtensionAPI) => {\n\t\tlet registry: BackgroundTaskRegistry | undefined;\n\t\tlet sessionCtx: ExtensionContext | undefined;\n\n\t\tconst requireRegistry = (): BackgroundTaskRegistry => {\n\t\t\tif (!registry) throw new Error(\"Background tasks are not available yet (no active session).\");\n\t\t\treturn registry;\n\t\t};\n\n\t\t/** Read-only live peek for the pending wait renderer; never throws. */\n\t\tconst waitLiveProbe: WaitLiveProbe = (taskId) => {\n\t\t\tif (!registry) return undefined;\n\t\t\tconst resolved = registry.resolveTask(taskId);\n\t\t\treturn resolved.ok ? { status: resolved.task.status, outputBytes: resolved.task.outputBytes } : undefined;\n\t\t};\n\n\t\tconst updateStatus = () => {\n\t\t\tif (!registry || registry.isShuttingDown) return;\n\t\t\tsessionCtx?.ui.setStatus(\"background\", formatStatusline(registry.counts()));\n\t\t};\n\n\t\tpi.on(\"session_start\", (_event, ctx) => {\n\t\t\tsessionCtx = ctx;\n\t\t\t// Defensive: a leftover registry (session_shutdown not seen) must not leak processes.\n\t\t\tif (registry) void registry.shutdown();\n\t\t\tregistry = new BackgroundTaskRegistry({\n\t\t\t\toperations: overrides?.operations ?? createSessionBashOperations(ctx),\n\t\t\t\toutputDir: overrides?.outputDir,\n\t\t\t\tmaxOutputBytes: overrides?.maxOutputBytes,\n\t\t\t\tstall: overrides?.stall,\n\t\t\t\t// Completion and stall reach the model the same way; that choice lives here only.\n\t\t\t\tonNotify: (notification) =>\n\t\t\t\t\tpi.sendMessage(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcustomType: BG_NOTIFICATION_TYPE,\n\t\t\t\t\t\t\tcontent: buildNotificationContent(notification),\n\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tdetails: toNotificationDetails(notification),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ deliverAs: \"followUp\", triggerTurn: true },\n\t\t\t\t\t),\n\t\t\t\tonChange: updateStatus,\n\t\t\t});\n\t\t\tupdateStatus();\n\t\t});\n\n\t\tpi.on(\"session_shutdown\", async (_event, ctx) => {\n\t\t\tctx.ui.setStatus(\"background\", undefined);\n\t\t\tsessionCtx = undefined;\n\t\t\tconst active = registry;\n\t\t\tregistry = undefined;\n\t\t\tawait active?.shutdown();\n\t\t});\n\n\t\tpi.registerTool<typeof bgSchema, BgDetails, BgRenderState>({\n\t\t\tname: \"bg\",\n\t\t\tlabel: \"bg\",\n\t\t\tdescription: BG_TOOL_DESCRIPTION,\n\t\t\tpromptSnippet: BG_PROMPT_SNIPPET,\n\t\t\tpromptGuidelines: BG_PROMPT_GUIDELINES,\n\t\t\tparameters: bgSchema,\n\t\t\tasync execute(_toolCallId, params, signal, _onUpdate, ctx): Promise<AgentToolResult<BgDetails>> {\n\t\t\t\tconst active = requireRegistry();\n\t\t\t\tswitch (params.action) {\n\t\t\t\t\tcase \"create\":\n\t\t\t\t\t\treturn runCreate(active, params, ctx);\n\t\t\t\t\tcase \"read\":\n\t\t\t\t\t\treturn runRead(active, params);\n\t\t\t\t\tcase \"wait\":\n\t\t\t\t\t\treturn runWait(active, params, signal);\n\t\t\t\t\tcase \"kill\":\n\t\t\t\t\t\treturn runKill(active, params);\n\t\t\t\t\tcase \"list\":\n\t\t\t\t\t\treturn runList(active);\n\t\t\t\t}\n\t\t\t},\n\t\t\trenderCall(args, theme, context) {\n\t\t\t\treturn renderBgCall(args, theme, context, waitLiveProbe);\n\t\t\t},\n\t\t\trenderResult(result, options, theme, context) {\n\t\t\t\treturn renderBgResult(result, options, theme, context);\n\t\t\t},\n\t\t});\n\n\t\tpi.registerMessageRenderer<BgNotificationDetails>(BG_NOTIFICATION_TYPE, renderBackgroundNotification);\n\n\t\tpi.registerCommand(\"bg\", {\n\t\t\tdescription: \"View and manage background tasks\",\n\t\t\thandler: async (_args, ctx: ExtensionCommandContext) => {\n\t\t\t\tconst active = registry;\n\t\t\t\tif (!active || active.counts().total === 0) {\n\t\t\t\t\tctx.ui.notify(\"No background tasks.\", \"info\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (ctx.mode !== \"tui\") {\n\t\t\t\t\t// RPC/print: ctx.ui.custom is unavailable — show a bounded summary.\n\t\t\t\t\tconst now = Date.now();\n\t\t\t\t\tconst lines = active\n\t\t\t\t\t\t.listTasks()\n\t\t\t\t\t\t.slice(0, BG_COMMAND_SUMMARY_SHOWN)\n\t\t\t\t\t\t.map((task) => describeTaskLine(task, now));\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t`Background tasks:\\n${lines.join(\"\\n\")}\\nUse the bg tool (action kill) to stop a task.`,\n\t\t\t\t\t\t\"info\",\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tawait showBackgroundManager(ctx, active);\n\t\t\t},\n\t\t});\n\t};\n}\n\nasync function showBackgroundManager(ctx: ExtensionCommandContext, registry: BackgroundTaskRegistry): Promise<void> {\n\t// No overlay options: the component mounts inline in the editor slot, like /model.\n\tawait ctx.ui.custom(\n\t\t(tui, theme, keybindings, done) =>\n\t\t\tnew BackgroundTasksMenu({\n\t\t\t\ttui,\n\t\t\t\ttheme,\n\t\t\t\tkeybindings,\n\t\t\t\thost: {\n\t\t\t\t\tlistTasks: () => registry.listTasks(),\n\t\t\t\t\tkillTask: (id) => registry.killTask(id),\n\t\t\t\t\treadSlice: (filePath, options) => readOutputSlice(filePath, options),\n\t\t\t\t},\n\t\t\t\tonClose: () => done(undefined),\n\t\t\t}),\n\t);\n}\n\nexport default createBackgroundExtension();\n"]}
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
import { type Component, type Focusable } from "@earendil-works/pi-tui";
|
|
8
8
|
import type { KeybindingsManager } from "../../core/keybindings.ts";
|
|
9
9
|
import type { Theme } from "../../modes/interactive/theme/theme.ts";
|
|
10
|
-
import
|
|
10
|
+
import type { OutputSlice } from "./output-file.ts";
|
|
11
|
+
import type { BgTask } from "./registry.ts";
|
|
11
12
|
export interface BackgroundManagerHost {
|
|
12
13
|
listTasks(): BgTask[];
|
|
13
14
|
killTask(id: string): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../src/extensions/background/manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAA2C,MAAM,wBAAwB,CAAC;AACjH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGpE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAEpE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../src/extensions/background/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,8 +8,8 @@ import { stripTerminalSequences, truncateToWidth } from "@earendil-works/pi-tui"
|
|
|
8
8
|
import { formatSize } from "../../core/tools/truncate.js";
|
|
9
9
|
import { keyLabel } from "../../modes/interactive/components/keybinding-hints.js";
|
|
10
10
|
import { sanitizeBinaryOutput } from "../../utils/shell.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import { exitSuffix, runtimeLabel, statusColor, statusGlyph, taskLabel } from "./task-view.js";
|
|
12
|
+
import { fileNameOf } from "./text.js";
|
|
13
13
|
const POLL_INTERVAL_MS = 1000;
|
|
14
14
|
const VIEW_TAIL_BYTES = 128 * 1024;
|
|
15
15
|
const MAX_VIEW_LINES = 2000;
|
|
@@ -181,10 +181,8 @@ export class BackgroundTasksMenu {
|
|
|
181
181
|
return lines;
|
|
182
182
|
}
|
|
183
183
|
renderTaskRow(task, isSelected, width) {
|
|
184
|
-
const duration =
|
|
185
|
-
const label = task
|
|
186
|
-
? `${task.description} — ${firstCommandLine(task.command)}`
|
|
187
|
-
: firstCommandLine(task.command);
|
|
184
|
+
const duration = runtimeLabel(task);
|
|
185
|
+
const label = taskLabel(task);
|
|
188
186
|
if (isSelected) {
|
|
189
187
|
// Pad to full width before styling so the selection background spans the row.
|
|
190
188
|
const plain = padLine(`→ ${statusGlyph(task.status, task.stalled)} ${task.id} ${duration} ${label}`, width);
|
|
@@ -232,11 +230,11 @@ export class BackgroundTasksMenu {
|
|
|
232
230
|
detailHeader(task) {
|
|
233
231
|
if (!task)
|
|
234
232
|
return this.theme.fg("muted", "(no task selected)");
|
|
235
|
-
const duration =
|
|
236
|
-
const exit = task.exitCode
|
|
233
|
+
const duration = runtimeLabel(task);
|
|
234
|
+
const exit = exitSuffix(task.exitCode, " ");
|
|
237
235
|
const resumeLabel = keyLabel("tui.select.pageDown", { keybindings: this.keybindings });
|
|
238
236
|
const paused = this.follow ? "" : resumeLabel ? ` — paused (${resumeLabel} to follow)` : " — paused";
|
|
239
|
-
const fileName = task.outputPath
|
|
237
|
+
const fileName = fileNameOf(task.outputPath);
|
|
240
238
|
const glyph = this.theme.fg(statusColor(task.status, task.stalled), statusGlyph(task.status, task.stalled));
|
|
241
239
|
const statusLabel = task.stalled ? "running, waiting for input" : task.status;
|
|
242
240
|
const header = `${task.id} · ${statusLabel}${exit} · ${duration} · ${formatSize(task.outputBytes)} · ${fileName}${paused}`;
|
|
@@ -356,7 +354,7 @@ export class BackgroundTasksMenu {
|
|
|
356
354
|
: "",
|
|
357
355
|
];
|
|
358
356
|
for (const task of this.tasks) {
|
|
359
|
-
const duration =
|
|
357
|
+
const duration = runtimeLabel(task);
|
|
360
358
|
parts.push(`${task.id}:${task.status}:${String(task.stalled)}:${task.outputBytes}:${task.exitCode ?? ""}:${duration}`);
|
|
361
359
|
}
|
|
362
360
|
return parts.join("|");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/extensions/background/manager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * /bg task manager — an inline, /model-style menu that mounts in the editor\n * slot. Two views in one component: a task list, and a live output viewport\n * for the selected task (Enter to open, Esc to go back). The host dependency\n * is narrowed to three callbacks so the component stays testable.\n */\n\nimport { type Component, type Focusable, stripTerminalSequences, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport type { KeybindingsManager } from \"../../core/keybindings.ts\";\nimport { formatSize } from \"../../core/tools/truncate.ts\";\nimport { keyLabel } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { sanitizeBinaryOutput } from \"../../utils/shell.ts\";\nimport { type BgTask, firstCommandLine, formatDuration, type OutputSlice } from \"./registry.ts\";\nimport { statusColor, statusGlyph } from \"./render.ts\";\n\nconst POLL_INTERVAL_MS = 1000;\nconst VIEW_TAIL_BYTES = 128 * 1024;\nconst MAX_VIEW_LINES = 2000;\nconst LIST_MAX_VISIBLE = 10;\nconst LIST_MIN_VISIBLE = 3;\n/** Rows outside the task list itself (borders, title, counter, footer, padding). */\nconst LIST_RESERVED_ROWS = 14;\n\nexport interface BackgroundManagerHost {\n\tlistTasks(): BgTask[];\n\tkillTask(id: string): { killed: boolean };\n\treadSlice(filePath: string, options: { mode: \"tail\"; maxBytes: number }): Promise<OutputSlice>;\n}\n\ninterface MenuTui {\n\trequestRender(): void;\n\tterminal: { rows: number; columns: number };\n}\n\nexport interface BackgroundTasksMenuOptions {\n\ttui: MenuTui;\n\ttheme: Theme;\n\tkeybindings: Pick<KeybindingsManager, \"matches\" | \"getKeys\">;\n\thost: BackgroundManagerHost;\n\tonClose: () => void;\n\tpollIntervalMs?: number;\n}\n\ninterface TailCache {\n\ttaskId: string;\n\tlines: string[];\n\ttotalBytes: number;\n\t/** True once a terminal task's final output has been read; skips re-reads. */\n\tsettledRead?: boolean;\n\terror?: string;\n}\n\n/** Truncate to an exact visible width, padding short lines with spaces. */\nfunction padLine(line: string, width: number): string {\n\treturn truncateToWidth(line, width, \"…\", true);\n}\n\nexport class BackgroundTasksMenu implements Component, Focusable {\n\tprivate readonly tui: MenuTui;\n\tprivate readonly theme: Theme;\n\tprivate readonly keybindings: Pick<KeybindingsManager, \"matches\" | \"getKeys\">;\n\tprivate readonly host: BackgroundManagerHost;\n\tprivate readonly onClose: () => void;\n\tprivate readonly pollIntervalMs: number;\n\n\tprivate view: \"list\" | \"detail\" = \"list\";\n\tprivate tasks: BgTask[] = [];\n\tprivate selectedTaskId: string | undefined;\n\tprivate listScrollTop = 0;\n\tprivate follow = true;\n\tprivate tailOffsetLines = 0;\n\tprivate tailCache: TailCache | undefined;\n\tprivate killFeedback: string | undefined;\n\t/** Task whose settle expires killFeedback; undefined = persists until the next key. */\n\tprivate killFeedbackTaskId: string | undefined;\n\t/** Last tick's render signature; unchanged means nothing visible moved. */\n\tprivate lastSignature = \"\";\n\tprivate pollTimer: ReturnType<typeof setInterval> | undefined;\n\tprivate readBusy = false;\n\tprivate disposed = false;\n\tprivate _focused = false;\n\n\tconstructor(options: BackgroundTasksMenuOptions) {\n\t\tthis.tui = options.tui;\n\t\tthis.theme = options.theme;\n\t\tthis.keybindings = options.keybindings;\n\t\tthis.host = options.host;\n\t\tthis.onClose = options.onClose;\n\t\tthis.pollIntervalMs = options.pollIntervalMs ?? POLL_INTERVAL_MS;\n\n\t\tthis.tasks = this.host.listTasks();\n\t\tthis.selectedTaskId = this.tasks[0]?.id;\n\t\tvoid this.tick();\n\t\tthis.pollTimer = setInterval(() => void this.tick(), this.pollIntervalMs);\n\t}\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t}\n\n\tinvalidate(): void {\n\t\t// No cached render state; the poller drives refresh.\n\t}\n\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t\tif (this.pollTimer !== undefined) {\n\t\t\tclearInterval(this.pollTimer);\n\t\t\tthis.pollTimer = undefined;\n\t\t}\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (this.killFeedback !== undefined) {\n\t\t\tthis.killFeedback = undefined;\n\t\t\tthis.killFeedbackTaskId = undefined;\n\t\t\tthis.tui.requestRender();\n\t\t}\n\t\tif (this.keybindings.matches(data, \"tui.select.cancel\")) {\n\t\t\tif (this.view === \"detail\") {\n\t\t\t\tthis.view = \"list\";\n\t\t\t\tthis.tui.requestRender();\n\t\t\t} else {\n\t\t\t\tthis.onClose();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (this.keybindings.matches(data, \"app.backgroundTasks.kill\")) {\n\t\t\tthis.killSelected();\n\t\t\treturn;\n\t\t}\n\t\tif (this.view === \"list\") this.handleListInput(data);\n\t\telse this.handleDetailInput(data);\n\t}\n\n\tprivate handleListInput(data: string): void {\n\t\tif (this.keybindings.matches(data, \"tui.select.up\")) {\n\t\t\tthis.moveSelection(-1);\n\t\t\treturn;\n\t\t}\n\t\tif (this.keybindings.matches(data, \"tui.select.down\")) {\n\t\t\tthis.moveSelection(1);\n\t\t\treturn;\n\t\t}\n\t\tif (this.keybindings.matches(data, \"tui.select.confirm\")) {\n\t\t\tif (!this.selectedTask()) return;\n\t\t\tthis.view = \"detail\";\n\t\t\tthis.resetFollow();\n\t\t\tthis.tui.requestRender();\n\t\t}\n\t}\n\n\tprivate handleDetailInput(data: string): void {\n\t\tif (this.keybindings.matches(data, \"tui.select.pageUp\")) {\n\t\t\tthis.scrollDetail(Math.max(1, this.detailBodyHeight()));\n\t\t\treturn;\n\t\t}\n\t\tif (this.keybindings.matches(data, \"tui.select.pageDown\")) {\n\t\t\tif (!this.follow) this.scrollDetail(-Math.max(1, this.detailBodyHeight()));\n\t\t\treturn;\n\t\t}\n\t\tif (this.keybindings.matches(data, \"tui.select.up\")) {\n\t\t\tthis.scrollDetail(1);\n\t\t\treturn;\n\t\t}\n\t\tif (this.keybindings.matches(data, \"tui.select.down\")) {\n\t\t\tif (!this.follow) this.scrollDetail(-1);\n\t\t}\n\t}\n\n\t/** Scroll the detail viewport by `lines` (positive = back through history). */\n\tprivate scrollDetail(lines: number): void {\n\t\tif (lines > 0) {\n\t\t\tconst max = this.maxTailOffset();\n\t\t\tif (max === 0) return; // Nothing above the viewport to scroll back to.\n\t\t\tthis.follow = false;\n\t\t\tthis.tailOffsetLines = Math.min(max, this.tailOffsetLines + lines);\n\t\t} else {\n\t\t\tif (this.follow) return;\n\t\t\tthis.tailOffsetLines = Math.max(0, this.tailOffsetLines + lines);\n\t\t\tif (this.tailOffsetLines === 0) {\n\t\t\t\tthis.follow = true;\n\t\t\t\tvoid this.refreshViewport();\n\t\t\t}\n\t\t}\n\t\tthis.tui.requestRender();\n\t}\n\n\trender(width: number): string[] {\n\t\tconst body = this.view === \"list\" ? this.renderList(width) : this.renderDetail(width);\n\t\tconst border = this.theme.fg(\"border\", \"─\".repeat(Math.max(1, width)));\n\t\treturn [border, ...body, padLine(this.footerLine(), width), border];\n\t}\n\n\t// ── list view ──────────────────────────────────────────────────────────\n\n\t/** Task rows the terminal can spare; short windows trade rows for the transcript. */\n\tprivate listMaxVisible(): number {\n\t\treturn Math.min(LIST_MAX_VISIBLE, Math.max(LIST_MIN_VISIBLE, this.tui.terminal.rows - LIST_RESERVED_ROWS));\n\t}\n\n\tprivate renderList(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst counts = this.countsLabel();\n\t\tconst title = counts ? `Background tasks — ${counts}` : \"Background tasks\";\n\t\tlines.push(padLine(this.theme.fg(\"accent\", this.theme.bold(title)), width));\n\n\t\tif (this.tasks.length === 0) {\n\t\t\tlines.push(padLine(this.theme.fg(\"muted\", \" (no tasks)\"), width));\n\t\t\treturn lines;\n\t\t}\n\n\t\tconst selected = this.selectedTask();\n\t\tconst maxVisible = this.listMaxVisible();\n\t\tconst visible = this.tasks.slice(this.listScrollTop, this.listScrollTop + maxVisible);\n\t\tlet seenRunning = false;\n\t\tfor (const task of visible) {\n\t\t\t// listTasks() orders running first, finished after: one separator at the boundary.\n\t\t\tif (seenRunning && task.status !== \"running\") {\n\t\t\t\tlines.push(padLine(this.theme.fg(\"muted\", \" ── finished ──\"), width));\n\t\t\t\tseenRunning = false;\n\t\t\t}\n\t\t\tif (task.status === \"running\") seenRunning = true;\n\t\t\tlines.push(this.renderTaskRow(task, task === selected, width));\n\t\t}\n\t\tif (this.tasks.length > maxVisible) {\n\t\t\tconst index = this.tasks.findIndex((task) => task.id === this.selectedTaskId);\n\t\t\tlines.push(padLine(this.theme.fg(\"muted\", ` (${index + 1}/${this.tasks.length})`), width));\n\t\t}\n\t\treturn lines;\n\t}\n\n\tprivate renderTaskRow(task: BgTask, isSelected: boolean, width: number): string {\n\t\tconst duration = formatDuration((task.endedAt ?? Date.now()) - task.startedAt);\n\t\tconst label = task.description\n\t\t\t? `${task.description} — ${firstCommandLine(task.command)}`\n\t\t\t: firstCommandLine(task.command);\n\t\tif (isSelected) {\n\t\t\t// Pad to full width before styling so the selection background spans the row.\n\t\t\tconst plain = padLine(`→ ${statusGlyph(task.status, task.stalled)} ${task.id} ${duration} ${label}`, width);\n\t\t\treturn this.theme.bg(\"selectedBg\", this.theme.fg(\"text\", plain));\n\t\t}\n\t\tconst glyph = this.theme.fg(statusColor(task.status, task.stalled), statusGlyph(task.status, task.stalled));\n\t\tconst id = this.theme.fg(\"accent\", task.id);\n\t\tconst rest = this.theme.fg(\"muted\", `${duration} ${label}`);\n\t\treturn padLine(` ${glyph} ${id} ${rest}`, width);\n\t}\n\n\tprivate countsLabel(): string {\n\t\tlet running = 0;\n\t\tfor (const task of this.tasks) if (task.status === \"running\") running++;\n\t\tconst ended = this.tasks.length - running;\n\t\tconst parts: string[] = [];\n\t\tif (running > 0) parts.push(`${running} running`);\n\t\tif (ended > 0) parts.push(`${ended} done`);\n\t\treturn parts.join(\" · \");\n\t}\n\n\t// ── detail view ────────────────────────────────────────────────────────\n\n\tprivate renderDetail(width: number): string[] {\n\t\tconst task = this.selectedTask();\n\t\tconst lines: string[] = [padLine(this.detailHeader(task), width)];\n\t\tconst height = this.detailBodyHeight();\n\t\tconst cache = task && this.tailCache?.taskId === task.id ? this.tailCache : undefined;\n\t\tif (cache?.error) {\n\t\t\tlines.push(padLine(this.theme.fg(\"error\", `Cannot read output: ${cache.error}`), width));\n\t\t\tfor (let row = 1; row < height; row++) lines.push(padLine(\"\", width));\n\t\t\treturn lines;\n\t\t}\n\t\tconst content = cache?.lines ?? [];\n\t\tconst fromEnd = this.follow ? 0 : this.tailOffsetLines;\n\t\tconst start = content.length - height - fromEnd;\n\t\tfor (let row = 0; row < height; row++) {\n\t\t\tconst line = content[start + row];\n\t\t\tlines.push(line === undefined ? padLine(\"\", width) : padLine(this.theme.fg(\"toolOutput\", line), width));\n\t\t}\n\t\treturn lines;\n\t}\n\n\tprivate detailHeader(task: BgTask | undefined): string {\n\t\tif (!task) return this.theme.fg(\"muted\", \"(no task selected)\");\n\t\tconst duration = formatDuration((task.endedAt ?? Date.now()) - task.startedAt);\n\t\tconst exit = task.exitCode !== undefined && task.exitCode !== null ? ` exit ${task.exitCode}` : \"\";\n\t\tconst resumeLabel = keyLabel(\"tui.select.pageDown\", { keybindings: this.keybindings });\n\t\tconst paused = this.follow ? \"\" : resumeLabel ? ` — paused (${resumeLabel} to follow)` : \" — paused\";\n\t\tconst fileName = task.outputPath.replace(/\\\\/g, \"/\").split(\"/\").at(-1) ?? task.outputPath;\n\t\tconst glyph = this.theme.fg(statusColor(task.status, task.stalled), statusGlyph(task.status, task.stalled));\n\t\tconst statusLabel = task.stalled ? \"running, waiting for input\" : task.status;\n\t\tconst header = `${task.id} · ${statusLabel}${exit} · ${duration} · ${formatSize(task.outputBytes)} · ${fileName}${paused}`;\n\t\treturn `${glyph} ${this.theme.fg(\"muted\", header)}`;\n\t}\n\n\tprivate detailBodyHeight(): number {\n\t\t// Inline component: keep the chat transcript visible above the menu.\n\t\treturn Math.min(20, Math.max(4, this.tui.terminal.rows - 8));\n\t}\n\n\t// ── shared behavior ────────────────────────────────────────────────────\n\n\tprivate footerLine(): string {\n\t\tif (this.killFeedback) return this.theme.fg(\"warning\", this.killFeedback);\n\t\tconst opts = { keybindings: this.keybindings };\n\t\tconst parts =\n\t\t\tthis.view === \"list\"\n\t\t\t\t? [\n\t\t\t\t\t\t`${keyLabel(\"tui.select.up\", opts)}/${keyLabel(\"tui.select.down\", opts)} select`,\n\t\t\t\t\t\t`${keyLabel(\"tui.select.confirm\", opts)} output`,\n\t\t\t\t\t\t`${keyLabel(\"app.backgroundTasks.kill\", opts)} kill`,\n\t\t\t\t\t\t`${keyLabel(\"tui.select.cancel\", opts)} close`,\n\t\t\t\t\t]\n\t\t\t\t: [\n\t\t\t\t\t\t`${keyLabel(\"tui.select.up\", opts)}/${keyLabel(\"tui.select.down\", opts)} scroll`,\n\t\t\t\t\t\t`${keyLabel(\"tui.select.pageUp\", opts)}/${keyLabel(\"tui.select.pageDown\", opts)} page`,\n\t\t\t\t\t\t`${keyLabel(\"app.backgroundTasks.kill\", opts)} kill`,\n\t\t\t\t\t\t`${keyLabel(\"tui.select.cancel\", opts)} back`,\n\t\t\t\t\t];\n\t\treturn this.theme.fg(\"dim\", parts.join(\" · \"));\n\t}\n\n\tprivate selectedTask(): BgTask | undefined {\n\t\treturn this.tasks.find((task) => task.id === this.selectedTaskId);\n\t}\n\n\tprivate moveSelection(offset: -1 | 1): void {\n\t\tif (this.tasks.length === 0) return;\n\t\tconst current = this.tasks.findIndex((task) => task.id === this.selectedTaskId);\n\t\tconst next = (current + offset + this.tasks.length) % this.tasks.length;\n\t\tconst task = this.tasks[next];\n\t\tif (!task) return;\n\t\tthis.selectedTaskId = task.id;\n\t\tif (next < this.listScrollTop) this.listScrollTop = next;\n\t\tif (next >= this.listScrollTop + this.listMaxVisible()) {\n\t\t\tthis.listScrollTop = next - this.listMaxVisible() + 1;\n\t\t}\n\t\tthis.resetFollow();\n\t\tthis.tui.requestRender();\n\t}\n\n\tprivate resetFollow(): void {\n\t\tthis.follow = true;\n\t\tthis.tailOffsetLines = 0;\n\t\tthis.tailCache = undefined;\n\t\tvoid this.refreshViewport();\n\t}\n\n\tprivate currentLines(): string[] {\n\t\tconst task = this.selectedTask();\n\t\tconst cache = this.tailCache;\n\t\treturn task && cache && cache.taskId === task.id ? cache.lines : [];\n\t}\n\n\tprivate maxTailOffset(): number {\n\t\treturn Math.max(0, this.currentLines().length - this.detailBodyHeight());\n\t}\n\n\tprivate killSelected(): void {\n\t\tconst task = this.selectedTask();\n\t\tif (!task) return;\n\t\tif (task.status !== \"running\") {\n\t\t\tthis.killFeedback = `${task.id} is not running`;\n\t\t\tthis.tui.requestRender();\n\t\t\treturn;\n\t\t}\n\t\tthis.host.killTask(task.id);\n\t\t// Terminal state lands on the next poll; the feedback expires with it (tick).\n\t\tthis.killFeedback = `stopping ${task.id}…`;\n\t\tthis.killFeedbackTaskId = task.id;\n\t\tthis.tui.requestRender();\n\t}\n\n\tprivate async tick(): Promise<void> {\n\t\tif (this.disposed) return;\n\t\tthis.tasks = this.host.listTasks();\n\t\tif (!this.selectedTask() && this.tasks[0]) this.selectedTaskId = this.tasks[0].id;\n\t\tthis.expireKillFeedback();\n\t\t// A pending re-read counts as a change: refreshViewport may skip this tick\n\t\t// (readBusy), and the signature alone would let that retry be dropped.\n\t\tconst needsRead = this.view === \"detail\" && this.follow && this.detailOutputChanged();\n\t\tif (!needsRead && this.renderSignature() === this.lastSignature) return; // Nothing visible changed.\n\t\tif (needsRead) await this.refreshViewport();\n\t\tthis.lastSignature = this.renderSignature();\n\t\tthis.tui.requestRender();\n\t}\n\n\t/** Drop \"stopping\" feedback once its task has settled. */\n\tprivate expireKillFeedback(): void {\n\t\tif (this.killFeedbackTaskId === undefined) return;\n\t\tconst task = this.tasks.find((candidate) => candidate.id === this.killFeedbackTaskId);\n\t\tif (!task || task.status !== \"running\") {\n\t\t\tthis.killFeedback = undefined;\n\t\t\tthis.killFeedbackTaskId = undefined;\n\t\t}\n\t}\n\n\t/** Everything the rendered output depends on; equal signatures need no redraw. */\n\tprivate renderSignature(): string {\n\t\tconst parts = [\n\t\t\tthis.view,\n\t\t\tthis.selectedTaskId ?? \"\",\n\t\t\tString(this.listScrollTop),\n\t\t\tString(this.follow),\n\t\t\tString(this.tailOffsetLines),\n\t\t\tthis.killFeedback ?? \"\",\n\t\t\tthis.tailCache\n\t\t\t\t? `${this.tailCache.taskId}:${this.tailCache.lines.length}:${this.tailCache.totalBytes}:${this.tailCache.error ?? \"\"}:${String(this.tailCache.settledRead ?? false)}`\n\t\t\t\t: \"\",\n\t\t];\n\t\tfor (const task of this.tasks) {\n\t\t\tconst duration = formatDuration((task.endedAt ?? Date.now()) - task.startedAt);\n\t\t\tparts.push(\n\t\t\t\t`${task.id}:${task.status}:${String(task.stalled)}:${task.outputBytes}:${task.exitCode ?? \"\"}:${duration}`,\n\t\t\t);\n\t\t}\n\t\treturn parts.join(\"|\");\n\t}\n\n\t/** True when the detail viewport must re-read the output file this tick. */\n\tprivate detailOutputChanged(): boolean {\n\t\tconst task = this.selectedTask();\n\t\tif (!task) return false;\n\t\tconst cache = this.tailCache;\n\t\tif (!cache || cache.taskId !== task.id) return true;\n\t\tif (cache.error !== undefined) return true; // Keep retrying; failed reads are cheap.\n\t\tif (task.status !== \"running\") {\n\t\t\t// Terminal task: the file is final — read it once, then never again.\n\t\t\treturn cache.settledRead !== true;\n\t\t}\n\t\treturn cache.totalBytes !== task.outputBytes;\n\t}\n\n\tprivate async refreshViewport(): Promise<void> {\n\t\tif (this.readBusy) return;\n\t\tconst task = this.selectedTask();\n\t\tif (!task) return;\n\t\tthis.readBusy = true;\n\t\ttry {\n\t\t\tconst slice = await this.host.readSlice(task.outputPath, { mode: \"tail\", maxBytes: VIEW_TAIL_BYTES });\n\t\t\tif (this.disposed || this.selectedTaskId !== task.id || !this.follow) return;\n\t\t\tthis.tailCache = {\n\t\t\t\ttaskId: task.id,\n\t\t\t\tlines: toViewLines(slice.text),\n\t\t\t\ttotalBytes: slice.totalBytes,\n\t\t\t\tsettledRead: task.status !== \"running\",\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tif (this.disposed || this.selectedTaskId !== task.id) return;\n\t\t\tthis.tailCache = {\n\t\t\t\ttaskId: task.id,\n\t\t\t\tlines: [],\n\t\t\t\ttotalBytes: task.outputBytes,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t} finally {\n\t\t\tthis.readBusy = false;\n\t\t}\n\t}\n}\n\nfunction toViewLines(text: string): string[] {\n\t// Strip ANSI first: sanitize would remove the escape bytes alone, leaving\n\t// orphaned \"[31m\" fragments that strip can no longer see.\n\tconst lines = sanitizeBinaryOutput(stripTerminalSequences(text)).split(\"\\n\");\n\t// Drop the trailing empty line produced by a final newline, then bound the\n\t// window: a 128KB slice of one-byte lines must never become 128k rows.\n\twhile (lines.length > 0 && lines[lines.length - 1] === \"\") lines.pop();\n\treturn lines.slice(-MAX_VIEW_LINES);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/extensions/background/manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAkC,sBAAsB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEjH,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,wDAAwD,CAAC;AAElF,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG5D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC9B,MAAM,eAAe,GAAG,GAAG,GAAG,IAAI,CAAC;AACnC,MAAM,cAAc,GAAG,IAAI,CAAC;AAC5B,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAC3B,oFAAoF;AACpF,MAAM,kBAAkB,GAAG,EAAE,CAAC;AA+B9B,2EAA2E;AAC3E,SAAS,OAAO,CAAC,IAAY,EAAE,KAAa;IAC3C,OAAO,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,OAAO,mBAAmB;IAyB/B,YAAY,OAAmC;QAjBvC,SAAI,GAAsB,MAAM,CAAC;QACjC,UAAK,GAAa,EAAE,CAAC;QAErB,kBAAa,GAAG,CAAC,CAAC;QAClB,WAAM,GAAG,IAAI,CAAC;QACd,oBAAe,GAAG,CAAC,CAAC;QAK5B,2EAA2E;QACnE,kBAAa,GAAG,EAAE,CAAC;QAEnB,aAAQ,GAAG,KAAK,CAAC;QACjB,aAAQ,GAAG,KAAK,CAAC;QACjB,aAAQ,GAAG,KAAK,CAAC;QAGxB,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,gBAAgB,CAAC;QAEjE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QACnC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACxC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED,IAAI,OAAO,CAAC,KAAc;QACzB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,UAAU;QACT,qDAAqD;IACtD,CAAC;IAED,OAAO;QACN,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAClC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC9B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC5B,CAAC;IACF,CAAC;IAED,WAAW,CAAC,IAAY;QACvB,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACrC,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;YAC9B,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;YACpC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC1B,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,mBAAmB,CAAC,EAAE,CAAC;YACzD,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC5B,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC;gBACnB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACP,IAAI,CAAC,OAAO,EAAE,CAAC;YAChB,CAAC;YACD,OAAO;QACR,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,0BAA0B,CAAC,EAAE,CAAC;YAChE,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,OAAO;QACR,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;;YAChD,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAEO,eAAe,CAAC,IAAY;QACnC,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,CAAC;YACrD,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;YACvB,OAAO;QACR,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,iBAAiB,CAAC,EAAE,CAAC;YACvD,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;YACtB,OAAO;QACR,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,oBAAoB,CAAC,EAAE,CAAC;YAC1D,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;gBAAE,OAAO;YACjC,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC;YACrB,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC1B,CAAC;IACF,CAAC;IAEO,iBAAiB,CAAC,IAAY;QACrC,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,mBAAmB,CAAC,EAAE,CAAC;YACzD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC;YACxD,OAAO;QACR,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,qBAAqB,CAAC,EAAE,CAAC;YAC3D,IAAI,CAAC,IAAI,CAAC,MAAM;gBAAE,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC;YAC3E,OAAO;QACR,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,CAAC;YACrD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACrB,OAAO;QACR,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,iBAAiB,CAAC,EAAE,CAAC;YACvD,IAAI,CAAC,IAAI,CAAC,MAAM;gBAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;IACF,CAAC;IAED,+EAA+E;IACvE,YAAY,CAAC,KAAa;QACjC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YACjC,IAAI,GAAG,KAAK,CAAC;gBAAE,OAAO,CAAC,gDAAgD;YACvE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,CAAC;QACpE,CAAC;aAAM,CAAC;YACP,IAAI,IAAI,CAAC,MAAM;gBAAE,OAAO;YACxB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,CAAC;YACjE,IAAI,IAAI,CAAC,eAAe,KAAK,CAAC,EAAE,CAAC;gBAChC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;gBACnB,KAAK,IAAI,CAAC,eAAe,EAAE,CAAC;YAC7B,CAAC;QACF,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC1B,CAAC;IAED,MAAM,CAAC,KAAa;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACtF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QACvE,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;IACrE,CAAC;IAED,0EAA0E;IAE1E,qFAAqF;IAC7E,cAAc;QACrB,OAAO,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,kBAAkB,CAAC,CAAC,CAAC;IAC5G,CAAC;IAEO,UAAU,CAAC,KAAa;QAC/B,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,sBAAsB,MAAM,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC;QAC3E,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QAE5E,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;YACnE,OAAO,KAAK,CAAC;QACd,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC,CAAC;QACtF,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC5B,mFAAmF;YACnF,IAAI,WAAW,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC9C,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;gBACvE,WAAW,GAAG,KAAK,CAAC;YACrB,CAAC;YACD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;gBAAE,WAAW,GAAG,IAAI,CAAC;YAClD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,KAAK,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;YACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,cAAc,CAAC,CAAC;YAC9E,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QAC7F,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC;IAEO,aAAa,CAAC,IAAY,EAAE,UAAmB,EAAE,KAAa;QACrE,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,UAAU,EAAE,CAAC;YAChB,8EAA8E;YAC9E,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,EAAE,IAAI,QAAQ,IAAI,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;YAC5G,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5G,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,QAAQ,IAAI,KAAK,EAAE,CAAC,CAAC;QAC5D,OAAO,OAAO,CAAC,KAAK,KAAK,IAAI,EAAE,IAAI,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC;IAEO,WAAW;QAClB,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;gBAAE,OAAO,EAAE,CAAC;QACxE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC;QAC1C,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,OAAO,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,UAAU,CAAC,CAAC;QAClD,IAAI,KAAK,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC;QAC3C,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,0EAA0E;IAElE,YAAY,CAAC,KAAa;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACjC,MAAM,KAAK,GAAa,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QACtF,IAAI,KAAK,EAAE,KAAK,EAAE,CAAC;YAClB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;YACzF,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,MAAM,EAAE,GAAG,EAAE;gBAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;YACtE,OAAO,KAAK,CAAC;QACd,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC;QACvD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;QAChD,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC;YACvC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QACzG,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC;IAEO,YAAY,CAAC,IAAwB;QAC5C,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;QAC/D,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAC5C,MAAM,WAAW,GAAG,QAAQ,CAAC,qBAAqB,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACvF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc,WAAW,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC;QACrG,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5G,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QAC9E,MAAM,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,MAAM,WAAW,GAAG,IAAI,MAAM,QAAQ,MAAM,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC;QAC3H,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;IACrD,CAAC;IAEO,gBAAgB;QACvB,qEAAqE;QACrE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,0EAA0E;IAElE,UAAU;QACjB,IAAI,IAAI,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1E,MAAM,IAAI,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/C,MAAM,KAAK,GACV,IAAI,CAAC,IAAI,KAAK,MAAM;YACnB,CAAC,CAAC;gBACA,GAAG,QAAQ,CAAC,eAAe,EAAE,IAAI,CAAC,IAAI,QAAQ,CAAC,iBAAiB,EAAE,IAAI,CAAC,SAAS;gBAChF,GAAG,QAAQ,CAAC,oBAAoB,EAAE,IAAI,CAAC,SAAS;gBAChD,GAAG,QAAQ,CAAC,0BAA0B,EAAE,IAAI,CAAC,OAAO;gBACpD,GAAG,QAAQ,CAAC,mBAAmB,EAAE,IAAI,CAAC,QAAQ;aAC9C;YACF,CAAC,CAAC;gBACA,GAAG,QAAQ,CAAC,eAAe,EAAE,IAAI,CAAC,IAAI,QAAQ,CAAC,iBAAiB,EAAE,IAAI,CAAC,SAAS;gBAChF,GAAG,QAAQ,CAAC,mBAAmB,EAAE,IAAI,CAAC,IAAI,QAAQ,CAAC,qBAAqB,EAAE,IAAI,CAAC,OAAO;gBACtF,GAAG,QAAQ,CAAC,0BAA0B,EAAE,IAAI,CAAC,OAAO;gBACpD,GAAG,QAAQ,CAAC,mBAAmB,EAAE,IAAI,CAAC,OAAO;aAC7C,CAAC;QACL,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,CAAC;IAEO,YAAY;QACnB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,cAAc,CAAC,CAAC;IACnE,CAAC;IAEO,aAAa,CAAC,MAAc;QACnC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,cAAc,CAAC,CAAC;QAChF,MAAM,IAAI,GAAG,CAAC,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QACxE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,EAAE,CAAC;QAC9B,IAAI,IAAI,GAAG,IAAI,CAAC,aAAa;YAAE,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QACzD,IAAI,IAAI,IAAI,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;YACxD,IAAI,CAAC,aAAa,GAAG,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;QACvD,CAAC;QACD,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC1B,CAAC;IAEO,WAAW;QAClB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,KAAK,IAAI,CAAC,eAAe,EAAE,CAAC;IAC7B,CAAC;IAEO,YAAY;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC;QAC7B,OAAO,IAAI,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACrE,CAAC;IAEO,aAAa;QACpB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAC1E,CAAC;IAEO,YAAY;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACjC,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC/B,IAAI,CAAC,YAAY,GAAG,GAAG,IAAI,CAAC,EAAE,iBAAiB,CAAC;YAChD,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YACzB,OAAO;QACR,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5B,8EAA8E;QAC9E,IAAI,CAAC,YAAY,GAAG,YAAY,IAAI,CAAC,EAAE,GAAG,CAAC;QAC3C,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC1B,CAAC;IAEO,KAAK,CAAC,IAAI;QACjB,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAAE,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,2EAA2E;QAC3E,uEAAuE;QACvE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACtF,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,eAAe,EAAE,KAAK,IAAI,CAAC,aAAa;YAAE,OAAO,CAAC,2BAA2B;QACpG,IAAI,SAAS;YAAE,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC5C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QAC5C,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC1B,CAAC;IAED,0DAA0D;IAClD,kBAAkB;QACzB,IAAI,IAAI,CAAC,kBAAkB,KAAK,SAAS;YAAE,OAAO;QAClD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACtF,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACxC,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;YAC9B,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;QACrC,CAAC;IACF,CAAC;IAED,kFAAkF;IAC1E,eAAe;QACtB,MAAM,KAAK,GAAG;YACb,IAAI,CAAC,IAAI;YACT,IAAI,CAAC,cAAc,IAAI,EAAE;YACzB,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;YACnB,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC;YAC5B,IAAI,CAAC,YAAY,IAAI,EAAE;YACvB,IAAI,CAAC,SAAS;gBACb,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,IAAI,KAAK,CAAC,EAAE;gBACrK,CAAC,CAAC,EAAE;SACL,CAAC;QACF,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC/B,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;YACpC,KAAK,CAAC,IAAI,CACT,GAAG,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,IAAI,QAAQ,EAAE,CAC1G,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,4EAA4E;IACpE,mBAAmB;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACjC,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAC;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC;QAC7B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACpD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,CAAC,yCAAyC;QACrF,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC/B,qEAAqE;YACrE,OAAO,KAAK,CAAC,WAAW,KAAK,IAAI,CAAC;QACnC,CAAC;QACD,OAAO,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC,WAAW,CAAC;IAC9C,CAAC;IAEO,KAAK,CAAC,eAAe;QAC5B,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACjC,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC;YACJ,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC,CAAC;YACtG,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM;gBAAE,OAAO;YAC7E,IAAI,CAAC,SAAS,GAAG;gBAChB,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC;gBAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,WAAW,EAAE,IAAI,CAAC,MAAM,KAAK,SAAS;aACtC,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI,CAAC,EAAE;gBAAE,OAAO;YAC7D,IAAI,CAAC,SAAS,GAAG;gBAChB,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,KAAK,EAAE,EAAE;gBACT,UAAU,EAAE,IAAI,CAAC,WAAW;gBAC5B,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC7D,CAAC;QACH,CAAC;gBAAS,CAAC;YACV,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACvB,CAAC;IACF,CAAC;CACD;AAED,SAAS,WAAW,CAAC,IAAY;IAChC,0EAA0E;IAC1E,0DAA0D;IAC1D,MAAM,KAAK,GAAG,oBAAoB,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7E,2EAA2E;IAC3E,uEAAuE;IACvE,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE;QAAE,KAAK,CAAC,GAAG,EAAE,CAAC;IACvE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,CAAC;AACrC,CAAC","sourcesContent":["/**\n * /bg task manager — an inline, /model-style menu that mounts in the editor\n * slot. Two views in one component: a task list, and a live output viewport\n * for the selected task (Enter to open, Esc to go back). The host dependency\n * is narrowed to three callbacks so the component stays testable.\n */\n\nimport { type Component, type Focusable, stripTerminalSequences, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport type { KeybindingsManager } from \"../../core/keybindings.ts\";\nimport { formatSize } from \"../../core/tools/truncate.ts\";\nimport { keyLabel } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { sanitizeBinaryOutput } from \"../../utils/shell.ts\";\nimport type { OutputSlice } from \"./output-file.ts\";\nimport type { BgTask } from \"./registry.ts\";\nimport { exitSuffix, runtimeLabel, statusColor, statusGlyph, taskLabel } from \"./task-view.ts\";\nimport { fileNameOf } from \"./text.ts\";\n\nconst POLL_INTERVAL_MS = 1000;\nconst VIEW_TAIL_BYTES = 128 * 1024;\nconst MAX_VIEW_LINES = 2000;\nconst LIST_MAX_VISIBLE = 10;\nconst LIST_MIN_VISIBLE = 3;\n/** Rows outside the task list itself (borders, title, counter, footer, padding). */\nconst LIST_RESERVED_ROWS = 14;\n\nexport interface BackgroundManagerHost {\n\tlistTasks(): BgTask[];\n\tkillTask(id: string): { killed: boolean };\n\treadSlice(filePath: string, options: { mode: \"tail\"; maxBytes: number }): Promise<OutputSlice>;\n}\n\ninterface MenuTui {\n\trequestRender(): void;\n\tterminal: { rows: number; columns: number };\n}\n\nexport interface BackgroundTasksMenuOptions {\n\ttui: MenuTui;\n\ttheme: Theme;\n\tkeybindings: Pick<KeybindingsManager, \"matches\" | \"getKeys\">;\n\thost: BackgroundManagerHost;\n\tonClose: () => void;\n\tpollIntervalMs?: number;\n}\n\ninterface TailCache {\n\ttaskId: string;\n\tlines: string[];\n\ttotalBytes: number;\n\t/** True once a terminal task's final output has been read; skips re-reads. */\n\tsettledRead?: boolean;\n\terror?: string;\n}\n\n/** Truncate to an exact visible width, padding short lines with spaces. */\nfunction padLine(line: string, width: number): string {\n\treturn truncateToWidth(line, width, \"…\", true);\n}\n\nexport class BackgroundTasksMenu implements Component, Focusable {\n\tprivate readonly tui: MenuTui;\n\tprivate readonly theme: Theme;\n\tprivate readonly keybindings: Pick<KeybindingsManager, \"matches\" | \"getKeys\">;\n\tprivate readonly host: BackgroundManagerHost;\n\tprivate readonly onClose: () => void;\n\tprivate readonly pollIntervalMs: number;\n\n\tprivate view: \"list\" | \"detail\" = \"list\";\n\tprivate tasks: BgTask[] = [];\n\tprivate selectedTaskId: string | undefined;\n\tprivate listScrollTop = 0;\n\tprivate follow = true;\n\tprivate tailOffsetLines = 0;\n\tprivate tailCache: TailCache | undefined;\n\tprivate killFeedback: string | undefined;\n\t/** Task whose settle expires killFeedback; undefined = persists until the next key. */\n\tprivate killFeedbackTaskId: string | undefined;\n\t/** Last tick's render signature; unchanged means nothing visible moved. */\n\tprivate lastSignature = \"\";\n\tprivate pollTimer: ReturnType<typeof setInterval> | undefined;\n\tprivate readBusy = false;\n\tprivate disposed = false;\n\tprivate _focused = false;\n\n\tconstructor(options: BackgroundTasksMenuOptions) {\n\t\tthis.tui = options.tui;\n\t\tthis.theme = options.theme;\n\t\tthis.keybindings = options.keybindings;\n\t\tthis.host = options.host;\n\t\tthis.onClose = options.onClose;\n\t\tthis.pollIntervalMs = options.pollIntervalMs ?? POLL_INTERVAL_MS;\n\n\t\tthis.tasks = this.host.listTasks();\n\t\tthis.selectedTaskId = this.tasks[0]?.id;\n\t\tvoid this.tick();\n\t\tthis.pollTimer = setInterval(() => void this.tick(), this.pollIntervalMs);\n\t}\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t}\n\n\tinvalidate(): void {\n\t\t// No cached render state; the poller drives refresh.\n\t}\n\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t\tif (this.pollTimer !== undefined) {\n\t\t\tclearInterval(this.pollTimer);\n\t\t\tthis.pollTimer = undefined;\n\t\t}\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (this.killFeedback !== undefined) {\n\t\t\tthis.killFeedback = undefined;\n\t\t\tthis.killFeedbackTaskId = undefined;\n\t\t\tthis.tui.requestRender();\n\t\t}\n\t\tif (this.keybindings.matches(data, \"tui.select.cancel\")) {\n\t\t\tif (this.view === \"detail\") {\n\t\t\t\tthis.view = \"list\";\n\t\t\t\tthis.tui.requestRender();\n\t\t\t} else {\n\t\t\t\tthis.onClose();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (this.keybindings.matches(data, \"app.backgroundTasks.kill\")) {\n\t\t\tthis.killSelected();\n\t\t\treturn;\n\t\t}\n\t\tif (this.view === \"list\") this.handleListInput(data);\n\t\telse this.handleDetailInput(data);\n\t}\n\n\tprivate handleListInput(data: string): void {\n\t\tif (this.keybindings.matches(data, \"tui.select.up\")) {\n\t\t\tthis.moveSelection(-1);\n\t\t\treturn;\n\t\t}\n\t\tif (this.keybindings.matches(data, \"tui.select.down\")) {\n\t\t\tthis.moveSelection(1);\n\t\t\treturn;\n\t\t}\n\t\tif (this.keybindings.matches(data, \"tui.select.confirm\")) {\n\t\t\tif (!this.selectedTask()) return;\n\t\t\tthis.view = \"detail\";\n\t\t\tthis.resetFollow();\n\t\t\tthis.tui.requestRender();\n\t\t}\n\t}\n\n\tprivate handleDetailInput(data: string): void {\n\t\tif (this.keybindings.matches(data, \"tui.select.pageUp\")) {\n\t\t\tthis.scrollDetail(Math.max(1, this.detailBodyHeight()));\n\t\t\treturn;\n\t\t}\n\t\tif (this.keybindings.matches(data, \"tui.select.pageDown\")) {\n\t\t\tif (!this.follow) this.scrollDetail(-Math.max(1, this.detailBodyHeight()));\n\t\t\treturn;\n\t\t}\n\t\tif (this.keybindings.matches(data, \"tui.select.up\")) {\n\t\t\tthis.scrollDetail(1);\n\t\t\treturn;\n\t\t}\n\t\tif (this.keybindings.matches(data, \"tui.select.down\")) {\n\t\t\tif (!this.follow) this.scrollDetail(-1);\n\t\t}\n\t}\n\n\t/** Scroll the detail viewport by `lines` (positive = back through history). */\n\tprivate scrollDetail(lines: number): void {\n\t\tif (lines > 0) {\n\t\t\tconst max = this.maxTailOffset();\n\t\t\tif (max === 0) return; // Nothing above the viewport to scroll back to.\n\t\t\tthis.follow = false;\n\t\t\tthis.tailOffsetLines = Math.min(max, this.tailOffsetLines + lines);\n\t\t} else {\n\t\t\tif (this.follow) return;\n\t\t\tthis.tailOffsetLines = Math.max(0, this.tailOffsetLines + lines);\n\t\t\tif (this.tailOffsetLines === 0) {\n\t\t\t\tthis.follow = true;\n\t\t\t\tvoid this.refreshViewport();\n\t\t\t}\n\t\t}\n\t\tthis.tui.requestRender();\n\t}\n\n\trender(width: number): string[] {\n\t\tconst body = this.view === \"list\" ? this.renderList(width) : this.renderDetail(width);\n\t\tconst border = this.theme.fg(\"border\", \"─\".repeat(Math.max(1, width)));\n\t\treturn [border, ...body, padLine(this.footerLine(), width), border];\n\t}\n\n\t// ── list view ──────────────────────────────────────────────────────────\n\n\t/** Task rows the terminal can spare; short windows trade rows for the transcript. */\n\tprivate listMaxVisible(): number {\n\t\treturn Math.min(LIST_MAX_VISIBLE, Math.max(LIST_MIN_VISIBLE, this.tui.terminal.rows - LIST_RESERVED_ROWS));\n\t}\n\n\tprivate renderList(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst counts = this.countsLabel();\n\t\tconst title = counts ? `Background tasks — ${counts}` : \"Background tasks\";\n\t\tlines.push(padLine(this.theme.fg(\"accent\", this.theme.bold(title)), width));\n\n\t\tif (this.tasks.length === 0) {\n\t\t\tlines.push(padLine(this.theme.fg(\"muted\", \" (no tasks)\"), width));\n\t\t\treturn lines;\n\t\t}\n\n\t\tconst selected = this.selectedTask();\n\t\tconst maxVisible = this.listMaxVisible();\n\t\tconst visible = this.tasks.slice(this.listScrollTop, this.listScrollTop + maxVisible);\n\t\tlet seenRunning = false;\n\t\tfor (const task of visible) {\n\t\t\t// listTasks() orders running first, finished after: one separator at the boundary.\n\t\t\tif (seenRunning && task.status !== \"running\") {\n\t\t\t\tlines.push(padLine(this.theme.fg(\"muted\", \" ── finished ──\"), width));\n\t\t\t\tseenRunning = false;\n\t\t\t}\n\t\t\tif (task.status === \"running\") seenRunning = true;\n\t\t\tlines.push(this.renderTaskRow(task, task === selected, width));\n\t\t}\n\t\tif (this.tasks.length > maxVisible) {\n\t\t\tconst index = this.tasks.findIndex((task) => task.id === this.selectedTaskId);\n\t\t\tlines.push(padLine(this.theme.fg(\"muted\", ` (${index + 1}/${this.tasks.length})`), width));\n\t\t}\n\t\treturn lines;\n\t}\n\n\tprivate renderTaskRow(task: BgTask, isSelected: boolean, width: number): string {\n\t\tconst duration = runtimeLabel(task);\n\t\tconst label = taskLabel(task);\n\t\tif (isSelected) {\n\t\t\t// Pad to full width before styling so the selection background spans the row.\n\t\t\tconst plain = padLine(`→ ${statusGlyph(task.status, task.stalled)} ${task.id} ${duration} ${label}`, width);\n\t\t\treturn this.theme.bg(\"selectedBg\", this.theme.fg(\"text\", plain));\n\t\t}\n\t\tconst glyph = this.theme.fg(statusColor(task.status, task.stalled), statusGlyph(task.status, task.stalled));\n\t\tconst id = this.theme.fg(\"accent\", task.id);\n\t\tconst rest = this.theme.fg(\"muted\", `${duration} ${label}`);\n\t\treturn padLine(` ${glyph} ${id} ${rest}`, width);\n\t}\n\n\tprivate countsLabel(): string {\n\t\tlet running = 0;\n\t\tfor (const task of this.tasks) if (task.status === \"running\") running++;\n\t\tconst ended = this.tasks.length - running;\n\t\tconst parts: string[] = [];\n\t\tif (running > 0) parts.push(`${running} running`);\n\t\tif (ended > 0) parts.push(`${ended} done`);\n\t\treturn parts.join(\" · \");\n\t}\n\n\t// ── detail view ────────────────────────────────────────────────────────\n\n\tprivate renderDetail(width: number): string[] {\n\t\tconst task = this.selectedTask();\n\t\tconst lines: string[] = [padLine(this.detailHeader(task), width)];\n\t\tconst height = this.detailBodyHeight();\n\t\tconst cache = task && this.tailCache?.taskId === task.id ? this.tailCache : undefined;\n\t\tif (cache?.error) {\n\t\t\tlines.push(padLine(this.theme.fg(\"error\", `Cannot read output: ${cache.error}`), width));\n\t\t\tfor (let row = 1; row < height; row++) lines.push(padLine(\"\", width));\n\t\t\treturn lines;\n\t\t}\n\t\tconst content = cache?.lines ?? [];\n\t\tconst fromEnd = this.follow ? 0 : this.tailOffsetLines;\n\t\tconst start = content.length - height - fromEnd;\n\t\tfor (let row = 0; row < height; row++) {\n\t\t\tconst line = content[start + row];\n\t\t\tlines.push(line === undefined ? padLine(\"\", width) : padLine(this.theme.fg(\"toolOutput\", line), width));\n\t\t}\n\t\treturn lines;\n\t}\n\n\tprivate detailHeader(task: BgTask | undefined): string {\n\t\tif (!task) return this.theme.fg(\"muted\", \"(no task selected)\");\n\t\tconst duration = runtimeLabel(task);\n\t\tconst exit = exitSuffix(task.exitCode, \" \");\n\t\tconst resumeLabel = keyLabel(\"tui.select.pageDown\", { keybindings: this.keybindings });\n\t\tconst paused = this.follow ? \"\" : resumeLabel ? ` — paused (${resumeLabel} to follow)` : \" — paused\";\n\t\tconst fileName = fileNameOf(task.outputPath);\n\t\tconst glyph = this.theme.fg(statusColor(task.status, task.stalled), statusGlyph(task.status, task.stalled));\n\t\tconst statusLabel = task.stalled ? \"running, waiting for input\" : task.status;\n\t\tconst header = `${task.id} · ${statusLabel}${exit} · ${duration} · ${formatSize(task.outputBytes)} · ${fileName}${paused}`;\n\t\treturn `${glyph} ${this.theme.fg(\"muted\", header)}`;\n\t}\n\n\tprivate detailBodyHeight(): number {\n\t\t// Inline component: keep the chat transcript visible above the menu.\n\t\treturn Math.min(20, Math.max(4, this.tui.terminal.rows - 8));\n\t}\n\n\t// ── shared behavior ────────────────────────────────────────────────────\n\n\tprivate footerLine(): string {\n\t\tif (this.killFeedback) return this.theme.fg(\"warning\", this.killFeedback);\n\t\tconst opts = { keybindings: this.keybindings };\n\t\tconst parts =\n\t\t\tthis.view === \"list\"\n\t\t\t\t? [\n\t\t\t\t\t\t`${keyLabel(\"tui.select.up\", opts)}/${keyLabel(\"tui.select.down\", opts)} select`,\n\t\t\t\t\t\t`${keyLabel(\"tui.select.confirm\", opts)} output`,\n\t\t\t\t\t\t`${keyLabel(\"app.backgroundTasks.kill\", opts)} kill`,\n\t\t\t\t\t\t`${keyLabel(\"tui.select.cancel\", opts)} close`,\n\t\t\t\t\t]\n\t\t\t\t: [\n\t\t\t\t\t\t`${keyLabel(\"tui.select.up\", opts)}/${keyLabel(\"tui.select.down\", opts)} scroll`,\n\t\t\t\t\t\t`${keyLabel(\"tui.select.pageUp\", opts)}/${keyLabel(\"tui.select.pageDown\", opts)} page`,\n\t\t\t\t\t\t`${keyLabel(\"app.backgroundTasks.kill\", opts)} kill`,\n\t\t\t\t\t\t`${keyLabel(\"tui.select.cancel\", opts)} back`,\n\t\t\t\t\t];\n\t\treturn this.theme.fg(\"dim\", parts.join(\" · \"));\n\t}\n\n\tprivate selectedTask(): BgTask | undefined {\n\t\treturn this.tasks.find((task) => task.id === this.selectedTaskId);\n\t}\n\n\tprivate moveSelection(offset: -1 | 1): void {\n\t\tif (this.tasks.length === 0) return;\n\t\tconst current = this.tasks.findIndex((task) => task.id === this.selectedTaskId);\n\t\tconst next = (current + offset + this.tasks.length) % this.tasks.length;\n\t\tconst task = this.tasks[next];\n\t\tif (!task) return;\n\t\tthis.selectedTaskId = task.id;\n\t\tif (next < this.listScrollTop) this.listScrollTop = next;\n\t\tif (next >= this.listScrollTop + this.listMaxVisible()) {\n\t\t\tthis.listScrollTop = next - this.listMaxVisible() + 1;\n\t\t}\n\t\tthis.resetFollow();\n\t\tthis.tui.requestRender();\n\t}\n\n\tprivate resetFollow(): void {\n\t\tthis.follow = true;\n\t\tthis.tailOffsetLines = 0;\n\t\tthis.tailCache = undefined;\n\t\tvoid this.refreshViewport();\n\t}\n\n\tprivate currentLines(): string[] {\n\t\tconst task = this.selectedTask();\n\t\tconst cache = this.tailCache;\n\t\treturn task && cache && cache.taskId === task.id ? cache.lines : [];\n\t}\n\n\tprivate maxTailOffset(): number {\n\t\treturn Math.max(0, this.currentLines().length - this.detailBodyHeight());\n\t}\n\n\tprivate killSelected(): void {\n\t\tconst task = this.selectedTask();\n\t\tif (!task) return;\n\t\tif (task.status !== \"running\") {\n\t\t\tthis.killFeedback = `${task.id} is not running`;\n\t\t\tthis.tui.requestRender();\n\t\t\treturn;\n\t\t}\n\t\tthis.host.killTask(task.id);\n\t\t// Terminal state lands on the next poll; the feedback expires with it (tick).\n\t\tthis.killFeedback = `stopping ${task.id}…`;\n\t\tthis.killFeedbackTaskId = task.id;\n\t\tthis.tui.requestRender();\n\t}\n\n\tprivate async tick(): Promise<void> {\n\t\tif (this.disposed) return;\n\t\tthis.tasks = this.host.listTasks();\n\t\tif (!this.selectedTask() && this.tasks[0]) this.selectedTaskId = this.tasks[0].id;\n\t\tthis.expireKillFeedback();\n\t\t// A pending re-read counts as a change: refreshViewport may skip this tick\n\t\t// (readBusy), and the signature alone would let that retry be dropped.\n\t\tconst needsRead = this.view === \"detail\" && this.follow && this.detailOutputChanged();\n\t\tif (!needsRead && this.renderSignature() === this.lastSignature) return; // Nothing visible changed.\n\t\tif (needsRead) await this.refreshViewport();\n\t\tthis.lastSignature = this.renderSignature();\n\t\tthis.tui.requestRender();\n\t}\n\n\t/** Drop \"stopping\" feedback once its task has settled. */\n\tprivate expireKillFeedback(): void {\n\t\tif (this.killFeedbackTaskId === undefined) return;\n\t\tconst task = this.tasks.find((candidate) => candidate.id === this.killFeedbackTaskId);\n\t\tif (!task || task.status !== \"running\") {\n\t\t\tthis.killFeedback = undefined;\n\t\t\tthis.killFeedbackTaskId = undefined;\n\t\t}\n\t}\n\n\t/** Everything the rendered output depends on; equal signatures need no redraw. */\n\tprivate renderSignature(): string {\n\t\tconst parts = [\n\t\t\tthis.view,\n\t\t\tthis.selectedTaskId ?? \"\",\n\t\t\tString(this.listScrollTop),\n\t\t\tString(this.follow),\n\t\t\tString(this.tailOffsetLines),\n\t\t\tthis.killFeedback ?? \"\",\n\t\t\tthis.tailCache\n\t\t\t\t? `${this.tailCache.taskId}:${this.tailCache.lines.length}:${this.tailCache.totalBytes}:${this.tailCache.error ?? \"\"}:${String(this.tailCache.settledRead ?? false)}`\n\t\t\t\t: \"\",\n\t\t];\n\t\tfor (const task of this.tasks) {\n\t\t\tconst duration = runtimeLabel(task);\n\t\t\tparts.push(\n\t\t\t\t`${task.id}:${task.status}:${String(task.stalled)}:${task.outputBytes}:${task.exitCode ?? \"\"}:${duration}`,\n\t\t\t);\n\t\t}\n\t\treturn parts.join(\"|\");\n\t}\n\n\t/** True when the detail viewport must re-read the output file this tick. */\n\tprivate detailOutputChanged(): boolean {\n\t\tconst task = this.selectedTask();\n\t\tif (!task) return false;\n\t\tconst cache = this.tailCache;\n\t\tif (!cache || cache.taskId !== task.id) return true;\n\t\tif (cache.error !== undefined) return true; // Keep retrying; failed reads are cheap.\n\t\tif (task.status !== \"running\") {\n\t\t\t// Terminal task: the file is final — read it once, then never again.\n\t\t\treturn cache.settledRead !== true;\n\t\t}\n\t\treturn cache.totalBytes !== task.outputBytes;\n\t}\n\n\tprivate async refreshViewport(): Promise<void> {\n\t\tif (this.readBusy) return;\n\t\tconst task = this.selectedTask();\n\t\tif (!task) return;\n\t\tthis.readBusy = true;\n\t\ttry {\n\t\t\tconst slice = await this.host.readSlice(task.outputPath, { mode: \"tail\", maxBytes: VIEW_TAIL_BYTES });\n\t\t\tif (this.disposed || this.selectedTaskId !== task.id || !this.follow) return;\n\t\t\tthis.tailCache = {\n\t\t\t\ttaskId: task.id,\n\t\t\t\tlines: toViewLines(slice.text),\n\t\t\t\ttotalBytes: slice.totalBytes,\n\t\t\t\tsettledRead: task.status !== \"running\",\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tif (this.disposed || this.selectedTaskId !== task.id) return;\n\t\t\tthis.tailCache = {\n\t\t\t\ttaskId: task.id,\n\t\t\t\tlines: [],\n\t\t\t\ttotalBytes: task.outputBytes,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t} finally {\n\t\t\tthis.readBusy = false;\n\t\t}\n\t}\n}\n\nfunction toViewLines(text: string): string[] {\n\t// Strip ANSI first: sanitize would remove the escape bytes alone, leaving\n\t// orphaned \"[31m\" fragments that strip can no longer see.\n\tconst lines = sanitizeBinaryOutput(stripTerminalSequences(text)).split(\"\\n\");\n\t// Drop the trailing empty line produced by a final newline, then bound the\n\t// window: a 128KB slice of one-byte lines must never become 128k rows.\n\twhile (lines.length > 0 && lines[lines.length - 1] === \"\") lines.pop();\n\treturn lines.slice(-MAX_VIEW_LINES);\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* background — the `<background-task>` message sent to the model.
|
|
3
|
+
*
|
|
4
|
+
* Completion and stall are one message with one discriminant, not two parallel
|
|
5
|
+
* builders: they share every element except the opening attributes, the
|
|
6
|
+
* `<error>` a completion may carry, and the `<advice>` a stall always carries.
|
|
7
|
+
*
|
|
8
|
+
* The `details` this produces is persisted (see types.ts). `kind` deliberately
|
|
9
|
+
* does NOT appear there — the stored shape keeps the `stalled?: true` flag it
|
|
10
|
+
* has always had, so transcripts written by older builds keep rendering.
|
|
11
|
+
*/
|
|
12
|
+
import type { BgNotification } from "./registry.ts";
|
|
13
|
+
import type { BgNotificationDetails } from "./types.ts";
|
|
14
|
+
export declare function buildNotificationContent(notification: BgNotification): string;
|
|
15
|
+
export declare function toNotificationDetails(notification: BgNotification): BgNotificationDetails;
|
|
16
|
+
//# sourceMappingURL=notify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../../src/extensions/background/notify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAgExD,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,cAAc,GAAG,MAAM,CA4B7E;AAED,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,cAAc,GAAG,qBAAqB,CAkBzF"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* background — the `<background-task>` message sent to the model.
|
|
3
|
+
*
|
|
4
|
+
* Completion and stall are one message with one discriminant, not two parallel
|
|
5
|
+
* builders: they share every element except the opening attributes, the
|
|
6
|
+
* `<error>` a completion may carry, and the `<advice>` a stall always carries.
|
|
7
|
+
*
|
|
8
|
+
* The `details` this produces is persisted (see types.ts). `kind` deliberately
|
|
9
|
+
* does NOT appear there — the stored shape keeps the `stalled?: true` flag it
|
|
10
|
+
* has always had, so transcripts written by older builds keep rendering.
|
|
11
|
+
*/
|
|
12
|
+
import { hasExitCode, runtimeLabel, runtimeMs } from "./task-view.js";
|
|
13
|
+
function escapeXml(text) {
|
|
14
|
+
return text
|
|
15
|
+
.replaceAll("&", "&")
|
|
16
|
+
.replaceAll("<", "<")
|
|
17
|
+
.replaceAll(">", ">")
|
|
18
|
+
.replaceAll('"', """)
|
|
19
|
+
.replaceAll("'", "'");
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Strip characters XML 1.0 forbids: C0 controls (except \t \n \r), lone
|
|
23
|
+
* surrogates (U+D800–U+DFFF), and the non-characters U+FFFE/U+FFFF.
|
|
24
|
+
* sanitizeBinaryOutput does not remove the latter two classes, so this filter
|
|
25
|
+
* is the authority for every text field in the notification XML.
|
|
26
|
+
*/
|
|
27
|
+
function filterXmlCharacters(text) {
|
|
28
|
+
let result = "";
|
|
29
|
+
for (const char of text) {
|
|
30
|
+
const code = char.codePointAt(0) ?? 0;
|
|
31
|
+
if (code === 0x09 ||
|
|
32
|
+
code === 0x0a ||
|
|
33
|
+
code === 0x0d ||
|
|
34
|
+
(code >= 0x20 && code <= 0xd7ff) ||
|
|
35
|
+
(code >= 0xe000 && code <= 0xfffd) ||
|
|
36
|
+
code >= 0x10000) {
|
|
37
|
+
result += char;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* filterXmlCharacters keeps \t \n \r and every other XML-legal codepoint, so
|
|
44
|
+
* every field built with this is valid XML 1.0 after escaping.
|
|
45
|
+
*/
|
|
46
|
+
const xmlText = (text) => escapeXml(filterXmlCharacters(text));
|
|
47
|
+
const STALL_ADVICE = "The command appears blocked waiting for interactive input. Kill it (bg action kill) and " +
|
|
48
|
+
"re-run with piped input (e.g. echo y | command) or a non-interactive flag if one exists (e.g. --yes). " +
|
|
49
|
+
"The task keeps running until then.";
|
|
50
|
+
function renderOutputTail(notification) {
|
|
51
|
+
if (notification.tailError) {
|
|
52
|
+
return [`<output-tail unavailable="${xmlText(notification.tailError)}"/>`];
|
|
53
|
+
}
|
|
54
|
+
const tail = notification.tail;
|
|
55
|
+
const attrs = [
|
|
56
|
+
`bytes="${tail?.sliceBytes ?? 0}"`,
|
|
57
|
+
`totalBytes="${tail?.totalBytes ?? notification.task.outputBytes}"`,
|
|
58
|
+
tail?.truncated ? 'truncated="true"' : "",
|
|
59
|
+
tail?.startsMidLine ? 'startsMidLine="true"' : "",
|
|
60
|
+
]
|
|
61
|
+
.filter(Boolean)
|
|
62
|
+
.join(" ");
|
|
63
|
+
const text = tail?.text ?? "";
|
|
64
|
+
const body = text.length > 0 ? xmlText(text) : "(no output)";
|
|
65
|
+
return [`<output-tail ${attrs}>`, body.trimEnd(), "</output-tail>"];
|
|
66
|
+
}
|
|
67
|
+
export function buildNotificationContent(notification) {
|
|
68
|
+
const task = notification.task;
|
|
69
|
+
// A stalled task is still running: it reports no terminal status, no exit
|
|
70
|
+
// code, and no error — only that it appears to be waiting on input.
|
|
71
|
+
const stalled = notification.kind === "stall";
|
|
72
|
+
const attrs = [
|
|
73
|
+
`id="${task.id}"`,
|
|
74
|
+
stalled ? 'status="running" waiting-for-input="true"' : `status="${task.status}"`,
|
|
75
|
+
!stalled && hasExitCode(task.exitCode) ? `exitCode="${task.exitCode}"` : "",
|
|
76
|
+
`runtime="${runtimeLabel(task)}"`,
|
|
77
|
+
]
|
|
78
|
+
.filter(Boolean)
|
|
79
|
+
.join(" ");
|
|
80
|
+
const lines = [`<background-task ${attrs}>`, `<command>${xmlText(task.command)}</command>`];
|
|
81
|
+
if (task.description) {
|
|
82
|
+
lines.push(`<description>${xmlText(task.description)}</description>`);
|
|
83
|
+
}
|
|
84
|
+
lines.push(`<output-file>${xmlText(task.outputPath)}</output-file>`);
|
|
85
|
+
if (!stalled && task.error) {
|
|
86
|
+
lines.push(`<error>${xmlText(task.error)}</error>`);
|
|
87
|
+
}
|
|
88
|
+
lines.push(...renderOutputTail(notification));
|
|
89
|
+
if (stalled) {
|
|
90
|
+
lines.push(`<advice>${STALL_ADVICE}</advice>`);
|
|
91
|
+
}
|
|
92
|
+
lines.push("</background-task>");
|
|
93
|
+
return lines.join("\n");
|
|
94
|
+
}
|
|
95
|
+
export function toNotificationDetails(notification) {
|
|
96
|
+
const task = notification.task;
|
|
97
|
+
const stalled = notification.kind === "stall";
|
|
98
|
+
return {
|
|
99
|
+
taskId: task.id,
|
|
100
|
+
command: task.command,
|
|
101
|
+
description: task.description,
|
|
102
|
+
status: stalled ? "running" : task.status,
|
|
103
|
+
stalled: stalled ? true : undefined,
|
|
104
|
+
exitCode: stalled ? undefined : task.exitCode,
|
|
105
|
+
runtimeMs: runtimeMs(task),
|
|
106
|
+
outputPath: task.outputPath,
|
|
107
|
+
totalBytes: notification.tail?.totalBytes ?? task.outputBytes,
|
|
108
|
+
tailText: notification.tail?.text ?? "",
|
|
109
|
+
tailTruncated: notification.tail?.truncated ?? false,
|
|
110
|
+
error: stalled ? undefined : task.error,
|
|
111
|
+
tailError: notification.tailError,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../../src/extensions/background/notify.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * background — the `<background-task>` message sent to the model.\n *\n * Completion and stall are one message with one discriminant, not two parallel\n * builders: they share every element except the opening attributes, the\n * `<error>` a completion may carry, and the `<advice>` a stall always carries.\n *\n * The `details` this produces is persisted (see types.ts). `kind` deliberately\n * does NOT appear there — the stored shape keeps the `stalled?: true` flag it\n * has always had, so transcripts written by older builds keep rendering.\n */\n\nimport type { BgNotification } from \"./registry.ts\";\nimport { hasExitCode, runtimeLabel, runtimeMs } from \"./task-view.ts\";\nimport type { BgNotificationDetails } from \"./types.ts\";\n\nfunction escapeXml(text: string): string {\n\treturn text\n\t\t.replaceAll(\"&\", \"&\")\n\t\t.replaceAll(\"<\", \"<\")\n\t\t.replaceAll(\">\", \">\")\n\t\t.replaceAll('\"', \""\")\n\t\t.replaceAll(\"'\", \"'\");\n}\n\n/**\n * Strip characters XML 1.0 forbids: C0 controls (except \\t \\n \\r), lone\n * surrogates (U+D800–U+DFFF), and the non-characters U+FFFE/U+FFFF.\n * sanitizeBinaryOutput does not remove the latter two classes, so this filter\n * is the authority for every text field in the notification XML.\n */\nfunction filterXmlCharacters(text: string): string {\n\tlet result = \"\";\n\tfor (const char of text) {\n\t\tconst code = char.codePointAt(0) ?? 0;\n\t\tif (\n\t\t\tcode === 0x09 ||\n\t\t\tcode === 0x0a ||\n\t\t\tcode === 0x0d ||\n\t\t\t(code >= 0x20 && code <= 0xd7ff) ||\n\t\t\t(code >= 0xe000 && code <= 0xfffd) ||\n\t\t\tcode >= 0x10000\n\t\t) {\n\t\t\tresult += char;\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * filterXmlCharacters keeps \\t \\n \\r and every other XML-legal codepoint, so\n * every field built with this is valid XML 1.0 after escaping.\n */\nconst xmlText = (text: string) => escapeXml(filterXmlCharacters(text));\n\nconst STALL_ADVICE =\n\t\"The command appears blocked waiting for interactive input. Kill it (bg action kill) and \" +\n\t\"re-run with piped input (e.g. echo y | command) or a non-interactive flag if one exists (e.g. --yes). \" +\n\t\"The task keeps running until then.\";\n\nfunction renderOutputTail(notification: BgNotification): string[] {\n\tif (notification.tailError) {\n\t\treturn [`<output-tail unavailable=\"${xmlText(notification.tailError)}\"/>`];\n\t}\n\tconst tail = notification.tail;\n\tconst attrs = [\n\t\t`bytes=\"${tail?.sliceBytes ?? 0}\"`,\n\t\t`totalBytes=\"${tail?.totalBytes ?? notification.task.outputBytes}\"`,\n\t\ttail?.truncated ? 'truncated=\"true\"' : \"\",\n\t\ttail?.startsMidLine ? 'startsMidLine=\"true\"' : \"\",\n\t]\n\t\t.filter(Boolean)\n\t\t.join(\" \");\n\tconst text = tail?.text ?? \"\";\n\tconst body = text.length > 0 ? xmlText(text) : \"(no output)\";\n\treturn [`<output-tail ${attrs}>`, body.trimEnd(), \"</output-tail>\"];\n}\n\nexport function buildNotificationContent(notification: BgNotification): string {\n\tconst task = notification.task;\n\t// A stalled task is still running: it reports no terminal status, no exit\n\t// code, and no error — only that it appears to be waiting on input.\n\tconst stalled = notification.kind === \"stall\";\n\tconst attrs = [\n\t\t`id=\"${task.id}\"`,\n\t\tstalled ? 'status=\"running\" waiting-for-input=\"true\"' : `status=\"${task.status}\"`,\n\t\t!stalled && hasExitCode(task.exitCode) ? `exitCode=\"${task.exitCode}\"` : \"\",\n\t\t`runtime=\"${runtimeLabel(task)}\"`,\n\t]\n\t\t.filter(Boolean)\n\t\t.join(\" \");\n\n\tconst lines = [`<background-task ${attrs}>`, `<command>${xmlText(task.command)}</command>`];\n\tif (task.description) {\n\t\tlines.push(`<description>${xmlText(task.description)}</description>`);\n\t}\n\tlines.push(`<output-file>${xmlText(task.outputPath)}</output-file>`);\n\tif (!stalled && task.error) {\n\t\tlines.push(`<error>${xmlText(task.error)}</error>`);\n\t}\n\tlines.push(...renderOutputTail(notification));\n\tif (stalled) {\n\t\tlines.push(`<advice>${STALL_ADVICE}</advice>`);\n\t}\n\tlines.push(\"</background-task>\");\n\treturn lines.join(\"\\n\");\n}\n\nexport function toNotificationDetails(notification: BgNotification): BgNotificationDetails {\n\tconst task = notification.task;\n\tconst stalled = notification.kind === \"stall\";\n\treturn {\n\t\ttaskId: task.id,\n\t\tcommand: task.command,\n\t\tdescription: task.description,\n\t\tstatus: stalled ? \"running\" : task.status,\n\t\tstalled: stalled ? true : undefined,\n\t\texitCode: stalled ? undefined : task.exitCode,\n\t\truntimeMs: runtimeMs(task),\n\t\toutputPath: task.outputPath,\n\t\ttotalBytes: notification.tail?.totalBytes ?? task.outputBytes,\n\t\ttailText: notification.tail?.text ?? \"\",\n\t\ttailTruncated: notification.tail?.truncated ?? false,\n\t\terror: stalled ? undefined : task.error,\n\t\ttailError: notification.tailError,\n\t};\n}\n"]}
|