chainlesschain 0.162.118 → 0.162.120
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-D4dNL7oX.js → AIOps-MUE7jVfi.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DqMM3fea.js → ActionButton-DKkJNgJW.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DMep218S.js → Analytics-DcHt5MVA.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-TdTGCiOR.js → AppLayout-BjF0MsBB.js} +5 -5
- package/src/assets/web-panel/assets/{Audit-1Dml711-.js → Audit-CybGKBUd.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DbHx9UYj.js → Backup-CzZoTRnY.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-C2ahEcJR.js → BaseInput-CG8BgY54.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-5ZjuBfuS.js → Chat-S6AcW4T2.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-XpONY6wA.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-Dg6tGe59.js → Checkbox-DZ_LDoVZ.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CNDPJTao.js → Codegen-DN2ZYd_4.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DWU7gipF.js → Col-Cidm2Ykv.js} +1 -1
- package/src/assets/web-panel/assets/{Community-5nkmoyvL.js → Community-ByNGbzcY.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BzCJj8eL.js → Compact-Dj9vY8yk.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-DbZq8BJH.js → Compliance-_0ipnnBf.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BK7yKRsT.js → Cowork-BNdunLG9.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-BSbTeh9k.js → Cron-BvzsO_i-.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BIyLL_7v.js → Crosschain-BSR_odwN.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DeLWtwx2.js → DID-AsJk_1HF.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-SGbCH8zO.js → Dashboard-tYbIuKgu.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CmsCZDkh.js → Dropdown-CVuLEkIH.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-Tfc7sbeH.js → EmailListRenderer-C4DBbxZ8.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-K2YlYDx7.js → FamilyGuardDashboard-DNX_oWxL.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-kLpstbZZ.js → Federation-Cl5fg-2b.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BBFI-PfE.js → FormItemContext-sMFqQO5g.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-D0xM21cK.js → GenericCardRenderer-qZpi2wH1.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DoRk-Z87.js → Git-uO96e0En.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DLpgG6NJ.js → Governance-CAkQyU1W.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-DhXCaVnC.js → Inference-kQgYGwuX.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DY9bjNvM.js → KnowledgeGraph-B3r3qbm6.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-0hjq8gkO.js → Logs-BhnUcQP2.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-BiwZtXvR.js → Marketplace-cSrDXJRg.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-FQPVVxpt.js → McpTools-D7tn-iuQ.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-DFx_G11g.js → Memory-YfMrETfK.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CffhLXKL.js → MobileBridge-QYTJAlGR.js} +2 -2
- package/src/assets/web-panel/assets/MobileProjects-hulCHsOG.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-CZYjK-51.js → Mtc-C6a2fTit.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-Da34fMPk.js → MtcAudit-tPoY6xsu.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-Bd_rBnNq.js → Multisig-VVdmiLTB.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-C5gqAWjv.js → NLProgramming-BuI8pzz1.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Dhu_Cm2p.js → Notes-f_coT28Z.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DtJcANAI.js → NotificationSettings-D8Beg8OP.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-BSZfBr8T.js → OrderTableRenderer-C9PxKWwg.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BUr7Rir7.js → Organization-fUX97U1w.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-DWshgXbT.js → Overflow-vVjV0pGU.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CyD_epxc.js → P2P-DGM6VCzC.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-5XCiifmp.js → PdhVaultBrowser-j01q6J9e.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-7f399Gvr.js → Permissions-Q7NYy0Wv.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-DxlSJUU3.js → PersonalDataHub-Bdp3MI1-.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-DgEcnlAm.js → Pipeline-CB1xH835.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-zisFH3nX.js → Privacy-DIbp3aJd.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CJoxhT5P.js → ProjectInit-DzEtaFH9.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-PiZfKRl5.js → ProjectSettings-CiciM4K4.js} +2 -2
- package/src/assets/web-panel/assets/Projects-C7KoEuf4.js +1 -0
- package/src/assets/web-panel/assets/{Providers-BNZjDnSc.js → Providers-CXgLwW2L.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-khmv9SgN.js → QuickAsk-nzHdN2F2.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BDY0V36V.js → Recommend-BicIztEZ.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-C4wPt5Hv.js → Reputation-C_Y8oRqf.js} +1 -1
- package/src/assets/web-panel/assets/{Row-B9kpAVZb.js → Row-CkNhTYCZ.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CiyeJRzB.js → RssFeed-D_fjy-vQ.js} +3 -3
- package/src/assets/web-panel/assets/{Search-BAJIzXKP.js → Search-CCsIRDKU.js} +1 -1
- package/src/assets/web-panel/assets/{Security-_SyGiA39.js → Security-CHJPSsH6.js} +4 -4
- package/src/assets/web-panel/assets/{Services-CpCisy2A.js → Services-BQr5Adu-.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BbgLYFnt.js → Skeleton-BQtvUIf2.js} +1 -1
- package/src/assets/web-panel/assets/Skills-Dc0LU3LK.js +1 -0
- package/src/assets/web-panel/assets/{Sla-BXoqLXMq.js → Sla-BO5j3PAQ.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-BY9Kooi0.js → SpeechSettings-BmPQTYAi.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CcArvVNF.js → SyncSettings-BnobmeAo.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-DFFcr6Zm.js +1 -0
- package/src/assets/web-panel/assets/{Templates-C7uVsXry.js → Templates-RZh0Oh_Q.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-YTp4gRv1.js → Tenant-BD6D6Ak7.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CVyqc079.js → Terminal-BSuShSOU.js} +2 -2
- package/src/assets/web-panel/assets/TimelineRenderer-DmwdA_BU.js +1 -0
- package/src/assets/web-panel/assets/{Tokens-CDsEqDT7.js → Tokens-CMgdZ-HW.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-CpDIhVvj.js → Trigger-Ckz3UHfh.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CjEWMLXs.js → Trust-AKEeF68u.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CMuYjFkp.js → UkeySign-y_PA8Ugs.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-L76OwoPT.js → VideoEditing-BDCHMoYT.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CfhcIudB.js → Wallet-BUPNjLDa.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-BhxSf50j.js → WebAuthn-BSkgJ_ej.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-CkYQGytv.js → WorkflowEditor-Cly_vJCn.js} +1 -1
- package/src/assets/web-panel/assets/{chat-Bke-Axcb.js → chat-B2upy0kk.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DDm7sxvR.js → colors-DRymaRcw.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-ptIaR2VC.js → compact-item-BjlECmvE.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-neR1onYf.js → createContext-NByPo135.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BQpi8pDO.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CdoIzexs.js → hasIn-CnapAb4N.js} +1 -1
- package/src/assets/web-panel/assets/{index-9dyEaJ48.js → index-3N2bkUYM.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGAoMIiF.js → index-69yznrDs.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cg7TMjLf.js → index-B0IxW10q.js} +1 -1
- package/src/assets/web-panel/assets/{index-B3RhcGp2.js → index-B1l9stj4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpqA23qT.js → index-B7EkRJNQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-8RY-s8Eq.js → index-B8mHLG8W.js} +1 -1
- package/src/assets/web-panel/assets/{index-rZfX7ufl.js → index-BC3lHdGe.js} +1 -1
- package/src/assets/web-panel/assets/{index-BsReT8kE.js → index-BCIn3-zn.js} +3 -3
- package/src/assets/web-panel/assets/{index-CBE4OYiN.js → index-BdsQCfwD.js} +1 -1
- package/src/assets/web-panel/assets/{index-CLhzHIgs.js → index-Bl67igbC.js} +1 -1
- package/src/assets/web-panel/assets/{index-f59BFqsD.js → index-BlVSeRLX.js} +1 -1
- package/src/assets/web-panel/assets/{index-KyM68byr.js → index-BnYbOEQ5.js} +1 -1
- package/src/assets/web-panel/assets/{index-BN_GcJv-.js → index-BuMhmoLi.js} +1 -1
- package/src/assets/web-panel/assets/index-BvYGiwBG.js +1 -0
- package/src/assets/web-panel/assets/{index-DRA35MTY.js → index-C35ewkvS.js} +1 -1
- package/src/assets/web-panel/assets/{index-CMk4reDk.js → index-C4Je7eKb.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEjcGiW_.js → index-C5QIx6d1.js} +1 -1
- package/src/assets/web-panel/assets/{index-B22DApaF.js → index-C8mpo9w0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DxabeJjC.js → index-CBqC10Mz.js} +1 -1
- package/src/assets/web-panel/assets/index-CC_4NPrV.js +1 -0
- package/src/assets/web-panel/assets/{index-DL-dAbq1.js → index-CQ6Td4oP.js} +1 -1
- package/src/assets/web-panel/assets/{index-DKJrSY7a.js → index-CmdbB6n1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCmaPYWj.js → index-CoZgzgDg.js} +1 -1
- package/src/assets/web-panel/assets/{index-Chu6dERk.js → index-DDOEPs_e.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bt8YI0Pg.js → index-DQRbttWF.js} +1 -1
- package/src/assets/web-panel/assets/{index-m7gmhBks.js → index-DSNzuCKY.js} +1 -1
- package/src/assets/web-panel/assets/{index-BSrWChEg.js → index-DUZ5OBUP.js} +1 -1
- package/src/assets/web-panel/assets/{index-li06k0zQ.js → index-DaQVzr6e.js} +1 -1
- package/src/assets/web-panel/assets/{index-BnujNUf1.js → index-DdWH7Nnq.js} +1 -1
- package/src/assets/web-panel/assets/{index-BB8JlhPb.js → index-DfV7ozPn.js} +1 -1
- package/src/assets/web-panel/assets/{index-BYVMCbtn.js → index-DpVmeNyO.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4kWzHqC.js → index-DrJVa6Gk.js} +1 -1
- package/src/assets/web-panel/assets/{index-5mAbzuWz.js → index-KbNiEQkd.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUPpvFG3.js → index-MtPi9EHn.js} +1 -1
- package/src/assets/web-panel/assets/{index-C83TTo0Y.js → index-aV-LQt0K.js} +1 -1
- package/src/assets/web-panel/assets/{index-D5oDZ8S7.js → index-iFODT6oN.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpMZQawE.js → index-o8nqsumS.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dl_I2P_E.js → index-qVEh-o74.js} +1 -1
- package/src/assets/web-panel/assets/{index-0ZL7FjnB.js → index-sX1MbnSU.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DoRyafUY.js → initDefaultProps-o1fFt3V7.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CXAFczEQ.js → motion-Bwj9ZiqO.js} +1 -1
- package/src/assets/web-panel/assets/{move-DNDMmkdZ.js → move-DoTSIAxU.js} +1 -1
- package/src/assets/web-panel/assets/{omit-D2wfCEns.js → omit-DkO-otLG.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-Dq7W_NtB.js → pickAttrs-7dqbsVWT.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CkNHdTmz.js → placementArrow-WPFcCNIM.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-j6LiN9K2.js → responsiveObserve-DqQxE3aN.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BKHHLvp8.js → slide-CyzizbNB.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-B3sdEvM3.js → statusUtils-C71vV6Kb.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-g4UCWzKN.js → styleChecker-DVrLfHrc.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-D_0KlvEp.js → useFlexGapSupport-DVNyuXrQ.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-ePxeifdP.js → useFs-BpBz_yQJ.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-4JoLBqJY.js → usePersonalDataHub-CYHp2Bn2.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-na-HJjyy.js → vnode-CXAL4PQ0.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Wmkm0KcD.js → zoom-mrlkZmnn.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/doctor.js +15 -0
- package/src/commands/note.js +13 -10
- package/src/commands/update.js +20 -0
- package/src/lib/instinct-manager.js +8 -2
- package/src/lib/memory-manager.js +7 -3
- package/src/lib/sql-like.js +23 -0
- package/src/lib/update-notice.js +34 -10
- package/src/lib/version-skew.js +29 -0
- package/src/repl/agent-repl.js +23 -9
- package/src/runtime/__tests__/message-roles.test.js +142 -0
- package/src/runtime/diagnostics.js +23 -1
- package/src/runtime/headless-runner.js +8 -2
- package/src/runtime/headless-stream.js +34 -1
- package/src/runtime/message-roles.js +94 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-B-1BKOW2.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-Ch6cai8d.js +0 -1
- package/src/assets/web-panel/assets/Projects-DsJd6uTW.js +0 -1
- package/src/assets/web-panel/assets/Skills-BetfsfpF.js +0 -1
- package/src/assets/web-panel/assets/Tasks-DqLoEIis.js +0 -1
- package/src/assets/web-panel/assets/TimelineRenderer-oJ9q5LkF.js +0 -1
- package/src/assets/web-panel/assets/devWarning-CQxKChUH.js +0 -1
- package/src/assets/web-panel/assets/index-DBA6F-Kp.js +0 -1
- package/src/assets/web-panel/assets/index-ffyvqxd5.js +0 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
mergeConsecutiveMessages,
|
|
4
|
+
_internal,
|
|
5
|
+
} from "../message-roles.js";
|
|
6
|
+
|
|
7
|
+
describe("mergeConsecutiveMessages", () => {
|
|
8
|
+
it("is a no-op on a healthy alternating transcript", () => {
|
|
9
|
+
const msgs = [
|
|
10
|
+
{ role: "system", content: "sys" },
|
|
11
|
+
{ role: "user", content: "a" },
|
|
12
|
+
{ role: "assistant", content: "b" },
|
|
13
|
+
{ role: "user", content: "c" },
|
|
14
|
+
];
|
|
15
|
+
expect(mergeConsecutiveMessages(msgs)).toEqual(msgs);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("merges two consecutive user turns (the --resume no-response bug)", () => {
|
|
19
|
+
// history ended with a bare `user` (prior run produced no assistant
|
|
20
|
+
// response); a new user prompt was spliced after it.
|
|
21
|
+
const out = mergeConsecutiveMessages([
|
|
22
|
+
{ role: "system", content: "sys" },
|
|
23
|
+
{ role: "user", content: "original task" },
|
|
24
|
+
{ role: "user", content: "continue please" },
|
|
25
|
+
]);
|
|
26
|
+
expect(out).toEqual([
|
|
27
|
+
{ role: "system", content: "sys" },
|
|
28
|
+
{ role: "user", content: "original task\n\ncontinue please" },
|
|
29
|
+
]);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("merges three-plus consecutive same-role turns", () => {
|
|
33
|
+
const out = mergeConsecutiveMessages([
|
|
34
|
+
{ role: "user", content: "one" },
|
|
35
|
+
{ role: "user", content: "two" },
|
|
36
|
+
{ role: "user", content: "three" },
|
|
37
|
+
]);
|
|
38
|
+
expect(out).toEqual([{ role: "user", content: "one\n\ntwo\n\nthree" }]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("merges consecutive assistant turns defensively", () => {
|
|
42
|
+
const out = mergeConsecutiveMessages([
|
|
43
|
+
{ role: "assistant", content: "x" },
|
|
44
|
+
{ role: "assistant", content: "y" },
|
|
45
|
+
]);
|
|
46
|
+
expect(out).toEqual([{ role: "assistant", content: "x\n\ny" }]);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("never merges system messages (leading base + context pair kept distinct)", () => {
|
|
50
|
+
const msgs = [
|
|
51
|
+
{ role: "system", content: "base" },
|
|
52
|
+
{ role: "system", content: "session-context" },
|
|
53
|
+
{ role: "user", content: "hi" },
|
|
54
|
+
];
|
|
55
|
+
expect(mergeConsecutiveMessages(msgs)).toEqual(msgs);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("preserves the user turn after a healthy assistant tail", () => {
|
|
59
|
+
const out = mergeConsecutiveMessages([
|
|
60
|
+
{ role: "assistant", content: "done" },
|
|
61
|
+
{ role: "user", content: "next" },
|
|
62
|
+
]);
|
|
63
|
+
expect(out).toEqual([
|
|
64
|
+
{ role: "assistant", content: "done" },
|
|
65
|
+
{ role: "user", content: "next" },
|
|
66
|
+
]);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("combines multimodal content arrays when merging user turns", () => {
|
|
70
|
+
const out = mergeConsecutiveMessages([
|
|
71
|
+
{
|
|
72
|
+
role: "user",
|
|
73
|
+
content: [
|
|
74
|
+
{ type: "text", text: "look" },
|
|
75
|
+
{ type: "image", source: "x" },
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
{ role: "user", content: "and describe" },
|
|
79
|
+
]);
|
|
80
|
+
expect(out).toHaveLength(1);
|
|
81
|
+
expect(out[0].role).toBe("user");
|
|
82
|
+
expect(out[0].content).toEqual([
|
|
83
|
+
{ type: "text", text: "look" },
|
|
84
|
+
{ type: "image", source: "x" },
|
|
85
|
+
{ type: "text", text: "and describe" },
|
|
86
|
+
]);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("treats an empty-string content as nothing when merging", () => {
|
|
90
|
+
const out = mergeConsecutiveMessages([
|
|
91
|
+
{ role: "user", content: "" },
|
|
92
|
+
{ role: "user", content: "real" },
|
|
93
|
+
]);
|
|
94
|
+
expect(out).toEqual([{ role: "user", content: "real" }]);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("does not mutate the input array or its messages", () => {
|
|
98
|
+
const input = [
|
|
99
|
+
{ role: "user", content: "a" },
|
|
100
|
+
{ role: "user", content: "b" },
|
|
101
|
+
];
|
|
102
|
+
const snapshot = JSON.parse(JSON.stringify(input));
|
|
103
|
+
mergeConsecutiveMessages(input);
|
|
104
|
+
expect(input).toEqual(snapshot);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("passes through falsy / role-less entries verbatim without crashing", () => {
|
|
108
|
+
const out = mergeConsecutiveMessages([
|
|
109
|
+
null,
|
|
110
|
+
{ content: "no role" },
|
|
111
|
+
{ role: "user", content: "a" },
|
|
112
|
+
{ role: "user", content: "b" },
|
|
113
|
+
]);
|
|
114
|
+
expect(out).toEqual([
|
|
115
|
+
null,
|
|
116
|
+
{ content: "no role" },
|
|
117
|
+
{ role: "user", content: "a\n\nb" },
|
|
118
|
+
]);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("returns the argument unchanged when not an array", () => {
|
|
122
|
+
expect(mergeConsecutiveMessages(null)).toBe(null);
|
|
123
|
+
expect(mergeConsecutiveMessages(undefined)).toBe(undefined);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe("_internal.joinContent", () => {
|
|
127
|
+
const { joinContent } = _internal;
|
|
128
|
+
it("joins two strings with a blank line", () => {
|
|
129
|
+
expect(joinContent("a", "b")).toBe("a\n\nb");
|
|
130
|
+
});
|
|
131
|
+
it("returns the non-empty side when one string is empty", () => {
|
|
132
|
+
expect(joinContent("", "b")).toBe("b");
|
|
133
|
+
expect(joinContent("a", "")).toBe("a");
|
|
134
|
+
});
|
|
135
|
+
it("promotes a string to a text block when joining with an array", () => {
|
|
136
|
+
expect(joinContent("hi", [{ type: "image", source: "x" }])).toEqual([
|
|
137
|
+
{ type: "text", text: "hi" },
|
|
138
|
+
{ type: "image", source: "x" },
|
|
139
|
+
]);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
});
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { execSync } from "node:child_process";
|
|
16
|
-
import { existsSync, readdirSync } from "node:fs";
|
|
16
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
17
|
+
import { join as pathJoin } from "node:path";
|
|
17
18
|
import { createRequire } from "node:module";
|
|
18
19
|
import { createConnection } from "node:net";
|
|
19
20
|
import semver from "semver";
|
|
@@ -28,6 +29,17 @@ import {
|
|
|
28
29
|
} from "../lib/service-manager.js";
|
|
29
30
|
import { loadConfig } from "../lib/config-manager.js";
|
|
30
31
|
import { isAppRunning, getAppPid } from "../lib/process-manager.js";
|
|
32
|
+
import { readDiskVersion, versionDiagnosis } from "../lib/version-skew.js";
|
|
33
|
+
|
|
34
|
+
/** Best-effort read of the npm `latest` cached by the startup update notice. */
|
|
35
|
+
function readCachedLatest() {
|
|
36
|
+
try {
|
|
37
|
+
const p = pathJoin(getHomeDir() || "", "update-check.json");
|
|
38
|
+
return JSON.parse(readFileSync(p, "utf-8"))?.latest || null;
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
31
43
|
|
|
32
44
|
/**
|
|
33
45
|
* Probe a TCP port. Resolves true if something is listening.
|
|
@@ -250,9 +262,19 @@ export async function collectDoctorReport() {
|
|
|
250
262
|
const failed = checks.filter((c) => !c.ok);
|
|
251
263
|
const criticalFailed = failed.filter((c) => !c.optional);
|
|
252
264
|
|
|
265
|
+
// Three-way version check: running (this process) vs installed (on disk) vs
|
|
266
|
+
// latest (npm, from the update-notice cache). Tells the user whether they need
|
|
267
|
+
// `npm i -g` (a new release) or just a restart (already updated on disk).
|
|
268
|
+
const versionCheck = versionDiagnosis({
|
|
269
|
+
running: VERSION,
|
|
270
|
+
installed: readDiskVersion(),
|
|
271
|
+
latest: readCachedLatest(),
|
|
272
|
+
});
|
|
273
|
+
|
|
253
274
|
return {
|
|
254
275
|
schema: "chainlesschain.doctor.v1",
|
|
255
276
|
version: VERSION,
|
|
277
|
+
versionCheck,
|
|
256
278
|
generatedAt: new Date().toISOString(),
|
|
257
279
|
checks,
|
|
258
280
|
ports,
|
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
import { expandFileRefsAsync } from "./file-ref-expander.js";
|
|
47
47
|
import { composeSystemPrompt } from "./system-prompt.js";
|
|
48
48
|
import { buildUserContent } from "../lib/image-input.js";
|
|
49
|
+
import { mergeConsecutiveMessages } from "./message-roles.js";
|
|
49
50
|
import { isHeadlessConfigCommand } from "../lib/headless-config-command.js";
|
|
50
51
|
import { withQuietStdout } from "./quiet-stdout.js";
|
|
51
52
|
import { CostBudget } from "../lib/cost-budget.js";
|
|
@@ -610,14 +611,19 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
610
611
|
// content array (agent-core converts it per-provider for ollama/anthropic).
|
|
611
612
|
const userMessageContent = buildUserContent(userContent, options.images);
|
|
612
613
|
|
|
613
|
-
|
|
614
|
+
// Merge consecutive same-role turns so a resumed session whose previous run
|
|
615
|
+
// produced NO assistant response (history ends with a bare `user` turn) does
|
|
616
|
+
// not yield two adjacent `user` messages — which Anthropic/Bedrock reject as
|
|
617
|
+
// "roles must alternate", failing the resume (Claude Code 2.1.187 parity).
|
|
618
|
+
// No-op on a healthy alternating transcript.
|
|
619
|
+
const messages = mergeConsecutiveMessages([
|
|
614
620
|
{ role: "system", content: systemContent },
|
|
615
621
|
...(sessionStartContext
|
|
616
622
|
? [{ role: "system", content: sessionStartContext }]
|
|
617
623
|
: []),
|
|
618
624
|
...history,
|
|
619
625
|
{ role: "user", content: userMessageContent },
|
|
620
|
-
];
|
|
626
|
+
]);
|
|
621
627
|
|
|
622
628
|
// Persist the user turn up front (best-effort) so a session is recoverable
|
|
623
629
|
// even if the run crashes mid-loop. startSession is append-safe: only seed
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
import { bootstrap } from "./bootstrap.js";
|
|
20
20
|
import { buildSystemPrompt, agentLoop as coreAgentLoop } from "./agent-core.js";
|
|
21
21
|
import { composeSystemPrompt } from "./system-prompt.js";
|
|
22
|
+
import { mergeConsecutiveMessages } from "./message-roles.js";
|
|
22
23
|
import { expandFileRefsAsync } from "./file-ref-expander.js";
|
|
23
24
|
import { detectImagePaths } from "../lib/image-input.js";
|
|
24
25
|
import { detectVersionSkew, versionSkewMessage } from "../lib/version-skew.js";
|
|
@@ -259,7 +260,22 @@ async function runTurn(messages, loopOptions, { runLoop, emit, costBudget }) {
|
|
|
259
260
|
let endReason = "complete";
|
|
260
261
|
let stopForCost = false;
|
|
261
262
|
|
|
262
|
-
|
|
263
|
+
// Merge consecutive same-role turns before the model call ONLY when the
|
|
264
|
+
// caller flags a resume-degenerate transcript (`mergeRoles`): a resumed
|
|
265
|
+
// session whose previous run produced NO assistant response leaves a trailing
|
|
266
|
+
// bare `user` turn, so splicing the first live prompt after it sends two
|
|
267
|
+
// adjacent `user` messages — which Anthropic/Bedrock reject as "roles must
|
|
268
|
+
// alternate" (Claude Code 2.1.187 parity). It is GATED rather than applied
|
|
269
|
+
// every turn because the live turn loop legitimately produces consecutive
|
|
270
|
+
// `user` messages — an interrupted turn's dangling prompt, a PDH feedback
|
|
271
|
+
// note (§3.5.13) — that must reach the model distinctly and must not be
|
|
272
|
+
// folded (folding the interrupt-dangling turn even resurrects the abandoned
|
|
273
|
+
// request). Non-mutating: the persistent `messages` array is untouched; only
|
|
274
|
+
// the provider payload is sanitized.
|
|
275
|
+
const modelMessages = loopOptions.mergeRoles
|
|
276
|
+
? mergeConsecutiveMessages(messages)
|
|
277
|
+
: messages;
|
|
278
|
+
for await (const event of runLoop(modelMessages, loopOptions)) {
|
|
263
279
|
switch (event.type) {
|
|
264
280
|
case "tool-executing":
|
|
265
281
|
toolCalls.push({ tool: event.tool, args: event.args });
|
|
@@ -642,6 +658,15 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
642
658
|
}
|
|
643
659
|
}
|
|
644
660
|
|
|
661
|
+
// Resume-degenerate role sanitation (Claude Code 2.1.187 parity): when the
|
|
662
|
+
// replayed history ends with a bare `user` turn (the prior run produced no
|
|
663
|
+
// assistant response), the FIRST live prompt would make two adjacent `user`
|
|
664
|
+
// messages. Arm a one-shot flag consumed by the first model call so the merge
|
|
665
|
+
// fires exactly once — the live turn loop's intentional consecutive-`user`
|
|
666
|
+
// states (interrupt-dangling turn, PDH feedback note) are never folded.
|
|
667
|
+
let sanitizeRolesNextTurn =
|
|
668
|
+
resumedMessages > 0 && messages[messages.length - 1]?.role === "user";
|
|
669
|
+
|
|
645
670
|
emit({
|
|
646
671
|
type: "system",
|
|
647
672
|
subtype: "init",
|
|
@@ -1294,6 +1319,12 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1294
1319
|
? AbortSignal.any([options.signal, currentAbort.signal])
|
|
1295
1320
|
: currentAbort.signal;
|
|
1296
1321
|
|
|
1322
|
+
// Consume the one-shot resume-degeneracy flag for THIS turn (see
|
|
1323
|
+
// sanitizeRolesNextTurn) so the role merge fires exactly once, whether the
|
|
1324
|
+
// model call completes or is interrupted.
|
|
1325
|
+
const mergeRolesThisTurn = sanitizeRolesNextTurn;
|
|
1326
|
+
sanitizeRolesNextTurn = false;
|
|
1327
|
+
|
|
1297
1328
|
let outcome;
|
|
1298
1329
|
try {
|
|
1299
1330
|
outcome = await runTurn(
|
|
@@ -1339,6 +1370,8 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1339
1370
|
: {}),
|
|
1340
1371
|
iterationBudget: budget,
|
|
1341
1372
|
signal: turnSignal,
|
|
1373
|
+
// Resume-degenerate role merge for the first live model call only.
|
|
1374
|
+
mergeRoles: mergeRolesThisTurn,
|
|
1342
1375
|
},
|
|
1343
1376
|
{ runLoop, emit, costBudget },
|
|
1344
1377
|
);
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation role sanitation shared by the headless runner and the
|
|
3
|
+
* stream-json runtime.
|
|
4
|
+
*
|
|
5
|
+
* Providers that strictly enforce alternating roles — Anthropic, Bedrock, and
|
|
6
|
+
* some OpenAI-compatible gateways — reject a payload with two consecutive
|
|
7
|
+
* messages of the same non-system role ("messages: roles must alternate").
|
|
8
|
+
*
|
|
9
|
+
* A degenerate transcript reaches that state on `--resume` when the ORIGINAL
|
|
10
|
+
* run produced NO assistant response (the model errored, the turn was
|
|
11
|
+
* interrupted, or the provider was down): the persisted JSONL ends with a bare
|
|
12
|
+
* `user` turn. Splicing the new resume prompt after it yields
|
|
13
|
+
* `[…, {role:"user"}, {role:"user"}]` → the provider 400s and resume fails.
|
|
14
|
+
*
|
|
15
|
+
* `mergeConsecutiveMessages` folds adjacent same-role (non-system) turns into a
|
|
16
|
+
* single message so the transcript always alternates, regardless of how it
|
|
17
|
+
* degenerated. This mirrors Claude Code 2.1.187 ("Fixed --resume failing when
|
|
18
|
+
* original run produced no model responses"). It is a no-op on a well-formed
|
|
19
|
+
* alternating transcript, so healthy sessions are byte-for-byte unchanged.
|
|
20
|
+
*
|
|
21
|
+
* @module runtime/message-roles
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Normalize a message `content` field to an array of content blocks. A plain
|
|
26
|
+
* string becomes a single `text` block; an empty string contributes nothing;
|
|
27
|
+
* an existing array is returned as-is; any other object is wrapped as a single
|
|
28
|
+
* opaque block so unknown shapes survive a merge.
|
|
29
|
+
* @param {*} content
|
|
30
|
+
* @returns {Array}
|
|
31
|
+
*/
|
|
32
|
+
function toBlocks(content) {
|
|
33
|
+
if (Array.isArray(content)) return content;
|
|
34
|
+
if (content == null) return [];
|
|
35
|
+
if (typeof content === "string") {
|
|
36
|
+
return content === "" ? [] : [{ type: "text", text: content }];
|
|
37
|
+
}
|
|
38
|
+
return [content];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Join two message `content` values. When both are plain strings the result
|
|
43
|
+
* stays a string (joined by a blank line) — the overwhelmingly common case, so
|
|
44
|
+
* a text-only resume keeps a string payload. When either side is a multimodal
|
|
45
|
+
* content array, both are normalized to block arrays and concatenated.
|
|
46
|
+
* @param {*} a
|
|
47
|
+
* @param {*} b
|
|
48
|
+
* @returns {string|Array}
|
|
49
|
+
*/
|
|
50
|
+
function joinContent(a, b) {
|
|
51
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
52
|
+
if (a === "") return b;
|
|
53
|
+
if (b === "") return a;
|
|
54
|
+
return `${a}\n\n${b}`;
|
|
55
|
+
}
|
|
56
|
+
return [...toBlocks(a), ...toBlocks(b)];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Merge consecutive same-role, non-system messages so the conversation
|
|
61
|
+
* alternates roles for the provider. System messages are passed through
|
|
62
|
+
* untouched and never participate in a merge (a leading base + session-context
|
|
63
|
+
* system pair stays distinct). Falsy / role-less entries are passed through
|
|
64
|
+
* verbatim rather than dropped.
|
|
65
|
+
*
|
|
66
|
+
* Returns a NEW array; the input is not mutated.
|
|
67
|
+
*
|
|
68
|
+
* @param {Array<object>} messages
|
|
69
|
+
* @returns {Array<object>}
|
|
70
|
+
*/
|
|
71
|
+
export function mergeConsecutiveMessages(messages) {
|
|
72
|
+
if (!Array.isArray(messages)) return messages;
|
|
73
|
+
const out = [];
|
|
74
|
+
for (const msg of messages) {
|
|
75
|
+
const prev = out[out.length - 1];
|
|
76
|
+
if (
|
|
77
|
+
prev &&
|
|
78
|
+
msg &&
|
|
79
|
+
typeof msg.role === "string" &&
|
|
80
|
+
msg.role !== "system" &&
|
|
81
|
+
prev.role === msg.role
|
|
82
|
+
) {
|
|
83
|
+
out[out.length - 1] = {
|
|
84
|
+
...prev,
|
|
85
|
+
content: joinContent(prev.content, msg.content),
|
|
86
|
+
};
|
|
87
|
+
} else {
|
|
88
|
+
out.push(msg);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export const _internal = { toBlocks, joinContent };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as v,P as u,J as y,U as n,R as a,S,K as C,Q as x,V as w,_ as B,b as s}from"./vendor-BvqAck49.js";import{_ as k}from"./index-BsReT8kE.js";import"./icons-DP3uiYxy.js";const N={__name:"ChatBubbleRenderer",props:{event:{type:Object,required:!0}},setup(c,{expose:d}){d();const t=c,r=s(()=>{const e=t.event.content||{};return e.text||e.body||e.message||e.title||JSON.stringify(e).slice(0,200)}),i=s(()=>{const e=t.event.content||{};return e.from||e.sender||e.senderName||t.event.actor||"(unknown)"}),l=s(()=>{const e=(t.event.actor||"").toLowerCase();return e.includes("self")||e==="me"||e.endsWith("_self")}),o=s(()=>{const e=t.event.source.adapter||"";return e.startsWith("messaging-qq")?"magenta":e==="wechat"?"green":"blue"}),m=s(()=>{if(!t.event.occurredAt)return"";try{const e=new Date(t.event.occurredAt),p=e.getFullYear(),f=String(e.getMonth()+1).padStart(2,"0"),g=String(e.getDate()).padStart(2,"0"),b=String(e.getHours()).padStart(2,"0"),h=String(e.getMinutes()).padStart(2,"0");return`${p}-${f}-${g} ${b}:${h}`}catch{return""}}),_={props:t,messageText:r,actorLabel:i,isMine:l,adapterColor:o,formattedTime:m,computed:s};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}},R={class:"bubble"},T={class:"meta"},M={class:"actor"},V={class:"time"},q={class:"body"};function D(c,d,t,r,i,l){const o=v("a-tag");return u(),y("div",{class:B(["chat-row",{mine:r.isMine}])},[n("div",R,[n("div",T,[n("span",M,a(r.actorLabel),1),n("span",V,a(r.formattedTime),1)]),n("div",q,a(r.messageText),1),t.event.source.adapter?(u(),S(o,{key:0,class:"src",color:r.adapterColor},{default:C(()=>[x(a(t.event.source.adapter),1)]),_:1},8,["color"])):w("v-if",!0)])],2)}const A=k(N,[["render",D],["__scopeId","data-v-49238629"],["__file","/tmp/cc-web-panel-R5yrKU/repo/packages/web-panel/src/components/pdh/renderers/ChatBubbleRenderer.vue"]]);export{A as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as n,J as g,c as l,K as r,N as u,P as h,U as o,R as t,Q as b}from"./vendor-BvqAck49.js";import{_ as v,b as m}from"./index-BsReT8kE.js";import{a7 as y,M}from"./icons-DP3uiYxy.js";const B={__name:"MobileProjects",setup(p,{expose:i}){i();const c=u(),{t:e}=m();function a(){c.push("/projects")}function _(){c.push("/mobile-bridge")}const s={router:c,t:e,goToProjects:a,goToMobileBridge:_,get useRouter(){return u},get useI18n(){return m},get MobileOutlined(){return M},get FolderOutlined(){return y}};return Object.defineProperty(s,"__isScriptSetup",{enumerable:!1,value:!0}),s}},x={class:"mobile-projects-placeholder"},O={class:"title"},k={class:"subtitle"},w={class:"explainer"};function T(p,i,c,e,a,_){const s=n("a-alert"),d=n("a-button"),f=n("a-space"),P=n("a-empty"),j=n("a-card");return h(),g("div",x,[l(j,null,{default:r(()=>[l(P,{description:!1},{image:r(()=>[l(e.MobileOutlined,{style:{fontSize:"64px",color:"#bfbfbf"}})]),default:r(()=>[o("h2",O,t(e.t("mobileProjects.title")),1),o("p",k,t(e.t("mobileProjects.subtitle")),1),l(s,{message:e.t("mobileProjects.v02Banner"),type:"info","show-icon":"",class:"banner"},null,8,["message"]),o("div",w,[o("h3",null,t(e.t("mobileProjects.currentDirection")),1),o("p",null,t(e.t("mobileProjects.currentDirectionBody")),1),o("ul",null,[o("li",null,t(e.t("mobileProjects.stepPhone")),1),o("li",null,t(e.t("mobileProjects.stepTap")),1),o("li",null,t(e.t("mobileProjects.stepPull")),1)]),o("h3",null,t(e.t("mobileProjects.reverseDirection")),1),o("p",null,t(e.t("mobileProjects.reverseDirectionBody")),1)]),l(f,{class:"actions"},{default:r(()=>[l(d,{type:"primary",onClick:e.goToProjects},{default:r(()=>[l(e.FolderOutlined),b(" "+t(e.t("mobileProjects.viewLocalProjects")),1)]),_:1}),l(d,{onClick:e.goToMobileBridge},{default:r(()=>[l(e.MobileOutlined),b(" "+t(e.t("mobileProjects.checkBridge")),1)]),_:1})]),_:1})]),_:1})]),_:1})])}const N=v(B,[["render",T],["__scopeId","data-v-9262cc45"],["__file","/tmp/cc-web-panel-R5yrKU/repo/packages/web-panel/src/views/MobileProjects.vue"]]);export{N as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as i,J as A,U as I,R as s,Q as r,c as t,K as a,V as _,S as x,o as oe,b as ee,r as u,P as p,F as ne,a2 as ge}from"./vendor-BvqAck49.js";import{_ as we,b as re,u as ie,d}from"./index-BsReT8kE.js";import{u as de}from"./useShellMode-CgR0wCYM.js";import{aM as ke,aN as Fe,aO as be,f as je,a4 as Ce,a7 as xe,as as Oe,R as Se}from"./icons-DP3uiYxy.js";const Pe={__name:"Projects",setup(se,{expose:l}){l();const{t:te}=re(),e=ie(),{isEmbedded:W}=de();async function w(o,f,ye,ae=8e3){if(W){const Z=await e.sendRaw({...f,type:o},ae);if(!Z?.ok){const $=Z?.error;throw new Error(typeof $=="string"?$:$?.message||`${o} failed`)}return Z.result}return e.executeJson(ye,ae)}const B=u(!1),y=u([]),O=u(""),S=u(""),P=u(!1),v=u(null),h=u([]),k=u(!1),E=u(!1),L=u(!1),F=u({name:"",description:"",type:"document",rootPath:""}),z=[{title:"ID",key:"id",width:110},{title:"名称",key:"name"},{title:"类型",key:"project_type",width:120},{title:"状态",key:"status",width:100},{title:"同步",key:"sync_status",width:100},{title:"更新",key:"updated_at",width:160},{title:"操作",key:"actions",width:180,fixed:"right"}],M=ee(()=>{const o={active:0,draft:0,completed:0,archived:0};for(const f of y.value)o[f.status]!==void 0&&(o[f.status]+=1);return o}),J=ee(()=>y.value.filter(o=>!(O.value&&o.status!==O.value||S.value&&!o.name.toLowerCase().includes(S.value.toLowerCase()))));function g(o){switch(o){case"active":return"green";case"draft":return"default";case"completed":return"cyan";case"archived":return"gold";default:return"default"}}function K(o){switch(o){case"synced":return"green";case"pending":return"orange";case"conflict":return"red";case"error":return"red";default:return"default"}}function Q(o){return!o&&o!==0?"-":new Date(typeof o=="number"?o:parseInt(o,10)).toLocaleString("zh-CN",{hour12:!1})}async function C(){B.value=!0;try{const o=await w("project.list",{limit:500},"project list --limit 500 --json",1e4);y.value=Array.isArray(o?.projects)?o.projects:Array.isArray(o)?o:[]}catch(o){d.error("加载失败: "+(o.message||o)),y.value=[]}finally{B.value=!1}}function G(o){return{onClick:()=>V(o)}}async function V(o){v.value=o,P.value=!0,k.value=!0,h.value=[];try{const f=await w("project.listFiles",{projectId:o.id,limit:200},`project list-files ${o.id} --json`,8e3);h.value=Array.isArray(f?.files)?f.files:[]}catch{h.value=[]}finally{k.value=!1}}async function H(o){try{(await w("project.delete",{id:o.id},`project delete ${o.id} --json`,8e3))?.ok?(d.success(`已删除项目 '${o.name}'`),P.value=!1,await C()):d.error("删除失败")}catch(f){d.error(f.message||String(f))}}function X(){F.value={name:"",description:"",type:"document",rootPath:""},E.value=!0}async function T(){if(!F.value.name.trim()){d.warning("请输入项目名称");return}L.value=!0;try{const o=await w("project.init",{name:F.value.name.trim(),description:F.value.description||null,projectType:F.value.type,rootPath:F.value.rootPath||null},`project init "${F.value.name.trim()}" --type ${F.value.type} --json`,8e3);o?.id?(d.success(`已创建项目 '${o.name}'`),E.value=!1,await C()):d.error("创建失败")}catch(o){d.error(o.message||String(o))}finally{L.value=!1}}const b=u(!1),D=u(!1),j=u({path:"",content:""}),U=u(!1),m=u(!1),R=u({path:""}),n=u(!1),c=u(null),q=u(""),Y=u(!1);function ue(){j.value={path:"",content:""},b.value=!0}function ce(){R.value={path:""},U.value=!0}async function N(){if(v.value){k.value=!0;try{const o=await w("project.listFiles",{projectId:v.value.id,limit:200},`project list-files ${v.value.id} --json`,8e3);h.value=Array.isArray(o?.files)?o.files:[]}catch(o){d.error("刷新文件失败: "+(o.message||o))}finally{k.value=!1}}}async function fe(){if(!j.value.path.trim()){d.warning("请输入文件路径");return}if(v.value){D.value=!0;try{const o=await w("project.createFile",{projectId:v.value.id,filePath:j.value.path.trim(),content:j.value.content||""},`project create-file ${v.value.id} "${j.value.path.trim()}" --json`,8e3);o?.id?(d.success(`已创建文件 '${o.file_name}'`),b.value=!1,await N(),await C()):d.error("创建文件失败")}catch(o){d.error(o.message||String(o))}finally{D.value=!1}}}async function pe(){if(!R.value.path.trim()){d.warning("请输入文件夹路径");return}if(v.value){m.value=!0;try{const o=await w("project.createFolder",{projectId:v.value.id,folderPath:R.value.path.trim()},`project create-folder ${v.value.id} "${R.value.path.trim()}" --json`,8e3);o?.id?(d.success(`已创建文件夹 '${o.file_name}'`),U.value=!1,await N(),await C()):d.error("创建文件夹失败")}catch(o){d.error(o.message||String(o))}finally{m.value=!1}}}async function ve(o){try{(await w("project.deleteFile",{fileId:o.id},`project delete-file ${o.id} --json`,8e3))?.deleted?(d.success(`已删除 '${o.file_name}'`),await N(),await C()):d.error("删除失败")}catch(f){d.error(f.message||String(f))}}async function me(o){if(o.is_folder){d.info("文件夹无内容可编辑");return}try{const f=await w("project.getFile",{fileId:o.id},`project get-file ${o.id} --json`,8e3);c.value=o,q.value=f?.content||"",n.value=!0}catch(f){d.error("读取文件失败: "+(f.message||f))}}async function _e(){if(c.value){Y.value=!0;try{(await w("project.writeFile",{fileId:c.value.id,content:q.value},`project write-file ${c.value.id} --json`,8e3))?.id?(d.success("已保存"),n.value=!1,await N()):d.error("保存失败")}catch(o){d.error(o.message||String(o))}finally{Y.value=!1}}}oe(()=>{C()});const le={t:te,ws:e,isEmbedded:W,callProjectTopic:w,loading:B,projects:y,statusFilter:O,nameFilter:S,detailOpen:P,detail:v,files:h,filesLoading:k,createOpen:E,creating:L,newProject:F,columns:z,countByStatus:M,filteredProjects:J,statusColor:g,syncColor:K,formatTime:Q,loadAll:C,onRowClick:G,openDetail:V,onDelete:H,onShowCreate:X,onCreate:T,createFileOpen:b,creatingFile:D,newFile:j,createFolderOpen:U,creatingFolder:m,newFolder:R,editFileOpen:n,editingFile:c,editFileContent:q,savingFile:Y,openCreateFile:ue,openCreateFolder:ce,refreshFiles:N,onCreateFile:fe,onCreateFolder:pe,onDeleteFile:ve,openEditFile:me,onSaveFile:_e,ref:u,computed:ee,onMounted:oe,get ReloadOutlined(){return Se},get PlusOutlined(){return Oe},get FolderOutlined(){return xe},get FileTextOutlined(){return Ce},get CheckCircleOutlined(){return je},get CheckSquareOutlined(){return be},get FileAddOutlined(){return Fe},get FolderAddOutlined(){return ke},get message(){return d},get useI18n(){return re},get useWsStore(){return ie},get useShellMode(){return de}};return Object.defineProperty(le,"__isScriptSetup",{enumerable:!1,value:!0}),le}},ze={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"24px"}},Ue={class:"page-title"},Ae={class:"page-sub"},Ie={class:"filter-bar",style:{"margin-bottom":"12px",display:"flex",gap:"12px","align-items":"center"}},he={key:0,style:{"font-size":"12px",color:"#888"}},De={key:0,style:{color:"#888","font-size":"12px"}},Re={key:0},Te={key:1,style:{color:"#888"}},Be=["onClick"],Ee={key:0,style:{color:"#888","font-size":"12px"}};function Le(se,l,te,e,W,w){const B=i("router-link"),y=i("a-button"),O=i("a-space"),S=i("a-statistic"),P=i("a-card"),v=i("a-col"),h=i("a-row"),k=i("a-radio-button"),E=i("a-radio-group"),L=i("a-input-search"),F=i("a-alert"),z=i("a-tag"),M=i("a-popconfirm"),J=i("a-table"),g=i("a-descriptions-item"),K=i("a-descriptions"),Q=i("a-divider"),C=i("a-empty"),G=i("a-list-item"),V=i("a-list"),H=i("a-spin"),X=i("a-drawer"),T=i("a-input"),b=i("a-form-item"),D=i("a-textarea"),j=i("a-form"),U=i("a-modal"),m=i("a-select-option"),R=i("a-select");return p(),A("div",null,[I("div",ze,[I("div",null,[I("h2",Ue,s(e.t("projects.title")),1),I("p",Ae,[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 "),I("div",Ie,[t(E,{value:e.statusFilter,"onUpdate:value":l[0]||(l[0]=n=>e.statusFilter=n),size:"small","button-style":"solid"},{default:a(()=>[t(k,{value:""},{default:a(()=>[...l[21]||(l[21]=[r("全部",-1)])]),_:1}),t(k,{value:"active"},{default:a(()=>[...l[22]||(l[22]=[r("活跃",-1)])]),_:1}),t(k,{value:"draft"},{default:a(()=>[...l[23]||(l[23]=[r("草稿",-1)])]),_:1}),t(k,{value:"completed"},{default:a(()=>[...l[24]||(l[24]=[r("已完成",-1)])]),_:1}),t(k,{value:"archived"},{default:a(()=>[...l[25]||(l[25]=[r("已归档",-1)])]),_:1})]),_:1},8,["value"]),t(L,{value:e.nameFilter,"onUpdate:value":l[1]||(l[1]=n=>e.nameFilter=n),placeholder:"按名称过滤",style:{"max-width":"260px"},"allow-clear":""},null,8,["value"])]),!e.projects.length&&!e.loading?(p(),x(F,{key:0,type:"info",message:"还没有项目",description:'运行 `cc project init <name>` 或点击右上角"新建项目"按钮创建。桌面 / CLI / 手机三端共享同一份数据。',"show-icon":"",style:{"margin-bottom":"16px"}})):_("v-if",!0),e.projects.length||e.loading?(p(),x(J,{key:1,columns:e.columns,"data-source":e.filteredProjects,loading:e.loading,pagination:{pageSize:20,showSizeChanger:!0},"row-key":"id","custom-row":e.onRowClick},{bodyCell:a(({column:n,record:c})=>[n.key==="id"?(p(),A("code",he,s(c.id.slice(0,8))+"…",1)):n.key==="name"?(p(),A(ne,{key:1},[I("strong",null,s(c.name),1),c.description?(p(),A("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(),A(ne,{key:5},[r(s(e.formatTime(c.updated_at)),1)],64)):n.key==="actions"?(p(),x(O,{key:6,onClick:l[2]||(l[2]=ge(()=>{},["stop"]))},{default:a(()=>[t(y,{size:"small",onClick:q=>e.openDetail(c)},{default:a(()=>[...l[26]||(l[26]=[r("详情",-1)])]),_:1},8,["onClick"]),t(M,{title:`删除项目 '${c.name}' ?`,"ok-text":"删除","ok-type":"danger","cancel-text":"取消",onConfirm:q=>e.onDelete(c)},{default:a(()=>[t(y,{size:"small",danger:""},{default:a(()=>[...l[27]||(l[27]=[r("删除",-1)])]),_:1})]),_:1},8,["title","onConfirm"])]),_:2},1024)):_("v-if",!0)]),_:1},8,["data-source","loading"])):_("v-if",!0),_(" Detail drawer "),t(X,{open:e.detailOpen,"onUpdate:open":l[3]||(l[3]=n=>e.detailOpen=n),title:e.detail?.name||"项目详情",width:"640",placement:"right"},{default:a(()=>[e.detail?(p(),x(K,{key:0,column:1,bordered:"",size:"small"},{default:a(()=>[t(g,{label:"ID"},{default:a(()=>[I("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(),A("code",Re,s(e.detail.root_path),1)):(p(),A("span",Te,"(无)"))]),_:1}),t(g,{label:"文件数"},{default:a(()=>[r(s(e.detail.file_count||0),1)]),_:1}),t(g,{label:"创建"},{default:a(()=>[r(s(e.formatTime(e.detail.created_at)),1)]),_:1}),t(g,{label:"更新"},{default:a(()=>[r(s(e.formatTime(e.detail.updated_at)),1)]),_:1})]),_:1})):_("v-if",!0),t(Q,null,{default:a(()=>[...l[28]||(l[28]=[r("文件",-1)])]),_:1}),_(" Sub-phase 7.3 (2026-05-17): 文件 CRUD toolbar "),t(O,{style:{"margin-bottom":"12px"}},{default:a(()=>[t(y,{size:"small",type:"primary",disabled:!e.detail,onClick:e.openCreateFile},{default:a(()=>[t(e.FileAddOutlined),l[29]||(l[29]=r(" 新建文件 ",-1))]),_:1},8,["disabled"]),t(y,{size:"small",disabled:!e.detail,onClick:e.openCreateFolder},{default:a(()=>[t(e.FolderAddOutlined),l[30]||(l[30]=r(" 新建文件夹 ",-1))]),_:1},8,["disabled"])]),_:1}),t(H,{spinning:e.filesLoading},{default:a(()=>[!e.files.length&&!e.filesLoading?(p(),x(C,{key:0,description:"无文件 (点上方按钮新建)"})):(p(),x(V,{key:1,size:"small","data-source":e.files},{renderItem:a(({item:n})=>[t(G,null,{extra:a(()=>[t(O,null,{default:a(()=>[n.file_size?(p(),A("span",Ee,s(n.file_size)+" B",1)):_("v-if",!0),t(M,{title:`删除 ${n.is_folder?"文件夹":"文件"} '${n.file_name}' ?`,"ok-text":"删除","ok-type":"danger","cancel-text":"取消",onConfirm:c=>e.onDeleteFile(n)},{default:a(()=>[t(y,{size:"small",danger:""},{default:a(()=>[...l[31]||(l[31]=[r("×",-1)])]),_:1})]),_:1},8,["title","onConfirm"])]),_:2},1024)]),default:a(()=>[I("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(U,{open:e.createFileOpen,"onUpdate:open":l[6]||(l[6]=n=>e.createFileOpen=n),title:"新建文件","confirm-loading":e.creatingFile,"ok-text":"创建","cancel-text":"取消",onOk:e.onCreateFile},{default:a(()=>[t(j,{layout:"vertical"},{default:a(()=>[t(b,{label:"文件路径(项目内)",required:""},{default:a(()=>[t(T,{value:e.newFile.path,"onUpdate:value":l[4]||(l[4]=n=>e.newFile.path=n),placeholder:"例如 README.md 或 src/main.kt"},null,8,["value"])]),_:1}),t(b,{label:"初始内容(可选)"},{default:a(()=>[t(D,{value:e.newFile.content,"onUpdate:value":l[5]||(l[5]=n=>e.newFile.content=n),rows:6,placeholder:"留空创建空文件"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"]),_(" Sub-phase 7.3: Create folder modal "),t(U,{open:e.createFolderOpen,"onUpdate:open":l[8]||(l[8]=n=>e.createFolderOpen=n),title:"新建文件夹","confirm-loading":e.creatingFolder,"ok-text":"创建","cancel-text":"取消",onOk:e.onCreateFolder},{default:a(()=>[t(j,{layout:"vertical"},{default:a(()=>[t(b,{label:"文件夹路径(项目内)",required:""},{default:a(()=>[t(T,{value:e.newFolder.path,"onUpdate:value":l[7]||(l[7]=n=>e.newFolder.path=n),placeholder:"例如 src/utils"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"]),_(" Sub-phase 7.3: Edit file content modal "),t(U,{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(U,{open:e.createOpen,"onUpdate:open":l[15]||(l[15]=n=>e.createOpen=n),title:"新建项目","confirm-loading":e.creating,"ok-text":"创建","cancel-text":"取消",onOk:e.onCreate},{default:a(()=>[t(j,{layout:"vertical"},{default:a(()=>[t(b,{label:"项目名称",required:""},{default:a(()=>[t(T,{value:e.newProject.name,"onUpdate:value":l[11]||(l[11]=n=>e.newProject.name=n),placeholder:"例如:旅行计划-上海"},null,8,["value"])]),_:1}),t(b,{label:"描述"},{default:a(()=>[t(D,{value:e.newProject.description,"onUpdate:value":l[12]||(l[12]=n=>e.newProject.description=n),rows:2},null,8,["value"])]),_:1}),t(b,{label:"类型"},{default:a(()=>[t(R,{value:e.newProject.type,"onUpdate:value":l[13]||(l[13]=n=>e.newProject.type=n)},{default:a(()=>[t(m,{value:"document"},{default:a(()=>[...l[32]||(l[32]=[r("文档 (document)",-1)])]),_:1}),t(m,{value:"data"},{default:a(()=>[...l[33]||(l[33]=[r("数据 (data)",-1)])]),_:1}),t(m,{value:"web"},{default:a(()=>[...l[34]||(l[34]=[r("Web",-1)])]),_:1}),t(m,{value:"app"},{default:a(()=>[...l[35]||(l[35]=[r("应用 (app)",-1)])]),_:1}),t(m,{value:"presentation"},{default:a(()=>[...l[36]||(l[36]=[r("演示文稿",-1)])]),_:1}),t(m,{value:"spreadsheet"},{default:a(()=>[...l[37]||(l[37]=[r("表格",-1)])]),_:1}),t(m,{value:"design"},{default:a(()=>[...l[38]||(l[38]=[r("设计",-1)])]),_:1}),t(m,{value:"code"},{default:a(()=>[...l[39]||(l[39]=[r("代码",-1)])]),_:1}),t(m,{value:"workflow"},{default:a(()=>[...l[40]||(l[40]=[r("工作流",-1)])]),_:1}),t(m,{value:"knowledge"},{default:a(()=>[...l[41]||(l[41]=[r("知识库",-1)])]),_:1})]),_:1},8,["value"])]),_:1}),t(b,{label:"根路径 (可选)"},{default:a(()=>[t(T,{value:e.newProject.rootPath,"onUpdate:value":l[14]||(l[14]=n=>e.newProject.rootPath=n),placeholder:"留空则仅元数据"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"])])}const We=we(Pe,[["render",Le],["__scopeId","data-v-019ac5aa"],["__file","/tmp/cc-web-panel-R5yrKU/repo/packages/web-panel/src/views/Projects.vue"]]);export{We as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{E as I,b as w,r as b,I as m,J as y,U as a,R as g,c as i,K as u,V as h,F as C,Z as L,N as O,o as M,P as p,Q as S,S as R}from"./vendor-BvqAck49.js";import{u as E,_ as N}from"./index-BsReT8kE.js";import{u as P}from"./useShellMode-CgR0wCYM.js";import{p as V}from"./parsers-UEvh_ShA.js";import{u as z}from"./chat-Bke-Axcb.js";import{a9 as j,ap as q,R as B}from"./icons-DP3uiYxy.js";const A=I("skills",()=>{const _=b(!1),t=b([]),n=b(""),e=b("all"),k=w(()=>{const o=new Set(["all"]);return t.value.forEach(l=>{l.category&&o.add(l.category),l.executionMode&&o.add(l.executionMode)}),[...o]}),v=w(()=>{let o=t.value;if(e.value!=="all"&&(o=o.filter(l=>l.category===e.value||l.executionMode===e.value)),n.value){const l=n.value.toLowerCase();o=o.filter(d=>d.name?.toLowerCase().includes(l)||d.description?.toLowerCase().includes(l)||d.title?.toLowerCase().includes(l))}return o});async function f(){const o=E();_.value=!0;try{if(P().isEmbedded){const c=await o.sendRaw({type:"skill.list"},2e4);c?.ok&&Array.isArray(c.result?.skills)?t.value=c.result.skills:(console.error("skill.list custom topic failed:",c?.error),t.value=[]);return}const{output:l}=await o.execute("skill list",2e4),d=V(l);t.value=d}catch(l){console.error("Failed to load skills:",l)}finally{_.value=!1}}return{loading:_,allSkills:t,searchQuery:n,selectedCategory:e,categories:k,filteredSkills:v,loadSkills:f}}),F={__name:"Skills",setup(_,{expose:t}){t();const n=A(),e=z(),k=O(),v=w(()=>n.categories.filter(r=>r!=="all").slice(0,6));function f(r){return{"built-in":"内置","cli-direct":"CLI",agent:"Agent","llm-query":"LLM",hybrid:"混合",workspace:"工作区",marketplace:"市场"}[r]||r}function o(r){return{"cli-direct":"CLI",agent:"Agent","llm-query":"LLM",hybrid:"混合","built-in":"内置"}[r]||r||"未知"}function l(r){return{"cli-direct":"cyan",agent:"purple","llm-query":"blue",hybrid:"orange","built-in":"green"}[r]||"default"}async function d(r){await e.createSession("agent"),k.push("/chat"),setTimeout(()=>{e.currentSessionId&&e.sendMessage(e.currentSessionId,`/skill run ${r}`)},300)}M(()=>{n.allSkills.length||n.loadSkills()});const c={skillsStore:n,chatStore:e,router:k,displayCategories:v,catLabel:f,modeLabel:o,modeColor:l,runSkill:d,computed:w,onMounted:M,get useRouter(){return O},get ReloadOutlined(){return B},get PlayCircleOutlined(){return q},get AppstoreOutlined(){return j},get useSkillsStore(){return A},get useChatStore(){return z}};return Object.defineProperty(c,"__isScriptSetup",{enumerable:!1,value:!0}),c}},Q={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"24px"}},U={class:"page-sub"},K={style:{display:"flex",gap:"12px","margin-bottom":"20px","flex-wrap":"wrap"}},T={key:0,style:{"text-align":"center",padding:"60px"}},D={class:"skills-grid"},G={style:{display:"flex","justify-content":"space-between","align-items":"flex-start"}},J={style:{flex:"1","min-width":"0"}},W={style:{"font-weight":"500",color:"#e0e0e0","font-size":"14px","margin-bottom":"4px","font-family":"monospace"}},Z={style:{color:"var(--text-secondary)","font-size":"12px","line-height":"1.5"}},H={style:{"margin-left":"12px","flex-shrink":"0"}},X={style:{"margin-top":"10px",display:"flex","justify-content":"flex-end"}},Y={style:{"text-align":"center",padding:"60px",color:"var(--text-muted)"}};function $(_,t,n,e,k,v){const f=m("a-button"),o=m("a-input-search"),l=m("a-radio-button"),d=m("a-radio-group"),c=m("a-spin"),r=m("a-tag"),x=m("a-card");return p(),y("div",null,[a("div",Q,[a("div",null,[t[3]||(t[3]=a("h2",{class:"page-title"},"技能管理",-1)),a("p",U,g(e.skillsStore.allSkills.length)+" 个可用技能",1)]),i(f,{type:"primary",ghost:"",loading:e.skillsStore.loading,onClick:t[0]||(t[0]=s=>e.skillsStore.loadSkills())},{icon:u(()=>[i(e.ReloadOutlined)]),default:u(()=>[t[4]||(t[4]=S(" 刷新 ",-1))]),_:1},8,["loading"])]),h(" Search & Filter "),a("div",K,[i(o,{value:e.skillsStore.searchQuery,"onUpdate:value":t[1]||(t[1]=s=>e.skillsStore.searchQuery=s),placeholder:"搜索技能名称或描述...",style:{width:"300px"},"allow-clear":""},null,8,["value"]),i(d,{value:e.skillsStore.selectedCategory,"onUpdate:value":t[2]||(t[2]=s=>e.skillsStore.selectedCategory=s),"button-style":"solid"},{default:u(()=>[i(l,{value:"all"},{default:u(()=>[...t[5]||(t[5]=[S("全部",-1)])]),_:1}),(p(!0),y(C,null,L(e.displayCategories,s=>(p(),R(l,{key:s,value:s},{default:u(()=>[S(g(e.catLabel(s)),1)]),_:2},1032,["value"]))),128))]),_:1},8,["value"])]),h(" Loading State "),e.skillsStore.loading?(p(),y("div",T,[i(c,{size:"large"}),t[6]||(t[6]=a("div",{style:{color:"var(--text-muted)","margin-top":"12px"}},"加载技能中...",-1))])):e.skillsStore.filteredSkills.length?(p(),y(C,{key:1},[h(" Skills Grid "),a("div",D,[(p(!0),y(C,null,L(e.skillsStore.filteredSkills,s=>(p(),R(x,{key:s.name,class:"skill-card",size:"small",hoverable:"",style:{background:"var(--bg-card)","border-color":"var(--border-color)",cursor:"default"}},{default:u(()=>[a("div",G,[a("div",J,[a("div",W,g(s.name),1),a("div",Z,g(s.description||"暂无描述"),1)]),a("div",H,[i(r,{color:e.modeColor(s.executionMode),style:{"font-size":"10px"}},{default:u(()=>[S(g(e.modeLabel(s.executionMode)),1)]),_:2},1032,["color"])])]),a("div",X,[i(f,{size:"small",type:"primary",ghost:"",onClick:ee=>e.runSkill(s.name)},{icon:u(()=>[i(e.PlayCircleOutlined)]),default:u(()=>[t[7]||(t[7]=S(" 运行 ",-1))]),_:1},8,["onClick"])])]),_:2},1024))),128))])],2112)):(p(),y(C,{key:2},[h(" Empty State "),a("div",Y,[i(e.AppstoreOutlined,{style:{"font-size":"48px","margin-bottom":"16px",display:"block"}}),a("div",null,g(e.skillsStore.allSkills.length?"没有匹配的技能":"点击刷新加载技能列表"),1)])],2112))])}const ie=N(F,[["render",$],["__scopeId","data-v-d64d43f5"],["__file","/tmp/cc-web-panel-R5yrKU/repo/packages/web-panel/src/views/Skills.vue"]]);export{ie as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{E as F,b as D,r as R,I as p,J as c,U as _,c as n,K as a,S as C,V as x,o as I,x as V,P as i,Q as k,R as r,F as T,Z as O}from"./vendor-BvqAck49.js";import{u as P,_ as U}from"./index-BsReT8kE.js";import{R as E}from"./icons-DP3uiYxy.js";const B=F("tasks",()=>{const y=R([]),l=R(!1);let u=null,t=null,d=null;const b=D(()=>y.value.filter(e=>e.status==="running")),v=D(()=>y.value.filter(e=>e.status==="pending")),w=D(()=>y.value.filter(e=>e.status==="completed"||e.status==="failed"||e.status==="timeout"));async function s(){const e=P();l.value=!0;try{const g=await e.sendRaw({type:"tasks-list"});g&&Array.isArray(g.tasks)&&(y.value=g.tasks)}catch{}finally{l.value=!1}}async function m(e){const g=P();try{await g.sendRaw({type:"tasks-stop",taskId:e})}catch{}finally{await s()}}const f=R(null);function h(e=5e3){N(),s(),u=setInterval(s,e),S()}function N(){u&&(clearInterval(u),u=null),t&&(t(),t=null),d&&(clearTimeout(d),d=null)}function S(){const e=P();if(t)return;const g=z=>{z.type==="task:notification"&&z.payload?.task&&(f.value=z.payload.task,s(),d&&clearTimeout(d),d=setTimeout(()=>{f.value=null,d=null},8e3))};t=e.onRuntimeEvent(g)}function A(e){return!e||e<0?"-":e<1e3?`${e}ms`:e<6e4?`${(e/1e3).toFixed(1)}s`:`${(e/6e4).toFixed(1)}m`}function o(e){switch(e){case"running":return"processing";case"pending":return"default";case"completed":return"success";case"failed":return"error";case"timeout":return"warning";default:return"default"}}return{tasks:y,loading:l,running:b,pending:v,completed:w,lastNotification:f,fetchTasks:s,stopTask:m,startPolling:h,stopPolling:N,formatDuration:A,getStatusColor:o}}),K={__name:"Tasks",setup(y,{expose:l}){l();const u=B(),t=[{title:"状态",key:"status",width:90},{title:"描述",key:"description",ellipsis:!0},{title:"类型",dataIndex:"type",width:100},{title:"耗时",key:"duration",width:90},{title:"创建时间",key:"createdAt",width:180},{title:"结果",key:"result",ellipsis:!0},{title:"操作",key:"action",width:80}];function d(s){return s.status==="running"&&s.startedAt?u.formatDuration(Date.now()-s.startedAt):s.completedAt&&s.startedAt?u.formatDuration(s.completedAt-s.startedAt):"-"}function b(s){return s?new Date(s).toLocaleString():"-"}function v(s,m){return s?s.length>m?`${s.slice(0,m)}...`:s:""}I(()=>u.startPolling(5e3)),V(()=>u.stopPolling());const w={store:u,columns:t,getDuration:d,formatTime:b,truncate:v,onMounted:I,onUnmounted:V,get ReloadOutlined(){return E},get useTasksStore(){return B}};return Object.defineProperty(w,"__isScriptSetup",{enumerable:!1,value:!0}),w}},L={class:"page-header"},j={key:0,class:"error-text"},J={key:1},M={class:"task-header"},Q={class:"task-desc"},W={class:"task-id"},Z={class:"task-meta"},q=["title"],G={key:0,class:"error-text"},H={key:1,class:"success-text"},X={key:2,class:"muted-text"};function Y(y,l,u,t,d,b){const v=p("a-button"),w=p("a-space"),s=p("a-alert"),m=p("a-statistic"),f=p("a-card"),h=p("a-col"),N=p("a-row"),S=p("a-tag"),A=p("a-table");return i(),c("div",null,[_("div",L,[l[3]||(l[3]=_("div",null,[_("h2",{class:"page-title"},"后台任务"),_("p",{class:"page-sub"},"查看后台任务队列、实时通知和任务执行结果。")],-1)),n(w,null,{default:a(()=>[n(v,{ghost:"",loading:t.store.loading,onClick:l[0]||(l[0]=o=>t.store.fetchTasks())},{icon:a(()=>[n(t.ReloadOutlined)]),default:a(()=>[l[2]||(l[2]=k(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),t.store.lastNotification?(i(),C(s,{key:0,type:t.store.lastNotification.status==="completed"?"success":"error","show-icon":"",closable:"",class:"banner",onClose:l[1]||(l[1]=o=>t.store.lastNotification=null)},{message:a(()=>[k(" 任务"+r(t.store.lastNotification.status==="completed"?"完成":"结束")+": "+r(t.store.lastNotification.description||t.store.lastNotification.id.slice(0,16)),1)]),description:a(()=>[t.store.lastNotification.error?(i(),c("span",j,r(t.store.lastNotification.error),1)):t.store.lastNotification.result?(i(),c("span",J,r(t.truncate(String(t.store.lastNotification.result),120)),1)):x("v-if",!0)]),_:1},8,["type"])):x("v-if",!0),n(N,{gutter:[16,16],class:"stats-row"},{default:a(()=>[n(h,{xs:12,sm:6},{default:a(()=>[n(f,{class:"stat-card",size:"small"},{default:a(()=>[n(m,{title:"全部任务",value:t.store.tasks.length},null,8,["value"])]),_:1})]),_:1}),n(h,{xs:12,sm:6},{default:a(()=>[n(f,{class:"stat-card",size:"small"},{default:a(()=>[n(m,{title:"运行中",value:t.store.running.length},null,8,["value"])]),_:1})]),_:1}),n(h,{xs:12,sm:6},{default:a(()=>[n(f,{class:"stat-card",size:"small"},{default:a(()=>[n(m,{title:"等待中",value:t.store.pending.length},null,8,["value"])]),_:1})]),_:1}),n(h,{xs:12,sm:6},{default:a(()=>[n(f,{class:"stat-card",size:"small"},{default:a(()=>[n(m,{title:"已完成",value:t.store.completed.length},null,8,["value"])]),_:1})]),_:1})]),_:1}),t.store.running.length>0?(i(),C(f,{key:1,title:"运行中的任务",class:"panel-card",size:"small"},{default:a(()=>[(i(!0),c(T,null,O(t.store.running,o=>(i(),c("div",{key:o.id,class:"task-item running"},[_("div",M,[n(S,{color:t.store.getStatusColor(o.status)},{default:a(()=>[k(r(o.status.toUpperCase()),1)]),_:2},1032,["color"]),_("span",Q,r(o.description),1),_("span",W,r(o.id.slice(0,16)),1)]),_("div",Z,[_("span",null,"类型: "+r(o.type||"-"),1),_("span",null,"已运行: "+r(t.store.formatDuration(Date.now()-o.startedAt)),1),n(v,{size:"small",danger:"",onClick:e=>t.store.stopTask(o.id)},{default:a(()=>[...l[4]||(l[4]=[k("停止",-1)])]),_:1},8,["onClick"])])]))),128))]),_:1})):x("v-if",!0),n(f,{class:"panel-card"},{default:a(()=>[n(A,{columns:t.columns,"data-source":t.store.tasks,pagination:{pageSize:15,size:"small"},loading:t.store.loading,"row-key":"id",size:"small"},{bodyCell:a(({column:o,record:e})=>[o.key==="status"?(i(),C(S,{key:0,color:t.store.getStatusColor(e.status)},{default:a(()=>[k(r(e.status),1)]),_:2},1032,["color"])):o.key==="description"?(i(),c("span",{key:1,title:e.command},r(e.description),9,q)):o.key==="duration"?(i(),c(T,{key:2},[k(r(t.getDuration(e)),1)],64)):o.key==="createdAt"?(i(),c(T,{key:3},[k(r(t.formatTime(e.createdAt)),1)],64)):o.key==="result"?(i(),c(T,{key:4},[e.error?(i(),c("span",G,r(t.truncate(e.error,60)),1)):e.result?(i(),c("span",H,r(t.truncate(String(e.result),60)),1)):(i(),c("span",X,"-"))],64)):o.key==="action"?(i(),c(T,{key:5},[e.status==="running"?(i(),C(v,{key:0,size:"small",danger:"",onClick:g=>t.store.stopTask(e.id)},{default:a(()=>[...l[5]||(l[5]=[k(" 停止 ",-1)])]),_:1},8,["onClick"])):x("v-if",!0)],64)):x("v-if",!0)]),_:1},8,["data-source","loading"])]),_:1})])}const st=U(K,[["render",Y],["__scopeId","data-v-da5ff6a2"],["__file","/tmp/cc-web-panel-R5yrKU/repo/packages/web-panel/src/views/Tasks.vue"]]);export{st as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as S,P as n,J as i,U as l,S as h,R as o,c,K as d,Q as u,V as g,b as a}from"./vendor-BvqAck49.js";import{_ as b}from"./index-BsReT8kE.js";import{aD as O,aH as D}from"./icons-DP3uiYxy.js";const C={__name:"TimelineRenderer",props:{event:{type:Object,required:!0}},setup(v,{expose:_}){_();const r=v,e=a(()=>r.event.content||{}),p=a(()=>{const t=r.event.source.adapter||"";return t.startsWith("travel-12306")||t.startsWith("travel-ctrip")}),m=a(()=>e.value.from&&e.value.to?`${e.value.from} → ${e.value.to}`:e.value.origin&&e.value.destination?`${e.value.origin} → ${e.value.destination}`:null),s=a(()=>r.event.place||e.value.placeName||e.value.poi),N=a(()=>e.value.trainNo),y=a(()=>e.value.flightNo),T=a(()=>e.value.title||e.value.text||e.value.description||"—"),k=a(()=>{const t=[];return e.value.departureTime&&t.push(`出发 ${e.value.departureTime}`),e.value.arrivalTime&&t.push(`到达 ${e.value.arrivalTime}`),e.value.duration&&t.push(`${e.value.duration}`),e.value.distance&&t.push(`${e.value.distance}`),t.length?t.join(" · "):null}),x=a(()=>{if(!r.event.occurredAt)return"";const t=new Date(r.event.occurredAt);return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")} ${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`}),f={props:r,c:e,isTravel:p,route:m,placeName:s,trainNo:N,flightNo:y,fallbackText:T,extraDetail:k,formattedTime:x,computed:a,get CarOutlined(){return D},get EnvironmentOutlined(){return O}};return Object.defineProperty(f,"__isScriptSetup",{enumerable:!1,value:!0}),f}},R={class:"timeline-event"},V={class:"dot"},w={class:"card"},B={class:"head"},E={class:"time"},j={class:"primary"},A={key:0},H={key:1},I={key:2},K={key:0,class:"trip-no"},M={key:1,class:"extra"};function P(v,_,r,e,p,m){const s=S("a-tag");return n(),i("div",R,[l("div",V,[e.isTravel?(n(),h(e.CarOutlined,{key:0})):(n(),h(e.EnvironmentOutlined,{key:1}))]),l("div",w,[l("div",B,[l("span",E,o(e.formattedTime),1),c(s,{color:"cyan"},{default:d(()=>[u(o(r.event.source.adapter),1)]),_:1}),c(s,null,{default:d(()=>[u(o(r.event.subtype),1)]),_:1})]),l("div",j,[e.route?(n(),i("span",A,o(e.route),1)):e.placeName?(n(),i("span",H,"📍 "+o(e.placeName),1)):(n(),i("span",I,o(e.fallbackText),1))]),e.trainNo||e.flightNo?(n(),i("div",K,[c(s,{color:"blue"},{default:d(()=>[u(o(e.trainNo||e.flightNo),1)]),_:1})])):g("v-if",!0),e.extraDetail?(n(),i("div",M,o(e.extraDetail),1)):g("v-if",!0)])])}const F=b(C,[["render",P],["__scopeId","data-v-18400280"],["__file","/tmp/cc-web-panel-R5yrKU/repo/packages/web-panel/src/components/pdh/renderers/TimelineRenderer.vue"]]);export{F as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{O as r}from"./index-BsReT8kE.js";const o=((n,a,e)=>{r(n,`[ant-design-vue: ${a}] ${e}`)});export{o as d};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{C as o}from"./Col-DWU7gipF.js";import{U as t}from"./index-BsReT8kE.js";import"./vendor-BvqAck49.js";import"./index-0ZL7FjnB.js";import"./icons-DP3uiYxy.js";const s=t(o);export{s as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{A as o}from"./Row-B9kpAVZb.js";import{U as t}from"./index-BsReT8kE.js";import"./vendor-BvqAck49.js";import"./responsiveObserve-j6LiN9K2.js";import"./useFlexGapSupport-D_0KlvEp.js";import"./styleChecker-g4UCWzKN.js";import"./index-0ZL7FjnB.js";import"./icons-DP3uiYxy.js";const l=t(o);export{l as default};
|