@youweichen/pi-harness 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +74 -2
- package/bin/pi-harness.mjs +1819 -0
- package/deploy/com.youweichen.pi-harness.plist +48 -0
- package/deploy/nginx-subpath.conf +88 -0
- package/deploy/pi-harness-task.xml +71 -0
- package/deploy/pi-harness.service +31 -0
- package/dist/server/agent-service.js +3051 -0
- package/dist/server/app-version.js +19 -0
- package/dist/server/attachments.js +526 -0
- package/dist/server/auth-file.js +61 -0
- package/dist/server/bg-servers.js +154 -0
- package/dist/server/client-eviction.js +19 -0
- package/dist/server/client-id.js +9 -0
- package/dist/server/client-state.js +202 -0
- package/dist/server/codemode-image-routes.js +36 -0
- package/dist/server/codemode-presentation.js +19 -0
- package/dist/server/component-updates.js +135 -0
- package/dist/server/context-breakdown.js +56 -0
- package/dist/server/control-socket.js +177 -0
- package/dist/server/conversation.js +65 -0
- package/dist/server/dir-browser.js +77 -0
- package/dist/server/editor-snapshot.js +38 -0
- package/dist/server/ensure-bash.js +80 -0
- package/dist/server/extension-display.js +23 -0
- package/dist/server/extensions-catalog.js +64 -0
- package/dist/server/extensions-model.js +46 -0
- package/dist/server/extensions-routes.js +255 -0
- package/dist/server/extensions-worker.js +187 -0
- package/dist/server/files-service.js +795 -0
- package/dist/server/index.js +1029 -0
- package/dist/server/markdown-images.js +42 -0
- package/dist/server/model-admin.js +801 -0
- package/dist/server/model-config-merge.js +32 -0
- package/dist/server/native-mcp-config.js +103 -0
- package/dist/server/native-mcp-presentation.js +12 -0
- package/dist/server/native-prompt-template.js +12 -0
- package/dist/server/native-tools.js +32 -0
- package/dist/server/node-sources.js +142 -0
- package/dist/server/node-workbench.js +668 -0
- package/dist/server/origin-policy.js +50 -0
- package/dist/server/patch-node-pty.js +96 -0
- package/dist/server/pi-environment.js +203 -0
- package/dist/server/plan/extension.js +74 -0
- package/dist/server/plan/progress.js +90 -0
- package/dist/server/plan/settings.js +41 -0
- package/dist/server/plan/state.js +113 -0
- package/dist/server/plugin-facilities.js +304 -0
- package/dist/server/plugin-updater.js +245 -0
- package/dist/server/plugins.js +712 -0
- package/dist/server/private-file.js +28 -0
- package/dist/server/process-utils.js +112 -0
- package/dist/server/prompt-delivery.js +80 -0
- package/dist/server/protocol-version.js +11 -0
- package/dist/server/protocol.js +6 -0
- package/dist/server/provider-auth.js +99 -0
- package/dist/server/query-cache.js +45 -0
- package/dist/server/recovery-state.js +37 -0
- package/dist/server/scm.js +459 -0
- package/dist/server/security-headers.js +24 -0
- package/dist/server/serialize.js +254 -0
- package/dist/server/session-file-read.js +225 -0
- package/dist/server/session-record-worker.js +21 -0
- package/dist/server/session-reload.js +13 -0
- package/dist/server/session-tree-controller.js +250 -0
- package/dist/server/session-tree.js +191 -0
- package/dist/server/settings-service.js +53 -0
- package/dist/server/skills-service.js +87 -0
- package/dist/server/slash-commands.js +280 -0
- package/dist/server/sqlite-preview.js +58 -0
- package/dist/server/sqlite-query.js +67 -0
- package/dist/server/sqlite-worker.js +12 -0
- package/dist/server/system-prompt-files.js +158 -0
- package/dist/server/system-prompt-routes.js +40 -0
- package/dist/server/system-prompt-view.js +49 -0
- package/dist/server/task-progress.js +233 -0
- package/dist/server/terminals.js +833 -0
- package/dist/server/text-sniff.js +269 -0
- package/dist/server/thinking-timing.js +91 -0
- package/dist/server/token-auth.js +37 -0
- package/dist/server/tool-output.js +97 -0
- package/dist/server/tool-text-incidents.js +82 -0
- package/dist/server/tool-text.js +67 -0
- package/dist/server/uploads.js +112 -0
- package/dist/server/user-attachments.js +96 -0
- package/dist/server/webui-context.js +257 -0
- package/dist/server/wiki-links.js +136 -0
- package/dist/server/wiki-pdf-worker.js +23 -0
- package/dist/server/wiki-pdf.js +36 -0
- package/dist/server/wiki-routes.js +177 -0
- package/dist/server/wiki-service.js +511 -0
- package/electron/main.mjs +607 -0
- package/extensions/webui.ts +192 -0
- package/package.json +122 -4
- package/web/dist/apple-touch-icon.png +0 -0
- package/web/dist/assets/NodeWorkbench-C4U1PldE.js +3 -0
- package/web/dist/assets/TerminalPanel-CWh6vw_N.js +2 -0
- package/web/dist/assets/abnfDiagram-VCTEODGH-D5Ti0Kpa.js +1 -0
- package/web/dist/assets/arc-DKJilLd6.js +1 -0
- package/web/dist/assets/architectureDiagram-5GKGNRK7-Cf0w38g-.js +36 -0
- package/web/dist/assets/blockDiagram-I7D4REHJ-BOTLWLIL.js +129 -0
- package/web/dist/assets/c4Diagram-7LVT6UL2-CLCCoJs3.js +38 -0
- package/web/dist/assets/channel-D8Hd7T4P.js +1 -0
- package/web/dist/assets/chunk-2Q5K7J3B-BHjga2Ge.js +1 -0
- package/web/dist/assets/chunk-5VM5RSS4-CQJ5VfDZ.js +15 -0
- package/web/dist/assets/chunk-F27PBJKO-C67qoPJH.js +1 -0
- package/web/dist/assets/chunk-IMKFNOWR-CgXXGwI8.js +231 -0
- package/web/dist/assets/chunk-JWPE2WC7-D0RPyByP.js +1 -0
- package/web/dist/assets/chunk-POPQ4Y6H-BeYC9s9x.js +1 -0
- package/web/dist/assets/chunk-SVP7TREG-eQPl4UBQ.js +88 -0
- package/web/dist/assets/chunk-TICWLB2K-DT73arPU.js +206 -0
- package/web/dist/assets/chunk-XXDRQBXY-B4FwQcP-.js +1 -0
- package/web/dist/assets/classDiagram-ZZMXUADV-B_btgYRB.js +1 -0
- package/web/dist/assets/classDiagram-v2-VYDZK3BY-B_btgYRB.js +1 -0
- package/web/dist/assets/cose-bilkent-JH36ORCC-Bnn5nlQN.js +1 -0
- package/web/dist/assets/cynefin-OW5HDTMX-CStWX9kE.js +178 -0
- package/web/dist/assets/cynefinDiagram-5FMLGOSQ-BMVHC03f.js +62 -0
- package/web/dist/assets/cytoscape.esm-Bch-eiPH.js +331 -0
- package/web/dist/assets/dagre-GXQ25YYZ-ClSaO4ml.js +4 -0
- package/web/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/web/dist/assets/diagram-S7CK7UJ4-C43LL08C.js +30 -0
- package/web/dist/assets/diagram-UQ7AKVKN-BPVn_ySW.js +41 -0
- package/web/dist/assets/diagram-VSXAHHWV-C34FFhRi.js +3 -0
- package/web/dist/assets/diagram-VX7I27RA-BRk4bncf.js +24 -0
- package/web/dist/assets/diagram-Z3DM3KII-O5hYPLEd.js +24 -0
- package/web/dist/assets/ebnfDiagram-PWID7BFC-DVGEBm99.js +1 -0
- package/web/dist/assets/erDiagram-RLTQ6QDP-M-BLpTEV.js +99 -0
- package/web/dist/assets/flowDiagram-HODETNUW-BwdLopEx.js +168 -0
- package/web/dist/assets/ganttDiagram-EL5Y4UJY-DYxx2ppA.js +292 -0
- package/web/dist/assets/gitGraphDiagram-WWUBYQGX-DUU0wMYB.js +106 -0
- package/web/dist/assets/index-CI2KfVSr.css +10 -0
- package/web/dist/assets/index-DQcpggFU.js +275 -0
- package/web/dist/assets/infoDiagram-27XIBGKW-CFaW5C0C.js +2 -0
- package/web/dist/assets/init-Gi6I4Gst.js +1 -0
- package/web/dist/assets/ishikawaDiagram-5VMMS53U--ENP1MTB.js +70 -0
- package/web/dist/assets/journeyDiagram-3NMN7TZE-DgnAzSTj.js +139 -0
- package/web/dist/assets/kanban-definition-UXKFOSKX-_STZN1vU.js +89 -0
- package/web/dist/assets/katex-C5jXJg4s.js +257 -0
- package/web/dist/assets/layout-CkUClkXt.js +1 -0
- package/web/dist/assets/linear-sYHiUOxa.js +1 -0
- package/web/dist/assets/markdown-vNTCZJ6d.js +51 -0
- package/web/dist/assets/mermaid.core-B8fKGWsc.js +312 -0
- package/web/dist/assets/mindmap-definition-YA3MSWOX-DP0BYOEx.js +96 -0
- package/web/dist/assets/ordinal-Cboi1Yqb.js +1 -0
- package/web/dist/assets/pegDiagram-XKGWAZYB-DkWTmZre.js +1 -0
- package/web/dist/assets/pieDiagram-E7YTZNPT-DfZgMV4u.js +39 -0
- package/web/dist/assets/quadrantDiagram-AXDQQJYC-Djl4TT7q.js +7 -0
- package/web/dist/assets/railroadDiagram-O6MQD6OU-DbKF6zXn.js +1 -0
- package/web/dist/assets/react-BNj3n7jX.js +24 -0
- package/web/dist/assets/requirementDiagram-BXWQKSXE-idola5qb.js +84 -0
- package/web/dist/assets/sankeyDiagram-P5KCCOFB-KA0hQOle.js +40 -0
- package/web/dist/assets/sequenceDiagram-WJ2MYXX4-BXSKvxzP.js +162 -0
- package/web/dist/assets/sizeCapture-INFHLROL-C_Ewv3S5.js +1 -0
- package/web/dist/assets/stateDiagram-D77RDMKH-DIf5X8oo.js +1 -0
- package/web/dist/assets/stateDiagram-v2-MP3YSRHH-DYwe_2mB.js +1 -0
- package/web/dist/assets/swimlanes-42K2YHIH-Cx_Rc8M2.js +1 -0
- package/web/dist/assets/swimlanesDiagram-VR7AAH4N-52Y8tgRV.js +8 -0
- package/web/dist/assets/timeline-definition-24CTP7MA-BRrDhWVz.js +120 -0
- package/web/dist/assets/vennDiagram-4TSXK5OY-Ad6G0YwD.js +34 -0
- package/web/dist/assets/wardleyDiagram-VM6X3IG4-X6-ENpSi.js +78 -0
- package/web/dist/assets/xterm-6GBZ9nXN.css +32 -0
- package/web/dist/assets/xterm-D1D2FVe3.js +38 -0
- package/web/dist/assets/xychartDiagram-S5SC5T6Z-DhegNS6d.js +7 -0
- package/web/dist/brand-mark.svg +5 -0
- package/web/dist/favicon-32.png +0 -0
- package/web/dist/favicon.svg +5 -0
- package/web/dist/fonts/WIKI-FONTS.md +5 -0
- package/web/dist/fonts/ibm-plex-mono/ibm-plex-mono-latin-400-normal.woff2 +0 -0
- package/web/dist/fonts/ibm-plex-mono/ibm-plex-mono-latin-500-normal.woff2 +0 -0
- package/web/dist/fonts/ibm-plex-mono/ibm-plex-mono-latin-600-normal.woff2 +0 -0
- package/web/dist/fonts/ibm-plex-mono/ibm-plex-mono-latin-ext-400-normal.woff2 +0 -0
- package/web/dist/fonts/ibm-plex-mono/ibm-plex-mono-latin-ext-500-normal.woff2 +0 -0
- package/web/dist/fonts/ibm-plex-mono/ibm-plex-mono-latin-ext-600-normal.woff2 +0 -0
- package/web/dist/fonts/ibm-plex-sans/LICENSE +93 -0
- package/web/dist/fonts/ibm-plex-sans/ibm-plex-sans-latin-400-normal.woff2 +0 -0
- package/web/dist/fonts/ibm-plex-sans/ibm-plex-sans-latin-500-normal.woff2 +0 -0
- package/web/dist/fonts/ibm-plex-sans/ibm-plex-sans-latin-600-normal.woff2 +0 -0
- package/web/dist/fonts/ibm-plex-sans/ibm-plex-sans-latin-ext-400-normal.woff2 +0 -0
- package/web/dist/fonts/ibm-plex-sans/ibm-plex-sans-latin-ext-500-normal.woff2 +0 -0
- package/web/dist/fonts/ibm-plex-sans/ibm-plex-sans-latin-ext-600-normal.woff2 +0 -0
- package/web/dist/fonts/inter/inter-latin-400-normal.woff2 +0 -0
- package/web/dist/fonts/inter/inter-latin-500-normal.woff2 +0 -0
- package/web/dist/fonts/inter/inter-latin-600-normal.woff2 +0 -0
- package/web/dist/fonts/inter/inter-latin-700-normal.woff2 +0 -0
- package/web/dist/fonts/inter/inter-latin-800-normal.woff2 +0 -0
- package/web/dist/fonts/inter/inter-latin-ext-400-normal.woff2 +0 -0
- package/web/dist/fonts/inter/inter-latin-ext-500-normal.woff2 +0 -0
- package/web/dist/fonts/inter/inter-latin-ext-600-normal.woff2 +0 -0
- package/web/dist/fonts/inter/inter-latin-ext-700-normal.woff2 +0 -0
- package/web/dist/fonts/inter/inter-latin-ext-800-normal.woff2 +0 -0
- package/web/dist/fonts/jetbrains-mono/LICENSE +93 -0
- package/web/dist/fonts/jetbrains-mono/jetbrains-mono-latin-400-normal.woff2 +0 -0
- package/web/dist/fonts/jetbrains-mono/jetbrains-mono-latin-500-normal.woff2 +0 -0
- package/web/dist/fonts/jetbrains-mono/jetbrains-mono-latin-600-normal.woff2 +0 -0
- package/web/dist/fonts/jetbrains-mono/jetbrains-mono-latin-ext-400-normal.woff2 +0 -0
- package/web/dist/fonts/jetbrains-mono/jetbrains-mono-latin-ext-500-normal.woff2 +0 -0
- package/web/dist/fonts/jetbrains-mono/jetbrains-mono-latin-ext-600-normal.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/LICENSE +94 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-0.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-1.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-10.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-100.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-11.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-12.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-13.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-14.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-15.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-16.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-17.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-18.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-19.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-2.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-20.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-21.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-22.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-23.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-24.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-25.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-26.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-27.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-28.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-29.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-3.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-30.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-31.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-32.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-33.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-34.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-35.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-36.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-37.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-38.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-39.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-4.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-40.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-41.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-42.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-43.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-44.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-45.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-46.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-47.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-48.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-49.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-5.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-50.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-51.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-52.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-53.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-54.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-55.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-56.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-57.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-58.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-59.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-6.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-60.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-61.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-62.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-63.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-64.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-65.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-66.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-67.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-68.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-69.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-7.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-70.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-71.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-72.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-73.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-74.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-75.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-76.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-77.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-78.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-79.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-8.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-80.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-81.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-82.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-83.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-84.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-85.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-86.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-87.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-88.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-89.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-9.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-90.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-91.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-92.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-93.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-94.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-95.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-96.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-97.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-98.woff2 +0 -0
- package/web/dist/fonts/noto-serif-sc/noto-serif-sc-500-99.woff2 +0 -0
- package/web/dist/fonts/source-serif-4/LICENSE +93 -0
- package/web/dist/fonts/source-serif-4/source-serif-4-500-0.woff2 +0 -0
- package/web/dist/fonts/source-serif-4/source-serif-4-500-1.woff2 +0 -0
- package/web/dist/fonts/source-serif-4/source-serif-4-500-2.woff2 +0 -0
- package/web/dist/fonts/source-serif-4/source-serif-4-500-3.woff2 +0 -0
- package/web/dist/fonts/source-serif-4/source-serif-4-500-4.woff2 +0 -0
- package/web/dist/fonts/source-serif-4/source-serif-4-500-5.woff2 +0 -0
- package/web/dist/icon/1a-mark.svg +1 -0
- package/web/dist/icon.ico +0 -0
- package/web/dist/index.html +18 -0
- package/web/public/apple-touch-icon.png +0 -0
- package/web/public/brand-mark.svg +5 -0
- package/web/public/favicon-32.png +0 -0
- package/web/public/favicon.svg +5 -0
- package/web/public/fonts/WIKI-FONTS.md +5 -0
- package/web/public/fonts/ibm-plex-mono/ibm-plex-mono-latin-400-normal.woff2 +0 -0
- package/web/public/fonts/ibm-plex-mono/ibm-plex-mono-latin-500-normal.woff2 +0 -0
- package/web/public/fonts/ibm-plex-mono/ibm-plex-mono-latin-600-normal.woff2 +0 -0
- package/web/public/fonts/ibm-plex-mono/ibm-plex-mono-latin-ext-400-normal.woff2 +0 -0
- package/web/public/fonts/ibm-plex-mono/ibm-plex-mono-latin-ext-500-normal.woff2 +0 -0
- package/web/public/fonts/ibm-plex-mono/ibm-plex-mono-latin-ext-600-normal.woff2 +0 -0
- package/web/public/fonts/ibm-plex-sans/LICENSE +93 -0
- package/web/public/fonts/ibm-plex-sans/ibm-plex-sans-latin-400-normal.woff2 +0 -0
- package/web/public/fonts/ibm-plex-sans/ibm-plex-sans-latin-500-normal.woff2 +0 -0
- package/web/public/fonts/ibm-plex-sans/ibm-plex-sans-latin-600-normal.woff2 +0 -0
- package/web/public/fonts/ibm-plex-sans/ibm-plex-sans-latin-ext-400-normal.woff2 +0 -0
- package/web/public/fonts/ibm-plex-sans/ibm-plex-sans-latin-ext-500-normal.woff2 +0 -0
- package/web/public/fonts/ibm-plex-sans/ibm-plex-sans-latin-ext-600-normal.woff2 +0 -0
- package/web/public/fonts/inter/inter-latin-400-normal.woff2 +0 -0
- package/web/public/fonts/inter/inter-latin-500-normal.woff2 +0 -0
- package/web/public/fonts/inter/inter-latin-600-normal.woff2 +0 -0
- package/web/public/fonts/inter/inter-latin-700-normal.woff2 +0 -0
- package/web/public/fonts/inter/inter-latin-800-normal.woff2 +0 -0
- package/web/public/fonts/inter/inter-latin-ext-400-normal.woff2 +0 -0
- package/web/public/fonts/inter/inter-latin-ext-500-normal.woff2 +0 -0
- package/web/public/fonts/inter/inter-latin-ext-600-normal.woff2 +0 -0
- package/web/public/fonts/inter/inter-latin-ext-700-normal.woff2 +0 -0
- package/web/public/fonts/inter/inter-latin-ext-800-normal.woff2 +0 -0
- package/web/public/fonts/jetbrains-mono/LICENSE +93 -0
- package/web/public/fonts/jetbrains-mono/jetbrains-mono-latin-400-normal.woff2 +0 -0
- package/web/public/fonts/jetbrains-mono/jetbrains-mono-latin-500-normal.woff2 +0 -0
- package/web/public/fonts/jetbrains-mono/jetbrains-mono-latin-600-normal.woff2 +0 -0
- package/web/public/fonts/jetbrains-mono/jetbrains-mono-latin-ext-400-normal.woff2 +0 -0
- package/web/public/fonts/jetbrains-mono/jetbrains-mono-latin-ext-500-normal.woff2 +0 -0
- package/web/public/fonts/jetbrains-mono/jetbrains-mono-latin-ext-600-normal.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/LICENSE +94 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-0.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-1.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-10.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-100.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-11.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-12.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-13.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-14.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-15.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-16.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-17.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-18.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-19.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-2.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-20.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-21.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-22.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-23.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-24.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-25.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-26.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-27.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-28.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-29.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-3.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-30.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-31.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-32.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-33.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-34.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-35.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-36.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-37.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-38.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-39.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-4.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-40.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-41.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-42.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-43.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-44.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-45.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-46.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-47.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-48.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-49.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-5.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-50.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-51.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-52.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-53.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-54.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-55.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-56.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-57.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-58.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-59.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-6.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-60.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-61.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-62.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-63.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-64.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-65.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-66.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-67.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-68.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-69.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-7.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-70.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-71.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-72.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-73.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-74.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-75.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-76.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-77.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-78.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-79.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-8.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-80.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-81.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-82.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-83.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-84.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-85.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-86.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-87.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-88.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-89.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-9.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-90.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-91.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-92.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-93.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-94.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-95.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-96.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-97.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-98.woff2 +0 -0
- package/web/public/fonts/noto-serif-sc/noto-serif-sc-500-99.woff2 +0 -0
- package/web/public/fonts/source-serif-4/LICENSE +93 -0
- package/web/public/fonts/source-serif-4/source-serif-4-500-0.woff2 +0 -0
- package/web/public/fonts/source-serif-4/source-serif-4-500-1.woff2 +0 -0
- package/web/public/fonts/source-serif-4/source-serif-4-500-2.woff2 +0 -0
- package/web/public/fonts/source-serif-4/source-serif-4-500-3.woff2 +0 -0
- package/web/public/fonts/source-serif-4/source-serif-4-500-4.woff2 +0 -0
- package/web/public/fonts/source-serif-4/source-serif-4-500-5.woff2 +0 -0
- package/web/public/icon/1a-mark.svg +1 -0
- package/web/public/icon.ico +0 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pi-harness 的 pi 扩展 —— 提供命令行集成。
|
|
3
|
+
*
|
|
4
|
+
* 能力:
|
|
5
|
+
* /webui 启动本机 pi-harness 服务器,打开浏览器访问
|
|
6
|
+
* /webui --port 9000 指定端口启动
|
|
7
|
+
* /webui --no-browser 启动但不开浏览器
|
|
8
|
+
* /webui stop 停止已启动的服务器
|
|
9
|
+
* /webui status 查看运行状态 / URL
|
|
10
|
+
*
|
|
11
|
+
* 实现说明:
|
|
12
|
+
* - 不依赖全局 bin(pi install 后 pi-harness 命令不一定在 PATH),直接用
|
|
13
|
+
* node 调包内 dist/server/index.js,通过环境变量 PORT / PI_WEB_CWD /
|
|
14
|
+
* PI_WEB_DATA_DIR 控制。
|
|
15
|
+
* - 工作目录默认用当前 pi 会话的 ctx.cwd;可用 --cwd / path 覆盖。
|
|
16
|
+
* - 服务器作为子进程后台运行,/webui 不阻塞 pi。
|
|
17
|
+
* - 每个 pi 会话管理一个子进程;session_shutdown 时清理,避免孤儿进程。
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { spawn } from "node:child_process";
|
|
21
|
+
import { existsSync } from "node:fs";
|
|
22
|
+
import { dirname, join, resolve } from "node:path";
|
|
23
|
+
import { fileURLToPath } from "node:url";
|
|
24
|
+
import net from "node:net";
|
|
25
|
+
import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
26
|
+
|
|
27
|
+
// 本文件位于 <pkg>/extensions/webui.ts → 包根在上一级
|
|
28
|
+
const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
29
|
+
const SERVER_ENTRY = join(PKG_ROOT, "dist", "server", "index.js");
|
|
30
|
+
const NODE = process.execPath;
|
|
31
|
+
|
|
32
|
+
/** 每个会话的服务器子进程 + 元数据 */
|
|
33
|
+
interface RunningServer {
|
|
34
|
+
proc: ReturnType<typeof spawn>;
|
|
35
|
+
port: number;
|
|
36
|
+
cwd: string;
|
|
37
|
+
url: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 会话 → 运行实例(模块级 Map;每会话一个会话对象,无需清理全局)
|
|
41
|
+
const running = new Map<string, RunningServer>();
|
|
42
|
+
|
|
43
|
+
/** 找一个空闲端口 */
|
|
44
|
+
function findFreePort(from = 8787): Promise<number> {
|
|
45
|
+
return new Promise((resolve_, reject) => {
|
|
46
|
+
const srv = net.createServer();
|
|
47
|
+
srv.listen(from, () => {
|
|
48
|
+
const port = (srv.address() as net.AddressInfo).port;
|
|
49
|
+
srv.close(() => resolve_(port));
|
|
50
|
+
});
|
|
51
|
+
srv.on("error", () => {
|
|
52
|
+
// 端口被占则顺延
|
|
53
|
+
findFreePort(from + 1).then(resolve_, reject);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** 解析 --key value / --flag 参数 */
|
|
59
|
+
function parseArgs(args: string): { port?: number; cwd?: string; noBrowser: boolean } {
|
|
60
|
+
const out: { port?: number; cwd?: string; noBrowser: boolean } = { noBrowser: false };
|
|
61
|
+
const toks = args.split(/\s+/).filter(Boolean);
|
|
62
|
+
for (let i = 0; i < toks.length; i++) {
|
|
63
|
+
const t = toks[i];
|
|
64
|
+
if ((t === "--port" || t === "-p") && toks[i + 1]) {
|
|
65
|
+
const n = Number(toks[++i]);
|
|
66
|
+
if (Number.isInteger(n) && n > 0 && n < 65536) out.port = n;
|
|
67
|
+
} else if ((t === "--cwd") && toks[i + 1]) {
|
|
68
|
+
out.cwd = resolve(toks[++i]);
|
|
69
|
+
} else if (t === "--no-browser") {
|
|
70
|
+
out.noBrowser = true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** 打开浏览器 */
|
|
77
|
+
async function openBrowser(url: string): Promise<void> {
|
|
78
|
+
const { platform } = process;
|
|
79
|
+
const [cmd, ...rest] =
|
|
80
|
+
platform === "darwin"
|
|
81
|
+
? ["open", url]
|
|
82
|
+
: platform === "win32"
|
|
83
|
+
? ["cmd", "/c", "start", "", url]
|
|
84
|
+
: ["xdg-open", url];
|
|
85
|
+
// 无界面环境缺少 xdg-open 等打开器时,ENOENT 以异步 'error' 事件触发,
|
|
86
|
+
// try/catch 拦不住会崩掉整个进程 —— 必须挂 error 监听。
|
|
87
|
+
spawn(cmd, rest, { stdio: "ignore", detached: true })
|
|
88
|
+
.on("error", (err) => {
|
|
89
|
+
if ((err as NodeJS.ErrnoException)?.code === "ENOENT") {
|
|
90
|
+
console.warn(
|
|
91
|
+
`[webui] 未找到浏览器打开器 (${(err as NodeJS.ErrnoException).path || "command not found"}),请用 --no-browser 关闭自动打开`
|
|
92
|
+
);
|
|
93
|
+
} else {
|
|
94
|
+
console.warn("[webui] 打开浏览器失败:", err.message);
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
.unref();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export default function (pi: ExtensionAPI): void {
|
|
101
|
+
pi.registerCommand("webui", {
|
|
102
|
+
description: "启动本机 pi-harness Web 界面(/webui [--port N] [--cwd PATH] [--no-browser] | stop | status)",
|
|
103
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
104
|
+
const sid = ctx.sessionManager.getSessionId();
|
|
105
|
+
const opts = parseArgs(args);
|
|
106
|
+
const action = (args.split(/\s+/)[0] || "start").toLowerCase();
|
|
107
|
+
|
|
108
|
+
// 停止
|
|
109
|
+
if (action === "stop" || action === "kill") {
|
|
110
|
+
const inst = running.get(sid);
|
|
111
|
+
if (!inst) {
|
|
112
|
+
ctx.ui.notify("没有正在运行的本机 pi-harness 服务器", "info");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
inst.proc.kill("SIGTERM");
|
|
116
|
+
running.delete(sid);
|
|
117
|
+
ctx.ui.notify(`已停止 pi-harness (${inst.url})`, "info");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 状态
|
|
122
|
+
if (action === "status") {
|
|
123
|
+
const inst = running.get(sid);
|
|
124
|
+
if (!inst) {
|
|
125
|
+
ctx.ui.notify("本机 pi-harness 未运行", "info");
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const alive = inst.proc.exitCode === null;
|
|
129
|
+
ctx.ui.notify(
|
|
130
|
+
alive ? `pi-harness 运行中 → ${inst.url}\n端口 ${inst.port} · cwd ${inst.cwd}` : `已退出(exit=${inst.proc.exitCode})`,
|
|
131
|
+
alive ? "info" : "warning",
|
|
132
|
+
);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 默认 start
|
|
137
|
+
if (action !== "start" && action !== "run") {
|
|
138
|
+
ctx.ui.notify(`未知动作 ${action}(可用 start|stop|status)`, "warning");
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// 已运行则提示
|
|
143
|
+
const existing = running.get(sid);
|
|
144
|
+
if (existing && existing.proc.exitCode === null) {
|
|
145
|
+
ctx.ui.notify(`pi-harness 已在运行 → ${existing.url}`, "info");
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 检查是否已构建
|
|
150
|
+
if (!existsSync(SERVER_ENTRY)) {
|
|
151
|
+
ctx.ui.notify(
|
|
152
|
+
"缺少 dist/ 产物(当前安装未包含已构建前端)。请运行 `npm run build` 后重试,或用 pi-harness 官方 npm 包。",
|
|
153
|
+
"warning",
|
|
154
|
+
);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const port = opts.port ?? (await findFreePort());
|
|
159
|
+
const cwd = opts.cwd ?? ctx.cwd;
|
|
160
|
+
const url = `http://localhost:${port}`;
|
|
161
|
+
|
|
162
|
+
const env = {
|
|
163
|
+
...process.env,
|
|
164
|
+
PORT: String(port),
|
|
165
|
+
PI_WEB_CWD: cwd,
|
|
166
|
+
...(process.env.PI_WEB_DATA_DIR ? {} : { PI_WEB_DATA_DIR: join(cwd, ".pi-web") }),
|
|
167
|
+
};
|
|
168
|
+
const proc = spawn(NODE, [SERVER_ENTRY], { cwd, env, stdio: "ignore", detached: true });
|
|
169
|
+
proc.unref();
|
|
170
|
+
running.set(sid, { proc, port, cwd, url });
|
|
171
|
+
|
|
172
|
+
ctx.ui.notify(`pi-harness 启动中 → ${url}\n端口 ${port} · cwd ${cwd}\n(几秒后可用,/webui status 查看)`);
|
|
173
|
+
|
|
174
|
+
if (!opts.noBrowser) await openBrowser(url);
|
|
175
|
+
|
|
176
|
+
// 进程退出时清理
|
|
177
|
+
proc.on("exit", () => {
|
|
178
|
+
if (running.get(sid)?.proc === proc) running.delete(sid);
|
|
179
|
+
});
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// 会话结束清理子进程,避免孤儿
|
|
184
|
+
pi.on("session_shutdown", async (_event, ctx) => {
|
|
185
|
+
const sid = ctx.sessionManager.getSessionId();
|
|
186
|
+
const inst = running.get(sid);
|
|
187
|
+
if (inst && inst.proc.exitCode === null) {
|
|
188
|
+
inst.proc.kill("SIGTERM");
|
|
189
|
+
running.delete(sid);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,124 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@youweichen/pi-harness",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Web chat interface for the pi coding agent, powered by the pi SDK (@earendil-works/pi-coding-agent) — one-command run, Docker/systemd/launchd deployable",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "youweichen",
|
|
8
|
+
"email": "youweichen0208@gmail.com"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"bin": {
|
|
12
|
+
"pi-harness": "bin/pi-harness.mjs"
|
|
13
|
+
},
|
|
14
|
+
"main": "electron/main.mjs",
|
|
15
|
+
"files": [
|
|
16
|
+
"bin/",
|
|
17
|
+
"dist/",
|
|
18
|
+
"web/dist/",
|
|
19
|
+
"web/public/",
|
|
20
|
+
"deploy/",
|
|
21
|
+
"extensions/",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"keywords": [
|
|
26
|
+
"pi",
|
|
27
|
+
"pi-package",
|
|
28
|
+
"coding-agent",
|
|
29
|
+
"ai",
|
|
30
|
+
"chat",
|
|
31
|
+
"web-ui",
|
|
32
|
+
"terminal",
|
|
33
|
+
"llm"
|
|
34
|
+
],
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/youweichen0208/pi-harness.git"
|
|
38
|
+
},
|
|
39
|
+
"pi": {
|
|
40
|
+
"extensions": [
|
|
41
|
+
"./extensions"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=22.19.0"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"prepublishOnly": "npm run build",
|
|
49
|
+
"dev": "concurrently -k -n server,web -c blue,green \"npm:dev:server\" \"npm:dev:web\"",
|
|
50
|
+
"dev:server": "cross-env PORT=8788 PI_WEB_ALLOW_ORIGINS=http://localhost:5173,http://127.0.0.1:5173 node --watch --import tsx server/index.ts",
|
|
51
|
+
"dev:web": "vite --config web/vite.config.ts",
|
|
52
|
+
"build": "npm run build:web && npm run build:server",
|
|
53
|
+
"build:web": "vite build --config web/vite.config.ts",
|
|
54
|
+
"build:server": "tsc -p tsconfig.server.json",
|
|
55
|
+
"typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p web/tsconfig.json --noEmit && tsc -p tsconfig.tests.json --noEmit",
|
|
56
|
+
"test": "node --test tests/check-design-tokens-test.mjs && npm run check:design && vitest run",
|
|
57
|
+
"test:unit": "vitest run",
|
|
58
|
+
"test:smoke": "node tests/run-smoke.mjs",
|
|
59
|
+
"check:lockfile": "node scripts/check-lockfile.mjs",
|
|
60
|
+
"check:protocol": "node scripts/check-protocol-sync.mjs",
|
|
61
|
+
"test:freeze": "node tests/freeze-test.mjs",
|
|
62
|
+
"start": "node dist/server/index.js",
|
|
63
|
+
"start:electron": "electron .",
|
|
64
|
+
"dev:electron": "electron .",
|
|
65
|
+
"build:electron": "electron-builder build",
|
|
66
|
+
"build:electron:mac": "electron-builder build --mac",
|
|
67
|
+
"build:electron:win": "electron-builder build --win",
|
|
68
|
+
"build:electron:linux": "electron-builder build --linux",
|
|
69
|
+
"publish:electron": "electron-builder build --publish always",
|
|
70
|
+
"check:design": "node scripts/check-design-tokens.mjs"
|
|
71
|
+
},
|
|
72
|
+
"dependencies": {
|
|
73
|
+
"@earendil-works/pi-ai": "1.0.4",
|
|
74
|
+
"@earendil-works/pi-coding-agent": "1.0.4",
|
|
75
|
+
"compression": "^1.8.1",
|
|
76
|
+
"electron-updater": "^6.0.0",
|
|
77
|
+
"express": "^4.21.2",
|
|
78
|
+
"node-pty": "^1.1.0",
|
|
79
|
+
"pdfjs-dist": "6.4.299",
|
|
80
|
+
"proper-lockfile": "4.1.2",
|
|
81
|
+
"remark-parse": "^11.0.0",
|
|
82
|
+
"ssh2": "^1.17.0",
|
|
83
|
+
"typebox": "^1.3.14",
|
|
84
|
+
"unified": "^11.0.5",
|
|
85
|
+
"ws": "^8.18.0"
|
|
86
|
+
},
|
|
87
|
+
"devDependencies": {
|
|
88
|
+
"@types/compression": "^1.8.1",
|
|
89
|
+
"@types/express": "^4.17.21",
|
|
90
|
+
"@types/node": "^22.10.0",
|
|
91
|
+
"@types/react": "^18.3.12",
|
|
92
|
+
"@types/react-dom": "^18.3.1",
|
|
93
|
+
"@types/ssh2": "^1.15.6",
|
|
94
|
+
"@types/turndown": "^5.0.6",
|
|
95
|
+
"@types/ws": "^8.5.13",
|
|
96
|
+
"@vitejs/plugin-react": "^4.3.4",
|
|
97
|
+
"@xterm/addon-fit": "^0.11.0",
|
|
98
|
+
"@xterm/xterm": "^6.0.0",
|
|
99
|
+
"concurrently": "^9.1.0",
|
|
100
|
+
"cross-env": "^10.1.0",
|
|
101
|
+
"electron": "^41.0.0",
|
|
102
|
+
"electron-builder": "^26.15.3",
|
|
103
|
+
"highlight.js": "^11.10.0",
|
|
104
|
+
"mermaid": "^11.17.2",
|
|
105
|
+
"playwright-core": "^1.62.1",
|
|
106
|
+
"postcss": "^8.5.25",
|
|
107
|
+
"react": "^18.3.1",
|
|
108
|
+
"react-dom": "^18.3.1",
|
|
109
|
+
"react-icons": "^5.7.0",
|
|
110
|
+
"react-markdown": "^9.0.1",
|
|
111
|
+
"rehype-highlight": "^7.0.1",
|
|
112
|
+
"remark-gfm": "^4.0.0",
|
|
113
|
+
"tsx": "^4.19.2",
|
|
114
|
+
"turndown": "^7.2.4",
|
|
115
|
+
"turndown-plugin-gfm": "^1.0.2",
|
|
116
|
+
"typescript": "^5.7.2",
|
|
117
|
+
"vite": "^6.0.3",
|
|
118
|
+
"vitest": "^4.1.11"
|
|
119
|
+
},
|
|
120
|
+
"allowScripts": {
|
|
121
|
+
"node-pty@1.1.0": true,
|
|
122
|
+
"electron@41.10.7": true
|
|
123
|
+
}
|
|
124
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{a as r,j as e}from"./markdown-vNTCZJ6d.js";import{u as rn,b as on,T as dn,r as X}from"./index-DQcpggFU.js";import{D as yn,o as bn}from"./xterm-D1D2FVe3.js";/* empty css */import"./react-BNj3n7jX.js";function kn({nodeId:K,tab:f,active:t,send:$,initialOutput:z}){const U=rn(),I=r.useRef(null),B=r.useRef(f.closed);B.current=f.closed;const[P,pe]=r.useState(""),[Q,v]=r.useState("");return r.useEffect(()=>{if(!I.current)return;const g=getComputedStyle(I.current),j=new yn({theme:{...on(),background:g.getPropertyValue("--node-terminal-bg").trim(),foreground:g.getPropertyValue("--node-terminal-fg").trim()},fontFamily:'"JetBrains Mono", Consolas, monospace',fontSize:13,scrollback:8e3,allowProposedApi:!0}),Y=()=>{j.options.theme={...on(),background:g.getPropertyValue("--node-terminal-bg").trim(),foreground:g.getPropertyValue("--node-terminal-fg").trim()}};window.addEventListener(dn,Y);const _=new bn;j.loadAddon(_),j.open(I.current),z&&j.write(z);const L=(S,C={})=>$({type:"node_request",action:S,requestId:X(),nodeId:K,terminalId:f.id,conversationId:f.conversationId,payload:C}),Z=j.onData(S=>{B.current||L(S===""?"interrupt":"terminal_input",{data:S})}),me=j.onSelectionChange(()=>pe(j.getSelection().slice(0,32e3))),w=S=>{var ee;const C=S.detail;C.nodeId!==K||C.terminalId!==f.id||C.event==="terminal_output"&&j.write(String(((ee=C.data)==null?void 0:ee.text)??""))};window.addEventListener("pi-node-event",w);const q=new ResizeObserver(()=>{var S;if(!(!((S=I.current)!=null&&S.clientWidth)||!I.current.clientHeight))try{_.fit(),B.current||L("terminal_resize",{cols:j.cols,rows:j.rows})}catch{}});return q.observe(I.current),()=>{window.removeEventListener(dn,Y),q.disconnect(),Z.dispose(),me.dispose(),window.removeEventListener("pi-node-event",w),j.dispose()}},[K,f.id,f.conversationId,$]),e.jsxs("div",{className:"node-terminal-wrap",style:{display:t?"block":"none"},children:[e.jsx("div",{ref:I,className:"node-xterm"}),P&&e.jsxs("div",{className:"node-selection-menu",children:[e.jsx("button",{onClick:()=>void navigator.clipboard.writeText(P).then(()=>v(U("nodeCopied"))).catch(g=>v(String(g))),children:U("nodeCopy")}),Q&&e.jsx("span",{role:"status",children:Q})]})]})}const wn=()=>({name:"",group:"默认",host:"",port:22,username:"root",auth:"password",defaultDir:"/"});function Dn({send:K,active:f}){var Ke,Le,Fe,Me;const t=rn(),[$,z]=r.useState([]),[U,I]=r.useState([]),[B,P]=r.useState(!1),[pe,Q]=r.useState(!1),[v,g]=r.useState(null),[j,Y]=r.useState(""),[_,L]=r.useState(!1),[Z,me]=r.useState(!1),[w,q]=r.useState("password"),[S,C]=r.useState(""),[ee,ne]=r.useState(null),[ye,an]=r.useState(!0),[xe,te]=r.useState(!1),[se,oe]=r.useState(!1),H=r.useRef(null),F=r.useRef(new Set),be=r.useRef(new Set),[ke,de]=r.useState(""),[T,cn]=r.useState([]),[re,ln]=r.useState({}),[we,un]=r.useState(Date.now()),[N,hn]=r.useState({}),[je,V]=r.useState({}),[i,ie]=r.useState(localStorage.getItem("pi-node-selected")??""),[pn,Ce]=r.useState({}),[m,D]=r.useState(null),[ae,y]=r.useState(""),[Ne,G]=r.useState(""),[ce,fe]=r.useState("/"),[Ie,mn]=r.useState({}),[b,le]=r.useState(null),M=r.useRef(new Map),Pe=r.useRef(new Map),_e=r.useRef(new Map),J=r.useRef(null),u=r.useCallback((n,o,s,a,x)=>{const O=X();return K({type:"node_request",requestId:O,action:n,nodeId:o,terminalId:a,conversationId:x,payload:s})?O:null},[K]);r.useEffect(()=>{if(!f||!_)return;const n=setInterval(()=>un(Date.now()),1e3);return()=>clearInterval(n)},[f,_]);const d=T.find(n=>n.id===i),W=je[i]??[],h=W.find(n=>n.id===pn[i])??W.at(-1),E=T.find(n=>n.id===ee),A=$.find(n=>n.id===(d==null?void 0:d.sourceId)),xn=((Ke=Ie[i])==null?void 0:Ke.path)===ce?Ie[i].entries:[];r.useEffect(()=>{f&&(u("state"),u("source_detect"))},[f,u]),r.useEffect(()=>{d&&fe(d.defaultDir)},[i,d==null?void 0:d.defaultDir]),r.useEffect(()=>{const n=o=>{var O,ge,Se,he,Re,qe,He,Te,Oe,Ue,Be,Ve,Ge,Je,We,Xe,ze,Qe,Ye,Ze,en,nn;const s=o.detail,a=s.nodeId??"";if(s.event==="state"){const l=((O=s.data)==null?void 0:O.nodes)??[];cn(l),ln(Object.fromEntries((((ge=s.data)==null?void 0:ge.connections)??[]).map(c=>[c.nodeId,c]))),z(((Se=s.data)==null?void 0:Se.sources)??[]),hn(Object.fromEntries((((he=s.data)==null?void 0:he.connections)??[]).map(c=>[c.nodeId,c.status])));for(const c of((Re=s.data)==null?void 0:Re.connections)??[])for(const p of c.terminals)M.current.set(`${c.nodeId}:${p.id}`,p.output??"");V(c=>{var tn,sn;const p={...c};for(const k of((tn=s.data)==null?void 0:tn.connections)??[]){const R=(c[k.nodeId]??[]).filter(ve=>!k.terminals.some(vn=>vn.id===ve.id)).map(ve=>({...ve,closed:!0}));p[k.nodeId]=[...R,...k.terminals]}for(const k of Object.keys(p))(((sn=s.data)==null?void 0:sn.connections)??[]).some(R=>R.nodeId===k)||(p[k]=p[k].map(R=>({...R,closed:!0})));for(const k of Object.keys(p))l.some(R=>R.id===k)||delete p[k];return p});return}if(s.event==="terminal_output"){const l=`${a}:${s.terminalId}`;M.current.set(l,((M.current.get(l)??"")+String(((qe=s.data)==null?void 0:qe.text)??"")).slice(-65536));return}if(s.event==="trust_required"){if(s.requestId&&be.current.add(s.requestId),window.confirm(t("nodeTrust",{name:String(((He=s.data)==null?void 0:He.name)??""),host:String(((Te=s.data)==null?void 0:Te.host)??""),fingerprint:String(((Oe=s.data)==null?void 0:Oe.fingerprint)??"")}))){const l=H.current;(l==null?void 0:l.nodeId)===a?u("credential_test",a,{...l.payload,fingerprint:(Ue=s.data)==null?void 0:Ue.fingerprint}):u("trust",a,{fingerprint:(Be=s.data)==null?void 0:Be.fingerprint})}else F.current.delete(a),H.current=null,oe(!1);return}if(s.event==="failure"){s.requestId===J.current&&(J.current=null);const l=String(((Ve=s.data)==null?void 0:Ve.message)??"");s.requestId&&be.current.delete(s.requestId)||(G(l),oe(!1),((Ge=s.data)==null?void 0:Ge.action)==="credential_test"&&(H.current=null),F.current.delete(a));return}if(s.event==="terminal_busy"){V(l=>({...l,[a]:(l[a]??[]).map(c=>{var p;return c.id===s.terminalId?{...c,busy:!!((p=s.data)!=null&&p.busy)}:c})}));return}if(s.event==="terminal_exit"){const l=`${a}:${s.terminalId}`;M.current.set(l,(M.current.get(l)??"")+`\r
|
|
2
|
+
[SSH 已断开]\r
|
|
3
|
+
`),V(c=>({...c,[a]:(c[a]??[]).map(p=>p.id===s.terminalId?{...p,closed:!0}:p)}));return}if(s.event!=="result")return;const x=(Je=s.data)==null?void 0:Je.action;if(x==="source_detect"&&(I(((We=s.data)==null?void 0:We.sources)??[]),Q(!0)),x==="source_add"&&(g(null),P(!1)),x==="credential_test"&&(H.current=null,oe(!1),ne(null),y(""),de(t("nodeCredentialsSaved",{n:Number(((Xe=s.data)==null?void 0:Xe.count)??1)}))),(x==="connect"||x==="trust"||x==="credential_test")&&F.current.has(a)&&(F.current.delete(a),u("terminal_open",a,{},X()),L(!0)),x==="terminal_open"){const l={id:String((ze=s.data)==null?void 0:ze.terminalId),conversationId:String((Qe=s.data)==null?void 0:Qe.conversationId),busy:!1};V(c=>({...c,[a]:(c[a]??[]).some(p=>p.id===l.id)?c[a]:[...c[a]??[],l]})),Ce(c=>({...c,[a]:l.id}))}x==="list"&&s.requestId===Pe.current.get(a)&&mn(l=>{var c,p;return{...l,[a]:{path:String(((c=s.data)==null?void 0:c.path)??""),entries:((p=s.data)==null?void 0:p.entries)??[]}}}),x==="read"&&s.requestId===_e.current.get(a)&&le({nodeId:a,path:String(((Ye=s.data)==null?void 0:Ye.path)??""),text:String(((Ze=s.data)==null?void 0:Ze.text)??"")}),x==="write"&&s.requestId===J.current&&(J.current=null,le(l=>{var c;return(l==null?void 0:l.nodeId)===a&&l.path===((c=s.data)==null?void 0:c.path)?null:l})),x==="save"&&(D(null),y(""),(en=s.data)!=null&&en.id&&ie(String(s.data.id))),(x==="import_legacy"||x==="import")&&de(t("nodeImported",{n:Number(((nn=s.data)==null?void 0:nn.count)??0)}))};return window.addEventListener("pi-node-event",n),()=>window.removeEventListener("pi-node-event",n)},[u,t]);const ue=r.useMemo(()=>T.filter(n=>`${n.name} ${n.host} ${n.username}`.toLowerCase().includes(j.toLowerCase())),[T,j]),jn=r.useMemo(()=>[...new Set(ue.map(n=>n.group))],[ue]),De=n=>{const o=u("list",i,{path:n},h==null?void 0:h.id,h==null?void 0:h.conversationId);o&&Pe.current.set(i,o)},fn=n=>{const o=u("read",i,{path:n},h==null?void 0:h.id,h==null?void 0:h.conversationId);o&&_e.current.set(i,o)},gn=()=>{!b||b.nodeId!==i||(J.current=u("write",b.nodeId,{path:b.path,text:b.text},h==null?void 0:h.id,h==null?void 0:h.conversationId))},$e=n=>{var o;if(ie(n.id),G(""),n.auth==="password"&&!n.hasSecret||n.auth==="key"&&(!n.keyPath||(o=n.unsupported)!=null&&o.includes("key"))&&!n.localKeyPath){q(n.auth==="key"?"key":"password"),C(n.localKeyPath||n.keyPath||""),ne(n.id),y(""),te(!1),F.current.add(n.id);return}L(!0),P(!1),N[n.id]==="connected"?(je[n.id]??[]).some(s=>!s.closed)||u("terminal_open",n.id,{},X()):(F.current.add(n.id),u("connect",n.id))},Ee=e.jsx("button",{onClick:()=>{D(wn()),y("")},"aria-label":t("nodeAdd"),children:"+"}),Ae=e.jsxs("label",{className:"node-secondary",children:[t("nodeImportJson"),e.jsx("input",{type:"file",accept:"application/json,.json",hidden:!0,onChange:async n=>{var s;const o=(s=n.target.files)==null?void 0:s[0];if(o){try{const a=JSON.parse(await o.text());u("import",void 0,{nodes:a.nodes})}catch{G(t("nodeInvalidJson"))}n.target.value=""}}})]}),Sn=e.jsxs("div",{className:"node-source-page",children:[e.jsx("div",{className:"node-eyebrow",children:t("nodeSources")}),e.jsx("h2",{children:t("nodeAdd")}),e.jsx("p",{className:"node-muted",children:t("nodeSourceIntro")}),pe&&!U.length&&!$.length&&e.jsx("p",{className:"node-muted",children:t("nodeNoSources")}),[...$,...U.filter(n=>!$.some(o=>o.path===n.path))].map(n=>e.jsxs("section",{className:"node-source-card",children:[e.jsxs("header",{children:[e.jsx("span",{className:"node-source-icon",children:n.kind==="xshell"?"X":"~/"}),e.jsxs("div",{children:[e.jsx("strong",{children:n.kind==="xshell"?"Xshell 8":"SSH config"}),e.jsx("small",{children:t("nodeSyncInfo",{n:n.count??0,g:n.groups??0})})]})]}),e.jsx("code",{children:n.path}),e.jsxs("p",{children:["✓ ",t("nodeSyncFields")]}),e.jsxs("p",{className:"node-muted",children:["— ",t("nodeSyncPassword"),e.jsx("br",{}),"— ",t("nodeSyncUnsupported")]}),n.error&&e.jsx("p",{className:"node-error",role:"alert",children:n.error}),n.lastSync&&e.jsx("small",{children:t("nodeSyncTime",{time:new Date(n.lastSync).toLocaleString()})}),e.jsxs("div",{className:"node-actions",children:[n.id?e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>u("source_sync",void 0,{id:n.id}),children:t("nodeSyncNow")}),e.jsx("button",{onClick:()=>u("source_toggle",void 0,{id:n.id,enabled:!n.enabled}),children:t(n.enabled?"nodeSyncPause":"nodeSyncResume")})]}):e.jsxs(e.Fragment,{children:[e.jsx("button",{className:"node-primary",onClick:()=>u("source_add",void 0,{kind:n.kind,path:n.path,enabled:!0}),children:t("nodeSyncKeep")}),e.jsx("button",{onClick:()=>u("source_add",void 0,{kind:n.kind,path:n.path,enabled:!1}),children:t("nodeImportOnce")})]}),e.jsx("button",{onClick:()=>g({kind:n.kind??"xshell",path:n.path??""}),children:t("nodeChangePath")})]})]},n.path)),e.jsxs("div",{className:"node-actions",children:[e.jsx("button",{onClick:()=>g({kind:"xshell",path:""}),children:t("nodeAddSource")}),e.jsx("button",{onClick:()=>u("source_detect"),children:t("nodeDetect")}),Ee,Ae]})]});return e.jsxs("div",{className:`node-workbench ${_&&d?"node-workspace-open":""}`,children:[Ne&&e.jsxs("div",{className:"node-global-message node-error",role:"alert",children:[Ne,e.jsx("button",{"aria-label":t("close"),onClick:()=>G(""),children:"×"})]}),ke&&e.jsxs("div",{className:"node-global-message node-notice",role:"status",children:[ke,e.jsx("button",{"aria-label":t("close"),onClick:()=>de(""),children:"×"})]}),!_&&e.jsxs("aside",{className:"node-sidebar",children:[e.jsxs("header",{children:[e.jsx("strong",{children:t("nodeWorkbench")}),Ee]}),e.jsx("input",{"aria-label":t("nodeSearch"),placeholder:t("nodeSearch"),value:j,onChange:n=>Y(n.target.value)}),$.map(n=>e.jsxs("button",{className:"node-source-status",onClick:()=>P(!0),children:[e.jsx("span",{className:`node-dot ${n.error?"connecting":n.enabled?"connected":"offline"}`}),n.kind==="xshell"?"Xshell 8":"SSH config",e.jsx("small",{children:n.error||(n.lastSync?new Date(n.lastSync).toLocaleTimeString():"…")})]},n.id)),e.jsx("div",{className:"node-list",children:jn.map(n=>e.jsxs("section",{children:[e.jsxs("h3",{children:[n,e.jsx("span",{children:ue.filter(o=>o.group===n).length})]}),ue.filter(o=>o.group===n).map(o=>{var s,a;return e.jsxs("div",{className:`node-item ${i===o.id?"selected":""}`,children:[e.jsxs("button",{onClick:()=>{ie(o.id),P(!1)},children:[e.jsx("span",{className:`node-dot ${N[o.id]??"offline"}`}),o.name,e.jsxs("small",{children:[o.username,"@",o.host,":",o.port]})]}),(o.sourceMissing||((s=o.unsupported)==null?void 0:s.length)||o.auth==="password"&&!o.hasSecret)&&e.jsx("span",{className:"node-badge",children:t(o.sourceMissing?"nodeSourceMissing":(a=o.unsupported)!=null&&a.length?"nodeUnsupported":"nodeMissingSecret")}),!o.sourceId&&e.jsx("button",{title:t("nodeEdit"),onClick:()=>{D(o),y("")},children:"⋯"})]},o.id)})]},n))}),e.jsxs("footer",{children:[e.jsx("button",{onClick:()=>P(!0),children:t("nodeSources")}),Ae,e.jsxs("details",{children:[e.jsx("summary",{children:"⋯"}),e.jsx("button",{onClick:()=>u("import_legacy"),children:t("nodeImportLegacy")}),e.jsx("button",{onClick:()=>{const n=T.map(({hasSecret:a,fingerprint:x,sourceId:O,sourceKey:ge,sourceMissing:Se,...he})=>he),o=URL.createObjectURL(new Blob([JSON.stringify({nodes:n},null,2)],{type:"application/json"})),s=document.createElement("a");s.href=o,s.download="pi-nodes.json",s.click(),setTimeout(()=>URL.revokeObjectURL(o),1e3)},children:t("nodeExport")})]})]})]}),!_&&(B||!d?Sn:e.jsxs("section",{className:"node-detail",children:[e.jsxs("header",{className:"node-detail-head",children:[e.jsxs("div",{children:[e.jsx("div",{className:"node-eyebrow",children:d.group}),e.jsx("h2",{children:d.name}),e.jsxs("code",{children:[d.username,"@",d.host,":",d.port]})]}),e.jsxs("div",{className:"node-actions",children:[A&&e.jsx("button",{onClick:()=>u("source_reveal",void 0,{id:A.id}),children:t("nodeRevealSource")}),!d.sourceId&&e.jsx("button",{onClick:()=>{D(d),y("")},children:t("nodeEdit")}),e.jsx("button",{className:"node-primary",disabled:!!((Le=d.unsupported)!=null&&Le.some(n=>n!=="key"))||d.sourceMissing||N[d.id]==="connecting",onClick:()=>$e(d),children:t("nodeOpenTerminal")})]})]}),d.sourceMissing&&e.jsx("p",{className:"node-warning",children:t("nodeSourceMissing")}),!!((Fe=d.unsupported)!=null&&Fe.length)&&e.jsxs("p",{className:"node-warning",children:[t("nodeUnsupported"),": ",d.unsupported.join(", ")]}),e.jsxs("div",{className:d.hasSecret?"node-credential-note":"node-warning",children:[e.jsxs("div",{children:[e.jsxs("strong",{children:[t(d.auth==="agent"?"nodeAgentAuth":d.auth==="password"?"nodePassword":"nodePassphrase"),!d.hasSecret&&d.auth==="password"&&` · ${t("nodeMissingSecret")}`]}),e.jsx("p",{children:t("nodeCredentialHint")})]}),e.jsx("button",{onClick:()=>{q(d.auth==="key"?"key":"password"),C(d.localKeyPath||d.keyPath||""),ne(d.id),y(""),te(!1)},children:t("nodeFillSecret")})]}),e.jsxs("dl",{children:[e.jsx("dt",{children:t("nodeAuth")}),e.jsx("dd",{children:t(d.auth==="key"?"nodeKey":d.auth==="agent"?"nodeAgentAuth":"nodePassword")}),(d.localKeyPath||d.keyPath)&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:t("nodeKeyPath")}),e.jsx("dd",{children:e.jsx("code",{children:d.localKeyPath||d.keyPath})})]}),A&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:t("nodeSourceLocation")}),e.jsxs("dd",{children:[e.jsxs("code",{children:[A.path,A.kind==="xshell"?`/${d.sourceKey}`:` · ${d.sourceKey}`]}),e.jsx("small",{children:t("nodeSourceReadonly")}),e.jsx("button",{title:t("nodeSourceOpenHint"),onClick:()=>void navigator.clipboard.writeText(A.kind==="xshell"?`${A.path}/${d.sourceKey}`:A.path).then(()=>de(t("nodeCopied"))).catch(n=>G(String(n))),children:t("nodeCopy")})]})]}),e.jsx("dt",{children:t("nodeLastConnected")}),e.jsx("dd",{children:d.lastConnected?new Date(d.lastConnected).toLocaleString():t("nodeNever")}),e.jsx("dt",{children:t("nodeDefaultDir")}),e.jsx("dd",{children:e.jsx("code",{children:d.defaultDir})})]})]})),_&&d&&e.jsxs("div",{className:"node-connected",children:[e.jsxs("nav",{className:"node-connection-tabs",children:[e.jsx("button",{onClick:()=>L(!1),children:t("nodeBackList")}),T.filter(n=>{var o;return n.id===i||N[n.id]||((o=je[n.id])==null?void 0:o.length)}).map(n=>e.jsxs("button",{className:n.id===i?"active":"",onClick:()=>ie(n.id),children:[e.jsx("span",{className:`node-dot ${N[n.id]??"offline"}`}),n.name]},n.id)),e.jsx("button",{onClick:()=>{L(!1),P(!0)},"aria-label":t("nodeAdd"),children:"+"}),((Me=re[i])==null?void 0:Me.connectedAt)&&e.jsx("span",{className:"node-connection-timing",children:t("nodeConnectionTiming",{ms:re[i].latencyMs??0,duration:`${Math.floor(Math.max(0,we-re[i].connectedAt)/6e4)}:${String(Math.floor(Math.max(0,we-re[i].connectedAt)/1e3)%60).padStart(2,"0")}`})})]}),e.jsx("div",{className:"node-connected-body",children:e.jsxs("section",{className:"node-main",children:[e.jsxs("header",{className:"node-main-head",children:[e.jsx("strong",{children:d.name}),e.jsxs("span",{children:[d.username,"@",d.host,":",d.port]}),e.jsx("em",{children:t(N[i]==="connected"?"nodeConnected":"nodeDisconnected")}),e.jsx("button",{onClick:()=>N[i]==="connected"?u("disconnect",i):$e(d),children:t(N[i]==="connected"?"nodeDisconnect":"nodeConnect")})]}),e.jsxs("div",{className:"node-tabs",children:[W.map((n,o)=>e.jsxs("div",{className:(h==null?void 0:h.id)===n.id?"active":"",children:[e.jsxs("button",{onClick:()=>Ce(s=>({...s,[i]:n.id})),children:[t("nodeTab",{n:o+1}),n.closed?` · ${t("nodeTabClosed")}`:n.busy?` · ${t("nodeTabBusy")}`:""]}),e.jsx("button",{"aria-label":t("nodeCloseTab"),onClick:()=>{n.closed||u("terminal_close",i,{},n.id,n.conversationId),M.current.delete(`${i}:${n.id}`),V(s=>({...s,[i]:(s[i]??[]).filter(a=>a.id!==n.id)}))},children:"×"})]},n.id)),e.jsx("button",{disabled:N[i]!=="connected",onClick:()=>u("terminal_open",i,{},X()),children:"+"})]}),e.jsxs("div",{className:"node-terminals",children:[W.map(n=>e.jsx(kn,{nodeId:i,tab:n,active:f&&(h==null?void 0:h.id)===n.id,send:K,initialOutput:M.current.get(`${i}:${n.id}`)??n.output},`${i}:${n.id}`)),!W.length&&e.jsx("div",{className:"node-empty",children:t("nodeOpenHint")})]}),e.jsxs("div",{className:"node-terminal-footer",children:[e.jsx("span",{children:t("nodeTerminalHint")}),e.jsx("button",{onClick:()=>me(!Z),children:t("nodeShowFiles")})]}),Z&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"node-filebar",children:[e.jsx("input",{value:ce,onChange:n=>fe(n.target.value),"aria-label":t("nodeDefaultDir")}),e.jsx("button",{disabled:N[i]!=="connected",onClick:()=>De(ce),children:t("nodeBrowse")})]}),e.jsx("div",{className:"node-files",children:xn.map(n=>{const o=`${ce.replace(/\/$/,"")}/${n.name}`;return e.jsxs("button",{onClick:()=>n.type==="dir"?(fe(o),De(o)):fn(o),children:[n.type==="dir"?"▸":"·"," ",n.name]},n.name)})})]}),(b==null?void 0:b.nodeId)===i&&e.jsxs("div",{className:"node-file-editor",children:[e.jsx("span",{children:b.path}),e.jsx("button",{onClick:gn,children:t("save")}),e.jsx("button",{onClick:()=>le(null),children:t("close")}),e.jsx("textarea",{value:b.text,onChange:n=>le({...b,text:n.target.value})})]})]})})]}),v&&e.jsx("div",{className:"node-modal-backdrop",children:e.jsxs("form",{className:"node-modal",onSubmit:n=>{n.preventDefault(),u("source_add",void 0,{...v,enabled:!0})},children:[e.jsx("h2",{children:t("nodeAddSource")}),e.jsxs("label",{children:[t("nodeSources"),e.jsxs("select",{value:v.kind,onChange:n=>g({...v,kind:n.target.value}),children:[e.jsx("option",{value:"xshell",children:"Xshell 8"}),e.jsx("option",{value:"ssh",children:"SSH config"})]})]}),e.jsxs("label",{children:[t("nodeSourcePath"),e.jsx("input",{required:!0,autoFocus:!0,value:v.path,onChange:n=>g({...v,path:n.target.value})})]}),e.jsxs("div",{className:"node-modal-actions",children:[e.jsx("button",{type:"button",onClick:()=>g(null),children:t("cancel")}),e.jsx("button",{type:"submit",children:t("nodeSyncKeep")}),e.jsx("button",{type:"button",disabled:!v.path.trim(),onClick:()=>u("source_add",void 0,{...v,enabled:!1}),children:t("nodeImportOnce")})]})]})}),E&&e.jsx("div",{className:"node-modal-backdrop",children:e.jsxs("form",{className:"node-modal",onSubmit:n=>{n.preventDefault();const o={auth:w,secret:ae,persist:ye,sameGroup:xe,...w==="key"?{keyPath:S}:{}};H.current={nodeId:E.id,payload:o},oe(!0),u("credential_test",E.id,o)},children:[e.jsx("h2",{children:E.name}),e.jsxs("code",{children:[E.username,"@",E.host,":",E.port]}),e.jsxs("label",{children:[t("nodeAuth"),e.jsxs("select",{disabled:se,value:w,onChange:n=>{q(n.target.value),y(""),te(!1)},children:[e.jsx("option",{value:"password",children:t("nodePassword")}),e.jsx("option",{value:"key",children:t("nodeKey")})]})]}),e.jsx("p",{className:"node-muted",children:t("nodeLocalAuthHint")}),e.jsx(e.Fragment,{children:w==="key"&&e.jsxs(e.Fragment,{children:[e.jsxs("label",{children:[t("nodeKeyPath"),e.jsx("input",{required:!0,value:S,onChange:n=>C(n.target.value)})]}),e.jsx("p",{className:"node-muted",children:t("nodePrivateKeyHint")})]})}),e.jsxs("label",{children:[t(w==="key"?"nodePassphrase":"nodePassword"),e.jsx("input",{autoFocus:!0,type:"password",autoComplete:"new-password",required:w==="password",value:ae,onChange:n=>y(n.target.value)})]}),e.jsxs("label",{className:"node-checkbox",children:[e.jsx("input",{type:"checkbox",checked:ye,onChange:n=>an(n.target.checked)}),t("nodePersistSecret")]}),w==="password"&&e.jsxs("label",{className:"node-checkbox",children:[e.jsx("input",{type:"checkbox",checked:xe,onChange:n=>te(n.target.checked)}),t("nodeGroupSecret")]}),xe&&e.jsx("p",{className:"node-muted",children:t("nodeGroupHint")}),e.jsx("p",{className:"node-muted",children:t("nodeCredentialHint")}),e.jsxs("div",{className:"node-modal-actions",children:[e.jsx("button",{type:"button",disabled:se,onClick:()=>{F.current.delete(E.id),ne(null),y(""),H.current=null},children:t("cancel")}),e.jsx("button",{disabled:se,className:"node-primary",children:t(se?"nodeTesting":"nodeTestSave")})]})]})}),m&&e.jsx("div",{className:"node-modal-backdrop",children:e.jsxs("form",{className:"node-modal",onSubmit:n=>{n.preventDefault(),u("save",m.id,{...m,secret:ae||void 0})},children:[e.jsx("h2",{children:m.id?t("nodeEdit"):t("nodeAdd")}),[["group",t("nodeGroup")],["name",t("nodeName")],["host",t("nodeAddress")],["port",t("nodePort")],["username",t("nodeUsername")],["defaultDir",t("nodeDefaultDir")]].map(([n,o])=>e.jsxs("label",{children:[o,e.jsx("input",{required:n!=="group",value:String(m[n]??""),onChange:s=>D({...m,[n]:n==="port"?Number(s.target.value):s.target.value})})]},n)),e.jsxs("label",{children:[t("nodeAuth"),e.jsxs("select",{value:m.auth,onChange:n=>D({...m,auth:n.target.value}),children:[e.jsx("option",{value:"password",children:t("nodePassword")}),e.jsx("option",{value:"key",children:t("nodeKey")}),e.jsx("option",{value:"agent",children:t("nodeAgentAuth")})]})]}),m.auth==="key"&&e.jsxs("label",{children:[t("nodeKeyPath"),e.jsx("input",{value:m.keyPath??"",onChange:n=>D({...m,keyPath:n.target.value})})]}),m.auth!=="agent"&&e.jsxs("label",{children:[m.auth==="key"?t("nodePassphrase"):t("nodePassword"),e.jsx("input",{type:"password",value:ae,onChange:n=>y(n.target.value),placeholder:m.hasSecret?t("nodeKeepSecret"):""})]}),e.jsxs("div",{className:"node-modal-actions",children:[m.id&&m.fingerprint&&e.jsx("button",{type:"button",onClick:()=>{window.confirm(t("nodeForgetHostKeyConfirm",{name:m.name??""}))&&u("forget_host_key",m.id)},children:t("nodeForgetHostKey")}),m.id&&e.jsx("button",{type:"button",onClick:()=>{window.confirm(t("nodeDeleteConfirm",{name:m.name??""}))&&(u("delete",m.id),D(null))},children:t("nodeDelete")}),e.jsx("button",{type:"button",onClick:()=>D(null),children:t("cancel")}),e.jsx("button",{type:"submit",children:t("save")})]})]})})," "]})}export{Dn as NodeWorkbench};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as m,j as n}from"./markdown-vNTCZJ6d.js";import{b as $,T as K,u as P,F as q,a as A,c as L,d as B,e as J,f as W,g as X,h as G,r as Q}from"./index-DQcpggFU.js";import{D as U,o as V}from"./xterm-D1D2FVe3.js";/* empty css */import"./react-BNj3n7jX.js";function Y({conversationId:s,terminalId:r,command:f,cwd:R,active:t,send:u,register:x}){const v=m.useRef(null),w=m.useRef(t);w.current=t;const N=m.useRef(null),b=f?JSON.stringify(f):"";return m.useEffect(()=>{const d=v.current;if(!d)return;const a=new U({theme:$(),fontFamily:'"SF Mono", "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace',fontSize:13,cursorBlink:!0,scrollback:8e3}),l=new V;a.loadAddon(l),a.open(d),N.current={term:a,fit:l},t&&a.focus();const j=()=>{a.options.theme=$()};window.addEventListener(K,j),a.attachCustomKeyEventHandler(o=>{var F;if(o.type!=="keydown")return!0;const E=(F=o.key)==null?void 0:F.toLowerCase();if((o.ctrlKey||o.metaKey)&&E==="v")return!1;if(o.ctrlKey&&!o.shiftKey&&!o.altKey&&E==="c"&&a.hasSelection()){const T=a.textarea;return T&&(T.value=a.getSelection(),T.select()),!1}return!0});const g=x(s,r,{write:o=>a.write(o),dispose:()=>a.dispose()}),C=()=>{if(!(!w.current||!d.clientWidth||!d.clientHeight))try{l.fit(),u({type:"terminal_resize",terminalId:r,conversationId:s,cols:a.cols,rows:a.rows})}catch{}},h=requestAnimationFrame(()=>{try{l.fit()}catch{}u(f?{type:"run_command",terminalId:r,conversationId:s,command:f,cols:a.cols,rows:a.rows}:{type:"terminal_create",terminalId:r,conversationId:s,cwd:R,cols:a.cols,rows:a.rows})}),k=a.onData(o=>{u({type:"terminal_input",terminalId:r,conversationId:s,data:o})});let y=null;return typeof ResizeObserver<"u"&&(y=new ResizeObserver(()=>{d.offsetWidth>0&&d.offsetHeight>0&&C()}),y.observe(d)),()=>{cancelAnimationFrame(h),k.dispose(),window.removeEventListener(K,j),y==null||y.disconnect(),g(),a.dispose(),N.current=null}},[s,r,b,u,x]),m.useEffect(()=>{if(!t)return;const d=requestAnimationFrame(()=>{const a=N.current;if(a){try{a.fit.fit(),u({type:"terminal_resize",terminalId:r,conversationId:s,cols:a.term.cols,rows:a.term.rows})}catch{}a.term.focus()}});return()=>cancelAnimationFrame(d)},[t]),n.jsx("div",{ref:v,className:`term-xterm ${t?"":"hidden"}`})}const H={name:"",command:"",cwd:"${pwd}"};function ae({chat:s,send:r,terminal:f,active:R}){const t=P(),[u,x]=m.useState(null),[v,w]=m.useState(!1),[N,b]=m.useState(!1),[d,a]=m.useState(null),[l,j]=m.useState(H),[g,C]=m.useState(null),h=m.useRef(null);m.useEffect(()=>{s.terminals.length===0?x(null):s.terminals.some(e=>e.id===u)||x(s.terminals[s.terminals.length-1].id)},[s.terminals,u]),m.useEffect(()=>()=>{h.current&&clearTimeout(h.current)},[]);const k=e=>{var p;if(!s.ready)return;const i=Q(),c=s.activeConversationId||((p=s.state)==null?void 0:p.conversationId)||"";f.create({...e,id:i,conversationId:c,cols:e.cols??80,rows:e.rows??24,running:!0,exitCode:null}),x(i),w(!1)},y=()=>{var e;return k({title:t("terminalTitle",{n:s.terminals.length+1}),cwd:((e=s.state)==null?void 0:e.cwd)??""})},o=e=>{var p;const i=e.name||e.command,c=s.terminals.find(_=>_.title===i);if(c){f.restart(c.id),x(c.id),r({type:"run_command",terminalId:c.id,conversationId:c.conversationId,command:e,cols:80,rows:24});return}k({title:i,cwd:((p=s.state)==null?void 0:p.cwd)??"",command:e})},E=e=>{const i=s.terminals.find(c=>c.id===e);if(i&&r({type:"terminal_kill",terminalId:e,conversationId:i.conversationId}),f.close(e),u===e){const c=s.terminals.filter(p=>p.id!==e);x(c.length>0?c[c.length-1].id:null)}},F=()=>{b(!0),a(null),j(H)},T=e=>{const i=s.commands[e];i&&(b(!1),a(e),j({name:i.name,command:i.command,cwd:i.cwd??""}))},D=()=>{b(!1),a(null)},S=()=>{const e=l.name.trim(),i=l.command.trim();if(!e||!i)return;const c=l.cwd.trim(),p={name:e,command:i,cwd:c||void 0},_=N?[...s.commands,p]:d!==null?s.commands.map((z,O)=>O===d?p:z):s.commands;r({type:"save_commands",commands:_}),D()},I=e=>{if(g===e){const i=s.commands.filter((c,p)=>p!==e);r({type:"save_commands",commands:i}),C(null),h.current&&clearTimeout(h.current)}else C(e),h.current&&clearTimeout(h.current),h.current=setTimeout(()=>C(null),2500)},M=N||d!==null;return n.jsxs("div",{className:"terminal-view",children:[n.jsxs("aside",{className:`term-side term-commands ${v?"open":""}`,children:[n.jsxs("div",{className:"panel-header",children:[n.jsx("span",{className:"panel-title",children:t("commands")}),n.jsxs("div",{className:"panel-header-actions",children:[n.jsx("button",{type:"button",className:"panel-refresh",title:t("rerun"),onClick:()=>r({type:"list_commands"}),children:n.jsx(q,{})}),n.jsx("button",{type:"button",className:"panel-new",title:t("newCommand"),onClick:F,children:n.jsx(A,{})})]})]}),n.jsx("div",{className:"panel-body",children:M?n.jsxs("div",{className:"cmd-form",children:[n.jsx("label",{htmlFor:"cmd-name",children:t("name")}),n.jsx("input",{id:"cmd-name",className:"cmd-input",value:l.name,placeholder:t("exampleName"),autoFocus:!0,onChange:e=>j({...l,name:e.target.value})}),n.jsx("label",{htmlFor:"cmd-command",children:t("command")}),n.jsx("input",{id:"cmd-command",className:"cmd-input",value:l.command,placeholder:t("exampleCommand"),onChange:e=>j({...l,command:e.target.value}),onKeyDown:e=>{e.key==="Enter"&&!e.nativeEvent.isComposing&&S()}}),n.jsxs("label",{htmlFor:"cmd-cwd",children:[t("directory")," ",n.jsx("span",{className:"cmd-hint",children:t("cwdHint")})]}),n.jsx("input",{id:"cmd-cwd",className:"cmd-input",value:l.cwd,placeholder:"${pwd}",onChange:e=>j({...l,cwd:e.target.value}),onKeyDown:e=>{e.key==="Enter"&&!e.nativeEvent.isComposing&&S()}}),n.jsxs("div",{className:"cmd-form-actions",children:[n.jsx("button",{type:"button",className:"btn",onClick:D,children:t("cancel")}),n.jsx("button",{type:"button",className:"btn primary",disabled:!l.name.trim()||!l.command.trim(),onClick:S,children:t("save")})]})]}):n.jsxs(n.Fragment,{children:[s.commands.length===0&&n.jsx("div",{className:"panel-empty",children:t("noCommands")}),s.commands.map((e,i)=>n.jsxs("div",{className:"cmd-item",children:[n.jsx("button",{type:"button",className:"cmd-run",title:t("clickToRun"),onClick:()=>o(e),children:n.jsx(L,{})}),n.jsxs("button",{type:"button",className:"cmd-main",title:t("clickToRun"),onClick:()=>o(e),children:[n.jsx("span",{className:"cmd-name",children:e.name}),n.jsx("span",{className:"cmd-command",children:e.command}),e.cwd&&n.jsx("span",{className:"cmd-cwd",children:e.cwd})]}),n.jsx("button",{type:"button",className:"cmd-act",title:t("edit"),onClick:()=>T(i),children:n.jsx(B,{})}),n.jsx("button",{type:"button",className:`cmd-act del ${g===i?"confirm":""}`,title:t("delete"),onClick:()=>I(i),children:g===i?t("confirmQ"):n.jsx(J,{})})]},i))]})}),n.jsxs("div",{className:"term-tabs-block",children:[n.jsxs("div",{className:"panel-header",children:[n.jsx("span",{className:"panel-title",children:t("terminal")}),n.jsx("button",{type:"button",className:"panel-new",title:t("newTerminal"),onClick:y,children:n.jsx(A,{})})]}),n.jsxs("div",{className:"panel-body",children:[s.terminals.length===0&&n.jsx("div",{className:"panel-empty",children:t("noTerminal")}),s.terminals.map(e=>n.jsxs("div",{className:`term-tab ${e.id===u?"active":""}`,children:[n.jsxs("button",{type:"button",className:"term-tab-main",title:`${e.cwd}${e.command?`
|
|
2
|
+
> ${e.command.command}`:""}`,onClick:()=>{x(e.id),w(!1)},children:[n.jsx("span",{className:`term-tab-dot ${e.running?"run":"exit"}`}),n.jsxs("span",{className:"term-tab-title",children:[e.title,!e.running&&n.jsx("span",{className:"term-tab-exit",children:t("exited",{code:e.exitCode===null?"":` ${e.exitCode}`})})]})]}),n.jsx("button",{type:"button",className:"term-tab-close",title:t("closeTerminal"),onClick:()=>E(e.id),children:n.jsx(W,{})})]},e.id))]})]})]}),n.jsxs("div",{className:"term-main",children:[v&&n.jsx("div",{className:"drawer-backdrop",onClick:()=>w(!1)}),n.jsx("button",{type:"button",className:"term-side-toggle",title:t("commands"),onClick:()=>w(e=>!e),children:n.jsx(X,{})}),s.terminals.length===0?n.jsxs("div",{className:"term-empty",children:[n.jsx(G,{className:"term-empty-icon"}),n.jsx("div",{className:"term-empty-title",children:t("builtinTerminal")}),n.jsx("div",{className:"term-empty-sub",children:t("termEmptySub")})]}):s.terminals.map(e=>n.jsx(Y,{conversationId:e.conversationId,terminalId:e.id,command:e.command,cwd:e.cwd,active:R&&e.id===u,send:r,register:f.register},`${e.conversationId}:${e.id}`))]})]})}export{ae as TerminalPanel};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{g as p,r as u,d as a}from"./chunk-SVP7TREG-eQPl4UBQ.js";import{p as f}from"./chunk-JWPE2WC7-D0RPyByP.js";import{_ as n,l as o}from"./mermaid.core-B8fKGWsc.js";import{M as c,b as d}from"./cynefin-OW5HDTMX-CStWX9kE.js";import"./index-DQcpggFU.js";import"./markdown-vNTCZJ6d.js";import"./react-BNj3n7jX.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},I={parser:R,db:a,renderer:u,styles:p};export{I as diagram};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a0 as ln,a1 as an,a2 as y,a3 as tn,a4 as H,a5 as q,a6 as _,a7 as un,a8 as rn,a9 as L,aa as o,ab as B,ac as sn,ad as on,ae as fn}from"./mermaid.core-B8fKGWsc.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,C,a){var O=I-l,i=D-h,n=C-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function W(l,h,I,D,v,A,C){var a=l-I,O=h-D,i=(C?A:-A)/L(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,F=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*L(fn(0,T*T*R-P*P)),j=(P*g-m*S)/R,z=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=j-F,e=z-t,r=w-F,G=p-t;return x*x+e*e>r*r+G*G&&(j=w,z=p),{cx:j,cy:z,x01:-n,y01:-d,x11:j*(v/T-1),y11:z*(v/T-1)}}function hn(){var l=cn,h=yn,I=B(0),D=null,v=gn,A=dn,C=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-an,c=A.apply(this,arguments)-an,F=un(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(F>tn-y)a.moveTo(s*H(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*H(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=F,S=F,j=C.apply(this,arguments)/2,z=j>y&&(D?+D.apply(this,arguments):L(u*u+s*s)),w=_(un(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if(z>y){var G=sn(z/u*q(j)),M=sn(z/s*q(j));(P-=G*2)>y?(G*=t?1:-1,R+=G,T-=G):(P=0,R=T=(f+c)/2),(S-=M*2)>y?(M*=t?1:-1,m+=M,g-=M):(S=0,m=g=(f+c)/2)}var J=s*H(m),K=s*q(m),N=u*H(T),Q=u*q(T);if(w>y){var U=s*H(g),V=s*q(g),X=u*H(R),Y=u*q(R),E;if(F<rn)if(E=pn(J,K,X,Y,U,V,N,Q)){var Z=J-E[0],$=K-E[1],b=U-E[0],k=V-E[1],nn=1/q(on((Z*b+$*k)/(L(Z*Z+$*$)*L(b*b+k*k)))/2),en=L(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=W(X,Y,J,K,s,x,t),r=W(U,V,N,Q,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(J,K),a.arc(0,0,s,m,g,!t)):a.moveTo(J,K),!(u>y)||!(P>y)?a.lineTo(N,Q):p>y?(e=W(N,Q,U,V,u,-p,t),r=W(J,K,X,Y,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-rn/2;return[H(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:B(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:B(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:B(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:B(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:B(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:B(+n),i):A},i.padAngle=function(n){return arguments.length?(C=typeof n=="function"?n:B(+n),i):C},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
|