@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,49 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { VERSION } from "@earendil-works/pi-coding-agent";
|
|
6
|
+
const sdkFile = createRequire(import.meta.url).resolve.paths("@earendil-works/pi-coding-agent")?.map(path => join(path, "@earendil-works/pi-coding-agent/dist/core/system-prompt.js")).find(path => existsSync(path));
|
|
7
|
+
if (!sdkFile)
|
|
8
|
+
throw Error("Native system prompt builder not found");
|
|
9
|
+
const builders = await import(pathToFileURL(sdkFile).href);
|
|
10
|
+
export const nativePromptSections = builders.buildSystemPromptSections;
|
|
11
|
+
export const nativePromptText = builders.buildSystemPrompt;
|
|
12
|
+
export const estimatePromptTokens = (text) => Math.ceil(text.replace(/[\u2e80-\u9fff\uf900-\ufaff]/g, "xxxx").length / 4);
|
|
13
|
+
const unwrap = (name, text) => name === "preamble" ? text : text.slice(`<${name}>\n`.length, -`\n</${name}>`.length);
|
|
14
|
+
const rules = (text) => text.split(/\n(?=- )/).map(s => s.replace(/^- /, "").trim()).filter(Boolean);
|
|
15
|
+
/** Read-only adapter for the exact pinned SDK. Rendering must match the public getter before exposing editable structure. */
|
|
16
|
+
export function promptView(session, cwd) {
|
|
17
|
+
const raw = session.systemPrompt;
|
|
18
|
+
const internals = session;
|
|
19
|
+
const options = internals._runSystemPromptOptions ?? internals._baseSystemPromptOptions;
|
|
20
|
+
const defaultPreamble = nativePromptSections({ cwd }).preamble;
|
|
21
|
+
if (VERSION !== "1.0.4" || !options || nativePromptText(options) !== raw)
|
|
22
|
+
return { raw, defaultPreamble, opaque: true, forced: false, sections: [], rules: [], options: undefined };
|
|
23
|
+
if (options.forceSystemPrompt !== undefined)
|
|
24
|
+
return { raw, defaultPreamble, opaque: true, forced: true, sections: [], rules: [], options: undefined };
|
|
25
|
+
const built = nativePromptSections(options);
|
|
26
|
+
const sections = Object.entries(built).map(([name, text]) => ({ name, text: unwrap(name, text) }));
|
|
27
|
+
const active = (options.selectedTools ?? ["read", "bash", "edit", "write"]).filter(name => !options.hiddenTools?.includes(name));
|
|
28
|
+
const definitions = session.getAllTools();
|
|
29
|
+
const sources = new Map();
|
|
30
|
+
const fixed = rules(unwrap("rules", nativePromptSections({ cwd, selectedTools: [] }).rules));
|
|
31
|
+
const allBuiltin = rules(unwrap("rules", nativePromptSections({ cwd, selectedTools: active }).rules));
|
|
32
|
+
for (const text of allBuiltin.filter(text => !fixed.includes(text)))
|
|
33
|
+
sources.set(text, { kind: "builtin" });
|
|
34
|
+
for (const name of active)
|
|
35
|
+
for (const text of options.toolGuidelines?.[name] ?? []) {
|
|
36
|
+
const normalized = text.trim();
|
|
37
|
+
if (!sources.has(normalized))
|
|
38
|
+
sources.set(normalized, { kind: "tool", name, path: definitions.find(t => t.name === name)?.sourceInfo.path });
|
|
39
|
+
}
|
|
40
|
+
// The SDK supplies no per-handler attribution for promptGuidelines. Never invent an extension name.
|
|
41
|
+
for (const text of options.promptGuidelines ?? [])
|
|
42
|
+
if (!sources.has(text.trim()))
|
|
43
|
+
sources.set(text.trim(), { kind: "extension" });
|
|
44
|
+
for (const text of fixed)
|
|
45
|
+
if (!sources.has(text))
|
|
46
|
+
sources.set(text, { kind: "builtin" });
|
|
47
|
+
const ruleViews = built.rules ? rules(unwrap("rules", built.rules)).map(text => ({ text, ...sources.get(text) ?? { kind: "unknown" } })) : [];
|
|
48
|
+
return { raw, defaultPreamble, opaque: false, forced: false, sections, rules: ruleViews, options };
|
|
49
|
+
}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { isToolTextContinuation } from "./tool-text.js";
|
|
2
|
+
import { planFromTranscript as nativePlanFromTranscript } from "./plan/progress.js";
|
|
3
|
+
const short = (text, limit) => {
|
|
4
|
+
const first = text.trim().replace(/\s+/g, " ").split(/[。!?\n]/)[0]?.trim() ?? "";
|
|
5
|
+
return first.length > limit ? `${first.slice(0, limit)}…` : first;
|
|
6
|
+
};
|
|
7
|
+
const continuation = /^(?:继续(?:吧|吗)?|可以(?:的|吧|了)?|好的?|开始|接着|可以(?:帮我)?继续(?:吗|吧)?|帮我继续(?:吗|吧)?|please continue|continue)[\s,。!!??]*$/i;
|
|
8
|
+
const nextStep = /^(?:(?:可以|能)?(?:帮我)?(?:开始|继续|接着|进行)(?:下一步|下个阶段|后续工作)?(?:吗|吧|了)?|下一步(?:呢|是什么)?)[\s,。!!??]*$/i;
|
|
9
|
+
const optionReply = /^(?:[1-9]\d?|[A-D])(?:[.、))])?[\s。!!]*$/i;
|
|
10
|
+
const vagueRequest = (text) => continuation.test(text.trim()) || nextStep.test(text.trim()) || optionReply.test(text.trim());
|
|
11
|
+
const greeting = /^(?:hi|hello|hey|你好|嗨|在吗|谢谢)[\s,。!!??]*$/i;
|
|
12
|
+
function taskTitle(messages, userIndex, steps) {
|
|
13
|
+
const textOf = (message) => message.content.map((part) => part.type === "text" && typeof part.text === "string" ? part.text : "").join(" ");
|
|
14
|
+
const current = textOf(messages[userIndex]);
|
|
15
|
+
if (vagueRequest(current)) {
|
|
16
|
+
for (let index = userIndex - 1; index >= 0; index--) {
|
|
17
|
+
if (messages[index].role !== "user" || isToolTextContinuation(messages, index))
|
|
18
|
+
continue;
|
|
19
|
+
const previous = textOf(messages[index]);
|
|
20
|
+
if (!vagueRequest(previous) && !greeting.test(previous.trim()) && previous.trim())
|
|
21
|
+
return short(previous, 56);
|
|
22
|
+
}
|
|
23
|
+
const firstAction = steps.find((step) => step.title && step.title !== "正在分析请求");
|
|
24
|
+
if (firstAction)
|
|
25
|
+
return short(firstAction.title, 56);
|
|
26
|
+
}
|
|
27
|
+
return short(current, 56) || "当前任务";
|
|
28
|
+
}
|
|
29
|
+
function artifact(call) {
|
|
30
|
+
let args = {};
|
|
31
|
+
try {
|
|
32
|
+
args = JSON.parse(call.argumentsText ?? "{}");
|
|
33
|
+
}
|
|
34
|
+
catch { /* keep tool name */ }
|
|
35
|
+
const path = typeof args.path === "string" ? args.path : undefined;
|
|
36
|
+
const command = typeof args.command === "string" ? args.command : undefined;
|
|
37
|
+
return { toolCallId: call.id, kind: call.name, label: path ?? (command ? short(command, 78) : call.name), ...(path ? { path } : {}) };
|
|
38
|
+
}
|
|
39
|
+
function defaultTitle(calls) {
|
|
40
|
+
if (calls.length === 1) {
|
|
41
|
+
const item = artifact(calls[0]);
|
|
42
|
+
return item.kind === "bash" ? `运行 ${item.label}` : item.path ? `${item.kind} ${item.label}` : item.label;
|
|
43
|
+
}
|
|
44
|
+
const name = calls.every((call) => call.name === calls[0].name) ? calls[0].name : "工具";
|
|
45
|
+
return `${name === "read" ? "读取" : name === "write" ? "写入" : name === "bash" ? "运行" : name} ${calls.length} 项`;
|
|
46
|
+
}
|
|
47
|
+
function planFromTranscript(tail, results, actualSteps, finished, finishedAt) {
|
|
48
|
+
const revisions = [];
|
|
49
|
+
const toolCallIds = new Map();
|
|
50
|
+
let activeStepId;
|
|
51
|
+
for (const message of tail) {
|
|
52
|
+
if (message.role !== "assistant")
|
|
53
|
+
continue;
|
|
54
|
+
for (const part of message.content) {
|
|
55
|
+
if (part.type !== "toolCall")
|
|
56
|
+
continue;
|
|
57
|
+
if (part.name !== "task_plan") {
|
|
58
|
+
if (activeStepId)
|
|
59
|
+
toolCallIds.set(activeStepId, [...(toolCallIds.get(activeStepId) ?? []), part.id]);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (results.get(part.id)?.isError)
|
|
63
|
+
continue;
|
|
64
|
+
try {
|
|
65
|
+
const data = JSON.parse(part.argumentsText ?? "{}");
|
|
66
|
+
if (!Array.isArray(data.steps) || !data.steps.length || data.steps.length > 16 || !data.steps.every((step) => typeof step === "object" && step !== null && typeof step.id === "string" && typeof step.title === "string"))
|
|
67
|
+
continue;
|
|
68
|
+
const steps = data.steps.map((step) => ({ id: step.id.trim(), title: short(step.title, 80), ...(typeof step.detail === "string" ? { detail: step.detail.slice(0, 500) } : {}) }));
|
|
69
|
+
if (steps.some((step) => !step.id || !step.title) || new Set(steps.map((step) => step.id)).size !== steps.length)
|
|
70
|
+
continue;
|
|
71
|
+
const ids = new Set(steps.map((step) => step.id));
|
|
72
|
+
if (data.currentStepId && !ids.has(data.currentStepId) || Array.isArray(data.completedStepIds) && data.completedStepIds.some((id) => typeof id !== "string" || !ids.has(id)))
|
|
73
|
+
continue;
|
|
74
|
+
revisions.push({ steps, title: typeof data.title === "string" ? short(data.title, 80) : undefined, completionCriteria: typeof data.completionCriteria === "string" ? data.completionCriteria.trim().slice(0, 240) : undefined, changeSummary: typeof data.changeSummary === "string" ? data.changeSummary.trim().slice(0, 240) : undefined, currentStepId: typeof data.currentStepId === "string" ? data.currentStepId : undefined, completedStepIds: Array.isArray(data.completedStepIds) ? data.completedStepIds.filter((id) => typeof id === "string") : [], timestamp: message.timestamp ?? 0 });
|
|
75
|
+
activeStepId = data.currentStepId || steps.find((step) => !revisions.at(-1).completedStepIds.includes(step.id))?.id;
|
|
76
|
+
}
|
|
77
|
+
catch { /* incomplete streamed tool arguments */ }
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!revisions.length)
|
|
81
|
+
return undefined;
|
|
82
|
+
const latest = revisions.at(-1);
|
|
83
|
+
const previous = revisions.at(-2);
|
|
84
|
+
const before = new Set(previous?.steps.map((step) => step.id));
|
|
85
|
+
const current = new Set(latest.steps.map((step) => step.id));
|
|
86
|
+
const history = new Map();
|
|
87
|
+
for (const [revision, entry] of revisions.entries())
|
|
88
|
+
for (const step of entry.steps)
|
|
89
|
+
if (!history.has(step.id))
|
|
90
|
+
history.set(step.id, { title: step.title, revision });
|
|
91
|
+
const timings = new Map();
|
|
92
|
+
for (const entry of revisions) {
|
|
93
|
+
if (entry.currentStepId && entry.timestamp) {
|
|
94
|
+
const timing = timings.get(entry.currentStepId) ?? {};
|
|
95
|
+
if (!timing.startedAt)
|
|
96
|
+
timing.startedAt = entry.timestamp;
|
|
97
|
+
timings.set(entry.currentStepId, timing);
|
|
98
|
+
}
|
|
99
|
+
for (const id of entry.completedStepIds) {
|
|
100
|
+
const timing = timings.get(id) ?? {};
|
|
101
|
+
if (entry.timestamp && !timing.endedAt)
|
|
102
|
+
timing.endedAt = entry.timestamp;
|
|
103
|
+
timings.set(id, timing);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const completed = new Set(latest.completedStepIds);
|
|
107
|
+
const items = latest.steps.map((step) => ({ id: step.id, title: step.title, detail: step.detail, toolCallIds: toolCallIds.get(step.id) ?? [], status: finished || completed.has(step.id) ? "done" : step.id === latest.currentStepId || !latest.currentStepId && step.id === latest.steps.find((item) => !completed.has(item.id))?.id ? "running" : "pending", ...(history.get(step.id).revision > 0 ? { added: true } : {}), ...timings.get(step.id), ...(finishedAt && timings.get(step.id)?.startedAt && !timings.get(step.id)?.endedAt ? { endedAt: finishedAt } : {}) }));
|
|
108
|
+
for (const item of items) {
|
|
109
|
+
const actions = { read: 0, write: 0, edit: 0, command: 0 };
|
|
110
|
+
for (const step of actualSteps) {
|
|
111
|
+
for (const artifact of step.artifacts) {
|
|
112
|
+
if (!item.toolCallIds?.includes(artifact.toolCallId))
|
|
113
|
+
continue;
|
|
114
|
+
if (artifact.kind === "read")
|
|
115
|
+
actions.read++;
|
|
116
|
+
else if (artifact.kind === "write")
|
|
117
|
+
actions.write++;
|
|
118
|
+
else if (artifact.kind === "edit")
|
|
119
|
+
actions.edit++;
|
|
120
|
+
else if (["bash", "terminal"].includes(artifact.kind))
|
|
121
|
+
actions.command++;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (Object.values(actions).some(Boolean))
|
|
125
|
+
item.actions = actions;
|
|
126
|
+
}
|
|
127
|
+
for (const [id, entry] of history)
|
|
128
|
+
if (!current.has(id))
|
|
129
|
+
items.push({ id, title: entry.title, status: "removed", toolCallIds: toolCallIds.get(id) ?? [], ...timings.get(id) });
|
|
130
|
+
let changes = [];
|
|
131
|
+
let changeSummary;
|
|
132
|
+
for (let index = 1; index < revisions.length; index++) {
|
|
133
|
+
const oldSteps = revisions[index - 1].steps;
|
|
134
|
+
const newSteps = revisions[index].steps;
|
|
135
|
+
const delta = [];
|
|
136
|
+
for (const [position, step] of newSteps.entries()) {
|
|
137
|
+
const oldIndex = oldSteps.findIndex((old) => old.id === step.id);
|
|
138
|
+
if (oldIndex < 0)
|
|
139
|
+
delta.push({ kind: "added", title: step.title, position: position + 1 });
|
|
140
|
+
else if (oldSteps[oldIndex].title !== step.title || oldIndex !== position && oldSteps.length === newSteps.length)
|
|
141
|
+
delta.push({ kind: "updated", title: step.title, position: position + 1 });
|
|
142
|
+
}
|
|
143
|
+
for (const step of oldSteps)
|
|
144
|
+
if (!newSteps.some((next) => next.id === step.id))
|
|
145
|
+
delta.push({ kind: "removed", title: step.title });
|
|
146
|
+
if (delta.length) {
|
|
147
|
+
changes = delta;
|
|
148
|
+
changeSummary = revisions[index].changeSummary;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return { revision: revisions.length, title: [...revisions].reverse().find((entry) => entry.title)?.title, completionCriteria: [...revisions].reverse().find((entry) => entry.completionCriteria)?.completionCriteria, changeSummary, changes, added: previous ? latest.steps.filter((step) => !before.has(step.id)).length : 0, removed: previous ? previous.steps.filter((step) => !current.has(step.id)).length : 0, items };
|
|
152
|
+
}
|
|
153
|
+
/** P0: infer the current task from the server's serialized transcript. The
|
|
154
|
+
* transcript remains authoritative; no browser heuristic decides completion. */
|
|
155
|
+
export function deriveTaskProgress(conversationId, messages, streamingMessage, isStreaming, turnEndedAt) {
|
|
156
|
+
const recorded = nativePlanFromTranscript([...messages, ...(streamingMessage ? [streamingMessage] : [])]);
|
|
157
|
+
const latestUserIndex = messages.findLastIndex((message, index) => message.role === "user" && !isToolTextContinuation(messages, index) && message.content.some((part) => part.type === "text" && typeof part.text === "string"));
|
|
158
|
+
if (latestUserIndex < 0)
|
|
159
|
+
return null;
|
|
160
|
+
const userIndex = latestUserIndex;
|
|
161
|
+
const user = messages[userIndex];
|
|
162
|
+
const tail = [...messages.slice(userIndex + 1), ...(streamingMessage?.role === "assistant" ? [streamingMessage] : [])];
|
|
163
|
+
// A plain conversation is not a task. Create the panel only after pi has
|
|
164
|
+
// actually invoked a tool in this turn.
|
|
165
|
+
if (!recorded.plan && !tail.some((message) => message.role === "assistant" && message.content.some((part) => part.type === "toolCall")))
|
|
166
|
+
return null;
|
|
167
|
+
const results = new Map(tail.filter((message) => message.role === "toolResult" && message.toolCallId).map((message) => [message.toolCallId, message]));
|
|
168
|
+
const steps = [];
|
|
169
|
+
for (const message of tail) {
|
|
170
|
+
if (message.role !== "assistant")
|
|
171
|
+
continue;
|
|
172
|
+
let narrative = "";
|
|
173
|
+
let calls = [];
|
|
174
|
+
let group = 0;
|
|
175
|
+
const flush = () => {
|
|
176
|
+
if (!calls.length)
|
|
177
|
+
return;
|
|
178
|
+
const completed = calls.filter((call) => results.has(call.id)).length;
|
|
179
|
+
const failed = calls.some((call) => results.get(call.id)?.isError);
|
|
180
|
+
const status = completed < calls.length ? "running" : failed ? "failed" : "done";
|
|
181
|
+
const endedAt = Math.max(message.timestamp ?? 0, ...calls.map((call) => results.get(call.id)?.timestamp ?? 0));
|
|
182
|
+
steps.push({ id: `${message.id}:${group++}`, messageId: message.id, title: short(narrative, 24) || defaultTitle(calls), status, startedAt: message.timestamp ?? user.timestamp ?? 0, ...(status !== "running" ? { endedAt } : {}), hint: status === "running" ? `${completed}/${calls.length} 项完成` : failed ? "有工具执行失败" : `${calls.length} 项完成`, artifacts: calls.map((call) => {
|
|
183
|
+
const item = artifact(call);
|
|
184
|
+
const output = results.get(call.id)?.content.filter((part) => part.type === "text" && typeof part.text === "string").map((part) => part.text).join("\n");
|
|
185
|
+
const outputLines = output ? output.replace(/\n$/, "").split("\n").length : 0;
|
|
186
|
+
return outputLines && ["bash", "read"].includes(item.kind) ? { ...item, outputLines } : item;
|
|
187
|
+
}) });
|
|
188
|
+
calls = [];
|
|
189
|
+
narrative = "";
|
|
190
|
+
};
|
|
191
|
+
for (const part of message.content) {
|
|
192
|
+
if (part.type === "toolCall" && typeof part.id === "string") {
|
|
193
|
+
if (["task_plan", "plan"].includes(part.name)) {
|
|
194
|
+
flush();
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
calls.push(part);
|
|
198
|
+
}
|
|
199
|
+
else if (part.type === "text" && typeof part.text === "string") {
|
|
200
|
+
flush();
|
|
201
|
+
narrative = part.text;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
flush();
|
|
205
|
+
}
|
|
206
|
+
if (isStreaming && !steps.some((step) => step.status === "running")) {
|
|
207
|
+
const previous = [...tail].reverse().find((message) => message.role === "assistant");
|
|
208
|
+
steps.push({ id: `${user.id}:pending`, messageId: previous?.id ?? user.id, title: "正在分析请求", status: "running", startedAt: previous?.timestamp ?? user.timestamp ?? 0, artifacts: [] });
|
|
209
|
+
}
|
|
210
|
+
const currentTail = messages.slice(latestUserIndex + 1).concat(streamingMessage ? [streamingMessage] : []);
|
|
211
|
+
const cancelled = currentTail.some((message) => message.role === "assistant" && message.stopReason === "aborted");
|
|
212
|
+
// Earlier failed commands can be followed by a successful fix or rerun.
|
|
213
|
+
// The latest completed tool group is the best observed outcome for this turn.
|
|
214
|
+
const lastCompleted = steps.findLast((step) => step.status !== "running");
|
|
215
|
+
// Plan calls do not create execution rows, but their latest unresolved error
|
|
216
|
+
// must still prevent a successful turn status. A corrected call clears it.
|
|
217
|
+
const planCalls = currentTail.flatMap(message => message.role === "assistant" ? message.content.filter((part) => part.type === "toolCall" && ["plan", "task_plan"].includes(part.name)) : []);
|
|
218
|
+
const planFailed = results.get(planCalls.at(-1)?.id ?? "")?.isError === true;
|
|
219
|
+
const status = cancelled ? "cancelled" : isStreaming ? "running" : planFailed || lastCompleted?.status === "failed" ? "failed" : "done";
|
|
220
|
+
const plannedEnd = status === "done" ? Math.max(user.timestamp ?? 0, turnEndedAt ?? 0, ...tail.map((message) => message.timestamp ?? 0), ...steps.map((step) => step.endedAt ?? 0)) : undefined;
|
|
221
|
+
const plan = recorded.known ? recorded.plan : planFromTranscript(tail, results, steps, status === "done", plannedEnd);
|
|
222
|
+
const planIncomplete = plan?.source === "plan" && plan.status === "active";
|
|
223
|
+
let taskStatus = status;
|
|
224
|
+
if (plan?.status === "cancelled" || plan?.status === "failed")
|
|
225
|
+
taskStatus = plan.status;
|
|
226
|
+
else if (!isStreaming && !cancelled && status !== "failed" && (plan?.awaitingConfirmation || planIncomplete))
|
|
227
|
+
taskStatus = "waiting";
|
|
228
|
+
if (!steps.length && !plan && !planFailed)
|
|
229
|
+
return null;
|
|
230
|
+
const title = (!plan?.awaitingConfirmation && plan?.title) || taskTitle(messages, userIndex, steps);
|
|
231
|
+
const endedAt = status === "running" ? undefined : Math.max(user.timestamp ?? 0, turnEndedAt ?? 0, ...tail.map((message) => message.timestamp ?? 0), ...steps.map((step) => step.endedAt ?? 0));
|
|
232
|
+
return { id: `task:${plan?.origin ?? user.id}`, conversationId, sourceMessageId: user.id, title, status: taskStatus, startedAt: user.timestamp ?? 0, ...(endedAt ? { endedAt } : {}), completed: steps.filter((step) => step.status === "done").length, steps, ...(plan ? { plan } : {}) };
|
|
233
|
+
}
|