cc-viewer 1.6.348 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -1
- package/cli.js +116 -37
- package/dist/assets/App-gUSmU6Ny.js +2 -0
- package/dist/assets/{MdxEditorPanel-ualoRFOL.js → MdxEditorPanel-DAR39A3S.js} +1 -1
- package/dist/assets/Mobile-qfRsRth0.js +1 -0
- package/dist/assets/{_baseUniq-CG81mgN_.js → _baseUniq-D9_E5ZDp.js} +1 -1
- package/dist/assets/{arc-C161J4f2.js → arc-D4iFrlhb.js} +1 -1
- package/dist/assets/{architectureDiagram-Q4EWVU46-BmbDMdn9.js → architectureDiagram-Q4EWVU46-f1neo7hg.js} +1 -1
- package/dist/assets/{blockDiagram-DXYQGD6D-DXpMvdxd.js → blockDiagram-DXYQGD6D-DWi9e9tG.js} +1 -1
- package/dist/assets/{c4Diagram-AHTNJAMY-8Mypg0IU.js → c4Diagram-AHTNJAMY-DAdj49A2.js} +1 -1
- package/dist/assets/{channel-B2khdmvc.js → channel-B3VthT0m.js} +1 -1
- package/dist/assets/{chunk-4BX2VUAB-I61r1g6z.js → chunk-4BX2VUAB-BrPcAHV3.js} +1 -1
- package/dist/assets/{chunk-4TB4RGXK-VFPlRE5E.js → chunk-4TB4RGXK-Bvopc1V9.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-DvCamg_6.js → chunk-55IACEB6-Juw-7Z3i.js} +1 -1
- package/dist/assets/{chunk-EDXVE4YY-Dj4Q8RwR.js → chunk-EDXVE4YY-DVYP9tpB.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-_bgQuuJh.js → chunk-FMBD7UC4-VQ7VOXl3.js} +1 -1
- package/dist/assets/{chunk-OYMX7WX6-3to38LyN.js → chunk-OYMX7WX6-F8Rj4ZUZ.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-Zl26wKKz.js → chunk-QZHKN3VN-Dn7K3yi9.js} +1 -1
- package/dist/assets/{chunk-YZCP3GAM-RLYPrlh0.js → chunk-YZCP3GAM-UjO-KTsn.js} +1 -1
- package/dist/assets/classDiagram-6PBFFD2Q-DmSozxoO.js +1 -0
- package/dist/assets/classDiagram-v2-HSJHXN6E-DmSozxoO.js +1 -0
- package/dist/assets/clone-BQtvy9Ae.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-CsYOjJ0V.js → cose-bilkent-S5V4N54A-BDhNj8rq.js} +1 -1
- package/dist/assets/{dagre-KV5264BT-C3YXXaFU.js → dagre-KV5264BT-BzdcDuyt.js} +1 -1
- package/dist/assets/{diagram-5BDNPKRD-DUCOg1ld.js → diagram-5BDNPKRD-DP_SX65N.js} +1 -1
- package/dist/assets/{diagram-G4DWMVQ6-BtlLl_zX.js → diagram-G4DWMVQ6-B-pBFw8Q.js} +1 -1
- package/dist/assets/{diagram-MMDJMWI5-1Qp9xfOk.js → diagram-MMDJMWI5-6XSfN1eN.js} +1 -1
- package/dist/assets/{diagram-TYMM5635-Cj7VMp3L.js → diagram-TYMM5635-DJvGxvpE.js} +1 -1
- package/dist/assets/{erDiagram-SMLLAGMA-CVZVn541.js → erDiagram-SMLLAGMA-CpqdpGYj.js} +1 -1
- package/dist/assets/{flowDiagram-DWJPFMVM-CiU9Fkkv.js → flowDiagram-DWJPFMVM-C9m7wjwI.js} +1 -1
- package/dist/assets/{ganttDiagram-T4ZO3ILL-aRaG97ID.js → ganttDiagram-T4ZO3ILL-CU0XOfY3.js} +1 -1
- package/dist/assets/{gitGraphDiagram-UUTBAWPF-Cr2LJlvX.js → gitGraphDiagram-UUTBAWPF-ipyGULnP.js} +1 -1
- package/dist/assets/{graph-B59lDyMn.js → graph-BR2KmES9.js} +1 -1
- package/dist/assets/{index-C1ptnCpq.js → index--wgRW_OB.js} +1 -1
- package/dist/assets/index-B51Ci0GL.js +2 -0
- package/dist/assets/{index-CRAWA8PC.js → index-C-be29ey.js} +1 -1
- package/dist/assets/{index-CSM1Kw8l.js → index-C16fiVhv.js} +1 -1
- package/dist/assets/{index-Ddk-kg22.js → index-D5YruOKD.js} +1 -1
- package/dist/assets/{index-BnhNIjbj.js → index-D5tSeMU7.js} +1 -1
- package/dist/assets/{index-vFEQq-NB.js → index-DuZQ6FqR.js} +1 -1
- package/dist/assets/{index-CO2hZ1s4.js → index-OWzSX2T8.js} +1 -1
- package/dist/assets/{infoDiagram-42DDH7IO-CnO22bw8.js → infoDiagram-42DDH7IO-BQWQjfFX.js} +1 -1
- package/dist/assets/{ishikawaDiagram-UXIWVN3A-ByNzpScH.js → ishikawaDiagram-UXIWVN3A-Df-KH_Hz.js} +1 -1
- package/dist/assets/{journeyDiagram-VCZTEJTY-yaVaCWPq.js → journeyDiagram-VCZTEJTY-CMbB_4G9.js} +1 -1
- package/dist/assets/{jszip.min-BdVFP3OW.js → jszip.min-B6k2t9Ch.js} +1 -1
- package/dist/assets/{kanban-definition-6JOO6SKY-RIPR_RQ3.js → kanban-definition-6JOO6SKY-CImdlKN3.js} +1 -1
- package/dist/assets/{layout-0rzel0v_.js → layout-DQl4aw09.js} +1 -1
- package/dist/assets/{linear-sktN0tB6.js → linear-CLD3aPlK.js} +1 -1
- package/dist/assets/mermaid.core-CN35dvKJ.js +7 -0
- package/dist/assets/{min-rspGOkz_.js → min-_D86henJ.js} +1 -1
- package/dist/assets/{mindmap-definition-QFDTVHPH-BsVzZzTz.js → mindmap-definition-QFDTVHPH-2JVcu1nk.js} +1 -1
- package/dist/assets/{pieDiagram-DEJITSTG-CsoWsw4f.js → pieDiagram-DEJITSTG-Dik-m5u7.js} +1 -1
- package/dist/assets/{quadrantDiagram-34T5L4WZ-CTMKuCAI.js → quadrantDiagram-34T5L4WZ-Bm5l40Jq.js} +1 -1
- package/dist/assets/{requirementDiagram-MS252O5E-C67256te.js → requirementDiagram-MS252O5E-Ck9w5rTj.js} +1 -1
- package/dist/assets/{sankeyDiagram-XADWPNL6-X8Y7KnW0.js → sankeyDiagram-XADWPNL6-BbGVCFEf.js} +1 -1
- package/dist/assets/{seqResourceLoaders-B5Zy_CC_.css → seqResourceLoaders-DFrHmgnK.css} +1 -1
- package/dist/assets/seqResourceLoaders-DZJxMMaR.js +2 -0
- package/dist/assets/{sequenceDiagram-FGHM5R23-Cils0TAp.js → sequenceDiagram-FGHM5R23-vjvEdksk.js} +1 -1
- package/dist/assets/{stateDiagram-FHFEXIEX-DFnohvpG.js → stateDiagram-FHFEXIEX-DTqMoiB2.js} +1 -1
- package/dist/assets/{stateDiagram-v2-QKLJ7IA2-BTX_4o81.js → stateDiagram-v2-QKLJ7IA2-CNbAwnhu.js} +1 -1
- package/dist/assets/{timeline-definition-GMOUNBTQ-DrIYFrzZ.js → timeline-definition-GMOUNBTQ-Cw8O-52d.js} +1 -1
- package/dist/assets/{vendor-antd-D5HmSDSg.js → vendor-antd-DI7JL-mE.js} +1 -1
- package/dist/assets/{vendor-codemirror-C5yuj7ze.js → vendor-codemirror-B9c49dtM.js} +1 -1
- package/dist/assets/{vendor-mdxeditor-BcEooTvb.js → vendor-mdxeditor-B6cpBtIE.js} +2 -2
- package/dist/assets/{vendor-qrcode-d9LCn0-9.js → vendor-qrcode-Dn90-s-u.js} +1 -1
- package/dist/assets/{vendor-virtuoso-K9m4MN6a.js → vendor-virtuoso-CpdSKD_6.js} +1 -1
- package/dist/assets/{vennDiagram-DHZGUBPP-lRqBYTr9.js → vennDiagram-DHZGUBPP-DCuqymb7.js} +1 -1
- package/dist/assets/{wardley-RL74JXVD-e8YfxpOe.js → wardley-RL74JXVD-BJ20wJUU.js} +1 -1
- package/dist/assets/{wardleyDiagram-NUSXRM2D-Bxrg774h.js → wardleyDiagram-NUSXRM2D-Vz6US3qt.js} +1 -1
- package/dist/assets/{xychartDiagram-5P7HB3ND-DWhZqhq8.js → xychartDiagram-5P7HB3ND-CzkLKrmi.js} +1 -1
- package/dist/index.html +4 -4
- package/findcc.js +4 -3
- package/package.json +3 -1
- package/server/i18n.js +21 -141
- package/server/interceptor.js +211 -403
- package/server/lib/async-write-queue.js +12 -1
- package/server/lib/delta-reconstructor.js +3 -3
- package/server/lib/error-report.js +45 -0
- package/server/lib/im-log-watcher.js +68 -8
- package/server/lib/interceptor-core.js +19 -174
- package/server/lib/log-management.js +214 -247
- package/server/lib/log-stream.js +59 -108
- package/server/lib/log-watcher.js +62 -274
- package/server/lib/log-zip.js +148 -0
- package/server/lib/session-boundary.js +266 -0
- package/server/lib/session-pin-store.js +10 -19
- package/server/lib/stats-worker.js +138 -267
- package/server/lib/user-prompt-extract.js +250 -0
- package/server/lib/v2/adapter.js +1124 -0
- package/server/lib/v2/blob-store.js +44 -0
- package/server/lib/v2/conversation-store.js +217 -0
- package/server/lib/v2/convert-manager.js +79 -0
- package/server/lib/v2/convert-worker.js +42 -0
- package/server/lib/v2/convert.js +409 -0
- package/server/lib/v2/identity.js +204 -0
- package/server/lib/v2/journal.js +62 -0
- package/server/lib/v2/layout.js +167 -0
- package/server/lib/v2/live-feed.js +558 -0
- package/server/lib/v2/meta-rows.js +360 -0
- package/server/lib/v2/migrate-prompt.js +54 -0
- package/server/lib/v2/replay.js +191 -0
- package/server/lib/v2/session-select.js +222 -0
- package/server/lib/v2/singleflight.js +104 -0
- package/server/lib/v2/v2-writer.js +528 -0
- package/server/lib/v2/verify.js +233 -0
- package/server/lib/wire-compress.js +167 -0
- package/server/routes/events.js +120 -150
- package/server/routes/files-fs.js +4 -2
- package/server/routes/im.js +11 -2
- package/server/routes/logs.js +209 -164
- package/server/routes/preferences.js +0 -3
- package/server/routes/project-meta.js +2 -3
- package/server/routes/session-pin.js +7 -8
- package/server/routes/v2.js +60 -0
- package/server/routes/workspaces.js +50 -14
- package/server/server.js +70 -66
- package/server/workspace-registry.js +24 -4
- package/src/utils/apiUrl.js +26 -0
- package/src/utils/askFallback.js +21 -0
- package/src/utils/askOptionDesc.js +55 -0
- package/src/utils/askPortalMatcher.js +54 -0
- package/src/utils/autoApproveOptions.js +27 -0
- package/src/utils/avatarAnimationPostPass.js +49 -0
- package/src/utils/builtinPresets.js +18 -0
- package/src/utils/clearCheckpoint.js +7 -0
- package/src/utils/commandValidator.js +45 -0
- package/src/utils/contentFilter.js +620 -0
- package/src/utils/contextRaw.js +18 -0
- package/src/utils/contextSidebarNavigation.js +16 -0
- package/src/utils/contextTurns.js +117 -0
- package/src/utils/displayScaleHelper.js +47 -0
- package/src/utils/effectiveModel.js +13 -0
- package/src/utils/entry-slim.js +563 -0
- package/src/utils/entryCache.js +144 -0
- package/src/utils/errorReport.js +6 -0
- package/src/utils/fileExpandedPathsStorage.js +70 -0
- package/src/utils/fileIcons.jsx +36 -0
- package/src/utils/fileOpen.js +37 -0
- package/src/utils/formatters.js +48 -0
- package/src/utils/gitApi.js +50 -0
- package/src/utils/gitTreeBuilder.js +19 -0
- package/src/utils/helpers.js +846 -0
- package/src/utils/identityHeal.js +99 -0
- package/src/utils/imConnState.js +59 -0
- package/src/utils/imOrigin.js +24 -0
- package/src/utils/imTr.js +7 -0
- package/src/utils/imageCompress.js +83 -0
- package/src/utils/imageDownscale.js +28 -0
- package/src/utils/imageResize.js +112 -0
- package/src/utils/ingestPipeline.js +47 -0
- package/src/utils/lazyWithReload.js +53 -0
- package/src/utils/markdown.js +30 -0
- package/src/utils/markdownIncremental.js +39 -0
- package/src/utils/markdownProfiler.js +113 -0
- package/src/utils/mdExtensionDetect.js +64 -0
- package/src/utils/memoryLinkParser.js +44 -0
- package/src/utils/modalMask.js +15 -0
- package/src/utils/monotime.js +6 -0
- package/src/utils/pinnedMenu.js +55 -0
- package/src/utils/presetShortcuts.js +14 -0
- package/src/utils/projectAlias.js +135 -0
- package/src/utils/promptClassifier.js +112 -0
- package/src/utils/promptDetect.js +196 -0
- package/src/utils/promptNav.js +60 -0
- package/src/utils/ptyChunkBuilder.js +251 -0
- package/src/utils/quickMenuHoverIntent.js +35 -0
- package/src/utils/rateLimitParser.js +119 -0
- package/src/utils/readResultPool.js +106 -0
- package/src/utils/refreshCachedItemProp.js +30 -0
- package/src/utils/requestType.js +208 -0
- package/src/utils/resizeCalc.js +21 -0
- package/src/utils/resolveLocalized.js +17 -0
- package/src/utils/searchApi.js +47 -0
- package/src/utils/searchReplace.js +51 -0
- package/src/utils/seqResourceLoaders.js +79 -0
- package/src/utils/sessionManager.js +471 -0
- package/src/utils/sessionMerge.js +180 -0
- package/src/utils/skillModalController.js +111 -0
- package/src/utils/skillsParser.js +116 -0
- package/src/utils/slashCommandLabels.js +80 -0
- package/src/utils/splitDragCalc.js +73 -0
- package/src/utils/stickyBottomController.js +643 -0
- package/src/utils/svgSanitize.js +48 -0
- package/src/utils/systemTags.js +47 -0
- package/src/utils/tClaude.js +20 -0
- package/src/utils/teamModalBuilder.js +351 -0
- package/src/utils/teamSessionParser.js +190 -0
- package/src/utils/teammateAvatars.js +194 -0
- package/src/utils/teammateDetector.js +121 -0
- package/src/utils/termDiag.js +114 -0
- package/src/utils/terminalClipboard.js +117 -0
- package/src/utils/terminalWriteQueue.js +398 -0
- package/src/utils/thinkingMerge.js +49 -0
- package/src/utils/toolCatalog.js +29 -0
- package/src/utils/toolResultBuilder.js +393 -0
- package/src/utils/toolResultClassifier.js +16 -0
- package/src/utils/toolResultCore.js +167 -0
- package/src/utils/toolsDiff.js +44 -0
- package/src/utils/toolsXmlFormatter.js +3 -0
- package/src/utils/ultraplanController.js +109 -0
- package/src/utils/ultraplanExperts.js +86 -0
- package/src/utils/ultraplanTemplates.js +154 -0
- package/src/utils/userImageRefs.js +49 -0
- package/src/utils/v3Assembler.js +112 -0
- package/src/utils/v3Rows.js +48 -0
- package/src/utils/voicePackPlayer.js +233 -0
- package/src/utils/webSearchGrouping.js +111 -0
- package/src/utils/workflowFormat.js +52 -0
- package/src/utils/workflowRuns.js +118 -0
- package/src/utils/workflowStore.js +94 -0
- package/dist/assets/App-VTo4NVdo.js +0 -2
- package/dist/assets/Mobile-CcmYvMm_.js +0 -1
- package/dist/assets/classDiagram-6PBFFD2Q-BXnyUgsj.js +0 -1
- package/dist/assets/classDiagram-v2-HSJHXN6E-BXnyUgsj.js +0 -1
- package/dist/assets/clone-md-Mc1-T.js +0 -1
- package/dist/assets/index-DCo650PG.js +0 -2
- package/dist/assets/mermaid.core-C2Parj1q.js +0 -7
- package/dist/assets/seqResourceLoaders-BVozq68i.js +0 -2
- package/server/lib/instance-registry.js +0 -57
- package/server/lib/jsonl-archive.js +0 -180
- package/server/lib/teammate-detect.js +0 -32
- package/server/lib/zip-safety.js +0 -68
package/README.md
CHANGED
|
@@ -52,11 +52,23 @@ Once started in programming mode, the web page opens automatically.
|
|
|
52
52
|
|
|
53
53
|
cc-viewer also ships as a native desktop app: [download page](https://github.com/weiesky/cc-viewer/releases)
|
|
54
54
|
|
|
55
|
+
### Upgrading to 1.7.0 (log format v2)
|
|
56
|
+
|
|
57
|
+
Since 1.7.0, logs are stored in a per-session directory format (wire-format v2) instead of single `.jsonl` files — roughly 90% smaller on disk. Existing v1 `.jsonl` files are never modified or deleted; the log dialog lists v2 sessions by default, and a small “View legacy (v1) logs” entry (shown while old files exist) opens a v1 view where they can be viewed, migrated, or deleted. On startup, cc-viewer offers one-click migration when legacy logs are found (strongly recommended when continuing an old conversation with `claude -c`, whose first half lives in the old files). You can also migrate from the terminal:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
ccv convert <project> # migrate one project
|
|
61
|
+
ccv convert --all # migrate every project
|
|
62
|
+
ccv verify <v1-file> # check a v1 file against its converted sessions
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
A session that fails golden verification is held in `sessions-quarantine/` for inspection instead of failing the whole migration — the other sessions still migrate.
|
|
66
|
+
|
|
55
67
|
### Logger mode
|
|
56
68
|
|
|
57
69
|
If you still prefer the native claude tool or the VS Code extension, use this mode.
|
|
58
70
|
|
|
59
|
-
In this mode, launching `claude` will automatically start a logging process that records request logs to \~/.claude/cc-viewer/*yourproject*/
|
|
71
|
+
In this mode, launching `claude` will automatically start a logging process that records request logs to per-session directories under \~/.claude/cc-viewer/*yourproject*/sessions/ (wire-format v2)
|
|
60
72
|
|
|
61
73
|
Enable logger mode:
|
|
62
74
|
|
package/cli.js
CHANGED
|
@@ -222,6 +222,9 @@ function removeCliJsInjection() {
|
|
|
222
222
|
|
|
223
223
|
async function runProxyCommand(args) {
|
|
224
224
|
try {
|
|
225
|
+
// P2 detection channel ①(shell-hook 形态):`claude -c` 经 hook 变成
|
|
226
|
+
// `ccv run -- claude --ccv-internal -c …`,在 proxy/server 模块加载前打标。
|
|
227
|
+
markContinueEnv(args);
|
|
225
228
|
// Dynamic import to avoid side effects when just installing
|
|
226
229
|
const { startProxy } = await import('./server/proxy.js');
|
|
227
230
|
const proxyPort = await startProxy();
|
|
@@ -306,16 +309,41 @@ async function runProxyCommand(args) {
|
|
|
306
309
|
|
|
307
310
|
// ensureHooks() extracted to server/lib/ensure-hooks.js (shared with electron/tab-worker.js)
|
|
308
311
|
|
|
309
|
-
//
|
|
310
|
-
//
|
|
311
|
-
|
|
312
|
+
// P2 (-c migration guidance, detection channel ①): the interceptor resolves
|
|
313
|
+
// CCV_CLAUDE_CONTINUE at prompt time, so setting it before the server module
|
|
314
|
+
// loads is sufficient — claude's own -c semantics are untouched.
|
|
315
|
+
function markContinueEnv(claudeArgs) {
|
|
316
|
+
if (!Array.isArray(claudeArgs)) return;
|
|
317
|
+
if (claudeArgs.some((a) => a === '-c' || a === '--continue' || a === '-r' || a === '--resume')) {
|
|
318
|
+
process.env.CCV_CLAUDE_CONTINUE = '1';
|
|
319
|
+
}
|
|
320
|
+
// Explicit `-r`/`--resume` targets a session of the user's choosing, while
|
|
321
|
+
// folder adoption always targets the LATEST main session — so a resume must
|
|
322
|
+
// keep its pre-adoption behavior (own folder). The CONTINUE env above still
|
|
323
|
+
// marks the launch for the migrate prompt.
|
|
324
|
+
if (claudeArgs.some((a) => a === '-r' || a === '--resume')) {
|
|
325
|
+
process.env.CCV_CLAUDE_RESUME = '1';
|
|
326
|
+
}
|
|
327
|
+
// `--fork-session` continues/resumes but mints a NEW session id on purpose —
|
|
328
|
+
// the interceptor reads this before the server module loads so `-c` folder
|
|
329
|
+
// adoption is suppressed (claude's own semantics are untouched).
|
|
330
|
+
if (claudeArgs.includes('--fork-session')) {
|
|
331
|
+
process.env.CCV_CLAUDE_FORK_SESSION = '1';
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// 1.7.0: legacy v1 logs still present → one localized banner line pointing at
|
|
336
|
+
// `ccv convert` (headless users never see the web migrate prompt).
|
|
337
|
+
async function printMigrationBanner() {
|
|
312
338
|
try {
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
if (
|
|
339
|
+
const { LOG_DIR } = await import('./findcc.js');
|
|
340
|
+
const { listConvertibleProjects } = await import('./server/lib/v2/convert.js');
|
|
341
|
+
const { migrationStatus } = await import('./server/lib/v2/migrate-prompt.js');
|
|
342
|
+
const pending = listConvertibleProjects(LOG_DIR)
|
|
343
|
+
.filter((p) => migrationStatus(LOG_DIR, p).pending);
|
|
344
|
+
if (pending.length > 0) {
|
|
345
|
+
console.log(` ${t('cli.v1LogsFound', { count: pending.length })}`);
|
|
346
|
+
}
|
|
319
347
|
} catch { /* banner is best-effort */ }
|
|
320
348
|
}
|
|
321
349
|
|
|
@@ -440,7 +468,7 @@ async function runCliMode(extraClaudeArgs = [], cwd, noOpen = false) {
|
|
|
440
468
|
if (_auth.password === '') console.error(` ${t('server.passwordEmptyWarn')}`);
|
|
441
469
|
else console.log(` ${t('server.passwordActive', { password: _auth.password })}`);
|
|
442
470
|
}
|
|
443
|
-
|
|
471
|
+
await printMigrationBanner();
|
|
444
472
|
|
|
445
473
|
// 5. 注册退出处理(hardened:watchdog 5s 强退 + 连按 Ctrl+C 立退,
|
|
446
474
|
// 防 Windows 上 ConPTY kill / IM teardown 挂住导致"Ctrl+C 完全无反应")
|
|
@@ -623,7 +651,7 @@ async function runSdkMode(extraClaudeArgs = [], cwd, noOpen = false) {
|
|
|
623
651
|
if (_auth.password === '') console.error(` ${t('server.passwordEmptyWarn')}`);
|
|
624
652
|
else console.log(` ${t('server.passwordActive', { password: _auth.password })}`);
|
|
625
653
|
}
|
|
626
|
-
|
|
654
|
+
await printMigrationBanner();
|
|
627
655
|
|
|
628
656
|
// 注册退出处理(hardened,与 PTY 模式同款三层防御)
|
|
629
657
|
const cleanup = createHardenedCleanup({
|
|
@@ -649,9 +677,9 @@ const logDirIdx = args.indexOf('--log-dir');
|
|
|
649
677
|
if (logDirIdx !== -1) {
|
|
650
678
|
const logDirVal = args[logDirIdx + 1];
|
|
651
679
|
if (logDirVal && !logDirVal.startsWith('-')) {
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
if (
|
|
680
|
+
// setLogDir returns false only on a rejected path; comparing LOG_DIR
|
|
681
|
+
// before/after mis-rejected a --log-dir equal to the current default.
|
|
682
|
+
if (!setLogDir(logDirVal)) {
|
|
655
683
|
console.error(`Error: --log-dir path rejected (must be under home directory or /tmp/): ${logDirVal}`);
|
|
656
684
|
process.exit(1);
|
|
657
685
|
}
|
|
@@ -721,29 +749,6 @@ if (usePwdIdx !== -1) {
|
|
|
721
749
|
args.splice(usePwdIdx, 1);
|
|
722
750
|
}
|
|
723
751
|
|
|
724
|
-
// Extract --pid[=<name>] / --pid <name> — instance id for per-instance session-pin isolation.
|
|
725
|
-
// NB: "pid" here is an instance *id* LABEL (user-chosen, e.g. alpha/beta), NOT an OS process id —
|
|
726
|
-
// it only keys the session-pin file `.session-pin.<id>.json`; unrelated to process.pid.
|
|
727
|
-
// ccv-owned (NEVER forwarded to claude — an unknown --pid would otherwise crash claude): sets
|
|
728
|
-
// CCV_INSTANCE_ID and splices out. Sanitized to a filesystem-safe token (it becomes part of a
|
|
729
|
-
// `.session-pin.<id>.json` filename → guard against path traversal / invalid names).
|
|
730
|
-
const pidIdx = args.findIndex((a) => a === '--pid' || a.startsWith('--pid='));
|
|
731
|
-
if (pidIdx !== -1) {
|
|
732
|
-
const arg = args[pidIdx];
|
|
733
|
-
let rawVal;
|
|
734
|
-
if (arg.startsWith('--pid=')) {
|
|
735
|
-
rawVal = arg.slice('--pid='.length);
|
|
736
|
-
args.splice(pidIdx, 1);
|
|
737
|
-
} else {
|
|
738
|
-
rawVal = args[pidIdx + 1];
|
|
739
|
-
if (rawVal && !rawVal.startsWith('-')) args.splice(pidIdx, 2);
|
|
740
|
-
else { console.error(t('cli.pidInvalid')); process.exit(1); }
|
|
741
|
-
}
|
|
742
|
-
const sanitized = (rawVal || '').replace(/[^a-zA-Z0-9_\-.]/g, '_');
|
|
743
|
-
if (!sanitized) { console.error(t('cli.pidInvalid')); process.exit(1); }
|
|
744
|
-
process.env.CCV_INSTANCE_ID = sanitized;
|
|
745
|
-
}
|
|
746
|
-
|
|
747
752
|
// Extract --im <platformId> — 启动一个独立常驻 IM worker:工作目录 IM_<id>/、绑 127.0.0.1、
|
|
748
753
|
// skip-permissions、全局唯一锁。必须在动态 import 之前提取(runImMode 会在 import server.js 前设 env)。
|
|
749
754
|
let imPlatform = null;
|
|
@@ -917,12 +922,85 @@ if (imPlatform) {
|
|
|
917
922
|
console.error('IM mode error:', err);
|
|
918
923
|
process.exit(1);
|
|
919
924
|
});
|
|
925
|
+
} else if (args[0] === 'verify') {
|
|
926
|
+
// wire-v2 S4: dual-write consistency check (docs/refactor/WIRE_FORMAT_V2_PLAN.md S4)
|
|
927
|
+
// Usage: ccv verify <v1-log.jsonl> [more.jsonl ...] — compares each v1 file
|
|
928
|
+
// against its project's v2 session dirs; exit 0 = zero diffs.
|
|
929
|
+
(async () => {
|
|
930
|
+
const files = args.slice(1).filter(a => a.endsWith('.jsonl'));
|
|
931
|
+
if (files.length === 0) {
|
|
932
|
+
console.error('usage: ccv verify <v1-log.jsonl> [more.jsonl ...]');
|
|
933
|
+
process.exit(2);
|
|
934
|
+
}
|
|
935
|
+
const { verifyV1File, renderReport } = await import('./server/lib/v2/verify.js');
|
|
936
|
+
let allOk = true;
|
|
937
|
+
for (const f of files) {
|
|
938
|
+
const report = await verifyV1File(resolve(f));
|
|
939
|
+
console.log(renderReport(report));
|
|
940
|
+
if (!report.ok) allOk = false;
|
|
941
|
+
}
|
|
942
|
+
process.exit(allOk ? 0 : 1);
|
|
943
|
+
})().catch(err => {
|
|
944
|
+
console.error('verify error:', err);
|
|
945
|
+
process.exit(1);
|
|
946
|
+
});
|
|
947
|
+
} else if (args[0] === 'convert') {
|
|
948
|
+
// wire-v2 S8: offline v1→v2 migration (docs/refactor/WIRE_FORMAT_V2_PLAN.md S8)
|
|
949
|
+
// Usage: ccv convert <project> [more-projects ...] | ccv convert --all
|
|
950
|
+
// [--log-dir <dir>] — chronological per project, file-level resume,
|
|
951
|
+
// staging + golden verify + promote. Strictly additive: v1 files untouched.
|
|
952
|
+
(async () => {
|
|
953
|
+
const { convertProject, listConvertibleProjects, QUARANTINE_DIR_NAME } = await import('./server/lib/v2/convert.js');
|
|
954
|
+
const rest = args.slice(1);
|
|
955
|
+
const dirIdx = rest.indexOf('--log-dir');
|
|
956
|
+
let logDir = LOG_DIR;
|
|
957
|
+
if (dirIdx !== -1) {
|
|
958
|
+
logDir = resolve(rest[dirIdx + 1] || '');
|
|
959
|
+
rest.splice(dirIdx, 2);
|
|
960
|
+
}
|
|
961
|
+
const all = rest.includes('--all');
|
|
962
|
+
const projects = all ? listConvertibleProjects(logDir) : rest.filter(a => !a.startsWith('-'));
|
|
963
|
+
if (projects.length === 0) {
|
|
964
|
+
console.error('usage: ccv convert <project> [more-projects ...] | ccv convert --all [--log-dir <dir>]');
|
|
965
|
+
process.exit(2);
|
|
966
|
+
}
|
|
967
|
+
let allOk = true;
|
|
968
|
+
for (const project of projects) {
|
|
969
|
+
console.error(`converting ${project} (${logDir}) ...`);
|
|
970
|
+
try {
|
|
971
|
+
const state = await convertProject(logDir, project, {
|
|
972
|
+
onProgress: (p) => {
|
|
973
|
+
if (p.phase === 'done') return;
|
|
974
|
+
console.error(` [${p.phase}] ${p.file} (${p.fileIndex}/${p.filesTotal}) entries=${p.entries} sessions=${p.sessionsConverted} skipped=${p.sessionsSkipped}`);
|
|
975
|
+
},
|
|
976
|
+
});
|
|
977
|
+
const quarantined = state.sessionsQuarantined || 0;
|
|
978
|
+
console.error(` ${project}: ${state.status} — ${state.sessionsConverted} sessions converted, ${state.sessionsSkipped} skipped${quarantined ? `, ${quarantined} quarantined` : ''}, ${state.entries} entries`);
|
|
979
|
+
if (quarantined > 0) {
|
|
980
|
+
// Non-blocking: the good sessions promoted; only the flagged ones are held.
|
|
981
|
+
console.error(` WARNING: ${quarantined} session(s) failed golden verify and were held in ${QUARANTINE_DIR_NAME}/ (not promoted). Suspect sessions:`);
|
|
982
|
+
for (const q of state.quarantined || []) {
|
|
983
|
+
console.error(` - ${q.sessionId}${q.reasons && q.reasons.length ? ` (${q.reasons.slice(0, 5).join(', ')})` : ''}`);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
if (state.status !== 'done') allOk = false;
|
|
987
|
+
} catch (err) {
|
|
988
|
+
console.error(` ${project}: FAILED — ${err.message}`);
|
|
989
|
+
allOk = false;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
process.exit(allOk ? 0 : 1);
|
|
993
|
+
})().catch(err => {
|
|
994
|
+
console.error('convert error:', err);
|
|
995
|
+
process.exit(1);
|
|
996
|
+
});
|
|
920
997
|
} else if (args[0] === 'run') {
|
|
921
998
|
runProxyCommand(args);
|
|
922
999
|
} else if (args.includes('-SDK') || args.includes('--sdk')) {
|
|
923
1000
|
// SDK 模式(显式 -SDK 切换)
|
|
924
1001
|
const claudeArgs = args.filter(a => a !== '-SDK' && a !== '--sdk')
|
|
925
1002
|
.map(a => a === '--d' ? '--dangerously-skip-permissions' : a === '--ad' ? '--allow-dangerously-skip-permissions' : a);
|
|
1003
|
+
markContinueEnv(claudeArgs);
|
|
926
1004
|
runSdkMode(claudeArgs, process.cwd(), noOpen).catch(err => {
|
|
927
1005
|
console.error('SDK mode error:', err);
|
|
928
1006
|
process.exit(1);
|
|
@@ -930,6 +1008,7 @@ if (imPlatform) {
|
|
|
930
1008
|
} else {
|
|
931
1009
|
// PTY 模式(默认)
|
|
932
1010
|
const claudeArgs = args.map(a => a === '--d' ? '--dangerously-skip-permissions' : a === '--ad' ? '--allow-dangerously-skip-permissions' : a);
|
|
1011
|
+
markContinueEnv(claudeArgs);
|
|
933
1012
|
runCliMode(claudeArgs, process.cwd(), noOpen).catch(err => {
|
|
934
1013
|
console.error('CLI mode error:', err);
|
|
935
1014
|
process.exit(1);
|