chainlesschain 0.162.148 → 0.162.149
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-DwpCCp64.js → AIOps-BJif14yR.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-C9pBYocA.js → ActionButton-CXek6gJY.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BWAkeXxK.js → Analytics-BgQhdAJi.js} +2 -2
- package/src/assets/web-panel/assets/{AppLayout-CivFGH6B.js → AppLayout-DTYl5NtR.js} +3 -3
- package/src/assets/web-panel/assets/{Audit-Cm8hRpZm.js → Audit-BzATQAeR.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DXdFMsE8.js → Backup-BzdPEQhL.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-uAwSTeql.js → BaseInput-BM0KVh8E.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-KU8eeJJE.js → Chat-D7fHXHkz.js} +4 -4
- package/src/assets/web-panel/assets/ChatBubbleRenderer-Wm34RR-b.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-C6AMDkjd.js → Checkbox-CAiSQ9vO.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-t2moDxcO.js → Codegen-Df40CrEe.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DCcsRRhN.js → Col-DIT2fNFU.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DtB-8SAC.js → Community-CSTIbW2k.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-CZm8THYA.js → Compact-DtqXZZUi.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-LiQgC7g1.js → Compliance-CUtzw6o7.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CA8SAxht.js → Cowork-CezmlnmU.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-CtRaF1wD.js → Cron-P4BITarg.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-6-br6Hub.js → Crosschain-BRRiYwvq.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Do2EccrL.js → DID-L5ijB9i4.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-wrXcbzGe.js → Dashboard-CFxro4ob.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-p3FsT245.js → Dropdown-BmAFCQ71.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-D95A2L8q.js → EmailListRenderer-DJBCEuon.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-cLuJW2zo.js → FamilyGuardDashboard-z4oLq6eT.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-Brgq_cbN.js → Federation-DsVCpHMF.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DWLCkNgh.js → FormItemContext-DP3bP5th.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BBqUfQd6.js → GenericCardRenderer-BAXP2Gc6.js} +1 -1
- package/src/assets/web-panel/assets/{Git-8F090w4I.js → Git-I3g_bAw9.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CCogEbxb.js → Governance-jHS5-ioS.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CfLD7v7C.js → Inference-CPL7sfx9.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DDuHJewd.js → KnowledgeGraph-Jf236h4C.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CE8KSEVC.js → Logs-Cm2tcSKg.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-DmwpZmhT.js → Marketplace-CZK82rhi.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-Bf7AazU8.js → McpTools-CZCeji7a.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-D0QU_00S.js → Memory-3l2KVS9k.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-yXS9xdhx.js → MobileBridge-VYdpoLh6.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BuDUoGUP.js → MobileProjects-CiB9cmm1.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-BYyHy28p.js → Mtc-wCFZbBuL.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-CK0aqpiZ.js → MtcAudit-1a3THIyG.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-mNimKYeb.js → Multisig-DMzLB2hG.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-AioAJ0YA.js → NLProgramming-D9wZbf6l.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CVVNCLHE.js → Notes-hrFe2ZM-.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-C4ABj-TK.js → NotificationSettings-CHGX5Jwm.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-CRIFE2Tj.js +1 -0
- package/src/assets/web-panel/assets/{Organization-uozl_gWK.js → Organization-By7FkhtY.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BCZOM2hK.js → Overflow--khGSzJn.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CArcaiaj.js → P2P-CAG9dH35.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Sgq2Srr8.js → PdhVaultBrowser-B3SQZmK9.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BYrQrXnH.js → Permissions-D35ec6JA.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BzHStAbz.js → PersonalDataHub-CxBF7hW_.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-k7KqxX1M.js → Pipeline-s6EtOO1s.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-IumTUWqx.js → Privacy-BbJYmWmO.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BRyImYTf.js → ProjectInit-VGQq1jMT.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BFIqTBFk.js → ProjectSettings-B1ew3Teh.js} +2 -2
- package/src/assets/web-panel/assets/Projects-CGcNIs_g.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CyyFnUPs.js → Providers-mrO47FIK.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-C82cRx-X.js → QrScannerModal-IJF2mHyw.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DGxDF521.js → QuickAsk-CU0wN_Z0.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Cns-Am1y.js → Recommend-DhN37R6G.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-R7OqAIlg.js → RemoteSession-D_xOX_hu.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-D7mgPIYV.js → Reputation-D_Ssv7uH.js} +1 -1
- package/src/assets/web-panel/assets/{Row-B3lEURyd.js → Row-Kx5dKxX7.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-9_UVrpBt.js → RssFeed-BlGwqZkY.js} +2 -2
- package/src/assets/web-panel/assets/{Search-ClZeO80q.js → Search-hLFQzxpb.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BNNJczEp.js → Security-DMlvsVt4.js} +3 -3
- package/src/assets/web-panel/assets/{Services-C5SjrWUj.js → Services-Bd0Qsj2m.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-Ci_obQ-g.js → Skeleton-DFclq9X3.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DdebN15P.js → Skills-BNtln2qY.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-OinZP2vi.js → Sla-Dch5H19G.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-CxzbNF51.js → SpeechSettings-2UfQcU1g.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-D06N_66b.js → SyncSettings-CD9YQr4i.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BdEdW0AZ.js → Tasks-BNu-7MzI.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-F1ctKmPa.js → Templates-D1n9CaIR.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CVz1Urot.js → Tenant-DenL3iBW.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-ZzU0Io1Y.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-Doitzjmf.js → TimelineRenderer-D87IfukO.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BpyVRpVA.js → Tokens-BkiZc8E3.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-nWhWYTbU.js → Trigger-BNRSytGN.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DK_G-wLx.js → Trust-Bwbd4X2m.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B5yBUojO.js → UkeySign-B8O2bs0o.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-C5D51qAe.js → VideoEditing-C2fL8zmH.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CLbL9K7v.js → Wallet-BORYDdE1.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DZUelI3V.js → WebAuthn-C0V5S2FM.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-8RPxt4KW.js → WorkflowEditor-2dR0fcHL.js} +1 -1
- package/src/assets/web-panel/assets/{chat-4N4tOA3d.js → chat-BmuAFAn8.js} +1 -1
- package/src/assets/web-panel/assets/{colors-zbbGVrua.js → colors-CN3smMcK.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-D7iMkbnE.js → compact-item-DCnxb4kW.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CBzPJv-w.js → createContext-vlR43pHn.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DxwmsL4j.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-bHdrQSqZ.js → hasIn-D04tHYFd.js} +1 -1
- package/src/assets/web-panel/assets/{index-DbE5D0WL.js → index-0DnaZGkC.js} +1 -1
- package/src/assets/web-panel/assets/{index-308gCGh7.js → index-430S68MN.js} +1 -1
- package/src/assets/web-panel/assets/{index-kmh1TxRa.js → index-B78xL3s2.js} +1 -1
- package/src/assets/web-panel/assets/{index-QFObYeo1.js → index-BTPEZTk1.js} +1 -1
- package/src/assets/web-panel/assets/{index-BZb8F8YG.js → index-BXRg8GFQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DE9j5YgT.js → index-BasvsWDM.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiG1IZao.js → index-BeGDEXFs.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bqmx24kh.js → index-BqhASEL4.js} +1 -1
- package/src/assets/web-panel/assets/{index-BCr0geV9.js → index-BudvKQfG.js} +1 -1
- package/src/assets/web-panel/assets/{index-S74FpAIn.js → index-C-6NO5il.js} +1 -1
- package/src/assets/web-panel/assets/{index-DyoNgbXl.js → index-C5Sxb1sE.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtbbdLnf.js → index-CP9m9Ggr.js} +3 -3
- package/src/assets/web-panel/assets/{index-CkxK86vf.js → index-CTOCnIQ7.js} +1 -1
- package/src/assets/web-panel/assets/index-Cg2ldRfU.js +1 -0
- package/src/assets/web-panel/assets/{index-BTIjjXry.js → index-ClhAHDK3.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7b1hGry.js → index-CnXebZLL.js} +1 -1
- package/src/assets/web-panel/assets/{index-CPxkoKgA.js → index-CngCC8hC.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ci009ijp.js → index-Cr-A0FYJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdmMoYN1.js → index-CsAsCPJ6.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBNr77E1.js → index-D28DeAAB.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1s0Bz9O.js → index-D5LZVZ0L.js} +1 -1
- package/src/assets/web-panel/assets/{index-oDKNgCsP.js → index-D65_XseV.js} +1 -1
- package/src/assets/web-panel/assets/{index-QNAG4JtR.js → index-D8vwp4qp.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQfu1U78.js → index-DDwLgQY9.js} +1 -1
- package/src/assets/web-panel/assets/{index-BnBOpqv3.js → index-DIpY0qM5.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQ6NcfWz.js → index-DTWg-18U.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4XKpj6c.js → index-DTtRscUa.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1YDh7Wr.js → index-DYAtmqiv.js} +1 -1
- package/src/assets/web-panel/assets/{index-CvRMA9uT.js → index-D_n8_vfI.js} +1 -1
- package/src/assets/web-panel/assets/{index-CahryTX0.js → index-DbADHwhr.js} +1 -1
- package/src/assets/web-panel/assets/{index-BJ4ZGyW0.js → index-DbVsQBOH.js} +1 -1
- package/src/assets/web-panel/assets/index-Dwzo-dtJ.js +1 -0
- package/src/assets/web-panel/assets/{index-xYCm6W2h.js → index-HhNjnCfe.js} +1 -1
- package/src/assets/web-panel/assets/{index-BS4_Mwk6.js → index-ToUh2b1-.js} +1 -1
- package/src/assets/web-panel/assets/{index-DISWAYce.js → index-TslMTwNy.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmqlJed-.js → index-_FIkN3jd.js} +1 -1
- package/src/assets/web-panel/assets/{index-CqdPyWm5.js → index-hpvvtAZ3.js} +1 -1
- package/src/assets/web-panel/assets/{index-BsKehmmS.js → index-jzR7Ujuw.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUyjUkY7.js → index-ljuBiQW9.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-BD55yNBt.js → initDefaultProps-C3wUb4je.js} +1 -1
- package/src/assets/web-panel/assets/{motion-B5Bbe77U.js → motion-D-jYFUNA.js} +1 -1
- package/src/assets/web-panel/assets/{move-CTvIqHEH.js → move-tqb8nwJ2.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BkNyPQKB.js → mtc-parser-DSOjMJMz.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BaXJXgHA.js → omit-CJ7VimIW.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-Bw6-YTxH.js → pickAttrs-qXiG1iT3.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BLdbkLqJ.js → placementArrow-CkGBcy1Z.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-IVYkzntU.js → responsiveObserve-D3WvTlLO.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DFMFwwtY.js → slide-BEE2ftge.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CURYRtZ1.js → statusUtils-CsfBpxiG.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Cfz63s1r.js → styleChecker-xPrIiJPI.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-COJL0KE3.js → useFlexGapSupport-C5Yd-SCR.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-YLLojQQf.js → useFs-D_MDS8HI.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BF_21qUC.js → usePersonalDataHub-BqJh-usA.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-9ZpkA7bb.js → vnode-chm_p-gz.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DhtAfhl8.js → zoom-3-YDNz0Z.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/assets/web-panel/remote-session-sw.js +43 -0
- package/src/command-manifest.json +22 -1
- package/src/commands/agent.js +44 -5
- package/src/commands/codeintel.js +252 -0
- package/src/commands/eval.js +248 -0
- package/src/commands/plugin.js +354 -0
- package/src/commands/team.js +456 -0
- package/src/gateways/ws/message-dispatcher.js +45 -2
- package/src/gateways/ws/remote-session-protocol.js +37 -0
- package/src/gateways/ws/ws-server.js +1 -1
- package/src/harness/prompt-compressor.js +27 -1
- package/src/harness/remote-command-ledger.js +158 -0
- package/src/harness/remote-session-push-apns.js +246 -0
- package/src/harness/remote-session-push-errors.js +15 -0
- package/src/harness/remote-session-push-fcm.js +9 -25
- package/src/harness/remote-session-push-huawei.js +174 -0
- package/src/harness/remote-session-push-oppo.js +171 -0
- package/src/harness/remote-session-push-senders.js +42 -0
- package/src/harness/remote-session-push-vivo.js +179 -0
- package/src/harness/remote-session-push-web.js +299 -0
- package/src/harness/remote-session-push-xiaomi.js +99 -0
- package/src/index.js +6 -0
- package/src/lib/agent-core.js +2 -0
- package/src/lib/agent-sandbox.js +161 -5
- package/src/lib/agent-team/task-lease.js +434 -0
- package/src/lib/agent-team/team-budget.js +165 -0
- package/src/lib/agent-team/team-mailbox.js +106 -0
- package/src/lib/agent-team/team-runner.js +266 -0
- package/src/lib/agent-team/team-worktree.js +204 -0
- package/src/lib/agents.js +18 -0
- package/src/lib/async-hook-supervisor.cjs +305 -0
- package/src/lib/eval/runner.js +163 -0
- package/src/lib/eval/tasks.js +456 -0
- package/src/lib/eval/trend.js +185 -0
- package/src/lib/lsp/__tests__/code-intelligence.integration.test.js +129 -0
- package/src/lib/lsp/__tests__/code-intelligence.test.js +228 -0
- package/src/lib/lsp/__tests__/jsonrpc-stream.test.js +104 -0
- package/src/lib/lsp/__tests__/lsp-client.test.js +258 -0
- package/src/lib/lsp/__tests__/lsp-manager.test.js +264 -0
- package/src/lib/lsp/__tests__/lsp-server-registry.test.js +128 -0
- package/src/lib/lsp/code-intelligence.js +356 -0
- package/src/lib/lsp/jsonrpc-stream.js +139 -0
- package/src/lib/lsp/lsp-client.js +318 -0
- package/src/lib/lsp/lsp-manager.js +323 -0
- package/src/lib/lsp/lsp-server-registry.js +196 -0
- package/src/lib/plugin-monitor-supervisor.js +238 -0
- package/src/lib/plugin-runtime/agents.js +51 -0
- package/src/lib/plugin-runtime/bin.js +100 -0
- package/src/lib/plugin-runtime/hooks.js +100 -0
- package/src/lib/plugin-runtime/install.js +388 -0
- package/src/lib/plugin-runtime/lsp.js +75 -0
- package/src/lib/plugin-runtime/manifest.js +458 -0
- package/src/lib/plugin-runtime/mcp.js +89 -0
- package/src/lib/plugin-runtime/monitors.js +100 -0
- package/src/lib/plugin-runtime/policy.js +144 -0
- package/src/lib/plugin-runtime/reload.js +79 -0
- package/src/lib/plugin-runtime/scopes.js +197 -0
- package/src/lib/plugin-runtime/settings.js +119 -0
- package/src/lib/plugin-runtime/signature.js +107 -0
- package/src/lib/plugin-runtime/skills.js +43 -0
- package/src/lib/plugin-runtime/trust.js +140 -0
- package/src/lib/sandbox-egress-proxy.js +162 -0
- package/src/lib/sandbox-network-policy.js +134 -0
- package/src/lib/sandbox-v2.js +10 -4
- package/src/lib/settings-hook-events.cjs +78 -6
- package/src/lib/settings-hooks.cjs +29 -3
- package/src/lib/settings-loader.cjs +35 -1
- package/src/lib/skill-loader.js +18 -0
- package/src/lib/telemetry/span-recorder.js +237 -0
- package/src/repl/agent-repl.js +400 -4
- package/src/runtime/agent-core.js +546 -52
- package/src/runtime/coding-agent-contract-shared.cjs +82 -8
- package/src/runtime/coding-agent-policy.cjs +32 -7
- package/src/runtime/fallback-model.js +134 -7
- package/src/runtime/headless-runner.js +353 -108
- package/src/runtime/mcp-config.js +46 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DCNfbdlx.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-DIp8Xcbd.js +0 -1
- package/src/assets/web-panel/assets/Projects-Dpid9CDg.js +0 -1
- package/src/assets/web-panel/assets/Terminal-BvAK_Zel.js +0 -3
- package/src/assets/web-panel/assets/devWarning-C2Z5LRgq.js +0 -1
- package/src/assets/web-panel/assets/index-BGp6Yr-Y.js +0 -1
- package/src/assets/web-panel/assets/index-BXiw9dQf.js +0 -1
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSP integration test — exercises the FULL stack (spawn → handshake → didOpen →
|
|
3
|
+
* query) against a REAL `typescript-language-server` if one is resolvable on
|
|
4
|
+
* PATH. When no server is installed (e.g. CI without the toolchain) the whole
|
|
5
|
+
* suite SKIPS visibly rather than passing hollowly ("不假绿" — no cosmetic green).
|
|
6
|
+
*
|
|
7
|
+
* To run it locally: `npm i -g typescript-language-server typescript` (or put a
|
|
8
|
+
* project-local one on PATH), then `npx vitest run code-intelligence.integration`.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
|
12
|
+
import os from "os";
|
|
13
|
+
import fs from "fs";
|
|
14
|
+
import path from "path";
|
|
15
|
+
import { resolveBin } from "../lsp-server-registry.js";
|
|
16
|
+
import { CodeIntelligence } from "../code-intelligence.js";
|
|
17
|
+
|
|
18
|
+
const serverAvailable = Boolean(resolveBin("typescript-language-server"));
|
|
19
|
+
const suite = serverAvailable ? describe : describe.skip;
|
|
20
|
+
|
|
21
|
+
if (!serverAvailable) {
|
|
22
|
+
// Make the skip reason obvious in test output.
|
|
23
|
+
// eslint-disable-next-line no-console
|
|
24
|
+
console.warn(
|
|
25
|
+
"[lsp.integration] SKIP — no `typescript-language-server` on PATH. " +
|
|
26
|
+
"Install it to run real LSP integration coverage.",
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
suite("CodeIntelligence against a real typescript-language-server", () => {
|
|
31
|
+
let tmp;
|
|
32
|
+
let ci;
|
|
33
|
+
|
|
34
|
+
beforeAll(() => {
|
|
35
|
+
tmp = fs.mkdtempSync(path.join(os.tmpdir(), "cc-lsp-it-"));
|
|
36
|
+
fs.mkdirSync(path.join(tmp, "src"));
|
|
37
|
+
fs.writeFileSync(
|
|
38
|
+
path.join(tmp, "package.json"),
|
|
39
|
+
JSON.stringify({ name: "lsp-it", version: "1.0.0", private: true }),
|
|
40
|
+
"utf8",
|
|
41
|
+
);
|
|
42
|
+
fs.writeFileSync(
|
|
43
|
+
path.join(tmp, "tsconfig.json"),
|
|
44
|
+
JSON.stringify({
|
|
45
|
+
compilerOptions: {
|
|
46
|
+
strict: true,
|
|
47
|
+
target: "ES2020",
|
|
48
|
+
module: "ESNext",
|
|
49
|
+
moduleResolution: "node",
|
|
50
|
+
},
|
|
51
|
+
include: ["src"],
|
|
52
|
+
}),
|
|
53
|
+
"utf8",
|
|
54
|
+
);
|
|
55
|
+
fs.writeFileSync(
|
|
56
|
+
path.join(tmp, "src", "math.ts"),
|
|
57
|
+
"export function add(a: number, b: number): number {\n return a + b;\n}\n",
|
|
58
|
+
"utf8",
|
|
59
|
+
);
|
|
60
|
+
fs.writeFileSync(
|
|
61
|
+
path.join(tmp, "src", "main.ts"),
|
|
62
|
+
'import { add } from "./math";\n\nconst total = add(1, 2);\nconsole.log(total);\nconst bad: number = notDeclared;\n',
|
|
63
|
+
"utf8",
|
|
64
|
+
);
|
|
65
|
+
ci = new CodeIntelligence({ projectRoot: tmp, coldStart: true });
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
afterAll(async () => {
|
|
69
|
+
if (ci) await ci.dispose();
|
|
70
|
+
try {
|
|
71
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
72
|
+
} catch {
|
|
73
|
+
/* best effort */
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("resolves a cross-file definition", async () => {
|
|
78
|
+
// `add` usage in main.ts (line 3, col 15) → declaration in math.ts
|
|
79
|
+
const res = await ci.definition(path.join(tmp, "src", "main.ts"), 3, 15);
|
|
80
|
+
expect(res.available).toBe(true);
|
|
81
|
+
expect(res.locations.length).toBeGreaterThan(0);
|
|
82
|
+
expect(res.locations.some((l) => l.file.endsWith("math.ts"))).toBe(true);
|
|
83
|
+
}, 30000);
|
|
84
|
+
|
|
85
|
+
it("finds all references to a symbol across files", async () => {
|
|
86
|
+
// `add` declaration in math.ts (line 1, col 17)
|
|
87
|
+
const res = await ci.references(path.join(tmp, "src", "math.ts"), 1, 17);
|
|
88
|
+
expect(res.available).toBe(true);
|
|
89
|
+
// declaration + import + call site
|
|
90
|
+
expect(res.locations.length).toBeGreaterThanOrEqual(2);
|
|
91
|
+
expect(res.locations.some((l) => l.file.endsWith("main.ts"))).toBe(true);
|
|
92
|
+
}, 30000);
|
|
93
|
+
|
|
94
|
+
it("reports diagnostics for an undefined name", async () => {
|
|
95
|
+
const res = await ci.diagnostics(path.join(tmp, "src", "main.ts"), {
|
|
96
|
+
timeoutMs: 8000,
|
|
97
|
+
});
|
|
98
|
+
expect(res.available).toBe(true);
|
|
99
|
+
expect(res.diagnostics.some((d) => /notDeclared/.test(d.message))).toBe(
|
|
100
|
+
true,
|
|
101
|
+
);
|
|
102
|
+
const err = res.diagnostics.find((d) => d.severity === "error");
|
|
103
|
+
expect(err).toBeTruthy();
|
|
104
|
+
}, 30000);
|
|
105
|
+
|
|
106
|
+
it("lists document symbols", async () => {
|
|
107
|
+
const res = await ci.documentSymbols(path.join(tmp, "src", "math.ts"));
|
|
108
|
+
expect(res.available).toBe(true);
|
|
109
|
+
expect(
|
|
110
|
+
res.symbols.some((s) => s.name === "add" && s.kind === "function"),
|
|
111
|
+
).toBe(true);
|
|
112
|
+
}, 30000);
|
|
113
|
+
|
|
114
|
+
it("previews a rename without mutating files", async () => {
|
|
115
|
+
const before = fs.readFileSync(path.join(tmp, "src", "math.ts"), "utf8");
|
|
116
|
+
const res = await ci.renamePreview(
|
|
117
|
+
path.join(tmp, "src", "math.ts"),
|
|
118
|
+
1,
|
|
119
|
+
17,
|
|
120
|
+
"sum",
|
|
121
|
+
);
|
|
122
|
+
expect(res.available).toBe(true);
|
|
123
|
+
expect(res.edits.length).toBeGreaterThan(0);
|
|
124
|
+
// preview only — the file on disk is unchanged
|
|
125
|
+
expect(fs.readFileSync(path.join(tmp, "src", "math.ts"), "utf8")).toBe(
|
|
126
|
+
before,
|
|
127
|
+
);
|
|
128
|
+
}, 30000);
|
|
129
|
+
});
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeIntelligence tests — result normalization + graceful degradation. Injects
|
|
3
|
+
* a fake LSPManager so no server runs; asserts that raw LSP shapes (Location vs
|
|
4
|
+
* LocationLink, DocumentSymbol vs SymbolInformation, WorkspaceEdit variants) are
|
|
5
|
+
* flattened to 1-based `{file,line,col}` and that "no server" degrades cleanly.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
9
|
+
import { CodeIntelligence, _deps } from "../code-intelligence.js";
|
|
10
|
+
|
|
11
|
+
/** Fake manager: canned request results, or an "unavailable" verdict. */
|
|
12
|
+
function fakeManager({ requestResult, unavailable, diagnostics } = {}) {
|
|
13
|
+
const client = {
|
|
14
|
+
request: async () => requestResult,
|
|
15
|
+
running: true,
|
|
16
|
+
};
|
|
17
|
+
return {
|
|
18
|
+
projectRoot: "/proj",
|
|
19
|
+
async ensureFor() {
|
|
20
|
+
if (unavailable) return { unavailable: true, reason: unavailable };
|
|
21
|
+
return {
|
|
22
|
+
client,
|
|
23
|
+
uri: "file:///proj/a.ts",
|
|
24
|
+
languageId: "typescript",
|
|
25
|
+
root: "/proj",
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
async didChangeFile() {
|
|
29
|
+
return this.ensureFor();
|
|
30
|
+
},
|
|
31
|
+
async waitForDiagnostics() {
|
|
32
|
+
return diagnostics || [];
|
|
33
|
+
},
|
|
34
|
+
async disposeAll() {},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let origRead;
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
origRead = _deps.readFileSync;
|
|
41
|
+
_deps.readFileSync = () => "const foo = 1;\nfoo();\n";
|
|
42
|
+
});
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
_deps.readFileSync = origRead;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe("definition/references normalization", () => {
|
|
48
|
+
it("normalizes a plain Location to 1-based with a snippet", async () => {
|
|
49
|
+
const mgr = fakeManager({
|
|
50
|
+
requestResult: [
|
|
51
|
+
{
|
|
52
|
+
uri: "file:///proj/a.ts",
|
|
53
|
+
range: {
|
|
54
|
+
start: { line: 0, character: 6 },
|
|
55
|
+
end: { line: 0, character: 9 },
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
});
|
|
60
|
+
const ci = new CodeIntelligence({ manager: mgr });
|
|
61
|
+
const res = await ci.definition("a.ts", 2, 1);
|
|
62
|
+
expect(res.available).toBe(true);
|
|
63
|
+
expect(res.locations[0]).toMatchObject({
|
|
64
|
+
file: expect.stringContaining("a.ts"),
|
|
65
|
+
line: 1, // 0 → 1
|
|
66
|
+
col: 7, // 6 → 7
|
|
67
|
+
endLine: 1,
|
|
68
|
+
endCol: 10,
|
|
69
|
+
});
|
|
70
|
+
expect(res.locations[0].snippet).toBe("const foo = 1;");
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("normalizes a LocationLink (targetUri/targetRange)", async () => {
|
|
74
|
+
const mgr = fakeManager({
|
|
75
|
+
requestResult: [
|
|
76
|
+
{
|
|
77
|
+
targetUri: "file:///proj/b.ts",
|
|
78
|
+
targetSelectionRange: {
|
|
79
|
+
start: { line: 4, character: 2 },
|
|
80
|
+
end: { line: 4, character: 5 },
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
});
|
|
85
|
+
const ci = new CodeIntelligence({ manager: mgr });
|
|
86
|
+
const res = await ci.definition("a.ts", 2, 1);
|
|
87
|
+
expect(res.locations[0]).toMatchObject({ line: 5, col: 3 });
|
|
88
|
+
expect(res.locations[0].file).toContain("b.ts");
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe("graceful degradation", () => {
|
|
93
|
+
it("returns available:false with a reason when no server is installed", async () => {
|
|
94
|
+
const mgr = fakeManager({
|
|
95
|
+
unavailable: "no language server installed for typescript",
|
|
96
|
+
});
|
|
97
|
+
const ci = new CodeIntelligence({ manager: mgr });
|
|
98
|
+
const res = await ci.definition("a.ts", 1, 1);
|
|
99
|
+
expect(res).toEqual({
|
|
100
|
+
available: false,
|
|
101
|
+
reason: "no language server installed for typescript",
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
describe("document symbols", () => {
|
|
107
|
+
it("flattens hierarchical DocumentSymbols with container names", async () => {
|
|
108
|
+
const mgr = fakeManager({
|
|
109
|
+
requestResult: [
|
|
110
|
+
{
|
|
111
|
+
name: "MyClass",
|
|
112
|
+
kind: 5, // class
|
|
113
|
+
selectionRange: {
|
|
114
|
+
start: { line: 0, character: 6 },
|
|
115
|
+
end: { line: 0, character: 13 },
|
|
116
|
+
},
|
|
117
|
+
children: [
|
|
118
|
+
{
|
|
119
|
+
name: "method1",
|
|
120
|
+
kind: 6,
|
|
121
|
+
selectionRange: {
|
|
122
|
+
start: { line: 1, character: 2 },
|
|
123
|
+
end: { line: 1, character: 9 },
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
});
|
|
130
|
+
const ci = new CodeIntelligence({ manager: mgr });
|
|
131
|
+
const res = await ci.documentSymbols("a.ts");
|
|
132
|
+
expect(res.symbols).toHaveLength(2);
|
|
133
|
+
expect(res.symbols[0]).toMatchObject({
|
|
134
|
+
name: "MyClass",
|
|
135
|
+
kind: "class",
|
|
136
|
+
line: 1,
|
|
137
|
+
});
|
|
138
|
+
expect(res.symbols[1]).toMatchObject({
|
|
139
|
+
name: "method1",
|
|
140
|
+
kind: "method",
|
|
141
|
+
container: "MyClass",
|
|
142
|
+
line: 2,
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe("diagnostics", () => {
|
|
148
|
+
it("normalizes severity and position", async () => {
|
|
149
|
+
const mgr = fakeManager({
|
|
150
|
+
diagnostics: [
|
|
151
|
+
{
|
|
152
|
+
severity: 1,
|
|
153
|
+
message: "Cannot find name 'x'.",
|
|
154
|
+
range: {
|
|
155
|
+
start: { line: 3, character: 4 },
|
|
156
|
+
end: { line: 3, character: 5 },
|
|
157
|
+
},
|
|
158
|
+
code: 2304,
|
|
159
|
+
source: "ts",
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
});
|
|
163
|
+
const ci = new CodeIntelligence({ manager: mgr });
|
|
164
|
+
const res = await ci.diagnostics("a.ts");
|
|
165
|
+
expect(res.diagnostics[0]).toMatchObject({
|
|
166
|
+
severity: "error",
|
|
167
|
+
message: "Cannot find name 'x'.",
|
|
168
|
+
line: 4,
|
|
169
|
+
col: 5,
|
|
170
|
+
code: "2304",
|
|
171
|
+
source: "ts",
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
describe("rename preview", () => {
|
|
177
|
+
it("flattens WorkspaceEdit.changes without applying", async () => {
|
|
178
|
+
const mgr = fakeManager({
|
|
179
|
+
requestResult: {
|
|
180
|
+
changes: {
|
|
181
|
+
"file:///proj/a.ts": [
|
|
182
|
+
{
|
|
183
|
+
range: {
|
|
184
|
+
start: { line: 0, character: 6 },
|
|
185
|
+
end: { line: 0, character: 9 },
|
|
186
|
+
},
|
|
187
|
+
newText: "bar",
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
const ci = new CodeIntelligence({ manager: mgr });
|
|
194
|
+
const res = await ci.renamePreview("a.ts", 1, 7, "bar");
|
|
195
|
+
expect(res.edits).toHaveLength(1);
|
|
196
|
+
expect(res.edits[0].file).toContain("a.ts");
|
|
197
|
+
expect(res.edits[0].edits[0]).toMatchObject({
|
|
198
|
+
line: 1,
|
|
199
|
+
col: 7,
|
|
200
|
+
newText: "bar",
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("flattens WorkspaceEdit.documentChanges", async () => {
|
|
205
|
+
const mgr = fakeManager({
|
|
206
|
+
requestResult: {
|
|
207
|
+
documentChanges: [
|
|
208
|
+
{
|
|
209
|
+
textDocument: { uri: "file:///proj/c.ts", version: 2 },
|
|
210
|
+
edits: [
|
|
211
|
+
{
|
|
212
|
+
range: {
|
|
213
|
+
start: { line: 9, character: 0 },
|
|
214
|
+
end: { line: 9, character: 3 },
|
|
215
|
+
},
|
|
216
|
+
newText: "baz",
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
},
|
|
220
|
+
],
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
const ci = new CodeIntelligence({ manager: mgr });
|
|
224
|
+
const res = await ci.renamePreview("a.ts", 1, 1, "baz");
|
|
225
|
+
expect(res.edits[0].file).toContain("c.ts");
|
|
226
|
+
expect(res.edits[0].edits[0]).toMatchObject({ line: 10, newText: "baz" });
|
|
227
|
+
});
|
|
228
|
+
});
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* jsonrpc-stream tests — LSP Content-Length framing. Pure, no IO. Pins the
|
|
3
|
+
* split-chunk / multi-message / multibyte-length / lenient-LF edge cases that a
|
|
4
|
+
* naive framer gets wrong.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect } from "vitest";
|
|
8
|
+
import {
|
|
9
|
+
encodeMessage,
|
|
10
|
+
parseContentLength,
|
|
11
|
+
MessageBuffer,
|
|
12
|
+
} from "../jsonrpc-stream.js";
|
|
13
|
+
|
|
14
|
+
describe("encodeMessage", () => {
|
|
15
|
+
it("frames a message with a byte-accurate Content-Length", () => {
|
|
16
|
+
const buf = encodeMessage({ jsonrpc: "2.0", id: 1, method: "ping" });
|
|
17
|
+
const text = buf.toString("utf8");
|
|
18
|
+
const body = JSON.stringify({ jsonrpc: "2.0", id: 1, method: "ping" });
|
|
19
|
+
expect(text).toBe(
|
|
20
|
+
`Content-Length: ${Buffer.byteLength(body)}\r\n\r\n${body}`,
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("counts BYTES not characters for multibyte content", () => {
|
|
25
|
+
const buf = encodeMessage({ text: "你好" }); // 6 UTF-8 bytes for the two chars
|
|
26
|
+
const headerLen = Number(
|
|
27
|
+
/Content-Length: (\d+)/.exec(buf.toString("utf8"))[1],
|
|
28
|
+
);
|
|
29
|
+
const body = JSON.stringify({ text: "你好" });
|
|
30
|
+
expect(headerLen).toBe(Buffer.byteLength(body, "utf8"));
|
|
31
|
+
// round-trips through the buffer intact
|
|
32
|
+
const mb = new MessageBuffer().append(buf);
|
|
33
|
+
expect(mb.read()).toEqual({ text: "你好" });
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe("parseContentLength", () => {
|
|
38
|
+
it("reads the header case-insensitively", () => {
|
|
39
|
+
expect(parseContentLength("content-length: 42")).toBe(42);
|
|
40
|
+
expect(parseContentLength("Content-Length: 7\r\nContent-Type: x")).toBe(
|
|
41
|
+
7,
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
it("returns null when absent or invalid", () => {
|
|
45
|
+
expect(parseContentLength("Content-Type: application/json")).toBeNull();
|
|
46
|
+
expect(parseContentLength("Content-Length: abc")).toBeNull();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe("MessageBuffer", () => {
|
|
51
|
+
it("decodes a single framed message", () => {
|
|
52
|
+
const mb = new MessageBuffer();
|
|
53
|
+
mb.append(encodeMessage({ id: 1, result: "ok" }));
|
|
54
|
+
expect(mb.read()).toEqual({ id: 1, result: "ok" });
|
|
55
|
+
expect(mb.read()).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("decodes multiple messages in one chunk", () => {
|
|
59
|
+
const mb = new MessageBuffer();
|
|
60
|
+
const chunk = Buffer.concat([
|
|
61
|
+
encodeMessage({ id: 1 }),
|
|
62
|
+
encodeMessage({ id: 2 }),
|
|
63
|
+
encodeMessage({ id: 3 }),
|
|
64
|
+
]);
|
|
65
|
+
mb.append(chunk);
|
|
66
|
+
expect(mb.readAll().map((m) => m.id)).toEqual([1, 2, 3]);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("reassembles a message split across chunks (header and body)", () => {
|
|
70
|
+
const full = encodeMessage({ id: 7, method: "textDocument/definition" });
|
|
71
|
+
const mb = new MessageBuffer();
|
|
72
|
+
// split mid-header and mid-body
|
|
73
|
+
for (let i = 0; i < full.length; i += 5) {
|
|
74
|
+
mb.append(full.slice(i, i + 5));
|
|
75
|
+
}
|
|
76
|
+
expect(mb.read()).toEqual({ id: 7, method: "textDocument/definition" });
|
|
77
|
+
expect(mb.hasPartial).toBe(false);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("retains a partial frame until the rest arrives", () => {
|
|
81
|
+
const full = encodeMessage({ id: 9 });
|
|
82
|
+
const mb = new MessageBuffer();
|
|
83
|
+
mb.append(full.slice(0, full.length - 3));
|
|
84
|
+
expect(mb.read()).toBeNull();
|
|
85
|
+
expect(mb.hasPartial).toBe(true);
|
|
86
|
+
mb.append(full.slice(full.length - 3));
|
|
87
|
+
expect(mb.read()).toEqual({ id: 9 });
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("tolerates LF-only header separators", () => {
|
|
91
|
+
const body = JSON.stringify({ id: 5 });
|
|
92
|
+
const mb = new MessageBuffer();
|
|
93
|
+
mb.append(`Content-Length: ${body.length}\n\n${body}`);
|
|
94
|
+
expect(mb.read()).toEqual({ id: 5 });
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("skips a body that isn't valid JSON but stays aligned for the next frame", () => {
|
|
98
|
+
const mb = new MessageBuffer();
|
|
99
|
+
const bad = "Content-Length: 3\r\n\r\n{{{";
|
|
100
|
+
mb.append(bad + encodeMessage({ id: 2 }).toString("utf8"));
|
|
101
|
+
// bad frame dropped, good one still decoded
|
|
102
|
+
expect(mb.read()).toEqual({ id: 2 });
|
|
103
|
+
});
|
|
104
|
+
});
|