chainlesschain 0.166.14 → 0.166.16
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/package.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-C8SyFhOo.js → AIOps-CTxa2Wbq.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-Dup5gFK0.js → ActionButton-DHrQyYhy.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-8FyOWA7V.js → Analytics-DQiUqcNl.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DBzdU9dg.js → AppLayout-_Iz4r6wt.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-C_0Z8gNy.js → Artifacts-BNs63YHo.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-Cf2a-58m.js → Audit-BgHIqRLn.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-M7w-2zgB.js → BackgroundAgents-DUQ5axBB.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CCTHQXoL.js → Backup-CJ51E9Vw.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DjXpeFwJ.js → BaseInput-o-5toA_R.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-cAvchsJU.js → Chat-Cu7a-x1L.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-DvEvxlZv.js → ChatBubbleRenderer-BUyYkAXr.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-DKs6qvOn.js → Checkbox-DwdmZ71L.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DlkA7b9X.js → Codegen-BrH2eYiP.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CkfdKhyJ.js → Col-BVJQEP2j.js} +1 -1
- package/src/assets/web-panel/assets/{Community-iNXMHzj6.js → Community-FGO3vZPq.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DQxPEd09.js → Compact-DYGAFVnT.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CSKvMCjs.js → Compliance-CRvc8Bdt.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CkWqazpD.js → Cowork-D6Ah2m7A.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-k6W8IzhB.js → Cron-AXbU2ifR.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-C8MS1OuY.js → Crosschain-C5DXgEFd.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DJuCcgiQ.js → DID-Bxh9QV9v.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-LeThKzp3.js → Dashboard-B-ZHEta-.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BvxwgpE4.js → Dropdown-66Ik1jqa.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-n3e_a1M3.js → EmailListRenderer-CCWk1BIM.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-509W6W6v.js → FamilyGuardDashboard--9faIULK.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-xgZReQm0.js → Federation-CejW9CgX.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-jZOhKcQx.js → FormItemContext-acHgcXki.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-Jo0ULzHv.js → GenericCardRenderer-D2ghd_K4.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BsRcyWQP.js → Git-BOe1YJrV.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-JlpMYTAk.js → Governance-BjgzJsof.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CUEz872-.js → Inference-CXCD5rnP.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DgrvvEDU.js → KnowledgeGraph-CHA8QgJT.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-Df-KY4U3.js → Logs-DORPMcL6.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-CPPHz01z.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-kPZDTOeI.js → Marketplace-BCFlo1Yx.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CRRzPqNX.js → McpTools-Dl_uZAKh.js} +2 -2
- package/src/assets/web-panel/assets/{Memory-D6pNSkg9.js → Memory-DupHamwz.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-g-pvtwRC.js → MobileBridge-BRSMPJxW.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-Bzayfrfe.js → MobileProjects-BHpuzsDl.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-B7S3W-XL.js → Mtc-Ch0jOQfZ.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-B8OMEWVb.js → MtcAudit-qzwQrDi7.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-CowRp7GH.js → Multisig-B5wHzUcm.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-BkQNyi4c.js → NLProgramming-Hy9uAiA0.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Cm7gtkKz.js → Notes-DkuchMC7.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-CbPTVh9m.js → NotificationSettings-CYZhD7Pi.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-Dswi26mJ.js → OrderTableRenderer-DKOoqajt.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BkjQ9yy7.js → Organization-D9AXn6j8.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-DmRFXP7Y.js → Overflow-Bg15J6hX.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DQE1toAu.js → P2P--B54HoQn.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-Cz9Kk2Nb.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-xSjfOaiU.js → Permissions-DHx38eS1.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-B9ICLqVP.js → PersonalDataHub-Dw8i2hAs.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-CUNwyN9E.js → Pipeline-B2o6Ur2G.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-SOoCricX.js → Privacy-8g-h2fnu.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CSaFul0F.js → ProjectInit-DuVTcINx.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CueiB_oe.js → ProjectSettings-C8njvdZX.js} +2 -2
- package/src/assets/web-panel/assets/Projects-Ca9BAfu7.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CTqf_31h.js → Providers-wFqgod_W.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-C8ZP31E9.js → QrScannerModal-9NCXrpmA.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CPgn4713.js → QuickAsk-WUTNvFkY.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-8_e0zw0i.js → Recommend-xT4nYmju.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-iT7lbGqw.js → RemoteSession-fak1PBGC.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-B4q9SUOz.js → Reputation-D1AkQvD-.js} +1 -1
- package/src/assets/web-panel/assets/{Row-CA_nASyL.js → Row-DVfm6xGt.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-Cwb0E3yv.js → RssFeed-BDunoLSE.js} +3 -3
- package/src/assets/web-panel/assets/{Search-D9iVsOxJ.js → Search-OPycRoU3.js} +1 -1
- package/src/assets/web-panel/assets/{Security-DPLbYchG.js → Security-C8-Fm3Dt.js} +3 -3
- package/src/assets/web-panel/assets/{Services-DGMVL_LF.js → Services-qM_sMpMl.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-B_6kym0D.js → Skeleton-D3HBJjVF.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-Ds6r0dXB.js → Skills-jr67X-tP.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BLHAbBhb.js → Sla-CS3ggyCg.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-CZuddd14.js → SpeechSettings-CTOCYxOi.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CdBq7oSl.js → SyncSettings-D3s3cLT5.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DfT60Nyl.js → Tasks-CdfoJ25m.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-RLfsKy2V.js → Templates-Drb4AI8X.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-Cw8xCNLE.js → Tenant-DzwR3Qkz.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BOUkNu4f.js → Terminal-D-ESq7xp.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-CgGZWaRm.js → TimelineRenderer-BK-AUuws.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CpwjVyir.js → Tokens-xGTouuNp.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DL21H-eb.js → Trigger-BvZj-v2H.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-B3ffFclW.js → Trust-BLC9CGmc.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CkBeb5aI.js → UkeySign-BSuCXpmE.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-U2iVaE3r.js → VideoEditing-DT3A-_Ql.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CQk2wzYd.js → Wallet-c1OXao85.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DYIuIYzT.js → WebAuthn-CuA-F7KJ.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-tg1c2mZQ.js → WorkflowEditor-MANZrf82.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CtL61spq.js → chat-D4Y4Ey0O.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DKpbeo8s.js → colors-DDH06hKO.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-gPZsrswt.js → compact-item-Cym756Xj.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CfHlwzVr.js → createContext-By4Nb1k-.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-KO3pAGeO.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-MV47g_6X.js → hasIn-Ch7OY258.js} +1 -1
- package/src/assets/web-panel/assets/{index-DMMvlLp9.js → index-6-2eYBXr.js} +1 -1
- package/src/assets/web-panel/assets/{index-DsH-i_3d.js → index-6CpOV3Pn.js} +1 -1
- package/src/assets/web-panel/assets/{index-CB1HnbNK.js → index-ArMrnx0v.js} +1 -1
- package/src/assets/web-panel/assets/{index-DU4rZpiK.js → index-B51otVoZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRv_uMLV.js → index-BBBUn5v7.js} +1 -1
- package/src/assets/web-panel/assets/{index-srBc9U_s.js → index-BFydNU6a.js} +1 -1
- package/src/assets/web-panel/assets/{index-DnZ_zS1M.js → index-BIrRX-ra.js} +1 -1
- package/src/assets/web-panel/assets/{index-DGtEBodr.js → index-BZB9q-Lp.js} +1 -1
- package/src/assets/web-panel/assets/index-Bh4Rgkg2.js +1 -0
- package/src/assets/web-panel/assets/{index-BjlPD7GO.js → index-Bo20BfdS.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_B9LiKs.js → index-CF3Lhyns.js} +1 -1
- package/src/assets/web-panel/assets/{index-Rb7CRMw9.js → index-CGsvEbbq.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIeJmlAA.js → index-CJPks33Y.js} +1 -1
- package/src/assets/web-panel/assets/{index-xUlgG0Xe.js → index-CT-3FYwd.js} +1 -1
- package/src/assets/web-panel/assets/{index-6G0ETFTW.js → index-CUSUzaB8.js} +1 -1
- package/src/assets/web-panel/assets/{index-CzfxTSPW.js → index-CV1UC4zo.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmPJpLoD.js → index-CV8qXTvb.js} +1 -1
- package/src/assets/web-panel/assets/{index-fYcS7NS0.js → index-CZn6dmZe.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cjv0kKCU.js → index-CjNUTBwe.js} +1 -1
- package/src/assets/web-panel/assets/{index-Df9sWKpl.js → index-CpudmDhf.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9RF4ieu.js → index-CykROEJA.js} +1 -1
- package/src/assets/web-panel/assets/{index-Zvkt9xqi.js → index-D5sADPGY.js} +1 -1
- package/src/assets/web-panel/assets/{index-yxxXlqBA.js → index-D9le0-dc.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBw52sEl.js → index-DAkk1M7x.js} +1 -1
- package/src/assets/web-panel/assets/{index-ExAGPAnX.js → index-DNEJzc0r.js} +1 -1
- package/src/assets/web-panel/assets/{index-BQp5M0s1.js → index-DNlxihs8.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ddcpj1El.js → index-DiewptTL.js} +1 -1
- package/src/assets/web-panel/assets/{index-BOyGUuBE.js → index-DjwgJ5Jd.js} +1 -1
- package/src/assets/web-panel/assets/index-Dox_coTY.js +1 -0
- package/src/assets/web-panel/assets/{index-CmM9jqwe.js → index-DtGValNi.js} +1 -1
- package/src/assets/web-panel/assets/{index-DfLyHCWi.js → index-DvnywwUj.js} +1 -1
- package/src/assets/web-panel/assets/{index-BN-wxSQ8.js → index-OU8DZ9BL.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1XB5-t5.js → index-XGeQMvWK.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4lF-f_z.js → index-ZY2Qs_Sn.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9gtY4nG.js → index-jx7kr6mB.js} +3 -3
- package/src/assets/web-panel/assets/{index-C6nC_DyY.js → index-mL3nOcH6.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dd19vRwy.js → index-oBsfUbyH.js} +1 -1
- package/src/assets/web-panel/assets/{index-bSFrAszw.js → index-q-s04OKn.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_Pl1GnW.js → index-tZ5BUdad.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-BeOZoSZ4.js → initDefaultProps-DGcX9iPP.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BXE8VMKx.js → motion-2SeL1D8A.js} +1 -1
- package/src/assets/web-panel/assets/{move-I9sdvPGX.js → move-3cYbQCpS.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-d25zrJd0.js → mtc-parser-IDdxfw0z.js} +1 -1
- package/src/assets/web-panel/assets/{omit-D71V_T4e.js → omit-BNswdKO6.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BNZKpIAR.js → pickAttrs-BwCnem2I.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-jOcgxTTz.js → placementArrow-B9PtZ5rq.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-pta_O8AU.js → responsiveObserve-CPB6iSzV.js} +1 -1
- package/src/assets/web-panel/assets/{slide-Dlq6om7z.js → slide-DZgyblZa.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BnkO_yRv.js → statusUtils-D82IBdsx.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-p8NfWmcG.js → styleChecker-qSHtosM-.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-KcjZZ5U7.js → useFlexGapSupport-CmWO7h0I.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-gqonDMWB.js → useFs-yLrs_ub4.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-jIIfE4go.js → usePersonalDataHub-CJ1VW6rh.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-Dyo7fBrM.js → vnode-CzY_moQ4.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-6l8BMg9W.js → zoom-DAa7rEY5.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +62 -11
- package/src/commands/learning.js +71 -1
- package/src/commands/team.js +100 -3
- package/src/data/changelog.json +29 -3
- package/src/harness/worktree-isolator.js +74 -9
- package/src/lib/agent-team/task-lease.js +12 -1
- package/src/lib/agent-team/team-graph-runtime-adapter.js +6 -0
- package/src/lib/agent-team/team-runner.js +4 -0
- package/src/lib/agent-team/team-worktree.js +4 -0
- package/src/lib/capability-manifest.js +212 -1
- package/src/lib/evolution/evolution-artifact-ports.js +3277 -0
- package/src/lib/evolution/evolution-eval-gate.js +6442 -0
- package/src/lib/evolution/evolution-evidence-projector.js +3786 -0
- package/src/lib/evolution/evolution-ledger-ports.js +2689 -0
- package/src/lib/evolution/evolution-ledger.js +4280 -0
- package/src/lib/evolution/skill-candidate-registry.js +2258 -0
- package/src/lib/evolution/skill-execution-manifest.js +942 -0
- package/src/lib/evolution/skill-mutation-authority.js +1677 -0
- package/src/lib/evolution/skill-promotion-controller.js +506 -0
- package/src/lib/evolution/skill-release-registry.js +3277 -0
- package/src/lib/evolution/skill-target-matrix-eval.js +3233 -0
- package/src/lib/evolution/skill-writer-inventory-manifest.js +998 -0
- package/src/lib/evolution/skill-writer-inventory-validator.js +816 -0
- package/src/lib/formal-quality-eval-runtime.js +192 -0
- package/src/lib/graph-kernel/cutover-contract.js +7 -0
- package/src/lib/graph-kernel/cutover-ledger.js +8 -7
- package/src/lib/graph-kernel/evidence-digest.js +47 -0
- package/src/lib/graph-kernel/graph-runtime-surfaces.json +8 -1
- package/src/lib/graph-kernel/production-cutover-evidence.js +342 -15
- package/src/lib/graph-kernel/production-source-evidence.js +1599 -0
- package/src/lib/graph-kernel/retirement-evidence.js +15 -5
- package/src/lib/graph-kernel/runtime-surface-manifest.js +67 -2
- package/src/lib/headless-manifest.js +3 -1
- package/src/lib/learning/skill-improver.js +311 -43
- package/src/lib/learning/skill-synthesizer.js +236 -16
- package/src/lib/process-execution-broker/index.js +32 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +5 -4
- package/src/lib/secure-fs.js +45 -2
- package/src/runtime/agent-core.js +17 -5
- package/src/runtime/headless-runner.js +16 -9
- package/src/assets/web-panel/assets/MarkdownRenderer-BEPDcSwz.js +0 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-BujyoDRG.js +0 -7
- package/src/assets/web-panel/assets/Projects-BOeXvU7y.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DdqnMhzi.js +0 -1
- package/src/assets/web-panel/assets/index-BcK8o4ke.js +0 -1
- package/src/assets/web-panel/assets/index-DvbAjyYI.js +0 -1
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* 1. Find eligible trajectories
|
|
13
13
|
* 2. Check for duplicates (tool chain fingerprint)
|
|
14
14
|
* 3. Send to LLM for pattern extraction
|
|
15
|
-
* 4. Generate SKILL.md
|
|
16
|
-
* 5.
|
|
15
|
+
* 4. Generate and evaluate a candidate SKILL.md
|
|
16
|
+
* 5. Persist the accepted candidate to an isolated candidate registry
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import fs from "fs";
|
|
@@ -24,6 +24,8 @@ import path from "path";
|
|
|
24
24
|
|
|
25
25
|
const _deps = { fs, path };
|
|
26
26
|
|
|
27
|
+
export const SYNTHESIS_UNAVAILABLE_CODE = "LEARNING_SYNTHESIS_UNAVAILABLE";
|
|
28
|
+
|
|
27
29
|
// ── Helpers ─────────────────────────────────────────────
|
|
28
30
|
|
|
29
31
|
/**
|
|
@@ -79,6 +81,42 @@ export function generateSkillName(userIntent) {
|
|
|
79
81
|
);
|
|
80
82
|
}
|
|
81
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Skill names become path segments in the candidate registry. Keep the
|
|
86
|
+
* accepted grammar deliberately small so an LLM response cannot escape the
|
|
87
|
+
* configured registry root.
|
|
88
|
+
* @param {string} skillName
|
|
89
|
+
* @returns {boolean}
|
|
90
|
+
*/
|
|
91
|
+
export function isSafeSkillName(skillName) {
|
|
92
|
+
return (
|
|
93
|
+
typeof skillName === "string" &&
|
|
94
|
+
/^[\p{L}\p{N}][\p{L}\p{N}._-]{0,127}$/u.test(skillName) &&
|
|
95
|
+
skillName !== "." &&
|
|
96
|
+
skillName !== ".." &&
|
|
97
|
+
!skillName.includes("..")
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function rootContains(parentRoot, childRoot) {
|
|
102
|
+
if (!parentRoot || !childRoot) return false;
|
|
103
|
+
const parent = path.resolve(parentRoot);
|
|
104
|
+
const child = path.resolve(childRoot);
|
|
105
|
+
const relative = path.relative(parent, child);
|
|
106
|
+
return (
|
|
107
|
+
relative === "" ||
|
|
108
|
+
(relative !== ".." &&
|
|
109
|
+
!relative.startsWith(`..${path.sep}`) &&
|
|
110
|
+
!path.isAbsolute(relative))
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function rootsOverlap(firstRoot, secondRoot) {
|
|
115
|
+
return (
|
|
116
|
+
rootContains(firstRoot, secondRoot) || rootContains(secondRoot, firstRoot)
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
82
120
|
// ── LLM prompt template ─────────────────────────────────
|
|
83
121
|
|
|
84
122
|
/**
|
|
@@ -167,7 +205,7 @@ export class SkillSynthesizer {
|
|
|
167
205
|
* @param {import("better-sqlite3").Database} db
|
|
168
206
|
* @param {function} llmChat — async (messages) => string (LLM response)
|
|
169
207
|
* @param {import("./trajectory-store.js").TrajectoryStore} trajectoryStore
|
|
170
|
-
* @param {{minToolCount?:number, minScore?:number, minSimilar?:number,
|
|
208
|
+
* @param {{minToolCount?:number, minScore?:number, minSimilar?:number, candidateOutputDir?:string, activeSkillsDirs?:string[], evaluateCandidate?:function}} [config]
|
|
171
209
|
*/
|
|
172
210
|
constructor(db, llmChat, trajectoryStore, config = {}) {
|
|
173
211
|
this.db = db;
|
|
@@ -176,14 +214,80 @@ export class SkillSynthesizer {
|
|
|
176
214
|
this.minToolCount = config.minToolCount ?? 5;
|
|
177
215
|
this.minScore = config.minScore ?? 0.7;
|
|
178
216
|
this.minSimilar = config.minSimilar ?? 2;
|
|
179
|
-
this.
|
|
217
|
+
this.candidateOutputDir = config.candidateOutputDir || null;
|
|
218
|
+
const configuredActiveSkillsDirs = Array.isArray(config.activeSkillsDirs)
|
|
219
|
+
? config.activeSkillsDirs
|
|
220
|
+
: [];
|
|
221
|
+
this.activeSkillsDirs = configuredActiveSkillsDirs.filter(
|
|
222
|
+
(root) => typeof root === "string" && root.trim().length > 0,
|
|
223
|
+
);
|
|
224
|
+
this.activeSkillsDirsInvalid =
|
|
225
|
+
configuredActiveSkillsDirs.length !== this.activeSkillsDirs.length;
|
|
226
|
+
this.evaluateCandidate =
|
|
227
|
+
typeof config.evaluateCandidate === "function"
|
|
228
|
+
? config.evaluateCandidate
|
|
229
|
+
: null;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Report whether this instance can truthfully create persisted candidates.
|
|
234
|
+
* No trajectory is queried or mutated while the synthesizer is unavailable.
|
|
235
|
+
* @returns {{available:boolean, missingDependencies:string[], blockers:string[]}}
|
|
236
|
+
*/
|
|
237
|
+
getAvailability() {
|
|
238
|
+
const missingDependencies = [];
|
|
239
|
+
const blockers = [];
|
|
240
|
+
if (typeof this.llmChat !== "function") missingDependencies.push("llm");
|
|
241
|
+
if (!this.candidateOutputDir) {
|
|
242
|
+
missingDependencies.push("candidate-output-registry");
|
|
243
|
+
}
|
|
244
|
+
if (typeof this.evaluateCandidate !== "function") {
|
|
245
|
+
missingDependencies.push("candidate-evaluator");
|
|
246
|
+
}
|
|
247
|
+
if (this.activeSkillsDirs.length === 0) {
|
|
248
|
+
missingDependencies.push("active-skill-registry-roots");
|
|
249
|
+
}
|
|
250
|
+
if (this.activeSkillsDirsInvalid) {
|
|
251
|
+
blockers.push("active-skill-registry-roots-invalid");
|
|
252
|
+
}
|
|
253
|
+
if (
|
|
254
|
+
this.candidateOutputDir &&
|
|
255
|
+
this.activeSkillsDirs.some((activeRoot) =>
|
|
256
|
+
rootsOverlap(activeRoot, this.candidateOutputDir),
|
|
257
|
+
)
|
|
258
|
+
) {
|
|
259
|
+
blockers.push("candidate-output-overlaps-active-skill-tree");
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
available: missingDependencies.length === 0 && blockers.length === 0,
|
|
263
|
+
missingDependencies,
|
|
264
|
+
blockers,
|
|
265
|
+
};
|
|
180
266
|
}
|
|
181
267
|
|
|
182
268
|
/**
|
|
183
269
|
* Scan for eligible trajectories and synthesize skills.
|
|
184
|
-
* @returns {Promise<{created: string[], skipped: string[]}>}
|
|
270
|
+
* @returns {Promise<{status:string, created: string[], skipped: string[], errors?:string[], code?:string, reason?:string, missingDependencies?:string[], blockers?:string[]}>}
|
|
185
271
|
*/
|
|
186
272
|
async synthesize() {
|
|
273
|
+
const availability = this.getAvailability();
|
|
274
|
+
if (!availability.available) {
|
|
275
|
+
const issues = [
|
|
276
|
+
...availability.missingDependencies.map((item) => `missing ${item}`),
|
|
277
|
+
...availability.blockers,
|
|
278
|
+
];
|
|
279
|
+
const reason = `Synthesis unavailable: ${issues.join(", ")}`;
|
|
280
|
+
return {
|
|
281
|
+
status: "unavailable",
|
|
282
|
+
code: SYNTHESIS_UNAVAILABLE_CODE,
|
|
283
|
+
reason,
|
|
284
|
+
missingDependencies: availability.missingDependencies,
|
|
285
|
+
blockers: availability.blockers,
|
|
286
|
+
created: [],
|
|
287
|
+
skipped: [],
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
187
291
|
const candidates = this.trajectoryStore.findComplexUnprocessed({
|
|
188
292
|
minToolCount: this.minToolCount,
|
|
189
293
|
minScore: this.minScore,
|
|
@@ -192,6 +296,7 @@ export class SkillSynthesizer {
|
|
|
192
296
|
|
|
193
297
|
const created = [];
|
|
194
298
|
const skipped = [];
|
|
299
|
+
const errors = [];
|
|
195
300
|
|
|
196
301
|
for (const traj of candidates) {
|
|
197
302
|
try {
|
|
@@ -225,25 +330,56 @@ export class SkillSynthesizer {
|
|
|
225
330
|
|
|
226
331
|
// Generate and persist
|
|
227
332
|
const skillName = pattern.name || generateSkillName(traj.userIntent);
|
|
333
|
+
if (!isSafeSkillName(skillName)) {
|
|
334
|
+
skipped.push(`${traj.id}: invalid candidate skill name`);
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
228
337
|
const content = generateSkillMd(
|
|
229
338
|
pattern,
|
|
230
339
|
traj.id,
|
|
231
340
|
traj.outcomeScore || 0.7,
|
|
232
341
|
);
|
|
233
342
|
|
|
234
|
-
|
|
235
|
-
|
|
343
|
+
const evaluation = await this.evaluateCandidate({
|
|
344
|
+
skillName,
|
|
345
|
+
content,
|
|
346
|
+
pattern,
|
|
347
|
+
trajectory: traj,
|
|
348
|
+
});
|
|
349
|
+
const accepted =
|
|
350
|
+
evaluation === true ||
|
|
351
|
+
(evaluation &&
|
|
352
|
+
typeof evaluation === "object" &&
|
|
353
|
+
evaluation.accepted === true);
|
|
354
|
+
if (!accepted) {
|
|
355
|
+
const evaluationReason =
|
|
356
|
+
evaluation && typeof evaluation === "object"
|
|
357
|
+
? evaluation.reason
|
|
358
|
+
: null;
|
|
359
|
+
skipped.push(
|
|
360
|
+
`${traj.id}: evaluator rejected candidate${evaluationReason ? ` - ${evaluationReason}` : ""}`,
|
|
361
|
+
);
|
|
362
|
+
continue;
|
|
236
363
|
}
|
|
237
364
|
|
|
238
|
-
|
|
365
|
+
await this._persistSkill(skillName, content);
|
|
366
|
+
|
|
367
|
+
// Only durable, evaluated candidates count as synthesized.
|
|
239
368
|
this.trajectoryStore.markSynthesized(traj.id, skillName);
|
|
240
369
|
created.push(skillName);
|
|
241
370
|
} catch (err) {
|
|
242
|
-
|
|
371
|
+
const message = `${traj.id}: error - ${err.message}`;
|
|
372
|
+
skipped.push(message);
|
|
373
|
+
errors.push(message);
|
|
243
374
|
}
|
|
244
375
|
}
|
|
245
376
|
|
|
246
|
-
return {
|
|
377
|
+
return {
|
|
378
|
+
status: errors.length > 0 ? "error" : "completed",
|
|
379
|
+
created,
|
|
380
|
+
skipped,
|
|
381
|
+
errors,
|
|
382
|
+
};
|
|
247
383
|
}
|
|
248
384
|
|
|
249
385
|
/**
|
|
@@ -297,19 +433,103 @@ export class SkillSynthesizer {
|
|
|
297
433
|
}
|
|
298
434
|
|
|
299
435
|
/**
|
|
300
|
-
* Write SKILL.md to the output
|
|
436
|
+
* Write SKILL.md to the isolated candidate output registry.
|
|
301
437
|
* @param {string} skillName
|
|
302
438
|
* @param {string} content
|
|
303
439
|
* @returns {Promise<{skillDir:string, skillFile:string}>}
|
|
304
440
|
*/
|
|
305
441
|
async _persistSkill(skillName, content) {
|
|
306
|
-
|
|
307
|
-
|
|
442
|
+
if (!this.candidateOutputDir) {
|
|
443
|
+
throw new Error("candidate output registry is unavailable");
|
|
444
|
+
}
|
|
445
|
+
if (!isSafeSkillName(skillName)) {
|
|
446
|
+
throw new Error("invalid candidate skill name");
|
|
447
|
+
}
|
|
448
|
+
const availability = this.getAvailability();
|
|
449
|
+
if (!availability.available) {
|
|
450
|
+
throw new Error(
|
|
451
|
+
`candidate output boundary unavailable: ${[
|
|
452
|
+
...availability.missingDependencies,
|
|
453
|
+
...availability.blockers,
|
|
454
|
+
].join(", ")}`,
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
this._assertCandidateFilesystemSupport();
|
|
458
|
+
const candidateRoot = await this._ensurePrivateDirectory(
|
|
459
|
+
this.candidateOutputDir,
|
|
460
|
+
{ recursive: true },
|
|
461
|
+
);
|
|
462
|
+
await this._assertRealpathIsolation(candidateRoot);
|
|
463
|
+
|
|
464
|
+
const skillNamespace = _deps.path.join(this.candidateOutputDir, skillName);
|
|
465
|
+
const canonicalSkillNamespace =
|
|
466
|
+
await this._ensurePrivateDirectory(skillNamespace);
|
|
467
|
+
this._assertPathWithinCandidateRoot(candidateRoot, canonicalSkillNamespace);
|
|
468
|
+
const skillDir = _deps.path.join(canonicalSkillNamespace, "1.0.0");
|
|
469
|
+
const canonicalSkillDir = await this._ensurePrivateDirectory(skillDir);
|
|
470
|
+
this._assertPathWithinCandidateRoot(candidateRoot, canonicalSkillDir);
|
|
471
|
+
const skillFile = _deps.path.join(canonicalSkillDir, "SKILL.md");
|
|
472
|
+
|
|
473
|
+
await _deps.fs.promises.writeFile(skillFile, content, {
|
|
474
|
+
encoding: "utf-8",
|
|
475
|
+
flag: "wx",
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
return { skillDir: canonicalSkillDir, skillFile };
|
|
479
|
+
}
|
|
308
480
|
|
|
309
|
-
|
|
310
|
-
|
|
481
|
+
_assertCandidateFilesystemSupport() {
|
|
482
|
+
if (
|
|
483
|
+
typeof _deps.fs.promises.realpath !== "function" ||
|
|
484
|
+
typeof _deps.fs.promises.lstat !== "function"
|
|
485
|
+
) {
|
|
486
|
+
throw new Error(
|
|
487
|
+
"candidate filesystem identity support unavailable; refusing write",
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
async _ensurePrivateDirectory(directory, options = {}) {
|
|
493
|
+
let stat;
|
|
494
|
+
try {
|
|
495
|
+
stat = await _deps.fs.promises.lstat(directory);
|
|
496
|
+
} catch (error) {
|
|
497
|
+
if (error?.code !== "ENOENT") throw error;
|
|
498
|
+
try {
|
|
499
|
+
await _deps.fs.promises.mkdir(directory, {
|
|
500
|
+
recursive: options.recursive === true,
|
|
501
|
+
mode: 0o700,
|
|
502
|
+
});
|
|
503
|
+
} catch (mkdirError) {
|
|
504
|
+
if (mkdirError?.code !== "EEXIST") throw mkdirError;
|
|
505
|
+
}
|
|
506
|
+
stat = await _deps.fs.promises.lstat(directory);
|
|
507
|
+
}
|
|
508
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
509
|
+
throw new Error(
|
|
510
|
+
`candidate directory is not a trusted directory: ${directory}`,
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
return _deps.fs.promises.realpath(directory);
|
|
514
|
+
}
|
|
311
515
|
|
|
312
|
-
|
|
516
|
+
async _assertRealpathIsolation(candidateRoot) {
|
|
517
|
+
const activeRoots = await Promise.all(
|
|
518
|
+
this.activeSkillsDirs.map((root) => _deps.fs.promises.realpath(root)),
|
|
519
|
+
);
|
|
520
|
+
if (activeRoots.some((root) => rootsOverlap(root, candidateRoot))) {
|
|
521
|
+
throw new Error(
|
|
522
|
+
"candidate output resolves into an active skill tree; refusing write",
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
_assertPathWithinCandidateRoot(candidateRoot, candidatePath) {
|
|
528
|
+
if (!rootContains(candidateRoot, candidatePath)) {
|
|
529
|
+
throw new Error(
|
|
530
|
+
"candidate parent resolves outside the candidate root; refusing write",
|
|
531
|
+
);
|
|
532
|
+
}
|
|
313
533
|
}
|
|
314
534
|
}
|
|
315
535
|
|
|
@@ -4201,9 +4201,35 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
4201
4201
|
args: filteredArgs,
|
|
4202
4202
|
env: filteredEnv,
|
|
4203
4203
|
report: credentialReport,
|
|
4204
|
+
referenceIds: Object.entries(filteredEnv)
|
|
4205
|
+
.filter(
|
|
4206
|
+
([key, value]) =>
|
|
4207
|
+
(key.startsWith("CC_CRED_REF_") ||
|
|
4208
|
+
key.startsWith("CC_CRED_ARG_REF_")) &&
|
|
4209
|
+
typeof value === "string" &&
|
|
4210
|
+
value.startsWith("cc-cred-"),
|
|
4211
|
+
)
|
|
4212
|
+
.map(([, value]) => value),
|
|
4204
4213
|
};
|
|
4205
4214
|
}
|
|
4206
4215
|
|
|
4216
|
+
_revokeCredentialReferences(referenceIds, reason) {
|
|
4217
|
+
if (
|
|
4218
|
+
!Array.isArray(referenceIds) ||
|
|
4219
|
+
typeof this._credentialAgent.revokeCredentialRef !== "function"
|
|
4220
|
+
) {
|
|
4221
|
+
return;
|
|
4222
|
+
}
|
|
4223
|
+
for (const refId of new Set(referenceIds)) {
|
|
4224
|
+
try {
|
|
4225
|
+
this._credentialAgent.revokeCredentialRef(refId, reason);
|
|
4226
|
+
} catch {
|
|
4227
|
+
// Credential cleanup must never replace the authoritative process
|
|
4228
|
+
// result. References remain bounded by their issuance TTL.
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
}
|
|
4232
|
+
|
|
4207
4233
|
_createCredentialContext(command, options, executionId, decision) {
|
|
4208
4234
|
if (typeof this._credentialAgent.createBrokerContext !== "function") {
|
|
4209
4235
|
return options.credentialContext;
|
|
@@ -4933,6 +4959,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
4933
4959
|
options = this._withAmbientProcessContext(command, options);
|
|
4934
4960
|
const executionId = crypto.randomUUID();
|
|
4935
4961
|
const startTime = Date.now();
|
|
4962
|
+
let credentialReferenceIds = [];
|
|
4936
4963
|
const origin = options.origin || "unknown";
|
|
4937
4964
|
const requestedCwd = options.cwd || process.cwd();
|
|
4938
4965
|
options = this._withWorkspaceTransactionBoundaries(options, requestedCwd, {
|
|
@@ -5055,6 +5082,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
5055
5082
|
);
|
|
5056
5083
|
spawnOpts.env = credentialBoundary.env;
|
|
5057
5084
|
args = credentialBoundary.args;
|
|
5085
|
+
credentialReferenceIds = credentialBoundary.referenceIds;
|
|
5058
5086
|
auditEntry.args = this._auditArgs(args, auditRedactArgIndexes);
|
|
5059
5087
|
this._recordCredentialReport(auditEntry, credentialBoundary.report);
|
|
5060
5088
|
this._stripCredentialControlOptions(spawnOpts);
|
|
@@ -5159,6 +5187,10 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
5159
5187
|
throw err;
|
|
5160
5188
|
} finally {
|
|
5161
5189
|
sandboxPlan.cleanup?.();
|
|
5190
|
+
this._revokeCredentialReferences(
|
|
5191
|
+
credentialReferenceIds,
|
|
5192
|
+
"sync-process-settled",
|
|
5193
|
+
);
|
|
5162
5194
|
}
|
|
5163
5195
|
}
|
|
5164
5196
|
|
|
@@ -2719,17 +2719,18 @@ function sameWindowsFileIdentity(left, right) {
|
|
|
2719
2719
|
);
|
|
2720
2720
|
}
|
|
2721
2721
|
|
|
2722
|
-
// Cleanup is authorized by the stable file
|
|
2722
|
+
// Cleanup is authorized by the stable volume/file identity, not by metadata
|
|
2723
2723
|
// that Windows may settle after the helper closes its last write handle. The
|
|
2724
2724
|
// strict identity above remains authoritative while content is read or
|
|
2725
2725
|
// attested; this cleanup-only comparison still rejects a same-path replacement
|
|
2726
|
-
// because that changes the inode
|
|
2726
|
+
// because that changes the inode. Node's Windows birthtime projection can
|
|
2727
|
+
// settle together with size/ctime/mtime, so it is metadata rather than part of
|
|
2728
|
+
// the deletion authority.
|
|
2727
2729
|
function sameWindowsFileObjectIdentity(left, right) {
|
|
2728
2730
|
return (
|
|
2729
2731
|
left.dev === right.dev &&
|
|
2730
2732
|
left.ino === right.ino &&
|
|
2731
|
-
left.mode === right.mode
|
|
2732
|
-
left.birthtimeNs === right.birthtimeNs
|
|
2733
|
+
left.mode === right.mode
|
|
2733
2734
|
);
|
|
2734
2735
|
}
|
|
2735
2736
|
|
package/src/lib/secure-fs.js
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
win32,
|
|
10
10
|
posix,
|
|
11
11
|
} from "node:path";
|
|
12
|
+
import { isFormalQualityHermeticRuntime } from "./formal-quality-eval-runtime.js";
|
|
12
13
|
|
|
13
14
|
export const PRIVATE_DIRECTORY_MODE = 0o700;
|
|
14
15
|
export const PRIVATE_FILE_MODE = 0o600;
|
|
@@ -605,6 +606,40 @@ export const _deps = {
|
|
|
605
606
|
// tests and repairPrivatePath() always execute and verify the operation.
|
|
606
607
|
const securedWindowsPaths = new Set();
|
|
607
608
|
const WINDOWS_ACL_BATCH_SIZE = 500;
|
|
609
|
+
const WINDOWS_ACL_TIMEOUT_ENV = "CC_SECURE_FS_WINDOWS_ACL_TIMEOUT_MS";
|
|
610
|
+
const MAX_WINDOWS_ACL_TIMEOUT_MS = 5 * 60_000;
|
|
611
|
+
|
|
612
|
+
export function _windowsAclWorkingDirectory(
|
|
613
|
+
environment = process.env,
|
|
614
|
+
filesystem = fs,
|
|
615
|
+
) {
|
|
616
|
+
if (!isFormalQualityHermeticRuntime(environment)) return null;
|
|
617
|
+
const configuredHome = resolve(String(environment.CHAINLESSCHAIN_HOME));
|
|
618
|
+
try {
|
|
619
|
+
const entry = filesystem.lstatSync(configuredHome);
|
|
620
|
+
if (!entry.isDirectory() || entry.isSymbolicLink()) return null;
|
|
621
|
+
} catch {
|
|
622
|
+
return null;
|
|
623
|
+
}
|
|
624
|
+
return configuredHome;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Windows hosted runners can need more than the normal 15/30 second allowance
|
|
628
|
+
// to cold-start PowerShell and load the access-control types. A trusted harness
|
|
629
|
+
// may raise (but never lower) that allowance; the cap prevents an inherited
|
|
630
|
+
// environment value from wedging owner-only storage initialization forever.
|
|
631
|
+
export function _resolveWindowsAclTimeout(
|
|
632
|
+
defaultTimeoutMs,
|
|
633
|
+
environment = process.env,
|
|
634
|
+
) {
|
|
635
|
+
const fallback = Math.max(1, Math.floor(Number(defaultTimeoutMs) || 1));
|
|
636
|
+
const configured = Number(environment?.[WINDOWS_ACL_TIMEOUT_ENV]);
|
|
637
|
+
if (!Number.isFinite(configured) || configured <= 0) return fallback;
|
|
638
|
+
return Math.min(
|
|
639
|
+
Math.max(fallback, Math.floor(configured)),
|
|
640
|
+
MAX_WINDOWS_ACL_TIMEOUT_MS,
|
|
641
|
+
);
|
|
642
|
+
}
|
|
608
643
|
|
|
609
644
|
function repairWindowsAclOnce(target, deps, options) {
|
|
610
645
|
const cacheable = !options.deps;
|
|
@@ -617,6 +652,7 @@ function repairWindowsAclOnce(target, deps, options) {
|
|
|
617
652
|
}
|
|
618
653
|
|
|
619
654
|
function windowsAcl(target, operation, deps) {
|
|
655
|
+
const workingDirectory = _windowsAclWorkingDirectory(process.env, deps.fs);
|
|
620
656
|
const result = deps.spawnSync(
|
|
621
657
|
"powershell.exe",
|
|
622
658
|
[
|
|
@@ -630,7 +666,12 @@ function windowsAcl(target, operation, deps) {
|
|
|
630
666
|
target,
|
|
631
667
|
operation,
|
|
632
668
|
],
|
|
633
|
-
{
|
|
669
|
+
{
|
|
670
|
+
encoding: "utf8",
|
|
671
|
+
windowsHide: true,
|
|
672
|
+
timeout: _resolveWindowsAclTimeout(15_000),
|
|
673
|
+
...(workingDirectory ? { cwd: workingDirectory } : {}),
|
|
674
|
+
},
|
|
634
675
|
);
|
|
635
676
|
let details = null;
|
|
636
677
|
try {
|
|
@@ -656,6 +697,7 @@ function windowsAcl(target, operation, deps) {
|
|
|
656
697
|
|
|
657
698
|
function windowsAclBatch(targets, operation, deps, expectedKind = null) {
|
|
658
699
|
if (targets.length === 0) return [];
|
|
700
|
+
const workingDirectory = _windowsAclWorkingDirectory(process.env, deps.fs);
|
|
659
701
|
const result = deps.spawnSync(
|
|
660
702
|
"powershell.exe",
|
|
661
703
|
[
|
|
@@ -675,8 +717,9 @@ function windowsAclBatch(targets, operation, deps, expectedKind = null) {
|
|
|
675
717
|
...(expectedKind ? { expectedKind } : {}),
|
|
676
718
|
}),
|
|
677
719
|
windowsHide: true,
|
|
678
|
-
timeout:
|
|
720
|
+
timeout: _resolveWindowsAclTimeout(30_000),
|
|
679
721
|
maxBuffer: 4 * 1024 * 1024,
|
|
722
|
+
...(workingDirectory ? { cwd: workingDirectory } : {}),
|
|
680
723
|
},
|
|
681
724
|
);
|
|
682
725
|
let details = [];
|
|
@@ -746,14 +746,25 @@ export function reapIdleBackgroundShellTasks(deps = {}) {
|
|
|
746
746
|
// Foreground (synchronous) run_shell timeout. Configurable per-call via the
|
|
747
747
|
// optional `timeout` arg; defaults to 60s and is hard-capped at 10 min so a
|
|
748
748
|
// synchronous call can never wedge the loop indefinitely (use run_in_background
|
|
749
|
-
// for genuinely long work).
|
|
749
|
+
// for genuinely long work). Trusted harnesses may set a minimum through the
|
|
750
|
+
// parent-process environment so model-generated tool arguments cannot shorten a
|
|
751
|
+
// benchmark's platform-neutral execution allowance. The unset path preserves
|
|
752
|
+
// the public per-call semantics byte-for-byte.
|
|
750
753
|
const DEFAULT_SHELL_TIMEOUT_MS = 60000;
|
|
751
754
|
const MAX_SHELL_TIMEOUT_MS = 600000;
|
|
752
|
-
function _resolveShellTimeout(raw) {
|
|
753
|
-
|
|
755
|
+
export function _resolveShellTimeout(raw, environment = process.env) {
|
|
756
|
+
const configuredMinimum = Number(environment?.CC_RUN_SHELL_MIN_TIMEOUT_MS);
|
|
757
|
+
const minimum =
|
|
758
|
+
Number.isFinite(configuredMinimum) && configuredMinimum > 0
|
|
759
|
+
? Math.min(Math.floor(configuredMinimum), MAX_SHELL_TIMEOUT_MS)
|
|
760
|
+
: 0;
|
|
761
|
+
if (raw == null) return Math.max(DEFAULT_SHELL_TIMEOUT_MS, minimum);
|
|
754
762
|
const n = Number(raw);
|
|
755
|
-
|
|
756
|
-
|
|
763
|
+
const requested =
|
|
764
|
+
Number.isFinite(n) && n > 0
|
|
765
|
+
? Math.min(Math.floor(n), MAX_SHELL_TIMEOUT_MS)
|
|
766
|
+
: DEFAULT_SHELL_TIMEOUT_MS;
|
|
767
|
+
return Math.max(requested, minimum);
|
|
757
768
|
}
|
|
758
769
|
|
|
759
770
|
/**
|
|
@@ -1325,6 +1336,7 @@ const GUARDED_FILE_MUTATION_TOOLS = new Set([
|
|
|
1325
1336
|
]);
|
|
1326
1337
|
const EXACT_FILE_MUTATION_SCOPE_TOOL_NAMES = new Set([
|
|
1327
1338
|
"read_file",
|
|
1339
|
+
"search_files",
|
|
1328
1340
|
"list_dir",
|
|
1329
1341
|
"write_file",
|
|
1330
1342
|
"edit_file",
|
|
@@ -40,6 +40,10 @@ import {
|
|
|
40
40
|
import { maybeApplyToolSearch } from "./mcp-tool-search.js";
|
|
41
41
|
import { IterationBudget } from "../lib/iteration-budget.js";
|
|
42
42
|
import { HostResourceBudget } from "../lib/host-resource-budget.js";
|
|
43
|
+
import {
|
|
44
|
+
FORMAL_QUALITY_FILE_TOOLS,
|
|
45
|
+
isFormalQualityHermeticRuntime,
|
|
46
|
+
} from "../lib/formal-quality-eval-runtime.js";
|
|
43
47
|
import {
|
|
44
48
|
startSession as jsonlStartSession,
|
|
45
49
|
appendUserMessage as jsonlAppendUserMessage,
|
|
@@ -186,7 +190,6 @@ const HERMETIC_SKILL_LOADER = Object.freeze({
|
|
|
186
190
|
getCacheLedger: () => null,
|
|
187
191
|
getLimits: () => null,
|
|
188
192
|
});
|
|
189
|
-
|
|
190
193
|
// EPIPE guard for `cc agent -p … | head`. Lives in pipe-safety.js (shared with
|
|
191
194
|
// the stream-json driver + REPL); re-exported here for existing importers.
|
|
192
195
|
export { installPipeSafety } from "./pipe-safety.js";
|
|
@@ -850,7 +853,9 @@ async function runAgentHeadlessInWorkspace(
|
|
|
850
853
|
const baseUrl = options.baseUrl || "http://localhost:11434";
|
|
851
854
|
const apiKey = options.apiKey || null;
|
|
852
855
|
const cwd = options.cwd || process.cwd();
|
|
853
|
-
const
|
|
856
|
+
const formalQualityHermetic = isFormalQualityHermeticRuntime(process.env);
|
|
857
|
+
const hermeticExecution =
|
|
858
|
+
options.hermeticExecution === true || formalQualityHermetic;
|
|
854
859
|
if (
|
|
855
860
|
options.fileMutationScope != null &&
|
|
856
861
|
(options.exactToolNames !== true || !hermeticExecution)
|
|
@@ -1220,12 +1225,14 @@ async function runAgentHeadlessInWorkspace(
|
|
|
1220
1225
|
assertManagedPermissionMode(options.permissionMode, managedSettings);
|
|
1221
1226
|
}
|
|
1222
1227
|
const perm = resolvePermissionMode(options.permissionMode);
|
|
1223
|
-
const enabledToolNames =
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1228
|
+
const enabledToolNames = formalQualityHermetic
|
|
1229
|
+
? [...FORMAL_QUALITY_FILE_TOOLS]
|
|
1230
|
+
: resolveEnabledTools({
|
|
1231
|
+
// An explicit --allowed-tools wins; otherwise a matched command's
|
|
1232
|
+
// `allowed-tools:` frontmatter scopes the run (null when neither applies).
|
|
1233
|
+
allowedTools: options.allowedTools || macroAllowedTools,
|
|
1234
|
+
readOnly: perm.readOnly,
|
|
1235
|
+
});
|
|
1229
1236
|
const disabledTools = options.disallowedTools || [];
|
|
1230
1237
|
|
|
1231
1238
|
// ── Best-effort runtime bootstrap (DB optional, like startAgentRepl) ───
|
|
@@ -1699,7 +1706,7 @@ async function runAgentHeadlessInWorkspace(
|
|
|
1699
1706
|
: options.skillLoader || new CLISkillLoader();
|
|
1700
1707
|
const systemContent = hermeticExecution
|
|
1701
1708
|
? composeSystemPrompt(
|
|
1702
|
-
"You are a hermetic code fixer.
|
|
1709
|
+
"You are a hermetic code fixer. The exposed file tools are the complete tool surface. Inspect and mutate only the exact paths authorized in the user request, then return a concise completion message.",
|
|
1703
1710
|
{ projectMemory: false },
|
|
1704
1711
|
)
|
|
1705
1712
|
: composeSystemPrompt(
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{P as c,J as p,b as s}from"./vendor-Bn1JzzAn.js";import{r as a}from"./markdown-Yo_c6Krv.js";import{_ as d}from"./index-C9gtY4nG.js";const _={__name:"MarkdownRenderer",props:{content:{type:String,default:""}},setup(t,{expose:o}){o();const e=t,r=s(()=>a(e.content||"")),n={props:e,rendered:r,computed:s,get renderMarkdown(){return a}};return Object.defineProperty(n,"__isScriptSetup",{enumerable:!1,value:!0}),n}},i=["innerHTML"];function l(t,o,e,r,n,m){return c(),p("div",{class:"markdown-content",innerHTML:r.rendered},null,8,i)}const w=d(_,[["render",l],["__scopeId","data-v-0b0b9f63"],["__file","/tmp/cc-web-panel-eI5lXL/repo/packages/web-panel/src/components/MarkdownRenderer.vue"]]);export{w as M};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./ChatBubbleRenderer-DvEvxlZv.js","./vendor-Bn1JzzAn.js","./index-C9gtY4nG.js","./icons-DG5UD-6K.js","./index-Cq93VfoF.css","./ChatBubbleRenderer-gy5SDGw2.css","./OrderTableRenderer-Dswi26mJ.js","./OrderTableRenderer-CfrDjSHT.css","./TimelineRenderer-CgGZWaRm.js","./TimelineRenderer-BlTAtkOc.css","./EmailListRenderer-n3e_a1M3.js","./EmailListRenderer-DTPZPx_S.css","./GenericCardRenderer-Jo0ULzHv.js","./GenericCardRenderer-o85VDYQS.css"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{E as ue,r as R,b as w,I as g,P as u,J as O,U as v,c,S as C,V as E,_ as M,F as V,Z as se,a0 as le,R as L,K as m,Q as b,W as A,o as J}from"./vendor-Bn1JzzAn.js";import{u as U}from"./usePersonalDataHub-jIIfE4go.js";import{_ as F,e as I,d as P}from"./index-C9gtY4nG.js";import{aa as q,ag as Q,M as z,aI as G,v as X,aH as H,aq as K,ac as W,e as de,d as fe,k as pe,ai as me,aA as _e,R as ye}from"./icons-DG5UD-6K.js";import"./useShellMode-CgR0wCYM.js";const T=Object.freeze({q:"",category:null,adapter:null,subtype:null,since:null,until:null}),B=50,Y=300,Z=ue("pdhBrowser",()=>{const r=R({...T}),t=R([]),n=R(null),e=R(!1),o=R(!1),l=R(null),a=R(null),s=R(!1),i=R({byCategory:{},byAdapter:{},bySubtype:{},total:0});let d=0,_=null;const x=w(()=>t.value.length>0),j=w(()=>n.value!=null);function h(S={}){const p={},f=r.value;return f.q&&f.q.trim()&&(p.q=f.q.trim()),f.category&&(p.category=f.category),f.adapter&&(p.adapter=f.adapter),f.subtype&&(p.subtype=f.subtype),Number.isFinite(f.since)&&(p.since=f.since),Number.isFinite(f.until)&&(p.until=f.until),{...p,...S}}async function y(){const S=++d;e.value=!0,l.value=null;const p=U();try{const[f,D]=await Promise.all([p.searchEvents(h({limit:B})),p.facetCounts({...r.value.q&&r.value.q.trim()?{q:r.value.q.trim()}:{},...Number.isFinite(r.value.since)?{since:r.value.since}:{},...Number.isFinite(r.value.until)?{until:r.value.until}:{}})]);if(S!==d)return;t.value=f.rows||[],n.value=f.nextCursor||null,a.value=f.mode||"like",s.value=!!f.shortQuery,i.value={byCategory:D.byCategory||{},byAdapter:D.byAdapter||{},bySubtype:D.bySubtype||{},total:D.total||0}}catch(f){if(S!==d)return;l.value=f&&f.message?f.message:String(f),t.value=[],n.value=null}finally{S===d&&(e.value=!1)}}async function k(){if(!n.value||o.value)return;o.value=!0,l.value=null;const S=U();try{const p=await S.searchEvents(h({cursor:n.value,limit:B}));t.value=t.value.concat(p.rows||[]),n.value=p.nextCursor||null,a.value=p.mode||a.value}catch(p){l.value=p&&p.message?p.message:String(p)}finally{o.value=!1}}function ae(S,p){if(!(S in T))throw new Error(`pdhBrowser.setFilter: unknown key "${S}"`);r.value={...r.value,[S]:p},_&&clearTimeout(_),_=setTimeout(()=>{_=null,y()},Y)}function ie(S){return r.value={...T,...S},_&&(clearTimeout(_),_=null),y()}function ce(){r.value={...T},t.value=[],n.value=null,l.value=null,i.value={byCategory:{},byAdapter:{},bySubtype:{},total:0}}return{filters:r,results:t,cursor:n,isLoading:e,isAppending:o,error:l,mode:a,shortQuery:s,facets:i,hasResults:x,canLoadMore:j,search:y,loadMore:k,setFilter:ae,setFilters:ie,reset:ce,PAGE_SIZE:B,SEARCH_DEBOUNCE_MS:Y}}),ge=Object.freeze(["chat","social","email","shopping","travel","system","ai-chat","other"]),ve=Object.freeze({chat:"社交聊天",social:"内容平台",email:"邮件",shopping:"支付订单",travel:"出行",system:"系统数据","ai-chat":"AI 对话",other:"其他"});function N(r){return ve[r]||r||"未知"}const be=Object.freeze([["wechat","chat"],["messaging-","chat"],["social-","social"],["email-","email"],["shopping-","shopping"],["alipay-","shopping"],["travel-","travel"],["system-data","system"],["browser-","system"],["meeting-","system"],["vscode","system"],["vscodium","system"],["jetbrains-ide","system"],["win-recent","system"],["git-activity","system"],["shell-history","system"],["hbuilderx","system"],["local-files","system"],["cursor","ai-chat"],["claude-code","ai-chat"],["ai-chat-","ai-chat"]]);function $(r){if(typeof r!="string"||r.length===0)return"other";for(const[t,n]of be)if(t.endsWith("-")||t==="system-data"){if(r.startsWith(t))return n}else if(r===t)return n;return"other"}const he={__name:"CategorySidebar",props:{selected:{type:String,default:null},facets:{type:Object,default:()=>({byCategory:{},total:0})}},emits:["select"],setup(r,{expose:t}){t();const n=r,e=w(()=>n.facets.total||0),o={chat:W,social:K,email:H,shopping:X,travel:G,system:z,"ai-chat":Q,other:q};function l(i){return o[i]||q}function a(i){return i?{backgroundColor:"#fff",color:"#1677ff"}:{backgroundColor:"#f0f0f0",color:"#666"}}const s={props:n,total:e,ICONS:o,iconFor:l,badgeStyle:a,computed:w,get AppstoreOutlined(){return q},get MessageOutlined(){return W},get PlayCircleOutlined(){return K},get MailOutlined(){return H},get ShoppingOutlined(){return X},get CarOutlined(){return G},get MobileOutlined(){return z},get RobotOutlined(){return Q},get CATEGORIES(){return ge},get categoryLabel(){return N}};return Object.defineProperty(s,"__isScriptSetup",{enumerable:!1,value:!0}),s}},Se={class:"pdh-sidebar"},Oe=["onClick"],we={class:"label"};function Ce(r,t,n,e,o,l){const a=g("a-badge");return u(),O("div",Se,[t[2]||(t[2]=v("div",{class:"sidebar-title"},"数据类型",-1)),v("div",{class:M(["cat-item",{active:n.selected===null}]),onClick:t[0]||(t[0]=s=>r.$emit("select",null))},[c(e.AppstoreOutlined,{class:"icon"}),t[1]||(t[1]=v("span",{class:"label"},"全部",-1)),e.total>0?(u(),C(a,{key:0,count:e.total,"number-style":e.badgeStyle(n.selected===null),"overflow-count":9999},null,8,["count","number-style"])):E("v-if",!0)],2),(u(!0),O(V,null,se(e.CATEGORIES,s=>(u(),O("div",{key:s,class:M(["cat-item",{active:n.selected===s,dim:!n.facets.byCategory[s]}]),onClick:i=>r.$emit("select",s)},[(u(),C(le(e.iconFor(s)),{class:"icon"})),v("span",we,L(e.categoryLabel(s)),1),n.facets.byCategory[s]?(u(),C(a,{key:0,count:n.facets.byCategory[s],"number-style":e.badgeStyle(n.selected===s),"overflow-count":9999},null,8,["count","number-style"])):E("v-if",!0)],10,Oe))),128))])}const ke=F(he,[["render",Ce],["__scopeId","data-v-6b62a22e"],["__file","/tmp/cc-web-panel-eI5lXL/repo/packages/web-panel/src/components/pdh/CategorySidebar.vue"]]),Ee={__name:"SearchFilterBar",props:{filters:{type:Object,required:!0},facets:{type:Object,default:()=>({byAdapter:{}})},isLoading:{type:Boolean,default:!1},mode:{type:String,default:null},shortQuery:{type:Boolean,default:!1}},emits:["set-filter","reset"],setup(r,{expose:t,emit:n}){t();const e=r,o=n,l=w(()=>e.filters.category?`在「${e.filters.category}」类目内搜索…`:"搜索关键词(如:支付宝、罗技、Kotlin)…"),a=w(()=>Object.entries(e.facets.byAdapter||{}).sort((y,k)=>k[1]-y[1]).map(([y,k])=>({value:y,label:`${y} (${k})`}))),s=w(()=>!e.filters.since&&!e.filters.until?null:[e.filters.since?new Date(e.filters.since):null,e.filters.until?new Date(e.filters.until):null]),i=w(()=>!!(e.filters.q||e.filters.adapter||e.filters.subtype||e.filters.since||e.filters.until));function d(h){o("set-filter","q",h||"")}function _(h){o("set-filter","q",h||"")}function x(h){if(!h||h.length===0){o("set-filter","since",null),o("set-filter","until",null);return}const[y,k]=h;o("set-filter","since",y?+y:null),o("set-filter","until",k?+k:null)}const j={props:e,emit:o,placeholderText:l,adapterOptions:a,dateRangeValue:s,hasActiveFilters:i,onQInput:d,onSearch:_,onDateChange:x,computed:w,get SearchOutlined(){return pe},get CloseCircleOutlined(){return fe},get InfoCircleOutlined(){return de}};return Object.defineProperty(j,"__isScriptSetup",{enumerable:!1,value:!0}),j}},Re={class:"pdh-filter-bar"},Le={key:1,class:"hint"},xe={key:2,class:"hint"};function je(r,t,n,e,o,l){const a=g("a-input-search"),s=g("a-select"),i=g("a-range-picker"),d=g("a-button");return u(),O("div",Re,[c(a,{value:n.filters.q,placeholder:e.placeholderText,"enter-button":"搜索","allow-clear":"",loading:n.isLoading,style:{flex:"1","max-width":"480px"},"onUpdate:value":e.onQInput,onSearch:e.onSearch},{prefix:m(()=>[c(e.SearchOutlined)]),_:1},8,["value","placeholder","loading"]),c(s,{value:n.filters.adapter,placeholder:"所有 adapter","allow-clear":"",options:e.adapterOptions,style:{width:"200px"},"onUpdate:value":t[0]||(t[0]=_=>r.$emit("set-filter","adapter",_||null))},null,8,["value","options"]),c(i,{value:e.dateRangeValue,placeholder:["开始日期","结束日期"],style:{width:"280px"},"onUpdate:value":e.onDateChange},null,8,["value"]),e.hasActiveFilters?(u(),C(d,{key:0,type:"link",danger:"",onClick:t[1]||(t[1]=_=>r.$emit("reset"))},{icon:m(()=>[c(e.CloseCircleOutlined)]),default:m(()=>[t[2]||(t[2]=b(" 清空筛选 ",-1))]),_:1})):E("v-if",!0),n.shortQuery?(u(),O("span",Le,[c(e.InfoCircleOutlined),t[3]||(t[3]=b(" 关键词需至少 3 字 (FTS5 trigram 限制) ",-1))])):n.mode==="like"?(u(),O("span",xe,[c(e.InfoCircleOutlined),t[4]||(t[4]=b(" 当前为 LIKE 兜底模式 ",-1))])):E("v-if",!0)])}const Ae=F(Ee,[["render",je],["__scopeId","data-v-d7cce6e9"],["__file","/tmp/cc-web-panel-eI5lXL/repo/packages/web-panel/src/components/pdh/SearchFilterBar.vue"]]),Ie={__name:"RendererDispatcher",props:{event:{type:Object,required:!0}},setup(r,{expose:t}){t();const n=A(()=>I(()=>import("./ChatBubbleRenderer-DvEvxlZv.js"),__vite__mapDeps([0,1,2,3,4,5]),import.meta.url)),e=A(()=>I(()=>import("./OrderTableRenderer-Dswi26mJ.js"),__vite__mapDeps([6,1,2,3,4,7]),import.meta.url)),o=A(()=>I(()=>import("./TimelineRenderer-CgGZWaRm.js"),__vite__mapDeps([8,1,2,3,4,9]),import.meta.url)),l=A(()=>I(()=>import("./EmailListRenderer-n3e_a1M3.js"),__vite__mapDeps([10,1,2,3,4,11]),import.meta.url)),a=A(()=>I(()=>import("./GenericCardRenderer-Jo0ULzHv.js"),__vite__mapDeps([12,1,2,3,4,13]),import.meta.url));function s(d){const _=d&&d.source&&d.source.adapter;switch($(_)){case"chat":case"ai-chat":return n;case"shopping":return e;case"travel":return o;case"email":return l;default:return a}}const i={ChatBubbleRenderer:n,OrderTableRenderer:e,TimelineRenderer:o,EmailListRenderer:l,GenericCardRenderer:a,rendererFor:s,defineAsyncComponent:A,get getCategory(){return $}};return Object.defineProperty(i,"__isScriptSetup",{enumerable:!1,value:!0}),i}};function Fe(r,t,n,e,o,l){return u(),C(le(e.rendererFor(n.event)),{event:n.event},null,8,["event"])}const De=F(Ie,[["render",Fe],["__file","/tmp/cc-web-panel-eI5lXL/repo/packages/web-panel/src/components/pdh/renderers/RendererDispatcher.vue"]]);function ee(r){return JSON.stringify(r,null,2)}function te(r){return r.map(t=>JSON.stringify(t)).join(`
|
|
3
|
-
`)+`
|
|
4
|
-
`}function ne(r){const n=["id","subtype","occurredAt","occurredAtIso","actor","place","adapter","summary","contentJson","extraJson"].join(","),e=r.map(o=>{const l=Number.isFinite(o.occurredAt)?o.occurredAt:null,a=l?new Date(l).toISOString():"",s=o.source&&o.source.adapter||"",i=o.content&&(o.content.text||o.content.title||o.content.subject)||"";return[o.id||"",o.subtype||"",l!=null?String(l):"",a,o.actor||"",o.place||"",s,i,o.content?JSON.stringify(o.content):"",o.extra?JSON.stringify(o.extra):""].map(Te).join(",")});return[n,...e].join(`
|
|
5
|
-
`)+`
|
|
6
|
-
`}function Te(r){const t=String(r??"");return t.includes(",")||t.includes('"')||t.includes(`
|
|
7
|
-
`)||t.includes("\r")?'"'+t.replace(/"/g,'""')+'"':t}function re(r,t,n="application/octet-stream"){if(typeof window>"u"||typeof document>"u")return t;const e=new Blob([r],{type:n}),o=URL.createObjectURL(e),l=document.createElement("a");return l.href=o,l.download=t,document.body.appendChild(l),l.click(),document.body.removeChild(l),setTimeout(()=>URL.revokeObjectURL(o),1e3),t}function oe(r,t=null){const n=new Date,e=n.getFullYear(),o=String(n.getMonth()+1).padStart(2,"0"),l=String(n.getDate()).padStart(2,"0"),a=r==="ndjson"?"ndjson":r,s=t?`-${t}`:"";return`pdh-events-${e}-${o}-${l}${s}.${a}`}const Pe={__name:"ExportDropdown",props:{events:{type:Array,required:!0},category:{type:String,default:null}},setup(r,{expose:t}){t();const n=r,e=w(()=>n.events.length>0),o={json:"application/json;charset=utf-8",ndjson:"application/x-ndjson;charset=utf-8",csv:"text/csv;charset=utf-8"};function l(i){switch(i){case"json":return ee(n.events);case"ndjson":return te(n.events);case"csv":return ne(n.events);default:throw new Error(`unknown format: ${i}`)}}function a({key:i}){try{const d=l(i),_=oe(i,n.category);re(d,_,o[i]),P.success(`已导出 ${n.events.length} 条到 ${_}`)}catch(d){P.error(`导出失败: ${d.message||d}`)}}const s={props:n,hasResults:e,MIME:o,serialize:l,onClick:a,computed:w,get DownloadOutlined(){return _e},get DownOutlined(){return me},get message(){return P},get eventsToJson(){return ee},get eventsToNdjson(){return te},get eventsToCsv(){return ne},get downloadAs(){return re},get suggestFilename(){return oe}};return Object.defineProperty(s,"__isScriptSetup",{enumerable:!1,value:!0}),s}};function qe(r,t,n,e,o,l){const a=g("a-button"),s=g("a-menu-item"),i=g("a-menu"),d=g("a-dropdown");return u(),C(d,{disabled:!e.hasResults},{overlay:m(()=>[c(i,{onClick:e.onClick},{default:m(()=>[c(s,{key:"json"},{default:m(()=>[...t[0]||(t[0]=[b("JSON (.json)",-1)])]),_:1}),c(s,{key:"ndjson"},{default:m(()=>[...t[1]||(t[1]=[b("NDJSON (.ndjson)",-1)])]),_:1}),c(s,{key:"csv"},{default:m(()=>[...t[2]||(t[2]=[b("CSV (.csv)",-1)])]),_:1})]),_:1})]),default:m(()=>[c(a,{disabled:!e.hasResults},{icon:m(()=>[c(e.DownloadOutlined)]),default:m(()=>[b(" 导出 ("+L(n.events.length)+") ",1),c(e.DownOutlined)]),_:1},8,["disabled"])]),_:1},8,["disabled"])}const Be=F(Pe,[["render",qe],["__file","/tmp/cc-web-panel-eI5lXL/repo/packages/web-panel/src/components/pdh/ExportDropdown.vue"]]),Ve={__name:"PdhVaultBrowser",setup(r,{expose:t}){t();const n=Z(),e=w(()=>n.filters.q?`没有匹配 "${n.filters.q}" 的事件 — 试试更短的关键词或换个类目`:n.filters.category?`「${N(n.filters.category)}」类目下还没有数据 — 去采集页同步对应 adapter`:"Vault 里还没有数据 — 去「个人数据中台」页面同步任意 adapter");function o(s){n.filters.category=s,n.search()}function l(s,i){n.setFilter(s,i)}J(()=>{!n.hasResults&&!n.isLoading&&n.search()});const a={store:n,emptyHint:e,onCategorySelect:o,onSetFilter:l,onMounted:J,computed:w,get ReloadOutlined(){return ye},get usePdhBrowserStore(){return Z},get categoryLabel(){return N},CategorySidebar:ke,SearchFilterBar:Ae,RendererDispatcher:De,ExportDropdown:Be};return Object.defineProperty(a,"__isScriptSetup",{enumerable:!1,value:!0}),a}},Ne={class:"pdh-browser-page"},Me={class:"page-header"},Je={class:"main-pane"},Ue={class:"results-summary"},Qe={key:0},ze={key:0},Ge={key:1},Xe={class:"loaded-of"},He={class:"results-list"},Ke={key:2,class:"load-more"};function We(r,t,n,e,o,l){const a=g("a-tag"),s=g("a-button"),i=g("a-space"),d=g("a-col"),_=g("a-spin"),x=g("a-alert"),j=g("a-empty"),h=g("a-row");return u(),O("div",Ne,[v("div",Me,[t[6]||(t[6]=v("div",null,[v("h2",{class:"page-title"},"数据浏览器"),v("p",{class:"page-sub"}," Vault 里所有已采集的数据,按类目浏览 / 全文检索 / 时间窗口筛选。 完全离线,不外传。 ")],-1)),c(i,null,{default:m(()=>[e.store.mode==="fts5"?(u(),C(a,{key:0,color:"green"},{default:m(()=>[...t[3]||(t[3]=[b("FTS5 trigram",-1)])]),_:1})):e.store.mode==="like"?(u(),C(a,{key:1,color:"orange"},{default:m(()=>[...t[4]||(t[4]=[b("LIKE 兜底",-1)])]),_:1})):E("v-if",!0),c(e.ExportDropdown,{events:e.store.results,category:e.store.filters.category},null,8,["events","category"]),c(s,{onClick:t[0]||(t[0]=y=>e.store.search()),loading:e.store.isLoading},{icon:m(()=>[c(e.ReloadOutlined)]),default:m(()=>[t[5]||(t[5]=b(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),c(h,{gutter:16,class:"browser-layout"},{default:m(()=>[c(d,{xs:24,sm:24,md:6,lg:5,xl:4},{default:m(()=>[c(e.CategorySidebar,{selected:e.store.filters.category,facets:e.store.facets,onSelect:e.onCategorySelect},null,8,["selected","facets"])]),_:1}),c(d,{xs:24,sm:24,md:18,lg:19,xl:20},{default:m(()=>[v("div",Je,[c(e.SearchFilterBar,{filters:e.store.filters,facets:e.store.facets,"is-loading":e.store.isLoading,mode:e.store.mode,"short-query":e.store.shortQuery,onSetFilter:e.onSetFilter,onReset:t[1]||(t[1]=y=>{e.store.reset(),e.store.search()})},null,8,["filters","facets","is-loading","mode","short-query"]),v("div",Ue,[e.store.isLoading&&e.store.results.length===0?(u(),O("span",Qe,[c(_,{size:"small"}),t[7]||(t[7]=b(" 载入中… ",-1))])):(u(),O(V,{key:1},[v("strong",null,L(e.store.facets.total),1),t[11]||(t[11]=b(" 条事件 ",-1)),e.store.filters.category?(u(),O("span",ze,[t[8]||(t[8]=b(" / 当前类目 ",-1)),v("strong",null,L(e.categoryLabel(e.store.filters.category)),1),v("strong",null,L(e.store.facets.byCategory[e.store.filters.category]||0),1)])):E("v-if",!0),e.store.filters.q?(u(),O("span",Ge,[t[9]||(t[9]=b(' / 关键词 "',-1)),v("em",null,L(e.store.filters.q),1),t[10]||(t[10]=b('"',-1))])):E("v-if",!0),v("span",Xe," / 已显示 "+L(e.store.results.length),1)],64))]),e.store.error?(u(),C(x,{key:0,type:"error","show-icon":"",message:e.store.error,closable:"",style:{margin:"12px 0"}},null,8,["message"])):E("v-if",!0),!e.store.isLoading&&e.store.results.length===0&&!e.store.error?(u(),C(j,{key:1,description:e.emptyHint,style:{"margin-top":"40px"}},null,8,["description"])):E("v-if",!0),v("div",He,[(u(!0),O(V,null,se(e.store.results,(y,k)=>(u(),C(e.RendererDispatcher,{key:`r-${k}-${y.id}`,event:y},null,8,["event"]))),128))]),e.store.canLoadMore?(u(),O("div",Ke,[c(s,{loading:e.store.isAppending,onClick:t[2]||(t[2]=y=>e.store.loadMore()),block:""},{default:m(()=>[...t[12]||(t[12]=[b(" 加载下一页 (50 条) ",-1)])]),_:1},8,["loading"])])):E("v-if",!0)])]),_:1})]),_:1})])}const nt=F(Ve,[["render",We],["__scopeId","data-v-0f7c02cd"],["__file","/tmp/cc-web-panel-eI5lXL/repo/packages/web-panel/src/views/PdhVaultBrowser.vue"]]);export{nt as default};
|