pi-kot 0.1.19 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +253 -17
- package/package.json +8 -60
- package/bin/pi-kot.mjs +0 -148
- package/dist/client/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/client/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/client/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/client/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/client/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/client/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/client/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/client/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/client/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/client/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/client/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/client/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/client/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/client/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/client/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/client/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/client/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/client/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/client/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/client/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/client/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/client/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/client/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/client/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/client/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/client/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/client/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/client/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/client/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/client/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/client/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/client/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/client/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/client/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/client/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/client/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/client/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/client/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/client/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/client/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/client/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/client/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/client/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/client/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/client/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/client/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/client/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/client/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/client/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/client/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/client/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/client/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/client/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/client/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/client/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/client/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/client/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/client/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/client/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/client/assets/index-B6Hxrz4s.js +0 -448
- package/dist/client/assets/index-B6Hxrz4s.js.map +0 -1
- package/dist/client/assets/index-BPImbgFg.css +0 -1
- package/dist/client/index.html +0 -14
- package/dist/server/ask-user-question/envelope.d.ts +0 -11
- package/dist/server/ask-user-question/envelope.d.ts.map +0 -1
- package/dist/server/ask-user-question/envelope.js +0 -41
- package/dist/server/ask-user-question/envelope.js.map +0 -1
- package/dist/server/ask-user-question/plan-mode-question-tool.d.ts +0 -26
- package/dist/server/ask-user-question/plan-mode-question-tool.d.ts.map +0 -1
- package/dist/server/ask-user-question/plan-mode-question-tool.js +0 -273
- package/dist/server/ask-user-question/plan-mode-question-tool.js.map +0 -1
- package/dist/server/ask-user-question/prompt-strings.d.ts +0 -4
- package/dist/server/ask-user-question/prompt-strings.d.ts.map +0 -1
- package/dist/server/ask-user-question/prompt-strings.js +0 -18
- package/dist/server/ask-user-question/prompt-strings.js.map +0 -1
- package/dist/server/ask-user-question/registry.d.ts +0 -39
- package/dist/server/ask-user-question/registry.d.ts.map +0 -1
- package/dist/server/ask-user-question/registry.js +0 -124
- package/dist/server/ask-user-question/registry.js.map +0 -1
- package/dist/server/ask-user-question/tool.d.ts +0 -4
- package/dist/server/ask-user-question/tool.d.ts.map +0 -1
- package/dist/server/ask-user-question/tool.js +0 -68
- package/dist/server/ask-user-question/tool.js.map +0 -1
- package/dist/server/ask-user-question/types.d.ts +0 -50
- package/dist/server/ask-user-question/types.d.ts.map +0 -1
- package/dist/server/ask-user-question/types.js +0 -7
- package/dist/server/ask-user-question/types.js.map +0 -1
- package/dist/server/ask-user-question/validate.d.ts +0 -3
- package/dist/server/ask-user-question/validate.d.ts.map +0 -1
- package/dist/server/ask-user-question/validate.js +0 -67
- package/dist/server/ask-user-question/validate.js.map +0 -1
- package/dist/server/compaction-continuation.d.ts +0 -113
- package/dist/server/compaction-continuation.d.ts.map +0 -1
- package/dist/server/compaction-continuation.js +0 -65
- package/dist/server/compaction-continuation.js.map +0 -1
- package/dist/server/compaction-history.d.ts +0 -62
- package/dist/server/compaction-history.d.ts.map +0 -1
- package/dist/server/compaction-history.js +0 -180
- package/dist/server/compaction-history.js.map +0 -1
- package/dist/server/config-manager.d.ts +0 -97
- package/dist/server/config-manager.d.ts.map +0 -1
- package/dist/server/config-manager.js +0 -352
- package/dist/server/config-manager.js.map +0 -1
- package/dist/server/config.d.ts +0 -24
- package/dist/server/config.d.ts.map +0 -1
- package/dist/server/config.js +0 -67
- package/dist/server/config.js.map +0 -1
- package/dist/server/extension-manager.d.ts +0 -116
- package/dist/server/extension-manager.d.ts.map +0 -1
- package/dist/server/extension-manager.js +0 -586
- package/dist/server/extension-manager.js.map +0 -1
- package/dist/server/extension-ui-bridge.d.ts +0 -35
- package/dist/server/extension-ui-bridge.d.ts.map +0 -1
- package/dist/server/extension-ui-bridge.js +0 -228
- package/dist/server/extension-ui-bridge.js.map +0 -1
- package/dist/server/extensions-discovery.d.ts +0 -26
- package/dist/server/extensions-discovery.d.ts.map +0 -1
- package/dist/server/extensions-discovery.js +0 -107
- package/dist/server/extensions-discovery.js.map +0 -1
- package/dist/server/file-manager.d.ts +0 -79
- package/dist/server/file-manager.d.ts.map +0 -1
- package/dist/server/file-manager.js +0 -535
- package/dist/server/file-manager.js.map +0 -1
- package/dist/server/file-references.d.ts +0 -5
- package/dist/server/file-references.d.ts.map +0 -1
- package/dist/server/file-references.js +0 -249
- package/dist/server/file-references.js.map +0 -1
- package/dist/server/file-searcher.d.ts +0 -29
- package/dist/server/file-searcher.d.ts.map +0 -1
- package/dist/server/file-searcher.js +0 -318
- package/dist/server/file-searcher.js.map +0 -1
- package/dist/server/git-clone.d.ts +0 -56
- package/dist/server/git-clone.d.ts.map +0 -1
- package/dist/server/git-clone.js +0 -173
- package/dist/server/git-clone.js.map +0 -1
- package/dist/server/git-hunk-stager.d.ts +0 -56
- package/dist/server/git-hunk-stager.d.ts.map +0 -1
- package/dist/server/git-hunk-stager.js +0 -137
- package/dist/server/git-hunk-stager.js.map +0 -1
- package/dist/server/git-runner.d.ts +0 -346
- package/dist/server/git-runner.d.ts.map +0 -1
- package/dist/server/git-runner.js +0 -884
- package/dist/server/git-runner.js.map +0 -1
- package/dist/server/index.d.ts +0 -22
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js +0 -262
- package/dist/server/index.js.map +0 -1
- package/dist/server/lifecycle-notifications.d.ts +0 -28
- package/dist/server/lifecycle-notifications.d.ts.map +0 -1
- package/dist/server/lifecycle-notifications.js +0 -38
- package/dist/server/lifecycle-notifications.js.map +0 -1
- package/dist/server/mcp/config.d.ts +0 -23
- package/dist/server/mcp/config.d.ts.map +0 -1
- package/dist/server/mcp/config.js +0 -139
- package/dist/server/mcp/config.js.map +0 -1
- package/dist/server/mcp/manager.d.ts +0 -40
- package/dist/server/mcp/manager.d.ts.map +0 -1
- package/dist/server/mcp/manager.js +0 -435
- package/dist/server/mcp/manager.js.map +0 -1
- package/dist/server/mcp/stdio-trust.d.ts +0 -5
- package/dist/server/mcp/stdio-trust.d.ts.map +0 -1
- package/dist/server/mcp/stdio-trust.js +0 -78
- package/dist/server/mcp/stdio-trust.js.map +0 -1
- package/dist/server/mcp/tool-bridge.d.ts +0 -33
- package/dist/server/mcp/tool-bridge.d.ts.map +0 -1
- package/dist/server/mcp/tool-bridge.js +0 -138
- package/dist/server/mcp/tool-bridge.js.map +0 -1
- package/dist/server/orchestration/config.d.ts +0 -5
- package/dist/server/orchestration/config.d.ts.map +0 -1
- package/dist/server/orchestration/config.js +0 -35
- package/dist/server/orchestration/config.js.map +0 -1
- package/dist/server/orchestration/event-bridge.d.ts +0 -32
- package/dist/server/orchestration/event-bridge.d.ts.map +0 -1
- package/dist/server/orchestration/event-bridge.js +0 -110
- package/dist/server/orchestration/event-bridge.js.map +0 -1
- package/dist/server/orchestration/inbox.d.ts +0 -9
- package/dist/server/orchestration/inbox.d.ts.map +0 -1
- package/dist/server/orchestration/inbox.js +0 -186
- package/dist/server/orchestration/inbox.js.map +0 -1
- package/dist/server/orchestration/init.d.ts +0 -2
- package/dist/server/orchestration/init.d.ts.map +0 -1
- package/dist/server/orchestration/init.js +0 -22
- package/dist/server/orchestration/init.js.map +0 -1
- package/dist/server/orchestration/store.d.ts +0 -33
- package/dist/server/orchestration/store.d.ts.map +0 -1
- package/dist/server/orchestration/store.js +0 -331
- package/dist/server/orchestration/store.js.map +0 -1
- package/dist/server/orchestration/tools.d.ts +0 -15
- package/dist/server/orchestration/tools.d.ts.map +0 -1
- package/dist/server/orchestration/tools.js +0 -621
- package/dist/server/orchestration/tools.js.map +0 -1
- package/dist/server/orchestration/types.d.ts +0 -68
- package/dist/server/orchestration/types.d.ts.map +0 -1
- package/dist/server/orchestration/types.js +0 -43
- package/dist/server/orchestration/types.js.map +0 -1
- package/dist/server/orchestration/worker-lifecycle.d.ts +0 -15
- package/dist/server/orchestration/worker-lifecycle.d.ts.map +0 -1
- package/dist/server/orchestration/worker-lifecycle.js +0 -45
- package/dist/server/orchestration/worker-lifecycle.js.map +0 -1
- package/dist/server/project-manager.d.ts +0 -25
- package/dist/server/project-manager.d.ts.map +0 -1
- package/dist/server/project-manager.js +0 -157
- package/dist/server/project-manager.js.map +0 -1
- package/dist/server/pty-manager.d.ts +0 -54
- package/dist/server/pty-manager.d.ts.map +0 -1
- package/dist/server/pty-manager.js +0 -220
- package/dist/server/pty-manager.js.map +0 -1
- package/dist/server/routes/_schemas.d.ts +0 -16
- package/dist/server/routes/_schemas.d.ts.map +0 -1
- package/dist/server/routes/_schemas.js +0 -12
- package/dist/server/routes/_schemas.js.map +0 -1
- package/dist/server/routes/ask-user-question.d.ts +0 -3
- package/dist/server/routes/ask-user-question.d.ts.map +0 -1
- package/dist/server/routes/ask-user-question.js +0 -105
- package/dist/server/routes/ask-user-question.js.map +0 -1
- package/dist/server/routes/auth.d.ts +0 -8
- package/dist/server/routes/auth.d.ts.map +0 -1
- package/dist/server/routes/auth.js +0 -225
- package/dist/server/routes/auth.js.map +0 -1
- package/dist/server/routes/config.d.ts +0 -3
- package/dist/server/routes/config.d.ts.map +0 -1
- package/dist/server/routes/config.js +0 -568
- package/dist/server/routes/config.js.map +0 -1
- package/dist/server/routes/control.d.ts +0 -3
- package/dist/server/routes/control.d.ts.map +0 -1
- package/dist/server/routes/control.js +0 -365
- package/dist/server/routes/control.js.map +0 -1
- package/dist/server/routes/exec.d.ts +0 -3
- package/dist/server/routes/exec.d.ts.map +0 -1
- package/dist/server/routes/exec.js +0 -426
- package/dist/server/routes/exec.js.map +0 -1
- package/dist/server/routes/extension-commands.d.ts +0 -22
- package/dist/server/routes/extension-commands.d.ts.map +0 -1
- package/dist/server/routes/extension-commands.js +0 -178
- package/dist/server/routes/extension-commands.js.map +0 -1
- package/dist/server/routes/extensions.d.ts +0 -8
- package/dist/server/routes/extensions.d.ts.map +0 -1
- package/dist/server/routes/extensions.js +0 -414
- package/dist/server/routes/extensions.js.map +0 -1
- package/dist/server/routes/files.d.ts +0 -3
- package/dist/server/routes/files.d.ts.map +0 -1
- package/dist/server/routes/files.js +0 -835
- package/dist/server/routes/files.js.map +0 -1
- package/dist/server/routes/git.d.ts +0 -3
- package/dist/server/routes/git.d.ts.map +0 -1
- package/dist/server/routes/git.js +0 -1058
- package/dist/server/routes/git.js.map +0 -1
- package/dist/server/routes/mcp.d.ts +0 -3
- package/dist/server/routes/mcp.d.ts.map +0 -1
- package/dist/server/routes/mcp.js +0 -403
- package/dist/server/routes/mcp.js.map +0 -1
- package/dist/server/routes/orchestration.d.ts +0 -3
- package/dist/server/routes/orchestration.d.ts.map +0 -1
- package/dist/server/routes/orchestration.js +0 -251
- package/dist/server/routes/orchestration.js.map +0 -1
- package/dist/server/routes/projects.d.ts +0 -3
- package/dist/server/routes/projects.d.ts.map +0 -1
- package/dist/server/routes/projects.js +0 -421
- package/dist/server/routes/projects.js.map +0 -1
- package/dist/server/routes/prompt.d.ts +0 -3
- package/dist/server/routes/prompt.d.ts.map +0 -1
- package/dist/server/routes/prompt.js +0 -311
- package/dist/server/routes/prompt.js.map +0 -1
- package/dist/server/routes/session-extensions.d.ts +0 -11
- package/dist/server/routes/session-extensions.d.ts.map +0 -1
- package/dist/server/routes/session-extensions.js +0 -171
- package/dist/server/routes/session-extensions.js.map +0 -1
- package/dist/server/routes/sessions.d.ts +0 -3
- package/dist/server/routes/sessions.d.ts.map +0 -1
- package/dist/server/routes/sessions.js +0 -706
- package/dist/server/routes/sessions.js.map +0 -1
- package/dist/server/routes/skills.d.ts +0 -14
- package/dist/server/routes/skills.d.ts.map +0 -1
- package/dist/server/routes/skills.js +0 -448
- package/dist/server/routes/skills.js.map +0 -1
- package/dist/server/routes/stream.d.ts +0 -3
- package/dist/server/routes/stream.d.ts.map +0 -1
- package/dist/server/routes/stream.js +0 -112
- package/dist/server/routes/stream.js.map +0 -1
- package/dist/server/routes/terminal.d.ts +0 -28
- package/dist/server/routes/terminal.d.ts.map +0 -1
- package/dist/server/routes/terminal.js +0 -211
- package/dist/server/routes/terminal.js.map +0 -1
- package/dist/server/routes/tunnel.d.ts +0 -13
- package/dist/server/routes/tunnel.d.ts.map +0 -1
- package/dist/server/routes/tunnel.js +0 -231
- package/dist/server/routes/tunnel.js.map +0 -1
- package/dist/server/session-registry.d.ts +0 -164
- package/dist/server/session-registry.d.ts.map +0 -1
- package/dist/server/session-registry.js +0 -754
- package/dist/server/session-registry.js.map +0 -1
- package/dist/server/skill-overrides.d.ts +0 -47
- package/dist/server/skill-overrides.d.ts.map +0 -1
- package/dist/server/skill-overrides.js +0 -178
- package/dist/server/skill-overrides.js.map +0 -1
- package/dist/server/sse-bridge.d.ts +0 -31
- package/dist/server/sse-bridge.d.ts.map +0 -1
- package/dist/server/sse-bridge.js +0 -158
- package/dist/server/sse-bridge.js.map +0 -1
- package/dist/server/tool-overrides.d.ts +0 -39
- package/dist/server/tool-overrides.d.ts.map +0 -1
- package/dist/server/tool-overrides.js +0 -121
- package/dist/server/tool-overrides.js.map +0 -1
- package/dist/server/tunnel/executable-search.d.ts +0 -45
- package/dist/server/tunnel/executable-search.d.ts.map +0 -1
- package/dist/server/tunnel/executable-search.js +0 -150
- package/dist/server/tunnel/executable-search.js.map +0 -1
- package/dist/server/tunnel/install-help.d.ts +0 -19
- package/dist/server/tunnel/install-help.d.ts.map +0 -1
- package/dist/server/tunnel/install-help.js +0 -47
- package/dist/server/tunnel/install-help.js.map +0 -1
- package/dist/server/tunnel/providers/ngrok.d.ts +0 -34
- package/dist/server/tunnel/providers/ngrok.d.ts.map +0 -1
- package/dist/server/tunnel/providers/ngrok.js +0 -464
- package/dist/server/tunnel/providers/ngrok.js.map +0 -1
- package/dist/server/tunnel/registry.d.ts +0 -15
- package/dist/server/tunnel/registry.d.ts.map +0 -1
- package/dist/server/tunnel/registry.js +0 -58
- package/dist/server/tunnel/registry.js.map +0 -1
- package/dist/server/tunnel/service.d.ts +0 -15
- package/dist/server/tunnel/service.d.ts.map +0 -1
- package/dist/server/tunnel/service.js +0 -158
- package/dist/server/tunnel/service.js.map +0 -1
- package/dist/server/tunnel/types.d.ts +0 -166
- package/dist/server/tunnel/types.d.ts.map +0 -1
- package/dist/server/tunnel/types.js +0 -217
- package/dist/server/tunnel/types.js.map +0 -1
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session orchestration — types + constants.
|
|
3
|
-
*
|
|
4
|
-
* A "supervisor" session has the `orchestrate_*` tool group enabled
|
|
5
|
-
* and can spawn / observe / message / interrupt / kill / detach a set
|
|
6
|
-
* of "worker" sessions. Workers are real first-class sessions (same
|
|
7
|
-
* .jsonl on disk, same browser visibility) — the link is purely
|
|
8
|
-
* forge-side metadata in `${FORGE_DATA_DIR}/session-orchestration.json`.
|
|
9
|
-
*
|
|
10
|
-
* Topology is strict hub-and-spoke: workers don't get the orchestrate
|
|
11
|
-
* tools and have no way to enumerate or message other workers.
|
|
12
|
-
* Enforcement is by tool-surface (the tools simply aren't there),
|
|
13
|
-
* not by permission check at the registry layer.
|
|
14
|
-
*
|
|
15
|
-
* Depth is limited to 1: a worker cannot become a supervisor. Keeps
|
|
16
|
-
* the worst case bounded against fork-bomb runaway prompts.
|
|
17
|
-
*/
|
|
18
|
-
export declare const ORCHESTRATION_VERSION: 1;
|
|
19
|
-
/**
|
|
20
|
-
* Worker event types stored in orchestration history and pushed to
|
|
21
|
-
* supervisors as `orchestration-notify` custom messages.
|
|
22
|
-
*/
|
|
23
|
-
export declare const INBOX_EVENT_TYPES: readonly ["worker.ended", "worker.ask_user", "worker.execution_stopped_without_agent_end", "worker.auto_retry_failed", "worker.process_alert", "worker.deleted"];
|
|
24
|
-
export type InboxEventType = (typeof INBOX_EVENT_TYPES)[number];
|
|
25
|
-
export declare function isInboxEventType(v: unknown): v is InboxEventType;
|
|
26
|
-
export interface InboxItem {
|
|
27
|
-
id: string;
|
|
28
|
-
type: InboxEventType;
|
|
29
|
-
workerId: string;
|
|
30
|
-
occurredAt: string;
|
|
31
|
-
data: Record<string, unknown>;
|
|
32
|
-
delivered: boolean;
|
|
33
|
-
}
|
|
34
|
-
export interface SupervisorRecord {
|
|
35
|
-
enabledAt: string;
|
|
36
|
-
workerIds: string[];
|
|
37
|
-
}
|
|
38
|
-
export type WorkerLifecycleState = "idle" | "running" | "ended" | "errored" | "stopped" | "deleted" | "awaiting_question";
|
|
39
|
-
export interface WorkerRecord {
|
|
40
|
-
supervisorId: string;
|
|
41
|
-
spawnedAt: string;
|
|
42
|
-
spawnedFrom?: {
|
|
43
|
-
sessionId: string;
|
|
44
|
-
mode: "fresh" | "summary";
|
|
45
|
-
};
|
|
46
|
-
state?: WorkerLifecycleState;
|
|
47
|
-
turnOpen?: boolean;
|
|
48
|
-
lastStateAt?: string;
|
|
49
|
-
lastAgentStartAt?: string;
|
|
50
|
-
lastAgentEndAt?: string;
|
|
51
|
-
stopReason?: string | null;
|
|
52
|
-
errorMessage?: string | null;
|
|
53
|
-
}
|
|
54
|
-
export interface OrchestrationStore {
|
|
55
|
-
version: typeof ORCHESTRATION_VERSION;
|
|
56
|
-
supervisors: Record<string, SupervisorRecord>;
|
|
57
|
-
workers: Record<string, WorkerRecord>;
|
|
58
|
-
}
|
|
59
|
-
export declare function emptyStore(): OrchestrationStore;
|
|
60
|
-
export interface InboxStore {
|
|
61
|
-
version: typeof ORCHESTRATION_VERSION;
|
|
62
|
-
inboxes: Record<string, InboxItem[]>;
|
|
63
|
-
}
|
|
64
|
-
export declare function emptyInboxStore(): InboxStore;
|
|
65
|
-
export declare const MAX_INBOX_ITEMS = 200;
|
|
66
|
-
export declare const DEFAULT_MAX_WORKERS_PER_SUPERVISOR = 8;
|
|
67
|
-
export declare const MAX_DEPTH = 1;
|
|
68
|
-
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/orchestration/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,eAAO,MAAM,qBAAqB,EAAG,CAAU,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,YAC5B,cAAc,EACd,iBAAiB,EACjB,4CAA4C,EAC5C,0BAA0B,EAC1B,sBAAsB,EACtB,gBAAgB,CACR,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,cAAc,CAEhE;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,MAAM,oBAAoB,GAC5B,MAAM,GACN,SAAS,GACT,OAAO,GACP,SAAS,GACT,SAAS,GACT,SAAS,GACT,mBAAmB,CAAC;AAExB,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE;QACZ,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;KAC3B,CAAC;IACF,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,qBAAqB,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC9C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACvC;AAED,wBAAgB,UAAU,IAAI,kBAAkB,CAE/C;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,qBAAqB,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;CACtC;AAED,wBAAgB,eAAe,IAAI,UAAU,CAE5C;AAED,eAAO,MAAM,eAAe,MAAM,CAAC;AACnC,eAAO,MAAM,kCAAkC,IAAI,CAAC;AACpD,eAAO,MAAM,SAAS,IAAI,CAAC"}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session orchestration — types + constants.
|
|
3
|
-
*
|
|
4
|
-
* A "supervisor" session has the `orchestrate_*` tool group enabled
|
|
5
|
-
* and can spawn / observe / message / interrupt / kill / detach a set
|
|
6
|
-
* of "worker" sessions. Workers are real first-class sessions (same
|
|
7
|
-
* .jsonl on disk, same browser visibility) — the link is purely
|
|
8
|
-
* forge-side metadata in `${FORGE_DATA_DIR}/session-orchestration.json`.
|
|
9
|
-
*
|
|
10
|
-
* Topology is strict hub-and-spoke: workers don't get the orchestrate
|
|
11
|
-
* tools and have no way to enumerate or message other workers.
|
|
12
|
-
* Enforcement is by tool-surface (the tools simply aren't there),
|
|
13
|
-
* not by permission check at the registry layer.
|
|
14
|
-
*
|
|
15
|
-
* Depth is limited to 1: a worker cannot become a supervisor. Keeps
|
|
16
|
-
* the worst case bounded against fork-bomb runaway prompts.
|
|
17
|
-
*/
|
|
18
|
-
export const ORCHESTRATION_VERSION = 1;
|
|
19
|
-
/**
|
|
20
|
-
* Worker event types stored in orchestration history and pushed to
|
|
21
|
-
* supervisors as `orchestration-notify` custom messages.
|
|
22
|
-
*/
|
|
23
|
-
export const INBOX_EVENT_TYPES = [
|
|
24
|
-
"worker.ended",
|
|
25
|
-
"worker.ask_user",
|
|
26
|
-
"worker.execution_stopped_without_agent_end",
|
|
27
|
-
"worker.auto_retry_failed",
|
|
28
|
-
"worker.process_alert",
|
|
29
|
-
"worker.deleted",
|
|
30
|
-
];
|
|
31
|
-
export function isInboxEventType(v) {
|
|
32
|
-
return typeof v === "string" && INBOX_EVENT_TYPES.includes(v);
|
|
33
|
-
}
|
|
34
|
-
export function emptyStore() {
|
|
35
|
-
return { version: ORCHESTRATION_VERSION, supervisors: {}, workers: {} };
|
|
36
|
-
}
|
|
37
|
-
export function emptyInboxStore() {
|
|
38
|
-
return { version: ORCHESTRATION_VERSION, inboxes: {} };
|
|
39
|
-
}
|
|
40
|
-
export const MAX_INBOX_ITEMS = 200;
|
|
41
|
-
export const DEFAULT_MAX_WORKERS_PER_SUPERVISOR = 8;
|
|
42
|
-
export const MAX_DEPTH = 1;
|
|
43
|
-
//# sourceMappingURL=types.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/orchestration/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAU,CAAC;AAEhD;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,cAAc;IACd,iBAAiB;IACjB,4CAA4C;IAC5C,0BAA0B;IAC1B,sBAAsB;IACtB,gBAAgB;CACR,CAAC;AAIX,MAAM,UAAU,gBAAgB,CAAC,CAAU;IACzC,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAK,iBAAuC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvF,CAAC;AA+CD,MAAM,UAAU,UAAU;IACxB,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AAC1E,CAAC;AAOD,MAAM,UAAU,eAAe;IAC7B,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AACnC,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export type WorkerArchiveStatus = "archived" | "not_found";
|
|
2
|
-
export interface KillWorkerResult {
|
|
3
|
-
wasLive: boolean;
|
|
4
|
-
archiveStatus: WorkerArchiveStatus;
|
|
5
|
-
}
|
|
6
|
-
export interface CleanupSupervisorWorkersResult {
|
|
7
|
-
workerIds: string[];
|
|
8
|
-
results: Record<string, KillWorkerResult>;
|
|
9
|
-
}
|
|
10
|
-
export declare function killWorkerAndArchive(args: {
|
|
11
|
-
supervisorId: string;
|
|
12
|
-
workerId: string;
|
|
13
|
-
}): Promise<KillWorkerResult>;
|
|
14
|
-
export declare function cleanupWorkersForDeletedSupervisor(supervisorId: string): Promise<CleanupSupervisorWorkersResult>;
|
|
15
|
-
//# sourceMappingURL=worker-lifecycle.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"worker-lifecycle.d.ts","sourceRoot":"","sources":["../../src/orchestration/worker-lifecycle.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,WAAW,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,mBAAmB,CAAC;CACpC;AAED,MAAM,WAAW,8BAA8B;IAC7C,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC3C;AAuBD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAe5B;AAED,wBAAsB,kCAAkC,CACtD,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,8BAA8B,CAAC,CAQzC"}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { disposeSession, getSession } from "../session-registry.js";
|
|
2
|
-
import { bridgeWorkerDeleted } from "./event-bridge.js";
|
|
3
|
-
import { disableSupervisor, getWorkerIds, unregisterWorker } from "./store.js";
|
|
4
|
-
function notifySupervisorSessionListChanged(args) {
|
|
5
|
-
const supervisor = getSession(args.supervisorId);
|
|
6
|
-
if (supervisor === undefined)
|
|
7
|
-
return;
|
|
8
|
-
for (const client of supervisor.clients) {
|
|
9
|
-
try {
|
|
10
|
-
client.send({
|
|
11
|
-
type: "session_list_changed",
|
|
12
|
-
reason: args.reason,
|
|
13
|
-
projectId: supervisor.projectId,
|
|
14
|
-
sessionId: args.workerId,
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
18
|
-
// SSE client already dropped
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
export async function killWorkerAndArchive(args) {
|
|
23
|
-
const wasLive = await disposeSession(args.workerId);
|
|
24
|
-
await bridgeWorkerDeleted(args.workerId, { wasLive, reason: "killed" }).catch(() => undefined);
|
|
25
|
-
await unregisterWorker(args.workerId);
|
|
26
|
-
notifySupervisorSessionListChanged({
|
|
27
|
-
supervisorId: args.supervisorId,
|
|
28
|
-
workerId: args.workerId,
|
|
29
|
-
reason: "kill_worker",
|
|
30
|
-
});
|
|
31
|
-
return {
|
|
32
|
-
wasLive,
|
|
33
|
-
archiveStatus: "archived",
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
export async function cleanupWorkersForDeletedSupervisor(supervisorId) {
|
|
37
|
-
const workerIds = await getWorkerIds(supervisorId);
|
|
38
|
-
const results = {};
|
|
39
|
-
for (const workerId of workerIds) {
|
|
40
|
-
results[workerId] = await killWorkerAndArchive({ supervisorId, workerId });
|
|
41
|
-
}
|
|
42
|
-
await disableSupervisor(supervisorId);
|
|
43
|
-
return { workerIds, results };
|
|
44
|
-
}
|
|
45
|
-
//# sourceMappingURL=worker-lifecycle.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"worker-lifecycle.js","sourceRoot":"","sources":["../../src/orchestration/worker-lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,cAAc,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAc/E,SAAS,kCAAkC,CAAC,IAI3C;IACC,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACjD,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO;IACrC,KAAK,MAAM,MAAM,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,sBAAsB;gBAC5B,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,SAAS,EAAE,UAAU,CAAC,SAAS;gBAC/B,SAAS,EAAE,IAAI,CAAC,QAAQ;aACzB,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,6BAA6B;QAC/B,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAG1C;IACC,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpD,MAAM,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAC3E,GAAG,EAAE,CAAC,SAAS,CAChB,CAAC;IACF,MAAM,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtC,kCAAkC,CAAC;QACjC,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,MAAM,EAAE,aAAa;KACtB,CAAC,CAAC;IACH,OAAO;QACL,OAAO;QACP,aAAa,EAAE,UAAU;KAC1B,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kCAAkC,CACtD,YAAoB;IAEpB,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,YAAY,CAAC,CAAC;IACnD,MAAM,OAAO,GAAqC,EAAE,CAAC;IACrD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,MAAM,oBAAoB,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,MAAM,iBAAiB,CAAC,YAAY,CAAC,CAAC;IACtC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;AAChC,CAAC"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export interface Project {
|
|
2
|
-
id: string;
|
|
3
|
-
name: string;
|
|
4
|
-
path: string;
|
|
5
|
-
createdAt: string;
|
|
6
|
-
}
|
|
7
|
-
export declare class ProjectNotFoundError extends Error {
|
|
8
|
-
constructor(id: string);
|
|
9
|
-
}
|
|
10
|
-
export declare class InvalidNameError extends Error {
|
|
11
|
-
constructor(msg?: string);
|
|
12
|
-
}
|
|
13
|
-
export declare class DuplicatePathError extends Error {
|
|
14
|
-
constructor(path: string);
|
|
15
|
-
}
|
|
16
|
-
export declare function readProjects(): Promise<Project[]>;
|
|
17
|
-
export declare function listProjects(): Promise<Project[]>;
|
|
18
|
-
export declare function getProject(id: string): Promise<Project | undefined>;
|
|
19
|
-
export declare function createProject(name: string, path: string): Promise<Project>;
|
|
20
|
-
export declare function updateProject(id: string, updates: {
|
|
21
|
-
name?: string;
|
|
22
|
-
path?: string;
|
|
23
|
-
}): Promise<Project>;
|
|
24
|
-
export declare function deleteProject(id: string): Promise<void>;
|
|
25
|
-
//# sourceMappingURL=project-manager.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"project-manager.d.ts","sourceRoot":"","sources":["../src/project-manager.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,EAAE,EAAE,MAAM,EAGrB;CACF;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,YAAY,GAAG,SAAyB,EAGvC;CACF;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,IAAI,EAAE,MAAM,EAGvB;CACF;AA2BD,wBAAsB,YAAY,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAUvD;AAeD,wBAAsB,YAAY,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAIvD;AAED,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAGzE;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,CA6ClB;AAED,wBAAsB,aAAa,CACjC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACxC,OAAO,CAAC,OAAO,CAAC,CA0BlB;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ7D"}
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import { readFile, rename, unlink, writeFile, mkdir, stat } from "node:fs/promises";
|
|
2
|
-
import { join, resolve } from "node:path";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import { randomUUID } from "node:crypto";
|
|
5
|
-
import { config } from "./config.js";
|
|
6
|
-
export class ProjectNotFoundError extends Error {
|
|
7
|
-
constructor(id) {
|
|
8
|
-
super(`project not found: ${id}`);
|
|
9
|
-
this.name = "ProjectNotFoundError";
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
export class InvalidNameError extends Error {
|
|
13
|
-
constructor(msg = "invalid project name") {
|
|
14
|
-
super(msg);
|
|
15
|
-
this.name = "InvalidNameError";
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
export class DuplicatePathError extends Error {
|
|
19
|
-
constructor(path) {
|
|
20
|
-
super(`a project already points at: ${path}`);
|
|
21
|
-
this.name = "DuplicatePathError";
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
const PROJECTS_FILE = () => join(config.forgeDataDir, "projects.json");
|
|
25
|
-
async function ensureDir(dir) {
|
|
26
|
-
await mkdir(dir, { recursive: true });
|
|
27
|
-
}
|
|
28
|
-
// Simple per-process lock for read-modify-write on projects.json
|
|
29
|
-
let projectsLock = Promise.resolve();
|
|
30
|
-
function withProjectsLock(fn) {
|
|
31
|
-
const next = projectsLock.then(fn, fn);
|
|
32
|
-
projectsLock = next.catch(() => undefined);
|
|
33
|
-
return next;
|
|
34
|
-
}
|
|
35
|
-
function isProject(v) {
|
|
36
|
-
if (typeof v !== "object" || v === null)
|
|
37
|
-
return false;
|
|
38
|
-
const r = v;
|
|
39
|
-
return (typeof r.id === "string" &&
|
|
40
|
-
typeof r.name === "string" &&
|
|
41
|
-
typeof r.path === "string" &&
|
|
42
|
-
typeof r.createdAt === "string");
|
|
43
|
-
}
|
|
44
|
-
export async function readProjects() {
|
|
45
|
-
try {
|
|
46
|
-
const raw = await readFile(PROJECTS_FILE(), "utf8");
|
|
47
|
-
const parsed = JSON.parse(raw);
|
|
48
|
-
if (!Array.isArray(parsed))
|
|
49
|
-
return [];
|
|
50
|
-
return parsed.filter(isProject);
|
|
51
|
-
}
|
|
52
|
-
catch (err) {
|
|
53
|
-
if (err.code === "ENOENT")
|
|
54
|
-
return [];
|
|
55
|
-
throw err;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
async function writeProjects(projects) {
|
|
59
|
-
await ensureDir(config.forgeDataDir);
|
|
60
|
-
const target = PROJECTS_FILE();
|
|
61
|
-
const tmp = `${target}.${randomUUID()}.tmp`;
|
|
62
|
-
await writeFile(tmp, JSON.stringify(projects, null, 2), "utf8");
|
|
63
|
-
try {
|
|
64
|
-
await rename(tmp, target);
|
|
65
|
-
}
|
|
66
|
-
catch (err) {
|
|
67
|
-
await unlink(tmp).catch(() => undefined);
|
|
68
|
-
throw err;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
export async function listProjects() {
|
|
72
|
-
return withProjectsLock(async () => {
|
|
73
|
-
return readProjects();
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
export async function getProject(id) {
|
|
77
|
-
const projects = await readProjects();
|
|
78
|
-
return projects.find((p) => p.id === id);
|
|
79
|
-
}
|
|
80
|
-
export async function createProject(name, path) {
|
|
81
|
-
const trimmed = name.trim();
|
|
82
|
-
if (trimmed.length === 0)
|
|
83
|
-
throw new InvalidNameError("project name cannot be empty");
|
|
84
|
-
// Expand ~/ to home directory
|
|
85
|
-
const expanded = path.startsWith("~/") ? join(homedir(), path.slice(2)) : path;
|
|
86
|
-
const resolvedPath = resolve(expanded);
|
|
87
|
-
return withProjectsLock(async () => {
|
|
88
|
-
const projects = await readProjects();
|
|
89
|
-
// Check duplicate path
|
|
90
|
-
for (const p of projects) {
|
|
91
|
-
if (resolve(p.path) === resolvedPath) {
|
|
92
|
-
throw new DuplicatePathError(resolvedPath);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
// Verify path exists and is a directory (warn if not, but still allow)
|
|
96
|
-
try {
|
|
97
|
-
const st = await stat(resolvedPath);
|
|
98
|
-
if (!st.isDirectory()) {
|
|
99
|
-
throw new InvalidNameError(`Path exists but is not a directory: ${resolvedPath}`);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
catch (err) {
|
|
103
|
-
if (err.code === "ENOENT") {
|
|
104
|
-
throw new InvalidNameError(`Directory does not exist: ${resolvedPath}. Create it first or choose an existing folder.`);
|
|
105
|
-
}
|
|
106
|
-
if (err instanceof InvalidNameError)
|
|
107
|
-
throw err;
|
|
108
|
-
throw err;
|
|
109
|
-
}
|
|
110
|
-
const project = {
|
|
111
|
-
id: randomUUID(),
|
|
112
|
-
name: trimmed,
|
|
113
|
-
path: resolvedPath,
|
|
114
|
-
createdAt: new Date().toISOString(),
|
|
115
|
-
};
|
|
116
|
-
projects.push(project);
|
|
117
|
-
await writeProjects(projects);
|
|
118
|
-
return project;
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
export async function updateProject(id, updates) {
|
|
122
|
-
return withProjectsLock(async () => {
|
|
123
|
-
const projects = await readProjects();
|
|
124
|
-
const idx = projects.findIndex((p) => p.id === id);
|
|
125
|
-
if (idx === -1)
|
|
126
|
-
throw new ProjectNotFoundError(id);
|
|
127
|
-
if (updates.name !== undefined) {
|
|
128
|
-
const trimmed = updates.name.trim();
|
|
129
|
-
if (trimmed.length === 0)
|
|
130
|
-
throw new InvalidNameError();
|
|
131
|
-
projects[idx].name = trimmed;
|
|
132
|
-
}
|
|
133
|
-
if (updates.path !== undefined) {
|
|
134
|
-
const resolvedPath = resolve(updates.path);
|
|
135
|
-
// Check duplicate
|
|
136
|
-
for (let i = 0; i < projects.length; i++) {
|
|
137
|
-
if (i !== idx && resolve(projects[i].path) === resolvedPath) {
|
|
138
|
-
throw new DuplicatePathError(resolvedPath);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
projects[idx].path = resolvedPath;
|
|
142
|
-
}
|
|
143
|
-
await writeProjects(projects);
|
|
144
|
-
return projects[idx];
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
export async function deleteProject(id) {
|
|
148
|
-
return withProjectsLock(async () => {
|
|
149
|
-
const projects = await readProjects();
|
|
150
|
-
const idx = projects.findIndex((p) => p.id === id);
|
|
151
|
-
if (idx === -1)
|
|
152
|
-
throw new ProjectNotFoundError(id);
|
|
153
|
-
projects.splice(idx, 1);
|
|
154
|
-
await writeProjects(projects);
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
//# sourceMappingURL=project-manager.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"project-manager.js","sourceRoot":"","sources":["../src/project-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PTY Manager — node-pty lifecycle with detach/reattach support.
|
|
3
|
-
*
|
|
4
|
-
* Each terminal tab opens its own WebSocket which spawns a dedicated
|
|
5
|
-
* PTY here — never share PTY instances across distinct tabs.
|
|
6
|
-
*
|
|
7
|
-
* **Survival across panel toggle / page refresh.** On WS close the
|
|
8
|
-
* PTY is NOT killed; it is detached and held for {@link IDLE_REAP_MS}
|
|
9
|
-
* so re-opening the panel (or a page reload) can reattach via `tabId`
|
|
10
|
-
* and pick up where the user left off. A rolling output buffer
|
|
11
|
-
* ({@link OUTPUT_BUFFER_BYTES}) is replayed on reattach so xterm shows
|
|
12
|
-
* recent output instead of just a fresh prompt.
|
|
13
|
-
*
|
|
14
|
-
* After {@link IDLE_REAP_MS} with no socket attached, the PTY is
|
|
15
|
-
* killed. This is the safety valve.
|
|
16
|
-
*
|
|
17
|
-
* Architecture for PTY session management.
|
|
18
|
-
*/
|
|
19
|
-
import * as nodePty from "node-pty";
|
|
20
|
-
export interface SpawnOptions {
|
|
21
|
-
shell?: string;
|
|
22
|
-
cwd: string;
|
|
23
|
-
env?: NodeJS.ProcessEnv;
|
|
24
|
-
cols?: number;
|
|
25
|
-
rows?: number;
|
|
26
|
-
/** Stable client-side identifier for this terminal tab. */
|
|
27
|
-
tabId: string;
|
|
28
|
-
/** Project id this PTY is scoped to. */
|
|
29
|
-
projectId: string;
|
|
30
|
-
}
|
|
31
|
-
export interface ManagedPty {
|
|
32
|
-
ptyId: string;
|
|
33
|
-
tabId: string;
|
|
34
|
-
projectId: string;
|
|
35
|
-
process: nodePty.IPty;
|
|
36
|
-
cwd: string;
|
|
37
|
-
}
|
|
38
|
-
export declare function findPtyByTabId(tabId: string, projectId: string): ManagedPty | undefined;
|
|
39
|
-
export declare function spawnPty(opts: SpawnOptions): ManagedPty;
|
|
40
|
-
/**
|
|
41
|
-
* Attach a data sink to a managed PTY.
|
|
42
|
-
* Replays the rolling output buffer, then forwards every subsequent
|
|
43
|
-
* `onData` chunk. Returns a detach function the caller MUST invoke
|
|
44
|
-
* on socket close.
|
|
45
|
-
*
|
|
46
|
-
* Cancels any pending idle reaper — the PTY is back in active use.
|
|
47
|
-
*/
|
|
48
|
-
export declare function attachSink(ptyId: string, onData: (chunk: Buffer) => void, replayBytes?: number, closeActiveSocket?: () => void): (() => void) | undefined;
|
|
49
|
-
export declare function getPty(ptyId: string): ManagedPty | undefined;
|
|
50
|
-
export declare function killPty(ptyId: string): boolean;
|
|
51
|
-
export declare function ptyCount(): number;
|
|
52
|
-
export declare function disposeAllPtys(): void;
|
|
53
|
-
export declare function installPtyExitHandler(): void;
|
|
54
|
-
//# sourceMappingURL=pty-manager.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pty-manager.d.ts","sourceRoot":"","sources":["../src/pty-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,OAAO,MAAM,UAAU,CAAC;AAGpC,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAqBD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAOvF;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,UAAU,CA8CvD;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EAC/B,WAAW,GAAE,MAA4B,EACzC,iBAAiB,CAAC,EAAE,MAAM,IAAI,GAC7B,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAgE1B;AAYD,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAE5D;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CA0B9C;AAED,wBAAgB,QAAQ,IAAI,MAAM,CAEjC;AAED,wBAAgB,cAAc,IAAI,IAAI,CAIrC;AAGD,wBAAgB,qBAAqB,IAAI,IAAI,CAa5C"}
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PTY Manager — node-pty lifecycle with detach/reattach support.
|
|
3
|
-
*
|
|
4
|
-
* Each terminal tab opens its own WebSocket which spawns a dedicated
|
|
5
|
-
* PTY here — never share PTY instances across distinct tabs.
|
|
6
|
-
*
|
|
7
|
-
* **Survival across panel toggle / page refresh.** On WS close the
|
|
8
|
-
* PTY is NOT killed; it is detached and held for {@link IDLE_REAP_MS}
|
|
9
|
-
* so re-opening the panel (or a page reload) can reattach via `tabId`
|
|
10
|
-
* and pick up where the user left off. A rolling output buffer
|
|
11
|
-
* ({@link OUTPUT_BUFFER_BYTES}) is replayed on reattach so xterm shows
|
|
12
|
-
* recent output instead of just a fresh prompt.
|
|
13
|
-
*
|
|
14
|
-
* After {@link IDLE_REAP_MS} with no socket attached, the PTY is
|
|
15
|
-
* killed. This is the safety valve.
|
|
16
|
-
*
|
|
17
|
-
* Architecture for PTY session management.
|
|
18
|
-
*/
|
|
19
|
-
import { randomUUID } from "node:crypto";
|
|
20
|
-
import * as nodePty from "node-pty";
|
|
21
|
-
const OUTPUT_BUFFER_BYTES = 256 * 1024; // 256 KB
|
|
22
|
-
const IDLE_REAP_MS = 10 * 60 * 1000; // 10 minutes
|
|
23
|
-
const SIGKILL_GRACE_MS = 2_000;
|
|
24
|
-
const ptys = new Map();
|
|
25
|
-
function defaultShell() {
|
|
26
|
-
return process.env.SHELL ?? "/bin/sh";
|
|
27
|
-
}
|
|
28
|
-
export function findPtyByTabId(tabId, projectId) {
|
|
29
|
-
for (const entry of ptys.values()) {
|
|
30
|
-
if (entry.managed.tabId !== tabId)
|
|
31
|
-
continue;
|
|
32
|
-
if (entry.managed.projectId !== projectId)
|
|
33
|
-
continue;
|
|
34
|
-
return entry.managed;
|
|
35
|
-
}
|
|
36
|
-
return undefined;
|
|
37
|
-
}
|
|
38
|
-
export function spawnPty(opts) {
|
|
39
|
-
const shell = opts.shell ?? defaultShell();
|
|
40
|
-
const cols = opts.cols ?? 80;
|
|
41
|
-
const rows = opts.rows ?? 24;
|
|
42
|
-
const env = opts.env ?? process.env;
|
|
43
|
-
const proc = nodePty.spawn(shell, [], {
|
|
44
|
-
name: "xterm-color",
|
|
45
|
-
cols,
|
|
46
|
-
rows,
|
|
47
|
-
cwd: opts.cwd,
|
|
48
|
-
env: { ...env, TERM: "xterm-256color" },
|
|
49
|
-
});
|
|
50
|
-
const ptyId = randomUUID();
|
|
51
|
-
const managed = {
|
|
52
|
-
ptyId,
|
|
53
|
-
tabId: opts.tabId,
|
|
54
|
-
projectId: opts.projectId,
|
|
55
|
-
process: proc,
|
|
56
|
-
cwd: opts.cwd,
|
|
57
|
-
};
|
|
58
|
-
const entry = {
|
|
59
|
-
managed,
|
|
60
|
-
dataDisposable: undefined,
|
|
61
|
-
closeActiveSocket: undefined,
|
|
62
|
-
idleTimer: undefined,
|
|
63
|
-
buffer: [],
|
|
64
|
-
bufferBytes: 0,
|
|
65
|
-
};
|
|
66
|
-
ptys.set(ptyId, entry);
|
|
67
|
-
// Always-on output capture — accumulates rolling buffer even
|
|
68
|
-
// when no socket is attached, so reattach replays recent output.
|
|
69
|
-
const captureDisposable = proc.onData((chunk) => {
|
|
70
|
-
appendToBuffer(entry, chunk);
|
|
71
|
-
});
|
|
72
|
-
proc.onExit(() => {
|
|
73
|
-
captureDisposable.dispose();
|
|
74
|
-
ptys.delete(ptyId);
|
|
75
|
-
if (entry.idleTimer !== undefined)
|
|
76
|
-
clearTimeout(entry.idleTimer);
|
|
77
|
-
});
|
|
78
|
-
return managed;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Attach a data sink to a managed PTY.
|
|
82
|
-
* Replays the rolling output buffer, then forwards every subsequent
|
|
83
|
-
* `onData` chunk. Returns a detach function the caller MUST invoke
|
|
84
|
-
* on socket close.
|
|
85
|
-
*
|
|
86
|
-
* Cancels any pending idle reaper — the PTY is back in active use.
|
|
87
|
-
*/
|
|
88
|
-
export function attachSink(ptyId, onData, replayBytes = OUTPUT_BUFFER_BYTES, closeActiveSocket) {
|
|
89
|
-
const entry = ptys.get(ptyId);
|
|
90
|
-
if (entry === undefined)
|
|
91
|
-
return undefined;
|
|
92
|
-
if (entry.idleTimer !== undefined) {
|
|
93
|
-
clearTimeout(entry.idleTimer);
|
|
94
|
-
entry.idleTimer = undefined;
|
|
95
|
-
}
|
|
96
|
-
// Dispose previous data sink
|
|
97
|
-
if (entry.dataDisposable !== undefined) {
|
|
98
|
-
entry.dataDisposable.dispose();
|
|
99
|
-
entry.dataDisposable = undefined;
|
|
100
|
-
}
|
|
101
|
-
// Close previously attached socket, if any
|
|
102
|
-
if (entry.closeActiveSocket !== undefined) {
|
|
103
|
-
try {
|
|
104
|
-
entry.closeActiveSocket();
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
// already gone
|
|
108
|
-
}
|
|
109
|
-
entry.closeActiveSocket = undefined;
|
|
110
|
-
}
|
|
111
|
-
entry.closeActiveSocket = closeActiveSocket;
|
|
112
|
-
// Replay output buffer
|
|
113
|
-
if (replayBytes > 0 && entry.bufferBytes > 0) {
|
|
114
|
-
let remaining = Math.min(replayBytes, entry.bufferBytes);
|
|
115
|
-
const tail = [];
|
|
116
|
-
for (let i = entry.buffer.length - 1; i >= 0 && remaining > 0; i--) {
|
|
117
|
-
const chunk = entry.buffer[i];
|
|
118
|
-
if (chunk.byteLength <= remaining) {
|
|
119
|
-
tail.unshift(chunk);
|
|
120
|
-
remaining -= chunk.byteLength;
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
tail.unshift(chunk.subarray(chunk.byteLength - remaining));
|
|
124
|
-
remaining = 0;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
for (const chunk of tail)
|
|
128
|
-
onData(chunk);
|
|
129
|
-
}
|
|
130
|
-
const live = entry.managed.process.onData((chunk) => {
|
|
131
|
-
onData(Buffer.from(chunk, "utf8"));
|
|
132
|
-
});
|
|
133
|
-
entry.dataDisposable = live;
|
|
134
|
-
return () => {
|
|
135
|
-
if (entry.dataDisposable === live) {
|
|
136
|
-
live.dispose();
|
|
137
|
-
entry.dataDisposable = undefined;
|
|
138
|
-
if (entry.closeActiveSocket === closeActiveSocket) {
|
|
139
|
-
entry.closeActiveSocket = undefined;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
// Start idle reaper
|
|
143
|
-
if (entry.idleTimer === undefined && ptys.has(ptyId)) {
|
|
144
|
-
entry.idleTimer = setTimeout(() => {
|
|
145
|
-
entry.idleTimer = undefined;
|
|
146
|
-
killPty(ptyId);
|
|
147
|
-
}, IDLE_REAP_MS);
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
function appendToBuffer(entry, chunk) {
|
|
152
|
-
const buf = Buffer.from(chunk, "utf8");
|
|
153
|
-
entry.buffer.push(buf);
|
|
154
|
-
entry.bufferBytes += buf.byteLength;
|
|
155
|
-
while (entry.bufferBytes > OUTPUT_BUFFER_BYTES && entry.buffer.length > 0) {
|
|
156
|
-
const head = entry.buffer.shift();
|
|
157
|
-
entry.bufferBytes -= head.byteLength;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
export function getPty(ptyId) {
|
|
161
|
-
return ptys.get(ptyId)?.managed;
|
|
162
|
-
}
|
|
163
|
-
export function killPty(ptyId) {
|
|
164
|
-
const entry = ptys.get(ptyId);
|
|
165
|
-
if (entry === undefined)
|
|
166
|
-
return false;
|
|
167
|
-
ptys.delete(ptyId);
|
|
168
|
-
if (entry.idleTimer !== undefined)
|
|
169
|
-
clearTimeout(entry.idleTimer);
|
|
170
|
-
if (entry.dataDisposable !== undefined)
|
|
171
|
-
entry.dataDisposable.dispose();
|
|
172
|
-
let killed = false;
|
|
173
|
-
const exitDisposable = entry.managed.process.onExit(() => {
|
|
174
|
-
killed = true;
|
|
175
|
-
});
|
|
176
|
-
try {
|
|
177
|
-
entry.managed.process.kill("SIGTERM");
|
|
178
|
-
}
|
|
179
|
-
catch {
|
|
180
|
-
return true;
|
|
181
|
-
}
|
|
182
|
-
setTimeout(() => {
|
|
183
|
-
exitDisposable.dispose();
|
|
184
|
-
if (killed)
|
|
185
|
-
return;
|
|
186
|
-
try {
|
|
187
|
-
entry.managed.process.kill("SIGKILL");
|
|
188
|
-
}
|
|
189
|
-
catch {
|
|
190
|
-
// already exited
|
|
191
|
-
}
|
|
192
|
-
}, SIGKILL_GRACE_MS).unref();
|
|
193
|
-
return true;
|
|
194
|
-
}
|
|
195
|
-
export function ptyCount() {
|
|
196
|
-
return ptys.size;
|
|
197
|
-
}
|
|
198
|
-
export function disposeAllPtys() {
|
|
199
|
-
for (const ptyId of Array.from(ptys.keys())) {
|
|
200
|
-
killPty(ptyId);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
let exitHandlerInstalled = false;
|
|
204
|
-
export function installPtyExitHandler() {
|
|
205
|
-
if (exitHandlerInstalled)
|
|
206
|
-
return;
|
|
207
|
-
exitHandlerInstalled = true;
|
|
208
|
-
process.on("exit", () => {
|
|
209
|
-
for (const entry of ptys.values()) {
|
|
210
|
-
try {
|
|
211
|
-
entry.managed.process.kill("SIGTERM");
|
|
212
|
-
}
|
|
213
|
-
catch {
|
|
214
|
-
// already gone
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
ptys.clear();
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
//# sourceMappingURL=pty-manager.js.map
|