chainlesschain 0.162.94 → 0.162.96
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/bin/chainlesschain.js +8 -18
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-CiEoV_Hg.js → AIOps-Bo9Ux24z.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DrrjQMuK.js → ActionButton-CExgXSQT.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-ChlhPe9a.js → Analytics-BNnZhRTZ.js} +2 -2
- package/src/assets/web-panel/assets/{AppLayout-CIkI7d5o.js → AppLayout-D9xfqFCT.js} +4 -4
- package/src/assets/web-panel/assets/{Audit-_sY9bNSN.js → Audit-Cpgu8uCw.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DvzaThN8.js → Backup-CHdEJnNE.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DDZW_DU8.js → BaseInput-Cbw-PxBq.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DqErkog2.js → Chat-ChHTZK_6.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-BcnNHS-r.js → ChatBubbleRenderer-Dl6z6ZH7.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-NWDuyRK6.js → Checkbox-Cj8d9bru.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-B_jnSC8a.js → Codegen-C2YobW4j.js} +1 -1
- package/src/assets/web-panel/assets/{Col-B-uyUy0z.js → Col-CxfV5FGT.js} +1 -1
- package/src/assets/web-panel/assets/{Community-Dmf1MpG7.js → Community-CiwOASMj.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-fGI68M5y.js → Compact-CTg_2iKW.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-PV9qT-iV.js → Compliance-HMbsTmtw.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BM6BvCgv.js → Cowork-DyNDqGR2.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-BsSWwFFo.js → Cron-9-x5M7qy.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DUdPVYvS.js → Crosschain-4msgDaYJ.js} +1 -1
- package/src/assets/web-panel/assets/{DID-PPLLhrJs.js → DID--2Beb5Po.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-Cn_Xjj80.js → Dashboard-T6nq0Lzs.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DkTXjy5D.js → Dropdown-D_Q6T10v.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-BnA27cjB.js → EmailListRenderer-TnN21bJx.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-jqrv5VCp.js → FamilyGuardDashboard-kky_uIij.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DESwXwtR.js → Federation-C1GkNY4B.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-C9gbyY1r.js → FormItemContext-5-_Fc5YV.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-CkZB9crH.js → GenericCardRenderer-CmHiB7sr.js} +1 -1
- package/src/assets/web-panel/assets/{Git-B6niu0W9.js → Git-Cuci_BPI.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BrF28dEi.js → Governance-BU0cO2LD.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CZDnV8SN.js → Inference-BDFNgEcx.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-eqZ0hP0l.js → KnowledgeGraph-DITXUzHz.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BlHS7DoS.js → Logs-Ea-07CRd.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-NOp9G83e.js → Marketplace-D6OBbRVG.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-B6wMx173.js → McpTools-eiKpIJMi.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-BKVeTAeT.js → Memory-M-X-T8UF.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Da2y6iYW.js → MobileBridge-xcZb9Ekv.js} +2 -2
- package/src/assets/web-panel/assets/MobileProjects-DCfoTPRC.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-B7Hy5rAT.js → Mtc-BWfGDzD8.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-BgBoX0XI.js → MtcAudit-imBuld-U.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-Db7bwi5J.js → Multisig-C2kcsq7I.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-f9ca2vst.js → NLProgramming-DObvXSXP.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-meVqoOMz.js → Notes-C-6OGJMe.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-BfEhBXNo.js → NotificationSettings-ub7Ozxci.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-e25Q6ALJ.js → OrderTableRenderer-CR2W89Vk.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BpgOG9lj.js → Organization-DNA_Wty7.js} +2 -2
- package/src/assets/web-panel/assets/{Overflow-fI3L05Rq.js → Overflow-rT4Wb4rQ.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-wD0wpJJY.js → P2P-CK-hARKv.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BWV9J4VZ.js → PdhVaultBrowser-C2pbtNbT.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BJH7W2iv.js → Permissions-B8EIEqGJ.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-CqQ3XpMz.js → PersonalDataHub-BxNVNU3s.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-CHyXCU1i.js → Pipeline-CT9pbkyY.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CJtfNlc7.js → Privacy-DhCNd2CS.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CKOaHFGR.js → ProjectInit-Qngnx-vQ.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-QD8wp_EM.js → ProjectSettings-Dfn-nQc1.js} +2 -2
- package/src/assets/web-panel/assets/Projects-BKdiSaPR.js +1 -0
- package/src/assets/web-panel/assets/{Providers-BPESqCEg.js → Providers-4o9B_n-X.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-C5AzvvRo.js → QuickAsk-bs1qvF30.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-cGpF3tsA.js → Recommend-CuEnKA2K.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-Duaxvbt9.js → Reputation-DbfvmRb2.js} +1 -1
- package/src/assets/web-panel/assets/{Row-xsUwB5Ay.js → Row-DvMJGAI3.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-DmUUsqaF.js → RssFeed-oJ0BZvmA.js} +3 -3
- package/src/assets/web-panel/assets/{Search-Do9YuDbX.js → Search-DnIVrY9O.js} +1 -1
- package/src/assets/web-panel/assets/{Security-06BgEn-d.js → Security-CIWhI_Tc.js} +3 -3
- package/src/assets/web-panel/assets/{Services-DyaCes7r.js → Services-DLrnpjwm.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-Cj_VbkFG.js → Skeleton-CYmqgtVb.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DCOWMJOR.js → Skills-BUzCkoeu.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-C44_86bu.js → Sla-DYRE4bnS.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-BXhBJSMB.js → SpeechSettings-_6MurdOg.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-BpHsaNWg.js → SyncSettings-UIdnF5Li.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-COx2CjT8.js +1 -0
- package/src/assets/web-panel/assets/{Templates-aEWbCOdo.js → Templates-BcHAmkZo.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DkOLw1Yz.js → Tenant-CjYQS8yZ.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-5Z4paIoh.js → Terminal-BmfOPcWt.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-CYhublOm.js → TimelineRenderer-D5HuarNQ.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-h57dBT4T.js → Tokens-C_fbProA.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-abE21FpD.js → Trigger-JPulpRx8.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-urB3VZip.js → Trust-CnO-062O.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-D6uXV9pp.js → UkeySign-HpNovvau.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-C9MxXAzw.js → VideoEditing-yMncxH7y.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DTn5rW4u.js → Wallet-Cug-t7Np.js} +3 -3
- package/src/assets/web-panel/assets/{WebAuthn-BNYEqeqr.js → WebAuthn--U1-NR-3.js} +2 -2
- package/src/assets/web-panel/assets/{WorkflowEditor-CsRoOJPT.js → WorkflowEditor-R-XvSJ3S.js} +1 -1
- package/src/assets/web-panel/assets/{chat-B5GoUHDS.js → chat-CCI1i6Rp.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BF_Rqaab.js → colors-C-mqoaLt.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BNPfqT4P.js → compact-item-De_N2iRR.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-C3qLKXX-.js → createContext-DbTM6sjZ.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-OcLPHSl5.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BLpAeFXB.js → hasIn-D0Adylyc.js} +1 -1
- package/src/assets/web-panel/assets/index-7E_mHkDU.js +1 -0
- package/src/assets/web-panel/assets/{index-BOoTjHGU.js → index-AY937BxS.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cv1WRH-j.js → index-B6hgy5VC.js} +1 -1
- package/src/assets/web-panel/assets/{index-C2wJowV1.js → index-B7XnpLHk.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dj6rUk3f.js → index-B7gw-tDm.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dz7o1Zt6.js → index-BBgDgkwW.js} +1 -1
- package/src/assets/web-panel/assets/{index-CMRdeB2r.js → index-BMmeiw88.js} +1 -1
- package/src/assets/web-panel/assets/{index-2-7AD4Fq.js → index-BU6XtnSx.js} +1 -1
- package/src/assets/web-panel/assets/{index-7Tt41tHa.js → index-Bi7VUG0R.js} +1 -1
- package/src/assets/web-panel/assets/{index-CaROOJ5Z.js → index-BtE3cw9m.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmrPbYXh.js → index-C9ej-MF0.js} +3 -3
- package/src/assets/web-panel/assets/{index-CgIrRLBP.js → index-CIEiQl1j.js} +1 -1
- package/src/assets/web-panel/assets/{index-DudglWTC.js → index-CKgaW9E5.js} +1 -1
- package/src/assets/web-panel/assets/{index-C8B3rHnr.js → index-CY0KKR5f.js} +1 -1
- package/src/assets/web-panel/assets/index-CbV3-WlB.js +1 -0
- package/src/assets/web-panel/assets/{index-ixN0R0We.js → index-Co1UkcFX.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cqb8TXEp.js → index-CzP5d5LW.js} +1 -1
- package/src/assets/web-panel/assets/{index-DH95hKUN.js → index-D0NJ5lRi.js} +1 -1
- package/src/assets/web-panel/assets/{index-C6yRwT6e.js → index-D0gBsqTX.js} +1 -1
- package/src/assets/web-panel/assets/{index-o1doEeT3.js → index-D5F6shtn.js} +1 -1
- package/src/assets/web-panel/assets/{index-BxWEK9FS.js → index-DVtamtlm.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cxd2RsZR.js → index-DWT18hDG.js} +1 -1
- package/src/assets/web-panel/assets/{index-vXHPZOmO.js → index-DaXb4B9P.js} +1 -1
- package/src/assets/web-panel/assets/{index-BJsVUj80.js → index-DjQA0Vez.js} +1 -1
- package/src/assets/web-panel/assets/{index-CIjPwa7h.js → index-Ds8NJVEL.js} +1 -1
- package/src/assets/web-panel/assets/{index-DMKiwMJa.js → index-DuP-8HWu.js} +1 -1
- package/src/assets/web-panel/assets/{index-BIpGZeh2.js → index-DwLTiJ31.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dn95Blhx.js → index-T3VhH8cO.js} +1 -1
- package/src/assets/web-panel/assets/{index-BqjU6Jp9.js → index-TDY1o0w3.js} +1 -1
- package/src/assets/web-panel/assets/{index-CBFekqcY.js → index-TRy2Gc3V.js} +1 -1
- package/src/assets/web-panel/assets/{index-D-PNuV4r.js → index-W1OMxCmI.js} +1 -1
- package/src/assets/web-panel/assets/{index-BlEDjdTc.js → index-ftFRZbuc.js} +1 -1
- package/src/assets/web-panel/assets/{index-DMKbLaTg.js → index-iGPGaORA.js} +1 -1
- package/src/assets/web-panel/assets/{index-DYWExa2Z.js → index-jhy5KQvg.js} +1 -1
- package/src/assets/web-panel/assets/{index-BryugSCS.js → index-qUSZJcgw.js} +1 -1
- package/src/assets/web-panel/assets/{index-81hgV6U6.js → index-w3f6lqkD.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmBMP52w.js → index-xdMc71Kh.js} +1 -1
- package/src/assets/web-panel/assets/{index-KUdyAwqr.js → index-xhX5eg2Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-DGVf-eOG.js → index-zkTiW6d6.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-Dhfx-jOJ.js → initDefaultProps-CIHqouWk.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DzZPc4Mq.js → motion-D1iUKftk.js} +1 -1
- package/src/assets/web-panel/assets/{move-D6R8EIjz.js → move-YOpWjmjL.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CPniUUR1.js → omit-C_1357UY.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DbzxHNNa.js → pickAttrs-CDb4dq6o.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-B_MxmwXz.js → placementArrow-D-OGYyhd.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-Em-jKJ7U.js → responsiveObserve-hS-j69A0.js} +1 -1
- package/src/assets/web-panel/assets/{slide-B2RV1mQl.js → slide-tnjuvphU.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-C9Ps6HQe.js → statusUtils-BERfMMcU.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DCoehh1S.js → styleChecker-DKpl2K9E.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DZOaLVto.js → useFlexGapSupport-C_sX4D3N.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-Dk_JA91R.js → useFs-DBcxC1vK.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CJR6Dqtz.js → usePersonalDataHub-CeoDf2XI.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BaFNaDQL.js → vnode-DC9Pmj_u.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CxA9IYpM.js → zoom-CZA58J7M.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/activitypub.js +19 -3
- package/src/commands/agent.js +25 -0
- package/src/commands/ask.js +13 -0
- package/src/commands/config.js +17 -1
- package/src/commands/cost.js +6 -1
- package/src/commands/dao.js +16 -3
- package/src/commands/dlp.js +7 -1
- package/src/commands/hub.js +13 -0
- package/src/commands/mtc.js +37 -1
- package/src/commands/pdh.js +162 -0
- package/src/gateways/discord/discord-formatter.js +18 -1
- package/src/gateways/telegram/telegram-formatter.js +6 -3
- package/src/gateways/ws/ws-server.js +19 -1
- package/src/harness/mcp-client.js +19 -2
- package/src/harness/plugin-manager.js +20 -0
- package/src/harness/worktree-isolator.js +17 -1
- package/src/index.js +2 -0
- package/src/lib/__tests__/model-deprecation.test.js +194 -0
- package/src/lib/a2a-protocol.js +23 -9
- package/src/lib/agent-core.js +2 -5
- package/src/lib/audit-mtc.js +40 -2
- package/src/lib/chat-core.js +141 -18
- package/src/lib/claude-code-bridge.js +14 -2
- package/src/lib/cli-anything-bridge.js +5 -0
- package/src/lib/cli-numeric.js +38 -0
- package/src/lib/config-manager.js +37 -6
- package/src/lib/cowork/ab-comparator-cli.js +6 -2
- package/src/lib/cowork-cron.js +45 -34
- package/src/lib/cowork-learning.js +31 -1
- package/src/lib/cowork-share.js +39 -3
- package/src/lib/cowork-template-marketplace.js +54 -2
- package/src/lib/cowork-workflow.js +33 -6
- package/src/lib/cross-chain-mtc.js +41 -12
- package/src/lib/crypto-manager.js +12 -2
- package/src/lib/dbevo.js +19 -8
- package/src/lib/downloader.js +24 -9
- package/src/lib/evomap-governance.js +4 -4
- package/src/lib/evomap-manager.js +54 -7
- package/src/lib/fatal-handler.js +48 -0
- package/src/lib/file-checkpoint.js +56 -4
- package/src/lib/git-integration.js +28 -0
- package/src/lib/goal-store.js +36 -10
- package/src/lib/hierarchical-memory.js +6 -0
- package/src/lib/llm-pricing.js +52 -2
- package/src/lib/mcp-oauth.js +37 -7
- package/src/lib/memory-manager.js +23 -2
- package/src/lib/model-deprecation.js +249 -0
- package/src/lib/pdh-feedback-ledger.js +131 -0
- package/src/lib/permanent-memory.js +30 -2
- package/src/lib/permission-rules.cjs +11 -3
- package/src/lib/personal-data-hub-aichat-wizard.js +33 -3
- package/src/lib/personal-data-hub-wiring.js +36 -13
- package/src/lib/project-instructions.js +10 -4
- package/src/lib/runnable-provider.js +62 -31
- package/src/lib/session-tail.js +6 -1
- package/src/lib/session-usage.js +34 -1
- package/src/lib/skill-loader.js +4 -1
- package/src/lib/skill-packs/generator.js +25 -2
- package/src/lib/stream-retry.js +56 -0
- package/src/lib/sync-credentials.js +53 -17
- package/src/lib/token-tracker.js +12 -2
- package/src/lib/with-file-lock.js +87 -0
- package/src/repl/agent-repl.js +52 -13
- package/src/repl/chat-repl.js +10 -0
- package/src/repl/session-cost.js +31 -3
- package/src/runtime/agent-core.js +474 -53
- package/src/runtime/coding-agent-contract-shared.cjs +58 -1
- package/src/runtime/coding-agent-policy.cjs +10 -0
- package/src/runtime/file-ref-expander.js +29 -1
- package/src/runtime/headless-runner.js +51 -6
- package/src/runtime/headless-stream.js +219 -2
- package/src/skills/video-editing/tools/commit.js +15 -1
- package/src/assets/web-panel/assets/MobileProjects-CTFPhn4A.js +0 -1
- package/src/assets/web-panel/assets/Projects-Dj33CO-H.js +0 -1
- package/src/assets/web-panel/assets/Tasks-C83eyBn8.js +0 -1
- package/src/assets/web-panel/assets/devWarning-D5Rwbl_Y.js +0 -1
- package/src/assets/web-panel/assets/index-7ls1Z3dH.js +0 -1
- package/src/assets/web-panel/assets/index-DoldiBPq.js +0 -1
|
@@ -27,11 +27,22 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
|
|
|
27
27
|
title: "Read File",
|
|
28
28
|
kind: "filesystem",
|
|
29
29
|
tier: "mvp",
|
|
30
|
-
description:
|
|
30
|
+
description:
|
|
31
|
+
"Read a file's content. Jupyter notebooks (.ipynb) are rendered as a compact cell listing (index/id/type/source, outputs hidden) for use with notebook_edit — pass raw:true for the underlying JSON.",
|
|
31
32
|
inputSchema: {
|
|
32
33
|
type: "object",
|
|
33
34
|
properties: {
|
|
34
35
|
path: { type: "string", description: "File path to read" },
|
|
36
|
+
hashed: {
|
|
37
|
+
type: "boolean",
|
|
38
|
+
description:
|
|
39
|
+
"Prefix each line with a 6-char content hash for edit_file_hashed anchoring",
|
|
40
|
+
},
|
|
41
|
+
raw: {
|
|
42
|
+
type: "boolean",
|
|
43
|
+
description:
|
|
44
|
+
"For .ipynb: return the raw notebook JSON instead of the rendered cell listing",
|
|
45
|
+
},
|
|
35
46
|
},
|
|
36
47
|
required: ["path"],
|
|
37
48
|
},
|
|
@@ -69,6 +80,52 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
|
|
|
69
80
|
tags: ["tool:write_file", "contract:coding-agent", "tier:mvp"],
|
|
70
81
|
},
|
|
71
82
|
},
|
|
83
|
+
{
|
|
84
|
+
name: "notebook_edit",
|
|
85
|
+
title: "Edit Notebook",
|
|
86
|
+
kind: "filesystem",
|
|
87
|
+
tier: "mvp",
|
|
88
|
+
description:
|
|
89
|
+
"Edit a Jupyter notebook (.ipynb) cell. edit_mode 'replace' (default) overwrites a cell's source; 'insert' adds a new cell (after the target cell, or at the top when no target given); 'delete' removes a cell. Identify the target with cell_id (preferred) or 0-based cell_index. cell_type ('code'|'markdown') is required for 'insert'. Source is plain text with newlines preserved; replacing a code cell clears its previous outputs + execution_count.",
|
|
90
|
+
inputSchema: {
|
|
91
|
+
type: "object",
|
|
92
|
+
properties: {
|
|
93
|
+
path: { type: "string", description: "Path to the .ipynb notebook" },
|
|
94
|
+
new_source: {
|
|
95
|
+
type: "string",
|
|
96
|
+
description: "New cell source text (required for replace/insert)",
|
|
97
|
+
},
|
|
98
|
+
cell_id: {
|
|
99
|
+
type: "string",
|
|
100
|
+
description: "Target cell id (preferred over cell_index)",
|
|
101
|
+
},
|
|
102
|
+
cell_index: {
|
|
103
|
+
type: "number",
|
|
104
|
+
description: "0-based cell index (when cell_id is unknown)",
|
|
105
|
+
},
|
|
106
|
+
cell_type: {
|
|
107
|
+
type: "string",
|
|
108
|
+
enum: ["code", "markdown"],
|
|
109
|
+
description: "Cell type — required for edit_mode 'insert'",
|
|
110
|
+
},
|
|
111
|
+
edit_mode: {
|
|
112
|
+
type: "string",
|
|
113
|
+
enum: ["replace", "insert", "delete"],
|
|
114
|
+
description: "replace (default) | insert | delete",
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
required: ["path"],
|
|
118
|
+
},
|
|
119
|
+
...TOOL_POLICY_METADATA.notebook_edit,
|
|
120
|
+
permissions: {
|
|
121
|
+
level: "elevated",
|
|
122
|
+
scopes: ["filesystem:write"],
|
|
123
|
+
},
|
|
124
|
+
telemetry: {
|
|
125
|
+
category: "filesystem",
|
|
126
|
+
tags: ["tool:notebook_edit", "contract:coding-agent", "tier:mvp"],
|
|
127
|
+
},
|
|
128
|
+
},
|
|
72
129
|
{
|
|
73
130
|
name: "edit_file",
|
|
74
131
|
title: "Edit File",
|
|
@@ -94,6 +94,16 @@ const TOOL_POLICY_METADATA = Object.freeze({
|
|
|
94
94
|
approvalFlow: "plan",
|
|
95
95
|
isReadOnly: false,
|
|
96
96
|
},
|
|
97
|
+
notebook_edit: {
|
|
98
|
+
riskLevel: RISK_LEVELS.MEDIUM,
|
|
99
|
+
category: TOOL_CATEGORIES.WRITE,
|
|
100
|
+
availableInPlanMode: false,
|
|
101
|
+
planModeBehavior: "blocked",
|
|
102
|
+
requiresPlanApproval: true,
|
|
103
|
+
requiresConfirmation: false,
|
|
104
|
+
approvalFlow: "plan",
|
|
105
|
+
isReadOnly: false,
|
|
106
|
+
},
|
|
97
107
|
run_shell: {
|
|
98
108
|
riskLevel: RISK_LEVELS.HIGH,
|
|
99
109
|
category: TOOL_CATEGORIES.EXECUTE,
|
|
@@ -110,6 +110,28 @@ function looksBinary(buf) {
|
|
|
110
110
|
return false;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Read at most `limit` bytes from the start of a file. A plain `@file` only
|
|
115
|
+
* ever shows the first `maxBytes`, so reading the whole thing into memory first
|
|
116
|
+
* (readFileSync) would allocate the entire file — pointless for a 300 MB log and
|
|
117
|
+
* a hard failure for files > 2 GB. We read `limit` bytes so truncation can still
|
|
118
|
+
* be detected (caller passes maxBytes + 1). Falls back to readFileSync if the
|
|
119
|
+
* injected fs lacks the lower-level calls.
|
|
120
|
+
*/
|
|
121
|
+
function readBoundedFile(fs, abs, limit) {
|
|
122
|
+
if (typeof fs.openSync !== "function" || typeof fs.readSync !== "function") {
|
|
123
|
+
return fs.readFileSync(abs);
|
|
124
|
+
}
|
|
125
|
+
const fd = fs.openSync(abs, "r");
|
|
126
|
+
try {
|
|
127
|
+
const buf = Buffer.alloc(limit);
|
|
128
|
+
const n = fs.readSync(fd, buf, 0, limit, 0);
|
|
129
|
+
return buf.subarray(0, n);
|
|
130
|
+
} finally {
|
|
131
|
+
fs.closeSync(fd);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
113
135
|
/**
|
|
114
136
|
* Resolve a single raw token to an injectable ref descriptor, or null when it
|
|
115
137
|
* does not resolve to an existing path. Tries the literal path first, then a
|
|
@@ -159,9 +181,15 @@ function resolveRef(raw, { cwd, fs, path, maxBytes, maxDirEntries }) {
|
|
|
159
181
|
};
|
|
160
182
|
}
|
|
161
183
|
if (stat.isFile()) {
|
|
184
|
+
// PDFs (pdf-parse needs the bytes) and line ranges (must reach the end
|
|
185
|
+
// line) need the whole file; a plain inline only ever shows the first
|
|
186
|
+
// maxBytes, so cap the read there instead of slurping the entire file.
|
|
187
|
+
const needsWholeFile = isPdf(fsPath) || range != null;
|
|
162
188
|
let buf;
|
|
163
189
|
try {
|
|
164
|
-
buf =
|
|
190
|
+
buf = needsWholeFile
|
|
191
|
+
? fs.readFileSync(abs)
|
|
192
|
+
: readBoundedFile(fs, abs, maxBytes + 1);
|
|
165
193
|
} catch (err) {
|
|
166
194
|
return {
|
|
167
195
|
kind: "error",
|
|
@@ -414,6 +414,40 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
414
414
|
writeErr("No previous session to continue; starting a new one.\n");
|
|
415
415
|
}
|
|
416
416
|
|
|
417
|
+
// Machine-readable modes (`--output-format json` / `stream-json`) must ALWAYS
|
|
418
|
+
// end with a terminal result envelope — a consumer parsing stdout otherwise
|
|
419
|
+
// gets nothing and can't tell success from failure. Several setup-phase error
|
|
420
|
+
// paths below early-return BEFORE the main loop's try/catch envelope (and
|
|
421
|
+
// before `system/init`), so route them through this so stdout is never empty.
|
|
422
|
+
// No-op in text mode (those paths already writeErr a human message).
|
|
423
|
+
const emitHeadlessError = (resultMsg) => {
|
|
424
|
+
if (isStream) {
|
|
425
|
+
writeOut(
|
|
426
|
+
JSON.stringify({
|
|
427
|
+
type: "result",
|
|
428
|
+
subtype: "error",
|
|
429
|
+
is_error: true,
|
|
430
|
+
error: resultMsg,
|
|
431
|
+
}) + "\n",
|
|
432
|
+
);
|
|
433
|
+
} else if (isJson) {
|
|
434
|
+
writeOut(
|
|
435
|
+
JSON.stringify(
|
|
436
|
+
buildResultEnvelope({
|
|
437
|
+
subtype: "error",
|
|
438
|
+
isError: true,
|
|
439
|
+
result: resultMsg,
|
|
440
|
+
sessionId,
|
|
441
|
+
toolCalls: [],
|
|
442
|
+
usage: {},
|
|
443
|
+
numTurns: 0,
|
|
444
|
+
durationMs: 0,
|
|
445
|
+
}),
|
|
446
|
+
) + "\n",
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
|
|
417
451
|
// Load prior conversation when resuming an existing session. The fresh
|
|
418
452
|
// system prompt always leads; we drop any persisted system turns so it is
|
|
419
453
|
// never duplicated.
|
|
@@ -489,11 +523,9 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
489
523
|
writeErr(
|
|
490
524
|
`[hook] prompt blocked${ups.reason ? ": " + ups.reason : ""}\n`,
|
|
491
525
|
);
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
isError: true,
|
|
496
|
-
};
|
|
526
|
+
const reason = ups.reason || "blocked by UserPromptSubmit hook";
|
|
527
|
+
emitHeadlessError(reason);
|
|
528
|
+
return { exitCode: 2, result: reason, isError: true };
|
|
497
529
|
}
|
|
498
530
|
if (ups.additionalContext) {
|
|
499
531
|
userContent += `\n\n[hook context]\n${ups.additionalContext}`;
|
|
@@ -575,6 +607,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
575
607
|
// registered (cc mcp add) + IDE bridge auto-discovery.
|
|
576
608
|
strict: options.strictMcpConfig === true,
|
|
577
609
|
ide: options.ide,
|
|
610
|
+
pdh: options.pdh,
|
|
578
611
|
cwd: options.cwd || process.cwd(),
|
|
579
612
|
// advertise the session id to spawned stdio MCP servers
|
|
580
613
|
sessionId,
|
|
@@ -593,6 +626,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
593
626
|
}
|
|
594
627
|
} catch (err) {
|
|
595
628
|
writeErr(`Error: ${err.message}\n`);
|
|
629
|
+
emitHeadlessError(err.message);
|
|
596
630
|
return { exitCode: 1, result: err.message, isError: true };
|
|
597
631
|
}
|
|
598
632
|
}
|
|
@@ -635,6 +669,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
635
669
|
} catch (err) {
|
|
636
670
|
writeErr(`Error: ${err.message}\n`);
|
|
637
671
|
if (mcp?.mcpClient) await mcp.mcpClient.disconnectAll().catch(() => {});
|
|
672
|
+
emitHeadlessError(err.message);
|
|
638
673
|
return { exitCode: 1, result: err.message, isError: true };
|
|
639
674
|
}
|
|
640
675
|
if (approvalGate && typeof approvalGate.setConfirmer === "function") {
|
|
@@ -726,7 +761,12 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
726
761
|
|
|
727
762
|
const startedAt = deps.now ? deps.now() : Date.now();
|
|
728
763
|
const toolCalls = [];
|
|
729
|
-
const usage = {
|
|
764
|
+
const usage = {
|
|
765
|
+
input_tokens: 0,
|
|
766
|
+
output_tokens: 0,
|
|
767
|
+
cache_read_input_tokens: 0,
|
|
768
|
+
cache_creation_input_tokens: 0,
|
|
769
|
+
};
|
|
730
770
|
let finalText = "";
|
|
731
771
|
let endReason = "complete";
|
|
732
772
|
let stopForCost = false;
|
|
@@ -803,6 +843,11 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
803
843
|
case "token-usage": {
|
|
804
844
|
usage.input_tokens += event.usage?.input_tokens || 0;
|
|
805
845
|
usage.output_tokens += event.usage?.output_tokens || 0;
|
|
846
|
+
// Carry prompt-cache tokens into accumulated usage (cost accuracy).
|
|
847
|
+
usage.cache_read_input_tokens +=
|
|
848
|
+
event.usage?.cache_read_input_tokens || 0;
|
|
849
|
+
usage.cache_creation_input_tokens +=
|
|
850
|
+
event.usage?.cache_creation_input_tokens || 0;
|
|
806
851
|
emitStream({ type: "token_usage", usage: event.usage });
|
|
807
852
|
if (costBudget) {
|
|
808
853
|
costBudget.add({
|
|
@@ -102,6 +102,46 @@ export function parseInputEvent(line) {
|
|
|
102
102
|
if (!obj.id) return null;
|
|
103
103
|
return { approval: { id: String(obj.id), approve: obj.approve === true } };
|
|
104
104
|
}
|
|
105
|
+
// Answer to an ask_user_question (panel QuickPick for interactive questions):
|
|
106
|
+
// {"type":"answer","id":"q-1","answer":<string|string[]|null>}
|
|
107
|
+
// A null/absent answer cancels (handler → user_timeout, model proceeds).
|
|
108
|
+
if (obj && typeof obj === "object" && obj.type === "answer") {
|
|
109
|
+
if (!obj.id) return null;
|
|
110
|
+
return {
|
|
111
|
+
answer: {
|
|
112
|
+
id: String(obj.id),
|
|
113
|
+
value: obj.answer === undefined ? null : obj.answer,
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
// PDH self-learning feedback (design module 101 §3.5.13). The personal-data
|
|
118
|
+
// chat's 纠正卡 sends {"type":"feedback","turn_id":…,"kind":"positive"|
|
|
119
|
+
// "negative"|"correction","comment":…} after a reply. A missing kind → skip.
|
|
120
|
+
if (obj && typeof obj === "object" && obj.type === "feedback") {
|
|
121
|
+
const kind = String(obj.kind || "").toLowerCase();
|
|
122
|
+
if (!kind) return null;
|
|
123
|
+
return {
|
|
124
|
+
feedback: {
|
|
125
|
+
turnId: obj.turn_id != null ? String(obj.turn_id) : null,
|
|
126
|
+
kind,
|
|
127
|
+
comment: typeof obj.comment === "string" ? obj.comment : null,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
// PDH guided-collection resume (design module 101 §3.5.15). When a PDH tool
|
|
132
|
+
// returns assist_required (e.g. "log into the app first") the chat's 引导卡
|
|
133
|
+
// sends {"type":"resume","token":…,"action":"completed"|"skip"} once the user
|
|
134
|
+
// finishes or skips the in-app step. A missing action → skip.
|
|
135
|
+
if (obj && typeof obj === "object" && obj.type === "resume") {
|
|
136
|
+
const action = String(obj.action || "").toLowerCase();
|
|
137
|
+
if (!action) return null;
|
|
138
|
+
return {
|
|
139
|
+
resume: {
|
|
140
|
+
token: obj.token != null ? String(obj.token) : null,
|
|
141
|
+
action,
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
105
145
|
const msg = obj && typeof obj === "object" ? obj.message || obj : {};
|
|
106
146
|
let content = msg.content ?? obj.text ?? obj.prompt;
|
|
107
147
|
if (Array.isArray(content)) {
|
|
@@ -147,14 +187,24 @@ export function parseInputEvent(line) {
|
|
|
147
187
|
*/
|
|
148
188
|
export async function* readJsonLines(input) {
|
|
149
189
|
let buf = "";
|
|
190
|
+
// Reuse ONE streaming decoder across chunks so a multi-byte UTF-8 character
|
|
191
|
+
// (e.g. a 3-byte Chinese char) split across two Buffer chunks is reassembled
|
|
192
|
+
// rather than corrupted. process.stdin yields Buffers with no setEncoding, so
|
|
193
|
+
// a per-chunk `chunk.toString("utf-8")` would turn a split character into
|
|
194
|
+
// U+FFFD replacement chars.
|
|
195
|
+
const decoder = new TextDecoder();
|
|
150
196
|
for await (const chunk of input) {
|
|
151
|
-
buf +=
|
|
197
|
+
buf +=
|
|
198
|
+
typeof chunk === "string"
|
|
199
|
+
? chunk
|
|
200
|
+
: decoder.decode(chunk, { stream: true });
|
|
152
201
|
let idx;
|
|
153
202
|
while ((idx = buf.indexOf("\n")) >= 0) {
|
|
154
203
|
yield buf.slice(0, idx);
|
|
155
204
|
buf = buf.slice(idx + 1);
|
|
156
205
|
}
|
|
157
206
|
}
|
|
207
|
+
buf += decoder.decode(); // flush any bytes held from a final partial char
|
|
158
208
|
if (buf.trim()) yield buf;
|
|
159
209
|
}
|
|
160
210
|
|
|
@@ -163,7 +213,12 @@ export async function* readJsonLines(input) {
|
|
|
163
213
|
* Returns the turn outcome so the caller can grow history + the result line.
|
|
164
214
|
*/
|
|
165
215
|
async function runTurn(messages, loopOptions, { runLoop, emit, costBudget }) {
|
|
166
|
-
const usage = {
|
|
216
|
+
const usage = {
|
|
217
|
+
input_tokens: 0,
|
|
218
|
+
output_tokens: 0,
|
|
219
|
+
cache_read_input_tokens: 0,
|
|
220
|
+
cache_creation_input_tokens: 0,
|
|
221
|
+
};
|
|
167
222
|
const toolCalls = [];
|
|
168
223
|
let finalText = "";
|
|
169
224
|
let endReason = "complete";
|
|
@@ -191,6 +246,12 @@ async function runTurn(messages, loopOptions, { runLoop, emit, costBudget }) {
|
|
|
191
246
|
case "token-usage":
|
|
192
247
|
usage.input_tokens += event.usage?.input_tokens || 0;
|
|
193
248
|
usage.output_tokens += event.usage?.output_tokens || 0;
|
|
249
|
+
// Carry prompt-cache tokens into the turn's accumulated usage so the
|
|
250
|
+
// final `result` envelope (read by IDE panels) reflects caching too.
|
|
251
|
+
usage.cache_read_input_tokens +=
|
|
252
|
+
event.usage?.cache_read_input_tokens || 0;
|
|
253
|
+
usage.cache_creation_input_tokens +=
|
|
254
|
+
event.usage?.cache_creation_input_tokens || 0;
|
|
194
255
|
emit({ type: "token_usage", usage: event.usage });
|
|
195
256
|
if (costBudget) {
|
|
196
257
|
costBudget.add({
|
|
@@ -404,6 +465,65 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
404
465
|
approvalGate = null;
|
|
405
466
|
}
|
|
406
467
|
|
|
468
|
+
// ── Interactive questions (ask_user_question round-trip; chat-panel UX) ────
|
|
469
|
+
// Same structured pattern as approvals: when the consumer opts in (the IDE
|
|
470
|
+
// panel sets CC_INTERACTIVE_QUESTIONS=1 in the child env), the model's
|
|
471
|
+
// `ask_user_question` tool emits `question_request`, BLOCKS until a
|
|
472
|
+
// {"type":"answer",id,answer} arrives on stdin, and times out gracefully
|
|
473
|
+
// (CC_QUESTION_TIMEOUT_MS, default 180s) — the handler maps the timeout to
|
|
474
|
+
// user_timeout so the model proceeds, never a hard failure. Off by default
|
|
475
|
+
// (env unset / pipes) → agent-core gets no askUser → user_not_reachable, the
|
|
476
|
+
// existing graceful "proceed autonomously" path. Backward-safe: an env var
|
|
477
|
+
// (not a flag) means an old `cc` simply ignores it.
|
|
478
|
+
const interactiveQuestions =
|
|
479
|
+
options.interactiveQuestions === true ||
|
|
480
|
+
process.env.CC_INTERACTIVE_QUESTIONS === "1";
|
|
481
|
+
const pendingQuestions = new Map();
|
|
482
|
+
let questionSeq = 0;
|
|
483
|
+
const questionTimeoutMs =
|
|
484
|
+
Number(process.env.CC_QUESTION_TIMEOUT_MS) > 0
|
|
485
|
+
? Number(process.env.CC_QUESTION_TIMEOUT_MS)
|
|
486
|
+
: 180000;
|
|
487
|
+
const settleQuestion = (id, answer, via) => {
|
|
488
|
+
const p = pendingQuestions.get(id);
|
|
489
|
+
if (!p) return;
|
|
490
|
+
pendingQuestions.delete(id);
|
|
491
|
+
clearTimeout(p.timer);
|
|
492
|
+
emit({ type: "question_resolved", id, via, session_id: sessionId });
|
|
493
|
+
p.resolve(answer);
|
|
494
|
+
};
|
|
495
|
+
const failQuestion = (id, via) => {
|
|
496
|
+
const p = pendingQuestions.get(id);
|
|
497
|
+
if (!p) return;
|
|
498
|
+
pendingQuestions.delete(id);
|
|
499
|
+
clearTimeout(p.timer);
|
|
500
|
+
emit({ type: "question_resolved", id, via, session_id: sessionId });
|
|
501
|
+
const e = new Error(`ask_user_question ${via}`);
|
|
502
|
+
e.code = "USER_TIMEOUT"; // handler → user_timeout (model proceeds, not a failure)
|
|
503
|
+
p.reject(e);
|
|
504
|
+
};
|
|
505
|
+
const interactionAskUser = ({
|
|
506
|
+
question,
|
|
507
|
+
options: qOptions,
|
|
508
|
+
multiSelect,
|
|
509
|
+
timeoutMs,
|
|
510
|
+
} = {}) =>
|
|
511
|
+
new Promise((resolve, reject) => {
|
|
512
|
+
const id = `q-${++questionSeq}`;
|
|
513
|
+
const ms = Number(timeoutMs) > 0 ? Number(timeoutMs) : questionTimeoutMs;
|
|
514
|
+
const timer = setTimeout(() => failQuestion(id, "timeout"), ms);
|
|
515
|
+
timer.unref?.();
|
|
516
|
+
pendingQuestions.set(id, { resolve, reject, timer });
|
|
517
|
+
emit({
|
|
518
|
+
type: "question_request",
|
|
519
|
+
id,
|
|
520
|
+
session_id: sessionId,
|
|
521
|
+
question: typeof question === "string" ? question : "",
|
|
522
|
+
options: Array.isArray(qOptions) ? qOptions : null,
|
|
523
|
+
multiSelect: multiSelect === true,
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
|
|
407
527
|
// --output-style (or settings.json `outputStyle`) persona, appended.
|
|
408
528
|
let outputStyleBody = null;
|
|
409
529
|
try {
|
|
@@ -423,6 +543,27 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
423
543
|
);
|
|
424
544
|
const messages = [{ role: "system", content: systemContent }];
|
|
425
545
|
|
|
546
|
+
// §3.5.13 flywheel consumption (design module 101): in a PDH session, lead
|
|
547
|
+
// with the user's standing feedback preferences learned ACROSS sessions
|
|
548
|
+
// (corrections + net sentiment) so the agent honours past corrections from
|
|
549
|
+
// the very first turn — the read side of pdh-feedback-ledger.js. Gated to PDH
|
|
550
|
+
// context (the in-APK chat sets CHAINLESSCHAIN_PDH_PORT; `--pdh` forces,
|
|
551
|
+
// `--no-pdh` opts out) so IDE/coding sessions are never polluted. Best-effort.
|
|
552
|
+
try {
|
|
553
|
+
const { isInPdhTerminal } = await import("../lib/pdh-bridge.js");
|
|
554
|
+
const pdhContext =
|
|
555
|
+
options.pdh === true ||
|
|
556
|
+
(options.pdh !== false && isInPdhTerminal(process.env));
|
|
557
|
+
if (pdhContext) {
|
|
558
|
+
const { readFeedback, summarizeFeedback, feedbackSystemNote } =
|
|
559
|
+
await import("../lib/pdh-feedback-ledger.js");
|
|
560
|
+
const note = feedbackSystemNote(summarizeFeedback(readFeedback()));
|
|
561
|
+
if (note) messages.push({ role: "system", content: note });
|
|
562
|
+
}
|
|
563
|
+
} catch {
|
|
564
|
+
/* learned-preference injection must never break the chat */
|
|
565
|
+
}
|
|
566
|
+
|
|
426
567
|
// settings.json SessionStart hooks → inject session context once (observe-only).
|
|
427
568
|
if (settingsHooks) {
|
|
428
569
|
try {
|
|
@@ -512,6 +653,7 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
512
653
|
// registered + IDE bridge) for a reproducible MCP surface.
|
|
513
654
|
strict: options.strictMcpConfig === true,
|
|
514
655
|
ide: options.ide,
|
|
656
|
+
pdh: options.pdh,
|
|
515
657
|
cwd: options.cwd || process.cwd(),
|
|
516
658
|
// advertise the session id to spawned stdio MCP servers
|
|
517
659
|
sessionId,
|
|
@@ -591,6 +733,12 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
591
733
|
// edit reviews via openDiff) route to the structured approval round-trip
|
|
592
734
|
// instead of failing closed. Absent in CI/pipes → unchanged fail-closed.
|
|
593
735
|
permissionConfirm: interactive ? interactiveConfirm : undefined,
|
|
736
|
+
// ask_user_question round-trip (opt-in via CC_INTERACTIVE_QUESTIONS): give
|
|
737
|
+
// the tool handler an askUser that emits question_request + blocks on stdin.
|
|
738
|
+
// Absent → agent-core returns user_not_reachable (graceful proceed).
|
|
739
|
+
interaction: interactiveQuestions
|
|
740
|
+
? { askUser: interactionAskUser }
|
|
741
|
+
: undefined,
|
|
594
742
|
prepareCall: goalPrepareCallFn,
|
|
595
743
|
// --mcp-config wiring (tool defs + dispatch map + live client).
|
|
596
744
|
mcpClient: mcp?.mcpClient || null,
|
|
@@ -684,6 +832,19 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
684
832
|
);
|
|
685
833
|
continue;
|
|
686
834
|
}
|
|
835
|
+
if (parsed.answer) {
|
|
836
|
+
// Answers settle a BLOCKED ask_user_question — never queued. A null
|
|
837
|
+
// value (user cancelled the QuickPick) → user_timeout (model proceeds).
|
|
838
|
+
if (parsed.answer.value == null)
|
|
839
|
+
failQuestion(parsed.answer.id, "cancelled");
|
|
840
|
+
else
|
|
841
|
+
settleQuestion(
|
|
842
|
+
parsed.answer.id,
|
|
843
|
+
parsed.answer.value,
|
|
844
|
+
"user-answer",
|
|
845
|
+
);
|
|
846
|
+
continue;
|
|
847
|
+
}
|
|
687
848
|
queue.push(parsed);
|
|
688
849
|
if (wakeQueue) wakeQueue();
|
|
689
850
|
}
|
|
@@ -696,6 +857,10 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
696
857
|
for (const id of [...pendingApprovals.keys()]) {
|
|
697
858
|
settleApproval(id, false, "stdin-closed");
|
|
698
859
|
}
|
|
860
|
+
// stdin closed while a question was pending → user_timeout (model proceeds).
|
|
861
|
+
for (const id of [...pendingQuestions.keys()]) {
|
|
862
|
+
failQuestion(id, "stdin-closed");
|
|
863
|
+
}
|
|
699
864
|
if (wakeQueue) wakeQueue();
|
|
700
865
|
})();
|
|
701
866
|
const nextEvent = async () => {
|
|
@@ -805,6 +970,58 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
805
970
|
}
|
|
806
971
|
}
|
|
807
972
|
|
|
973
|
+
// PDH self-learning feedback (design module 101 §3.5.13). Always ack so the
|
|
974
|
+
// chat app can confirm receipt. A `correction` re-drives a turn so the model
|
|
975
|
+
// adapts within the session; `positive`/`negative` are recorded as a
|
|
976
|
+
// lightweight preference note in history without forcing a fresh reply.
|
|
977
|
+
if (parsed.feedback) {
|
|
978
|
+
const { turnId, kind, comment } = parsed.feedback;
|
|
979
|
+
emit({
|
|
980
|
+
type: "feedback_ack",
|
|
981
|
+
turn_id: turnId,
|
|
982
|
+
kind,
|
|
983
|
+
session_id: sessionId,
|
|
984
|
+
});
|
|
985
|
+
// §3.5.13: persist to the cross-session learning ledger so the next
|
|
986
|
+
// session can honour the user's standing preferences ("越用越聪明"
|
|
987
|
+
// flywheel). Best-effort — a learning ledger must never break the chat.
|
|
988
|
+
try {
|
|
989
|
+
const { appendFeedback } =
|
|
990
|
+
await import("../lib/pdh-feedback-ledger.js");
|
|
991
|
+
appendFeedback({ sessionId, turnId, kind, comment });
|
|
992
|
+
} catch {
|
|
993
|
+
/* persistence is best-effort */
|
|
994
|
+
}
|
|
995
|
+
if (kind === "correction") {
|
|
996
|
+
parsed.text = comment
|
|
997
|
+
? `用户对上一轮回复给出纠正:${comment}\n请据此调整并重新回复。`
|
|
998
|
+
: "用户认为上一轮回复需要纠正,请反思后给出更准确的回复。";
|
|
999
|
+
// fall through into the normal turn machinery with the correction prompt
|
|
1000
|
+
} else {
|
|
1001
|
+
const tag = kind === "positive" ? "认可" : "不满意";
|
|
1002
|
+
messages.push({
|
|
1003
|
+
role: "user",
|
|
1004
|
+
content: `(用户反馈:对上一轮回复表示${tag}。请在后续回复中延续/修正此偏好。)`,
|
|
1005
|
+
});
|
|
1006
|
+
continue;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
// PDH guided-collection resume (design module 101 §3.5.15). A PDH tool
|
|
1011
|
+
// returned assist_required (e.g. "log into the app first"); the chat's 引导卡
|
|
1012
|
+
// sends a resume once the user finishes or skips the in-app step. Ack so the
|
|
1013
|
+
// app can dismiss the card, then re-drive the model to retry (completed) or
|
|
1014
|
+
// move on (skip).
|
|
1015
|
+
if (parsed.resume) {
|
|
1016
|
+
const { token, action } = parsed.resume;
|
|
1017
|
+
emit({ type: "resume_ack", token, action, session_id: sessionId });
|
|
1018
|
+
parsed.text =
|
|
1019
|
+
action === "skip"
|
|
1020
|
+
? "我跳过了刚才需要的引导操作,请不要重试该步骤,继续处理其它事项或做个小结。"
|
|
1021
|
+
: "我已完成刚才需要的引导操作,请重试刚才的采集/操作。";
|
|
1022
|
+
// fall through into the normal turn machinery with the continuation prompt
|
|
1023
|
+
}
|
|
1024
|
+
|
|
808
1025
|
// --replay-user-messages: echo each accepted user message back on the
|
|
809
1026
|
// output stream (Claude-Code parity) so a consumer can correlate replies to
|
|
810
1027
|
// inputs / log the transcript. Echoes the raw user text, before @file or
|
|
@@ -96,7 +96,21 @@ export async function execute({ section_idx, shot_idx, clips }, context) {
|
|
|
96
96
|
try {
|
|
97
97
|
const raw = await fs.readFile(context.shotPointPath, "utf-8");
|
|
98
98
|
existing = JSON.parse(raw);
|
|
99
|
-
|
|
99
|
+
if (!Array.isArray(existing)) {
|
|
100
|
+
throw new Error("shot-point log is not a JSON array");
|
|
101
|
+
}
|
|
102
|
+
} catch (err) {
|
|
103
|
+
// A missing file is the normal first-commit case — start fresh. Any other
|
|
104
|
+
// error (parse failure / wrong shape on an existing file, permission)
|
|
105
|
+
// means the log is present but unreadable; appending to a fresh [] would
|
|
106
|
+
// silently discard every previously committed clip, so surface it instead
|
|
107
|
+
// of clobbering.
|
|
108
|
+
if (err.code !== "ENOENT") {
|
|
109
|
+
throw new Error(
|
|
110
|
+
`Refusing to overwrite shot-point log ${context.shotPointPath}: ${err.message}`,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
100
114
|
existing.push(entry);
|
|
101
115
|
await fs.writeFile(
|
|
102
116
|
context.shotPointPath,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as n,J as g,c as l,K as r,N as u,P as h,U as o,R as t,Q as m}from"./vendor-BvqAck49.js";import{_ as v,b}from"./index-DmrPbYXh.js";import{a7 as y,M}from"./icons-DP3uiYxy.js";const B={__name:"MobileProjects",setup(p,{expose:i}){i();const c=u(),{t:e}=b();function a(){c.push("/projects")}function _(){c.push("/mobile-bridge")}const s={router:c,t:e,goToProjects:a,goToMobileBridge:_,get useRouter(){return u},get useI18n(){return b},get MobileOutlined(){return M},get FolderOutlined(){return y}};return Object.defineProperty(s,"__isScriptSetup",{enumerable:!1,value:!0}),s}},x={class:"mobile-projects-placeholder"},O={class:"title"},k={class:"subtitle"},w={class:"explainer"};function T(p,i,c,e,a,_){const s=n("a-alert"),d=n("a-button"),f=n("a-space"),P=n("a-empty"),j=n("a-card");return h(),g("div",x,[l(j,null,{default:r(()=>[l(P,{description:!1},{image:r(()=>[l(e.MobileOutlined,{style:{fontSize:"64px",color:"#bfbfbf"}})]),default:r(()=>[o("h2",O,t(e.t("mobileProjects.title")),1),o("p",k,t(e.t("mobileProjects.subtitle")),1),l(s,{message:e.t("mobileProjects.v02Banner"),type:"info","show-icon":"",class:"banner"},null,8,["message"]),o("div",w,[o("h3",null,t(e.t("mobileProjects.currentDirection")),1),o("p",null,t(e.t("mobileProjects.currentDirectionBody")),1),o("ul",null,[o("li",null,t(e.t("mobileProjects.stepPhone")),1),o("li",null,t(e.t("mobileProjects.stepTap")),1),o("li",null,t(e.t("mobileProjects.stepPull")),1)]),o("h3",null,t(e.t("mobileProjects.reverseDirection")),1),o("p",null,t(e.t("mobileProjects.reverseDirectionBody")),1)]),l(f,{class:"actions"},{default:r(()=>[l(d,{type:"primary",onClick:e.goToProjects},{default:r(()=>[l(e.FolderOutlined),m(" "+t(e.t("mobileProjects.viewLocalProjects")),1)]),_:1}),l(d,{onClick:e.goToMobileBridge},{default:r(()=>[l(e.MobileOutlined),m(" "+t(e.t("mobileProjects.checkBridge")),1)]),_:1})]),_:1})]),_:1})]),_:1})])}const I=v(B,[["render",T],["__scopeId","data-v-9262cc45"],["__file","/tmp/cc-web-panel-94r5Fm/repo/packages/web-panel/src/views/MobileProjects.vue"]]);export{I as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as i,J as I,U,R as s,Q as r,c as t,K as a,V as _,S as x,o as oe,b as ee,r as u,P as p,F as ne,a2 as ge}from"./vendor-BvqAck49.js";import{_ as we,b as re,u as ie,d}from"./index-DmrPbYXh.js";import{u as de}from"./useShellMode-CgR0wCYM.js";import{aM as ke,aN as Fe,aO as be,f as je,a4 as Ce,a7 as xe,as as Oe,R as Se}from"./icons-DP3uiYxy.js";const Pe={__name:"Projects",setup(se,{expose:l}){l();const{t:te}=re(),e=ie(),{isEmbedded:W}=de();async function w(o,f,ye,ae=8e3){if(W){const Z=await e.sendRaw({...f,type:o},ae);if(!Z?.ok){const $=Z?.error;throw new Error(typeof $=="string"?$:$?.message||`${o} failed`)}return Z.result}return e.executeJson(ye,ae)}const B=u(!1),y=u([]),O=u(""),S=u(""),P=u(!1),v=u(null),h=u([]),k=u(!1),E=u(!1),L=u(!1),F=u({name:"",description:"",type:"document",rootPath:""}),z=[{title:"ID",key:"id",width:110},{title:"名称",key:"name"},{title:"类型",key:"project_type",width:120},{title:"状态",key:"status",width:100},{title:"同步",key:"sync_status",width:100},{title:"更新",key:"updated_at",width:160},{title:"操作",key:"actions",width:180,fixed:"right"}],M=ee(()=>{const o={active:0,draft:0,completed:0,archived:0};for(const f of y.value)o[f.status]!==void 0&&(o[f.status]+=1);return o}),J=ee(()=>y.value.filter(o=>!(O.value&&o.status!==O.value||S.value&&!o.name.toLowerCase().includes(S.value.toLowerCase()))));function g(o){switch(o){case"active":return"green";case"draft":return"default";case"completed":return"cyan";case"archived":return"gold";default:return"default"}}function K(o){switch(o){case"synced":return"green";case"pending":return"orange";case"conflict":return"red";case"error":return"red";default:return"default"}}function Q(o){return!o&&o!==0?"-":new Date(typeof o=="number"?o:parseInt(o,10)).toLocaleString("zh-CN",{hour12:!1})}async function C(){B.value=!0;try{const o=await w("project.list",{limit:500},"project list --limit 500 --json",1e4);y.value=Array.isArray(o?.projects)?o.projects:Array.isArray(o)?o:[]}catch(o){d.error("加载失败: "+(o.message||o)),y.value=[]}finally{B.value=!1}}function G(o){return{onClick:()=>V(o)}}async function V(o){v.value=o,P.value=!0,k.value=!0,h.value=[];try{const f=await w("project.listFiles",{projectId:o.id,limit:200},`project list-files ${o.id} --json`,8e3);h.value=Array.isArray(f?.files)?f.files:[]}catch{h.value=[]}finally{k.value=!1}}async function H(o){try{(await w("project.delete",{id:o.id},`project delete ${o.id} --json`,8e3))?.ok?(d.success(`已删除项目 '${o.name}'`),P.value=!1,await C()):d.error("删除失败")}catch(f){d.error(f.message||String(f))}}function X(){F.value={name:"",description:"",type:"document",rootPath:""},E.value=!0}async function T(){if(!F.value.name.trim()){d.warning("请输入项目名称");return}L.value=!0;try{const o=await w("project.init",{name:F.value.name.trim(),description:F.value.description||null,projectType:F.value.type,rootPath:F.value.rootPath||null},`project init "${F.value.name.trim()}" --type ${F.value.type} --json`,8e3);o?.id?(d.success(`已创建项目 '${o.name}'`),E.value=!1,await C()):d.error("创建失败")}catch(o){d.error(o.message||String(o))}finally{L.value=!1}}const b=u(!1),D=u(!1),j=u({path:"",content:""}),A=u(!1),m=u(!1),R=u({path:""}),n=u(!1),c=u(null),q=u(""),Y=u(!1);function ue(){j.value={path:"",content:""},b.value=!0}function ce(){R.value={path:""},A.value=!0}async function N(){if(v.value){k.value=!0;try{const o=await w("project.listFiles",{projectId:v.value.id,limit:200},`project list-files ${v.value.id} --json`,8e3);h.value=Array.isArray(o?.files)?o.files:[]}catch(o){d.error("刷新文件失败: "+(o.message||o))}finally{k.value=!1}}}async function fe(){if(!j.value.path.trim()){d.warning("请输入文件路径");return}if(v.value){D.value=!0;try{const o=await w("project.createFile",{projectId:v.value.id,filePath:j.value.path.trim(),content:j.value.content||""},`project create-file ${v.value.id} "${j.value.path.trim()}" --json`,8e3);o?.id?(d.success(`已创建文件 '${o.file_name}'`),b.value=!1,await N(),await C()):d.error("创建文件失败")}catch(o){d.error(o.message||String(o))}finally{D.value=!1}}}async function pe(){if(!R.value.path.trim()){d.warning("请输入文件夹路径");return}if(v.value){m.value=!0;try{const o=await w("project.createFolder",{projectId:v.value.id,folderPath:R.value.path.trim()},`project create-folder ${v.value.id} "${R.value.path.trim()}" --json`,8e3);o?.id?(d.success(`已创建文件夹 '${o.file_name}'`),A.value=!1,await N(),await C()):d.error("创建文件夹失败")}catch(o){d.error(o.message||String(o))}finally{m.value=!1}}}async function ve(o){try{(await w("project.deleteFile",{fileId:o.id},`project delete-file ${o.id} --json`,8e3))?.deleted?(d.success(`已删除 '${o.file_name}'`),await N(),await C()):d.error("删除失败")}catch(f){d.error(f.message||String(f))}}async function me(o){if(o.is_folder){d.info("文件夹无内容可编辑");return}try{const f=await w("project.getFile",{fileId:o.id},`project get-file ${o.id} --json`,8e3);c.value=o,q.value=f?.content||"",n.value=!0}catch(f){d.error("读取文件失败: "+(f.message||f))}}async function _e(){if(c.value){Y.value=!0;try{(await w("project.writeFile",{fileId:c.value.id,content:q.value},`project write-file ${c.value.id} --json`,8e3))?.id?(d.success("已保存"),n.value=!1,await N()):d.error("保存失败")}catch(o){d.error(o.message||String(o))}finally{Y.value=!1}}}oe(()=>{C()});const le={t:te,ws:e,isEmbedded:W,callProjectTopic:w,loading:B,projects:y,statusFilter:O,nameFilter:S,detailOpen:P,detail:v,files:h,filesLoading:k,createOpen:E,creating:L,newProject:F,columns:z,countByStatus:M,filteredProjects:J,statusColor:g,syncColor:K,formatTime:Q,loadAll:C,onRowClick:G,openDetail:V,onDelete:H,onShowCreate:X,onCreate:T,createFileOpen:b,creatingFile:D,newFile:j,createFolderOpen:A,creatingFolder:m,newFolder:R,editFileOpen:n,editingFile:c,editFileContent:q,savingFile:Y,openCreateFile:ue,openCreateFolder:ce,refreshFiles:N,onCreateFile:fe,onCreateFolder:pe,onDeleteFile:ve,openEditFile:me,onSaveFile:_e,ref:u,computed:ee,onMounted:oe,get ReloadOutlined(){return Se},get PlusOutlined(){return Oe},get FolderOutlined(){return xe},get FileTextOutlined(){return Ce},get CheckCircleOutlined(){return je},get CheckSquareOutlined(){return be},get FileAddOutlined(){return Fe},get FolderAddOutlined(){return ke},get message(){return d},get useI18n(){return re},get useWsStore(){return ie},get useShellMode(){return de}};return Object.defineProperty(le,"__isScriptSetup",{enumerable:!1,value:!0}),le}},ze={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"24px"}},Ae={class:"page-title"},Ie={class:"page-sub"},Ue={class:"filter-bar",style:{"margin-bottom":"12px",display:"flex",gap:"12px","align-items":"center"}},he={key:0,style:{"font-size":"12px",color:"#888"}},De={key:0,style:{color:"#888","font-size":"12px"}},Re={key:0},Te={key:1,style:{color:"#888"}},Be=["onClick"],Ee={key:0,style:{color:"#888","font-size":"12px"}};function Le(se,l,te,e,W,w){const B=i("router-link"),y=i("a-button"),O=i("a-space"),S=i("a-statistic"),P=i("a-card"),v=i("a-col"),h=i("a-row"),k=i("a-radio-button"),E=i("a-radio-group"),L=i("a-input-search"),F=i("a-alert"),z=i("a-tag"),M=i("a-popconfirm"),J=i("a-table"),g=i("a-descriptions-item"),K=i("a-descriptions"),Q=i("a-divider"),C=i("a-empty"),G=i("a-list-item"),V=i("a-list"),H=i("a-spin"),X=i("a-drawer"),T=i("a-input"),b=i("a-form-item"),D=i("a-textarea"),j=i("a-form"),A=i("a-modal"),m=i("a-select-option"),R=i("a-select");return p(),I("div",null,[U("div",ze,[U("div",null,[U("h2",Ae,s(e.t("projects.title")),1),U("p",Ie,[l[17]||(l[17]=r("桌面 / CLI / 手机 三端共享同一份项目数据,Phase 3d sync 自动同步 (",-1)),t(B,{to:"/project-init"},{default:a(()=>[...l[16]||(l[16]=[r("项目初始化 / 环境设置",-1)])]),_:1}),l[18]||(l[18]=r(")",-1))])]),t(O,null,{default:a(()=>[t(y,{loading:e.loading,onClick:e.loadAll},{icon:a(()=>[t(e.ReloadOutlined)]),default:a(()=>[l[19]||(l[19]=r(" 刷新 ",-1))]),_:1},8,["loading"]),t(y,{type:"primary",onClick:e.onShowCreate},{icon:a(()=>[t(e.PlusOutlined)]),default:a(()=>[l[20]||(l[20]=r(" 新建项目 ",-1))]),_:1})]),_:1})]),_(" Stats "),t(h,{gutter:[16,16],style:{"margin-bottom":"20px"}},{default:a(()=>[t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"总项目",value:e.projects.length,"value-style":{color:"#1677ff",fontSize:"20px"}},{prefix:a(()=>[t(e.FolderOutlined)]),_:1},8,["value"])]),_:1})]),_:1}),t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"活跃",value:e.countByStatus.active,"value-style":{color:"#52c41a",fontSize:"20px"}},{prefix:a(()=>[t(e.CheckCircleOutlined)]),_:1},8,["value"])]),_:1})]),_:1}),t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"草稿",value:e.countByStatus.draft,"value-style":{color:"#8c8c8c",fontSize:"20px"}},{prefix:a(()=>[t(e.FileTextOutlined)]),_:1},8,["value"])]),_:1})]),_:1}),t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"已完成",value:e.countByStatus.completed,"value-style":{color:"#13c2c2",fontSize:"20px"}},{prefix:a(()=>[t(e.CheckSquareOutlined)]),_:1},8,["value"])]),_:1})]),_:1})]),_:1}),_(" Filter "),U("div",Ue,[t(E,{value:e.statusFilter,"onUpdate:value":l[0]||(l[0]=n=>e.statusFilter=n),size:"small","button-style":"solid"},{default:a(()=>[t(k,{value:""},{default:a(()=>[...l[21]||(l[21]=[r("全部",-1)])]),_:1}),t(k,{value:"active"},{default:a(()=>[...l[22]||(l[22]=[r("活跃",-1)])]),_:1}),t(k,{value:"draft"},{default:a(()=>[...l[23]||(l[23]=[r("草稿",-1)])]),_:1}),t(k,{value:"completed"},{default:a(()=>[...l[24]||(l[24]=[r("已完成",-1)])]),_:1}),t(k,{value:"archived"},{default:a(()=>[...l[25]||(l[25]=[r("已归档",-1)])]),_:1})]),_:1},8,["value"]),t(L,{value:e.nameFilter,"onUpdate:value":l[1]||(l[1]=n=>e.nameFilter=n),placeholder:"按名称过滤",style:{"max-width":"260px"},"allow-clear":""},null,8,["value"])]),!e.projects.length&&!e.loading?(p(),x(F,{key:0,type:"info",message:"还没有项目",description:'运行 `cc project init <name>` 或点击右上角"新建项目"按钮创建。桌面 / CLI / 手机三端共享同一份数据。',"show-icon":"",style:{"margin-bottom":"16px"}})):_("v-if",!0),e.projects.length||e.loading?(p(),x(J,{key:1,columns:e.columns,"data-source":e.filteredProjects,loading:e.loading,pagination:{pageSize:20,showSizeChanger:!0},"row-key":"id","custom-row":e.onRowClick},{bodyCell:a(({column:n,record:c})=>[n.key==="id"?(p(),I("code",he,s(c.id.slice(0,8))+"…",1)):n.key==="name"?(p(),I(ne,{key:1},[U("strong",null,s(c.name),1),c.description?(p(),I("div",De,s(c.description),1)):_("v-if",!0)],64)):n.key==="project_type"?(p(),x(z,{key:2},{default:a(()=>[r(s(c.project_type),1)]),_:2},1024)):n.key==="status"?(p(),x(z,{key:3,color:e.statusColor(c.status)},{default:a(()=>[r(s(c.status),1)]),_:2},1032,["color"])):n.key==="sync_status"?(p(),x(z,{key:4,color:e.syncColor(c.sync_status)},{default:a(()=>[r(s(c.sync_status||"unknown"),1)]),_:2},1032,["color"])):n.key==="updated_at"?(p(),I(ne,{key:5},[r(s(e.formatTime(c.updated_at)),1)],64)):n.key==="actions"?(p(),x(O,{key:6,onClick:l[2]||(l[2]=ge(()=>{},["stop"]))},{default:a(()=>[t(y,{size:"small",onClick:q=>e.openDetail(c)},{default:a(()=>[...l[26]||(l[26]=[r("详情",-1)])]),_:1},8,["onClick"]),t(M,{title:`删除项目 '${c.name}' ?`,"ok-text":"删除","ok-type":"danger","cancel-text":"取消",onConfirm:q=>e.onDelete(c)},{default:a(()=>[t(y,{size:"small",danger:""},{default:a(()=>[...l[27]||(l[27]=[r("删除",-1)])]),_:1})]),_:1},8,["title","onConfirm"])]),_:2},1024)):_("v-if",!0)]),_:1},8,["data-source","loading"])):_("v-if",!0),_(" Detail drawer "),t(X,{open:e.detailOpen,"onUpdate:open":l[3]||(l[3]=n=>e.detailOpen=n),title:e.detail?.name||"项目详情",width:"640",placement:"right"},{default:a(()=>[e.detail?(p(),x(K,{key:0,column:1,bordered:"",size:"small"},{default:a(()=>[t(g,{label:"ID"},{default:a(()=>[U("code",null,s(e.detail.id),1)]),_:1}),t(g,{label:"名称"},{default:a(()=>[r(s(e.detail.name),1)]),_:1}),t(g,{label:"描述"},{default:a(()=>[r(s(e.detail.description||"-"),1)]),_:1}),t(g,{label:"类型"},{default:a(()=>[t(z,null,{default:a(()=>[r(s(e.detail.project_type),1)]),_:1})]),_:1}),t(g,{label:"状态"},{default:a(()=>[t(z,{color:e.statusColor(e.detail.status)},{default:a(()=>[r(s(e.detail.status),1)]),_:1},8,["color"])]),_:1}),t(g,{label:"同步状态"},{default:a(()=>[t(z,{color:e.syncColor(e.detail.sync_status)},{default:a(()=>[r(s(e.detail.sync_status||"unknown"),1)]),_:1},8,["color"])]),_:1}),t(g,{label:"用户"},{default:a(()=>[r(s(e.detail.user_id),1)]),_:1}),t(g,{label:"根路径"},{default:a(()=>[e.detail.root_path?(p(),I("code",Re,s(e.detail.root_path),1)):(p(),I("span",Te,"(无)"))]),_:1}),t(g,{label:"文件数"},{default:a(()=>[r(s(e.detail.file_count||0),1)]),_:1}),t(g,{label:"创建"},{default:a(()=>[r(s(e.formatTime(e.detail.created_at)),1)]),_:1}),t(g,{label:"更新"},{default:a(()=>[r(s(e.formatTime(e.detail.updated_at)),1)]),_:1})]),_:1})):_("v-if",!0),t(Q,null,{default:a(()=>[...l[28]||(l[28]=[r("文件",-1)])]),_:1}),_(" Sub-phase 7.3 (2026-05-17): 文件 CRUD toolbar "),t(O,{style:{"margin-bottom":"12px"}},{default:a(()=>[t(y,{size:"small",type:"primary",disabled:!e.detail,onClick:e.openCreateFile},{default:a(()=>[t(e.FileAddOutlined),l[29]||(l[29]=r(" 新建文件 ",-1))]),_:1},8,["disabled"]),t(y,{size:"small",disabled:!e.detail,onClick:e.openCreateFolder},{default:a(()=>[t(e.FolderAddOutlined),l[30]||(l[30]=r(" 新建文件夹 ",-1))]),_:1},8,["disabled"])]),_:1}),t(H,{spinning:e.filesLoading},{default:a(()=>[!e.files.length&&!e.filesLoading?(p(),x(C,{key:0,description:"无文件 (点上方按钮新建)"})):(p(),x(V,{key:1,size:"small","data-source":e.files},{renderItem:a(({item:n})=>[t(G,null,{extra:a(()=>[t(O,null,{default:a(()=>[n.file_size?(p(),I("span",Ee,s(n.file_size)+" B",1)):_("v-if",!0),t(M,{title:`删除 ${n.is_folder?"文件夹":"文件"} '${n.file_name}' ?`,"ok-text":"删除","ok-type":"danger","cancel-text":"取消",onConfirm:c=>e.onDeleteFile(n)},{default:a(()=>[t(y,{size:"small",danger:""},{default:a(()=>[...l[31]||(l[31]=[r("×",-1)])]),_:1})]),_:1},8,["title","onConfirm"])]),_:2},1024)]),default:a(()=>[U("span",{style:{cursor:"pointer"},onClick:c=>e.openEditFile(n)},s(n.is_folder?"📁":"📄")+" "+s(n.file_path),9,Be)]),_:2},1024)]),_:1},8,["data-source"]))]),_:1},8,["spinning"])]),_:1},8,["open","title"]),_(" Sub-phase 7.3: Create file modal "),t(A,{open:e.createFileOpen,"onUpdate:open":l[6]||(l[6]=n=>e.createFileOpen=n),title:"新建文件","confirm-loading":e.creatingFile,"ok-text":"创建","cancel-text":"取消",onOk:e.onCreateFile},{default:a(()=>[t(j,{layout:"vertical"},{default:a(()=>[t(b,{label:"文件路径(项目内)",required:""},{default:a(()=>[t(T,{value:e.newFile.path,"onUpdate:value":l[4]||(l[4]=n=>e.newFile.path=n),placeholder:"例如 README.md 或 src/main.kt"},null,8,["value"])]),_:1}),t(b,{label:"初始内容(可选)"},{default:a(()=>[t(D,{value:e.newFile.content,"onUpdate:value":l[5]||(l[5]=n=>e.newFile.content=n),rows:6,placeholder:"留空创建空文件"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"]),_(" Sub-phase 7.3: Create folder modal "),t(A,{open:e.createFolderOpen,"onUpdate:open":l[8]||(l[8]=n=>e.createFolderOpen=n),title:"新建文件夹","confirm-loading":e.creatingFolder,"ok-text":"创建","cancel-text":"取消",onOk:e.onCreateFolder},{default:a(()=>[t(j,{layout:"vertical"},{default:a(()=>[t(b,{label:"文件夹路径(项目内)",required:""},{default:a(()=>[t(T,{value:e.newFolder.path,"onUpdate:value":l[7]||(l[7]=n=>e.newFolder.path=n),placeholder:"例如 src/utils"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"]),_(" Sub-phase 7.3: Edit file content modal "),t(A,{open:e.editFileOpen,"onUpdate:open":l[10]||(l[10]=n=>e.editFileOpen=n),title:`编辑 ${e.editingFile?.file_name||""}`,"confirm-loading":e.savingFile,"ok-text":"保存","cancel-text":"取消",onOk:e.onSaveFile,width:"720"},{default:a(()=>[t(D,{value:e.editFileContent,"onUpdate:value":l[9]||(l[9]=n=>e.editFileContent=n),rows:18,"auto-size":{minRows:12,maxRows:24},style:{"font-family":"monospace"}},null,8,["value"])]),_:1},8,["open","title","confirm-loading"]),_(" Create modal "),t(A,{open:e.createOpen,"onUpdate:open":l[15]||(l[15]=n=>e.createOpen=n),title:"新建项目","confirm-loading":e.creating,"ok-text":"创建","cancel-text":"取消",onOk:e.onCreate},{default:a(()=>[t(j,{layout:"vertical"},{default:a(()=>[t(b,{label:"项目名称",required:""},{default:a(()=>[t(T,{value:e.newProject.name,"onUpdate:value":l[11]||(l[11]=n=>e.newProject.name=n),placeholder:"例如:旅行计划-上海"},null,8,["value"])]),_:1}),t(b,{label:"描述"},{default:a(()=>[t(D,{value:e.newProject.description,"onUpdate:value":l[12]||(l[12]=n=>e.newProject.description=n),rows:2},null,8,["value"])]),_:1}),t(b,{label:"类型"},{default:a(()=>[t(R,{value:e.newProject.type,"onUpdate:value":l[13]||(l[13]=n=>e.newProject.type=n)},{default:a(()=>[t(m,{value:"document"},{default:a(()=>[...l[32]||(l[32]=[r("文档 (document)",-1)])]),_:1}),t(m,{value:"data"},{default:a(()=>[...l[33]||(l[33]=[r("数据 (data)",-1)])]),_:1}),t(m,{value:"web"},{default:a(()=>[...l[34]||(l[34]=[r("Web",-1)])]),_:1}),t(m,{value:"app"},{default:a(()=>[...l[35]||(l[35]=[r("应用 (app)",-1)])]),_:1}),t(m,{value:"presentation"},{default:a(()=>[...l[36]||(l[36]=[r("演示文稿",-1)])]),_:1}),t(m,{value:"spreadsheet"},{default:a(()=>[...l[37]||(l[37]=[r("表格",-1)])]),_:1}),t(m,{value:"design"},{default:a(()=>[...l[38]||(l[38]=[r("设计",-1)])]),_:1}),t(m,{value:"code"},{default:a(()=>[...l[39]||(l[39]=[r("代码",-1)])]),_:1}),t(m,{value:"workflow"},{default:a(()=>[...l[40]||(l[40]=[r("工作流",-1)])]),_:1}),t(m,{value:"knowledge"},{default:a(()=>[...l[41]||(l[41]=[r("知识库",-1)])]),_:1})]),_:1},8,["value"])]),_:1}),t(b,{label:"根路径 (可选)"},{default:a(()=>[t(T,{value:e.newProject.rootPath,"onUpdate:value":l[14]||(l[14]=n=>e.newProject.rootPath=n),placeholder:"留空则仅元数据"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"])])}const We=we(Pe,[["render",Le],["__scopeId","data-v-019ac5aa"],["__file","/tmp/cc-web-panel-94r5Fm/repo/packages/web-panel/src/views/Projects.vue"]]);export{We as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{E as V,b as z,r as D,I as p,J as c,U as _,c as n,K as a,S as T,V as w,o as P,x as F,P as i,Q as g,R as r,F as h,Z as B}from"./vendor-BvqAck49.js";import{u as R,_ as O}from"./index-DmrPbYXh.js";import{R as E}from"./icons-DP3uiYxy.js";const I=V("tasks",()=>{const k=D([]),l=D(!1);let u=null,e=null;const x=z(()=>k.value.filter(t=>t.status==="running")),b=z(()=>k.value.filter(t=>t.status==="pending")),y=z(()=>k.value.filter(t=>t.status==="completed"||t.status==="failed"||t.status==="timeout"));async function f(){const t=R();l.value=!0;try{const s=await t.sendRaw({type:"tasks-list"});s&&Array.isArray(s.tasks)&&(k.value=s.tasks)}catch{}finally{l.value=!1}}async function o(t){const s=R();try{await s.sendRaw({type:"tasks-stop",taskId:t})}catch{}finally{await f()}}const d=D(null);function m(t=5e3){v(),f(),u=setInterval(f,t),C()}function v(){u&&(clearInterval(u),u=null),e&&(e(),e=null)}function C(){const t=R();if(e)return;const s=S=>{S.type==="task:notification"&&S.payload?.task&&(d.value=S.payload.task,f(),setTimeout(()=>{d.value=null},8e3))};e=t.onRuntimeEvent(s)}function N(t){return!t||t<0?"-":t<1e3?`${t}ms`:t<6e4?`${(t/1e3).toFixed(1)}s`:`${(t/6e4).toFixed(1)}m`}function A(t){switch(t){case"running":return"processing";case"pending":return"default";case"completed":return"success";case"failed":return"error";case"timeout":return"warning";default:return"default"}}return{tasks:k,loading:l,running:x,pending:b,completed:y,lastNotification:d,fetchTasks:f,stopTask:o,startPolling:m,stopPolling:v,formatDuration:N,getStatusColor:A}}),U={__name:"Tasks",setup(k,{expose:l}){l();const u=I(),e=[{title:"状态",key:"status",width:90},{title:"描述",key:"description",ellipsis:!0},{title:"类型",dataIndex:"type",width:100},{title:"耗时",key:"duration",width:90},{title:"创建时间",key:"createdAt",width:180},{title:"结果",key:"result",ellipsis:!0},{title:"操作",key:"action",width:80}];function x(o){return o.status==="running"&&o.startedAt?u.formatDuration(Date.now()-o.startedAt):o.completedAt&&o.startedAt?u.formatDuration(o.completedAt-o.startedAt):"-"}function b(o){return o?new Date(o).toLocaleString():"-"}function y(o,d){return o?o.length>d?`${o.slice(0,d)}...`:o:""}P(()=>u.startPolling(5e3)),F(()=>u.stopPolling());const f={store:u,columns:e,getDuration:x,formatTime:b,truncate:y,onMounted:P,onUnmounted:F,get ReloadOutlined(){return E},get useTasksStore(){return I}};return Object.defineProperty(f,"__isScriptSetup",{enumerable:!1,value:!0}),f}},L={class:"page-header"},j={key:0,class:"error-text"},J={key:1},K={class:"task-header"},M={class:"task-desc"},Q={class:"task-id"},W={class:"task-meta"},Z=["title"],q={key:0,class:"error-text"},G={key:1,class:"success-text"},H={key:2,class:"muted-text"};function X(k,l,u,e,x,b){const y=p("a-button"),f=p("a-space"),o=p("a-alert"),d=p("a-statistic"),m=p("a-card"),v=p("a-col"),C=p("a-row"),N=p("a-tag"),A=p("a-table");return i(),c("div",null,[_("div",L,[l[3]||(l[3]=_("div",null,[_("h2",{class:"page-title"},"后台任务"),_("p",{class:"page-sub"},"查看后台任务队列、实时通知和任务执行结果。")],-1)),n(f,null,{default:a(()=>[n(y,{ghost:"",loading:e.store.loading,onClick:l[0]||(l[0]=t=>e.store.fetchTasks())},{icon:a(()=>[n(e.ReloadOutlined)]),default:a(()=>[l[2]||(l[2]=g(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),e.store.lastNotification?(i(),T(o,{key:0,type:e.store.lastNotification.status==="completed"?"success":"error","show-icon":"",closable:"",class:"banner",onClose:l[1]||(l[1]=t=>e.store.lastNotification=null)},{message:a(()=>[g(" 任务"+r(e.store.lastNotification.status==="completed"?"完成":"结束")+": "+r(e.store.lastNotification.description||e.store.lastNotification.id.slice(0,16)),1)]),description:a(()=>[e.store.lastNotification.error?(i(),c("span",j,r(e.store.lastNotification.error),1)):e.store.lastNotification.result?(i(),c("span",J,r(e.truncate(String(e.store.lastNotification.result),120)),1)):w("v-if",!0)]),_:1},8,["type"])):w("v-if",!0),n(C,{gutter:[16,16],class:"stats-row"},{default:a(()=>[n(v,{xs:12,sm:6},{default:a(()=>[n(m,{class:"stat-card",size:"small"},{default:a(()=>[n(d,{title:"全部任务",value:e.store.tasks.length},null,8,["value"])]),_:1})]),_:1}),n(v,{xs:12,sm:6},{default:a(()=>[n(m,{class:"stat-card",size:"small"},{default:a(()=>[n(d,{title:"运行中",value:e.store.running.length},null,8,["value"])]),_:1})]),_:1}),n(v,{xs:12,sm:6},{default:a(()=>[n(m,{class:"stat-card",size:"small"},{default:a(()=>[n(d,{title:"等待中",value:e.store.pending.length},null,8,["value"])]),_:1})]),_:1}),n(v,{xs:12,sm:6},{default:a(()=>[n(m,{class:"stat-card",size:"small"},{default:a(()=>[n(d,{title:"已完成",value:e.store.completed.length},null,8,["value"])]),_:1})]),_:1})]),_:1}),e.store.running.length>0?(i(),T(m,{key:1,title:"运行中的任务",class:"panel-card",size:"small"},{default:a(()=>[(i(!0),c(h,null,B(e.store.running,t=>(i(),c("div",{key:t.id,class:"task-item running"},[_("div",K,[n(N,{color:e.store.getStatusColor(t.status)},{default:a(()=>[g(r(t.status.toUpperCase()),1)]),_:2},1032,["color"]),_("span",M,r(t.description),1),_("span",Q,r(t.id.slice(0,16)),1)]),_("div",W,[_("span",null,"类型: "+r(t.type||"-"),1),_("span",null,"已运行: "+r(e.store.formatDuration(Date.now()-t.startedAt)),1),n(y,{size:"small",danger:"",onClick:s=>e.store.stopTask(t.id)},{default:a(()=>[...l[4]||(l[4]=[g("停止",-1)])]),_:1},8,["onClick"])])]))),128))]),_:1})):w("v-if",!0),n(m,{class:"panel-card"},{default:a(()=>[n(A,{columns:e.columns,"data-source":e.store.tasks,pagination:{pageSize:15,size:"small"},loading:e.store.loading,"row-key":"id",size:"small"},{bodyCell:a(({column:t,record:s})=>[t.key==="status"?(i(),T(N,{key:0,color:e.store.getStatusColor(s.status)},{default:a(()=>[g(r(s.status),1)]),_:2},1032,["color"])):t.key==="description"?(i(),c("span",{key:1,title:s.command},r(s.description),9,Z)):t.key==="duration"?(i(),c(h,{key:2},[g(r(e.getDuration(s)),1)],64)):t.key==="createdAt"?(i(),c(h,{key:3},[g(r(e.formatTime(s.createdAt)),1)],64)):t.key==="result"?(i(),c(h,{key:4},[s.error?(i(),c("span",q,r(e.truncate(s.error,60)),1)):s.result?(i(),c("span",G,r(e.truncate(String(s.result),60)),1)):(i(),c("span",H,"-"))],64)):t.key==="action"?(i(),c(h,{key:5},[s.status==="running"?(i(),T(y,{key:0,size:"small",danger:"",onClick:S=>e.store.stopTask(s.id)},{default:a(()=>[...l[5]||(l[5]=[g(" 停止 ",-1)])]),_:1},8,["onClick"])):w("v-if",!0)],64)):w("v-if",!0)]),_:1},8,["data-source","loading"])]),_:1})])}const et=O(U,[["render",X],["__scopeId","data-v-da5ff6a2"],["__file","/tmp/cc-web-panel-94r5Fm/repo/packages/web-panel/src/views/Tasks.vue"]]);export{et as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{O as r}from"./index-DmrPbYXh.js";const o=((n,a,e)=>{r(n,`[ant-design-vue: ${a}] ${e}`)});export{o as d};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{A as o}from"./Row-xsUwB5Ay.js";import{U as t}from"./index-DmrPbYXh.js";import"./vendor-BvqAck49.js";import"./responsiveObserve-Em-jKJ7U.js";import"./useFlexGapSupport-DZOaLVto.js";import"./styleChecker-DCoehh1S.js";import"./index-Dj6rUk3f.js";import"./icons-DP3uiYxy.js";const l=t(o);export{l as default};
|