chainlesschain 0.166.15 → 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-To-6rimH.js → AIOps-CTxa2Wbq.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CpdCnTv3.js → ActionButton-DHrQyYhy.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DK7VNES_.js → Analytics-DQiUqcNl.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-NZ5FvhCx.js → AppLayout-_Iz4r6wt.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-NXceQPmN.js → Artifacts-BNs63YHo.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-B2d64DH2.js → Audit-BgHIqRLn.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-ByYgvEVY.js → BackgroundAgents-DUQ5axBB.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BXvQLDvN.js → Backup-CJ51E9Vw.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-C4GZk-As.js → BaseInput-o-5toA_R.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CvPuohL8.js → Chat-Cu7a-x1L.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-DTftcclX.js → ChatBubbleRenderer-BUyYkAXr.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-C8dQGIqD.js → Checkbox-DwdmZ71L.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DRM6S1W4.js → Codegen-BrH2eYiP.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BDM8l-r5.js → Col-BVJQEP2j.js} +1 -1
- package/src/assets/web-panel/assets/{Community-Bvmfi1fX.js → Community-FGO3vZPq.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DGQTCima.js → Compact-DYGAFVnT.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-D_0C-2P6.js → Compliance-CRvc8Bdt.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-3C_q99ok.js → Cowork-D6Ah2m7A.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-CIiMQ1Hl.js → Cron-AXbU2ifR.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-peebGnES.js → Crosschain-C5DXgEFd.js} +1 -1
- package/src/assets/web-panel/assets/{DID-OkX4KB9T.js → DID-Bxh9QV9v.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-D9lm0Wxa.js → Dashboard-B-ZHEta-.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CitActXx.js → Dropdown-66Ik1jqa.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DSmFkNKV.js → EmailListRenderer-CCWk1BIM.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-CBWAi8XL.js → FamilyGuardDashboard--9faIULK.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-afj8jDcp.js → Federation-CejW9CgX.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Dabt59KY.js → FormItemContext-acHgcXki.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BQpXA9kj.js → GenericCardRenderer-D2ghd_K4.js} +1 -1
- package/src/assets/web-panel/assets/{Git-D2p2Moo1.js → Git-BOe1YJrV.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DkFfPykv.js → Governance-BjgzJsof.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-C1DKpeN2.js → Inference-CXCD5rnP.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CjfVg4oQ.js → KnowledgeGraph-CHA8QgJT.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-D-zMvdSf.js → Logs-DORPMcL6.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-jzEpGkbc.js → MarkdownRenderer-CPPHz01z.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-DfAjJLyS.js → Marketplace-BCFlo1Yx.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BGDHQES1.js → McpTools-Dl_uZAKh.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-BYqrGAPS.js → Memory-DupHamwz.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CQ6FEtty.js → MobileBridge-BRSMPJxW.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BpMvh5JW.js → MobileProjects-BHpuzsDl.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-CWH25SrU.js → Mtc-Ch0jOQfZ.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-D6DiLmei.js → MtcAudit-qzwQrDi7.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-BSxRN4jD.js → Multisig-B5wHzUcm.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-C0FDPKT4.js → NLProgramming-Hy9uAiA0.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-VKR78bH-.js → Notes-DkuchMC7.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DLSklSZB.js → NotificationSettings-CYZhD7Pi.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-Dpj7D6tC.js → OrderTableRenderer-DKOoqajt.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BB3pB27e.js → Organization-D9AXn6j8.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Cr7bzwcs.js → Overflow-Bg15J6hX.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-D1fkMMzI.js → P2P--B54HoQn.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BiDEbLNA.js → PdhVaultBrowser-Cz9Kk2Nb.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-c3Ijv0v4.js → Permissions-DHx38eS1.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BJwbh3P2.js → PersonalDataHub-Dw8i2hAs.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-C4fhXafB.js → Pipeline-B2o6Ur2G.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DzSx3CD-.js → Privacy-8g-h2fnu.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-D9fL5fED.js → ProjectInit-DuVTcINx.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CB5FVrOR.js → ProjectSettings-C8njvdZX.js} +2 -2
- package/src/assets/web-panel/assets/Projects-Ca9BAfu7.js +1 -0
- package/src/assets/web-panel/assets/{Providers-B9ZH4faS.js → Providers-wFqgod_W.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-BLKDHT8_.js → QrScannerModal-9NCXrpmA.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-D1oYUcSY.js → QuickAsk-WUTNvFkY.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CC2nmrOD.js → Recommend-xT4nYmju.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-qW9QF4-r.js → RemoteSession-fak1PBGC.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-BDWqfzcr.js → Reputation-D1AkQvD-.js} +1 -1
- package/src/assets/web-panel/assets/{Row-BBV2iCjT.js → Row-DVfm6xGt.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CcwrNwZB.js → RssFeed-BDunoLSE.js} +3 -3
- package/src/assets/web-panel/assets/{Search-Dr6fZ0D_.js → Search-OPycRoU3.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BPzaoCU6.js → Security-C8-Fm3Dt.js} +4 -4
- package/src/assets/web-panel/assets/{Services-BoKUU1I_.js → Services-qM_sMpMl.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-C8lT8GUg.js → Skeleton-D3HBJjVF.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DPpWeicz.js → Skills-jr67X-tP.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-UiijzpMU.js → Sla-CS3ggyCg.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DoofrLwS.js → SpeechSettings-CTOCYxOi.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DXnyfTDw.js → SyncSettings-D3s3cLT5.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-g_WHjKeg.js → Tasks-CdfoJ25m.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DRuCh9g2.js → Templates-Drb4AI8X.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-QHIq1pH1.js → Tenant-DzwR3Qkz.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-G0fuI216.js → Terminal-D-ESq7xp.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-4MT7SpGk.js → TimelineRenderer-BK-AUuws.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-B5xT5umA.js → Tokens-xGTouuNp.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-D7HPbNgc.js → Trigger-BvZj-v2H.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CxH69dU5.js → Trust-BLC9CGmc.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CPPosveH.js → UkeySign-BSuCXpmE.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Du5lGwAt.js → VideoEditing-DT3A-_Ql.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BBIGNESK.js → Wallet-c1OXao85.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-Cc3HSGmv.js → WebAuthn-CuA-F7KJ.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-DBoVPNCh.js → WorkflowEditor-MANZrf82.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DHcjgiem.js → chat-D4Y4Ey0O.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DrRrvJIV.js → colors-DDH06hKO.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BuY_sAoN.js → compact-item-Cym756Xj.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CepH1Fha.js → createContext-By4Nb1k-.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-KO3pAGeO.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-Dh80Ot6o.js → hasIn-Ch7OY258.js} +1 -1
- package/src/assets/web-panel/assets/{index-BW9Pycxh.js → index-6-2eYBXr.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7lstbTh.js → index-6CpOV3Pn.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUnd5hyp.js → index-ArMrnx0v.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0rvJjId.js → index-B51otVoZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-D6tOVlq-.js → index-BBBUn5v7.js} +1 -1
- package/src/assets/web-panel/assets/{index-NS9dW1F1.js → index-BFydNU6a.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiUx-tkV.js → index-BIrRX-ra.js} +1 -1
- package/src/assets/web-panel/assets/{index-By0qqC3S.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-CNQK9DIr.js → index-Bo20BfdS.js} +1 -1
- package/src/assets/web-panel/assets/{index-C10033eO.js → index-CF3Lhyns.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRy3_beb.js → index-CGsvEbbq.js} +1 -1
- package/src/assets/web-panel/assets/{index-DWANFMlq.js → index-CJPks33Y.js} +1 -1
- package/src/assets/web-panel/assets/{index-CnRK8_Dd.js → index-CT-3FYwd.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPDEOOlA.js → index-CUSUzaB8.js} +1 -1
- package/src/assets/web-panel/assets/{index-DYN49m7k.js → index-CV1UC4zo.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5vhNRqS.js → index-CV8qXTvb.js} +1 -1
- package/src/assets/web-panel/assets/{index-9crgJ3Id.js → index-CZn6dmZe.js} +1 -1
- package/src/assets/web-panel/assets/{index-DkZP_QaB.js → index-CjNUTBwe.js} +1 -1
- package/src/assets/web-panel/assets/{index-BoRy2yup.js → index-CpudmDhf.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ca5d64IH.js → index-CykROEJA.js} +1 -1
- package/src/assets/web-panel/assets/{index-A5lVwYVq.js → index-D5sADPGY.js} +1 -1
- package/src/assets/web-panel/assets/{index-BnVIvc15.js → index-D9le0-dc.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cx21_p3m.js → index-DAkk1M7x.js} +1 -1
- package/src/assets/web-panel/assets/{index-0TYLnd11.js → index-DNEJzc0r.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9Gh-SOn.js → index-DNlxihs8.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtqigRzf.js → index-DiewptTL.js} +1 -1
- package/src/assets/web-panel/assets/{index-CW_23-gU.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-LBkSOwky.js → index-DtGValNi.js} +1 -1
- package/src/assets/web-panel/assets/{index-D5_K3GKu.js → index-DvnywwUj.js} +1 -1
- package/src/assets/web-panel/assets/{index-BiZQooWK.js → index-OU8DZ9BL.js} +1 -1
- package/src/assets/web-panel/assets/{index-CYydOga6.js → index-XGeQMvWK.js} +1 -1
- package/src/assets/web-panel/assets/{index-hYaigdGm.js → index-ZY2Qs_Sn.js} +1 -1
- package/src/assets/web-panel/assets/{index-zGH9zH3w.js → index-jx7kr6mB.js} +3 -3
- package/src/assets/web-panel/assets/{index-DuRYBWrj.js → index-mL3nOcH6.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuSUCH7h.js → index-oBsfUbyH.js} +1 -1
- package/src/assets/web-panel/assets/{index-CEfVkKIY.js → index-q-s04OKn.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUNyTmkS.js → index-tZ5BUdad.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-nI_X3wKl.js → initDefaultProps-DGcX9iPP.js} +1 -1
- package/src/assets/web-panel/assets/{motion-LUHbQu_R.js → motion-2SeL1D8A.js} +1 -1
- package/src/assets/web-panel/assets/{move-DHI_KvJt.js → move-3cYbQCpS.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-AYdL_7Mo.js → mtc-parser-IDdxfw0z.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CtV3HRKa.js → omit-BNswdKO6.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CcJLTOu4.js → pickAttrs-BwCnem2I.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DHbiLUps.js → placementArrow-B9PtZ5rq.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BC2DGkWP.js → responsiveObserve-CPB6iSzV.js} +1 -1
- package/src/assets/web-panel/assets/{slide-B4ga4pPY.js → slide-DZgyblZa.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-hzphgKfH.js → statusUtils-D82IBdsx.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-IfN9Bxoi.js → styleChecker-qSHtosM-.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-pcGKJ4pT.js → useFlexGapSupport-CmWO7h0I.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-COXhQpTG.js → useFs-yLrs_ub4.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-xp9F9szv.js → usePersonalDataHub-CJ1VW6rh.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BdSQy1Ve.js → vnode-CzY_moQ4.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CHCt5P55.js → zoom-DAa7rEY5.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/learning.js +71 -1
- package/src/commands/team.js +5 -0
- package/src/data/changelog.json +15 -2
- package/src/lib/agent-team/task-lease.js +12 -1
- 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 +100 -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/secure-fs.js +20 -0
- package/src/assets/web-panel/assets/Projects-DWhwdgfY.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DIb8j04q.js +0 -1
- package/src/assets/web-panel/assets/index-BJc3t4PC.js +0 -1
- package/src/assets/web-panel/assets/index-CkksSUnI.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
|
|
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;
|
|
@@ -608,6 +609,21 @@ const WINDOWS_ACL_BATCH_SIZE = 500;
|
|
|
608
609
|
const WINDOWS_ACL_TIMEOUT_ENV = "CC_SECURE_FS_WINDOWS_ACL_TIMEOUT_MS";
|
|
609
610
|
const MAX_WINDOWS_ACL_TIMEOUT_MS = 5 * 60_000;
|
|
610
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
|
+
|
|
611
627
|
// Windows hosted runners can need more than the normal 15/30 second allowance
|
|
612
628
|
// to cold-start PowerShell and load the access-control types. A trusted harness
|
|
613
629
|
// may raise (but never lower) that allowance; the cap prevents an inherited
|
|
@@ -636,6 +652,7 @@ function repairWindowsAclOnce(target, deps, options) {
|
|
|
636
652
|
}
|
|
637
653
|
|
|
638
654
|
function windowsAcl(target, operation, deps) {
|
|
655
|
+
const workingDirectory = _windowsAclWorkingDirectory(process.env, deps.fs);
|
|
639
656
|
const result = deps.spawnSync(
|
|
640
657
|
"powershell.exe",
|
|
641
658
|
[
|
|
@@ -653,6 +670,7 @@ function windowsAcl(target, operation, deps) {
|
|
|
653
670
|
encoding: "utf8",
|
|
654
671
|
windowsHide: true,
|
|
655
672
|
timeout: _resolveWindowsAclTimeout(15_000),
|
|
673
|
+
...(workingDirectory ? { cwd: workingDirectory } : {}),
|
|
656
674
|
},
|
|
657
675
|
);
|
|
658
676
|
let details = null;
|
|
@@ -679,6 +697,7 @@ function windowsAcl(target, operation, deps) {
|
|
|
679
697
|
|
|
680
698
|
function windowsAclBatch(targets, operation, deps, expectedKind = null) {
|
|
681
699
|
if (targets.length === 0) return [];
|
|
700
|
+
const workingDirectory = _windowsAclWorkingDirectory(process.env, deps.fs);
|
|
682
701
|
const result = deps.spawnSync(
|
|
683
702
|
"powershell.exe",
|
|
684
703
|
[
|
|
@@ -700,6 +719,7 @@ function windowsAclBatch(targets, operation, deps, expectedKind = null) {
|
|
|
700
719
|
windowsHide: true,
|
|
701
720
|
timeout: _resolveWindowsAclTimeout(30_000),
|
|
702
721
|
maxBuffer: 4 * 1024 * 1024,
|
|
722
|
+
...(workingDirectory ? { cwd: workingDirectory } : {}),
|
|
703
723
|
},
|
|
704
724
|
);
|
|
705
725
|
let details = [];
|
|
@@ -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-Bn1JzzAn.js";import{_ as we,b as re,u as ie,d}from"./index-zGH9zH3w.js";import{u as de}from"./useShellMode-CgR0wCYM.js";import{aN as ke,aO as be,aP as Fe,f as je,a5 as Ce,a8 as xe,at as Oe,R as Se}from"./icons-DG5UD-6K.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),L=u(!1),E=u(!1),b=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"}],V=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:()=>M(o)}}async function M(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(){b.value={name:"",description:"",type:"document",rootPath:""},L.value=!0}async function T(){if(!b.value.name.trim()){d.warning("请输入项目名称");return}E.value=!0;try{const o=await w("project.init",{name:b.value.name.trim(),description:b.value.description||null,projectType:b.value.type,rootPath:b.value.rootPath||null},`project init "${b.value.name.trim()}" --type ${b.value.type} --json`,8e3);o?.id?(d.success(`已创建项目 '${o.name}'`),L.value=!1,await C()):d.error("创建失败")}catch(o){d.error(o.message||String(o))}finally{E.value=!1}}const F=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:""},F.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}'`),F.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:L,creating:E,newProject:b,columns:z,countByStatus:V,filteredProjects:J,statusColor:g,syncColor:K,formatTime:Q,loadAll:C,onRowClick:G,openDetail:M,onDelete:H,onShowCreate:X,onCreate:T,createFileOpen:F,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 Fe},get FileAddOutlined(){return be},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"],Le={key:0,style:{color:"#888","font-size":"12px"}};function Ee(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"),L=i("a-radio-group"),E=i("a-input-search"),b=i("a-alert"),z=i("a-tag"),V=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"),M=i("a-list"),H=i("a-spin"),X=i("a-drawer"),T=i("a-input"),F=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(L,{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(E,{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(b,{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(V,{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(M,{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",Le,s(n.file_size)+" B",1)):_("v-if",!0),t(V,{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(F,{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(F,{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(F,{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(F,{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(F,{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(F,{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(F,{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",Ee],["__scopeId","data-v-019ac5aa"],["__file","/tmp/cc-web-panel-LDgqkb/repo/packages/web-panel/src/views/Projects.vue"]]);export{We as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{Q as r}from"./index-zGH9zH3w.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-BBV2iCjT.js";import{a0 as t}from"./index-zGH9zH3w.js";import"./vendor-Bn1JzzAn.js";import"./responsiveObserve-BC2DGkWP.js";import"./useFlexGapSupport-pcGKJ4pT.js";import"./styleChecker-IfN9Bxoi.js";import"./index-B9Gh-SOn.js";import"./icons-DG5UD-6K.js";const l=t(o);export{l as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{C as o}from"./Col-BDM8l-r5.js";import{a0 as t}from"./index-zGH9zH3w.js";import"./vendor-Bn1JzzAn.js";import"./index-B9Gh-SOn.js";import"./icons-DG5UD-6K.js";const s=t(o);export{s as default};
|