@zzusp/ccsm 1.0.1 → 1.0.3

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.
Files changed (70) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +236 -236
  3. package/bin/cli.mjs +52 -52
  4. package/dist/assets/{DiskUsage-CKhggLs5.js → DiskUsage-BY6XwffG.js} +2 -2
  5. package/dist/assets/DiskUsage-BY6XwffG.js.map +1 -0
  6. package/dist/assets/{ImportPage-wge4VhZ-.js → ImportPage-Cwq5bx7G.js} +2 -2
  7. package/dist/assets/ImportPage-Cwq5bx7G.js.map +1 -0
  8. package/dist/assets/MarkdownContent-BFu7Nkk_.js +2 -0
  9. package/dist/assets/MarkdownContent-BFu7Nkk_.js.map +1 -0
  10. package/dist/assets/{ProjectMemory-Q4XX40j_.js → ProjectMemory-CcE3KbUK.js} +2 -2
  11. package/dist/assets/ProjectMemory-CcE3KbUK.js.map +1 -0
  12. package/dist/assets/index-CrWxV6sb.css +1 -0
  13. package/dist/assets/index-DTbWl1jb.js +11 -0
  14. package/dist/assets/index-DTbWl1jb.js.map +1 -0
  15. package/dist/assets/markdown-Bag5rX3T.js +30 -0
  16. package/dist/assets/markdown-Bag5rX3T.js.map +1 -0
  17. package/dist/index.html +26 -26
  18. package/package.json +81 -83
  19. package/server/index.ts +130 -130
  20. package/server/lib/active-sessions.test.ts +119 -119
  21. package/server/lib/active-sessions.ts +95 -95
  22. package/server/lib/bundle.test.ts +182 -182
  23. package/server/lib/bundle.ts +86 -86
  24. package/server/lib/claude-paths.test.ts +126 -126
  25. package/server/lib/claude-paths.ts +43 -43
  26. package/server/lib/cleanup-suggestions.ts +131 -131
  27. package/server/lib/constants.ts +8 -8
  28. package/server/lib/delete-project.ts +100 -100
  29. package/server/lib/delete.test.ts +244 -244
  30. package/server/lib/delete.ts +192 -192
  31. package/server/lib/disk-usage.ts +81 -81
  32. package/server/lib/encode-cwd.ts +24 -24
  33. package/server/lib/export-bundle.ts +236 -236
  34. package/server/lib/export-import-bundle.test.ts +337 -337
  35. package/server/lib/fs-size.ts +38 -38
  36. package/server/lib/import-bundle.ts +488 -488
  37. package/server/lib/load-memory.ts +120 -120
  38. package/server/lib/load-session.ts +209 -209
  39. package/server/lib/modified-files.test.ts +280 -280
  40. package/server/lib/modified-files.ts +228 -228
  41. package/server/lib/open-folder.ts +47 -47
  42. package/server/lib/parse-jsonl.ts +160 -139
  43. package/server/lib/port.ts +23 -23
  44. package/server/lib/safe-id.test.ts +41 -41
  45. package/server/lib/safe-id.ts +6 -6
  46. package/server/lib/safe-remove.test.ts +73 -73
  47. package/server/lib/safe-remove.ts +25 -25
  48. package/server/lib/scan.ts +289 -286
  49. package/server/lib/search-all.ts +130 -130
  50. package/server/lib/search-session.ts +203 -203
  51. package/server/lib/system-tags.ts +20 -20
  52. package/server/lib/update.ts +67 -67
  53. package/server/lib/version.test.ts +39 -39
  54. package/server/lib/version.ts +117 -117
  55. package/server/routes/disk-cleanup.ts +54 -54
  56. package/server/routes/disk.ts +9 -9
  57. package/server/routes/import.ts +87 -87
  58. package/server/routes/projects.ts +104 -104
  59. package/server/routes/search.ts +79 -79
  60. package/server/routes/sessions.ts +130 -130
  61. package/server/routes/version.ts +34 -34
  62. package/server/types.ts +1 -1
  63. package/shared/constants.ts +7 -7
  64. package/shared/types.ts +513 -511
  65. package/dist/assets/DiskUsage-CKhggLs5.js.map +0 -1
  66. package/dist/assets/ImportPage-wge4VhZ-.js.map +0 -1
  67. package/dist/assets/ProjectMemory-Q4XX40j_.js.map +0 -1
  68. package/dist/assets/index-7aMrnHJG.js +0 -7
  69. package/dist/assets/index-7aMrnHJG.js.map +0 -1
  70. package/dist/assets/index-BOeI_J4B.css +0 -1
@@ -1,100 +1,100 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { buildActiveSessionMap } from './active-sessions.ts';
4
- import { isUnderClaudeRoot, PATHS } from './claude-paths.ts';
5
- import { RECENT_ACTIVITY_WINDOW_MS } from './constants.ts';
6
- import { deleteSessions } from './delete.ts';
7
- import { isSafeId } from './safe-id.ts';
8
- import type { DeleteProjectResult, SkippedItem } from '../types.ts';
9
-
10
- const JSONL_EXT = '.jsonl';
11
-
12
- export async function deleteProject(projectId: string): Promise<DeleteProjectResult> {
13
- if (!isSafeId(projectId)) {
14
- return {
15
- deleted: [],
16
- skipped: [{ projectId, sessionId: '', reason: 'invalid project id' }],
17
- historyLinesRemoved: 0,
18
- projectDirRemoved: false,
19
- };
20
- }
21
-
22
- const projectDir = path.join(PATHS.projects, projectId);
23
- if (!isUnderClaudeRoot(projectDir)) {
24
- return {
25
- deleted: [],
26
- skipped: [{ projectId, sessionId: '', reason: 'path escapes ~/.claude' }],
27
- historyLinesRemoved: 0,
28
- projectDirRemoved: false,
29
- };
30
- }
31
- if (!fs.existsSync(projectDir)) {
32
- return {
33
- deleted: [],
34
- skipped: [{ projectId, sessionId: '', reason: 'project directory does not exist' }],
35
- historyLinesRemoved: 0,
36
- projectDirRemoved: false,
37
- };
38
- }
39
-
40
- const sessionIds: string[] = [];
41
- for (const ent of fs.readdirSync(projectDir, { withFileTypes: true })) {
42
- if (ent.isFile() && ent.name.endsWith(JSONL_EXT)) {
43
- sessionIds.push(ent.name.slice(0, -JSONL_EXT.length));
44
- }
45
- }
46
-
47
- // All-or-nothing precheck: refuse to touch any session if even one is live or
48
- // recently active. Confirmed by the user — partial deletes leave the project
49
- // half-cleared, which is more confusing than a clean "try again later".
50
- const liveMap = buildActiveSessionMap();
51
- const blockers: SkippedItem[] = [];
52
- for (const sid of sessionIds) {
53
- if (liveMap.has(sid)) {
54
- blockers.push({
55
- projectId,
56
- sessionId: sid,
57
- reason: `live PID ${liveMap.get(sid)} owns this session`,
58
- });
59
- continue;
60
- }
61
- const jsonlPath = path.join(projectDir, `${sid}${JSONL_EXT}`);
62
- try {
63
- if (Date.now() - fs.statSync(jsonlPath).mtimeMs < RECENT_ACTIVITY_WINDOW_MS) {
64
- blockers.push({
65
- projectId,
66
- sessionId: sid,
67
- reason: 'jsonl modified within the last 5 minutes — could still be in use',
68
- });
69
- }
70
- } catch {
71
- /* missing file is fine — deleteSessions will skip it */
72
- }
73
- }
74
-
75
- if (blockers.length > 0) {
76
- return {
77
- deleted: [],
78
- skipped: blockers,
79
- historyLinesRemoved: 0,
80
- projectDirRemoved: false,
81
- };
82
- }
83
-
84
- const result = await deleteSessions(
85
- sessionIds.map((sessionId) => ({ projectId, sessionId })),
86
- );
87
-
88
- let projectDirRemoved = false;
89
- if (result.skipped.length === 0) {
90
- try {
91
- // Recursive remove also catches any orphan subdirs whose .jsonl was missing.
92
- fs.rmSync(projectDir, { recursive: true, force: true });
93
- projectDirRemoved = true;
94
- } catch {
95
- /* leave dir for manual cleanup */
96
- }
97
- }
98
-
99
- return { ...result, projectDirRemoved };
100
- }
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { buildActiveSessionMap } from './active-sessions.ts';
4
+ import { isUnderClaudeRoot, PATHS } from './claude-paths.ts';
5
+ import { RECENT_ACTIVITY_WINDOW_MS } from './constants.ts';
6
+ import { deleteSessions } from './delete.ts';
7
+ import { isSafeId } from './safe-id.ts';
8
+ import type { DeleteProjectResult, SkippedItem } from '../types.ts';
9
+
10
+ const JSONL_EXT = '.jsonl';
11
+
12
+ export async function deleteProject(projectId: string): Promise<DeleteProjectResult> {
13
+ if (!isSafeId(projectId)) {
14
+ return {
15
+ deleted: [],
16
+ skipped: [{ projectId, sessionId: '', reason: 'invalid project id' }],
17
+ historyLinesRemoved: 0,
18
+ projectDirRemoved: false,
19
+ };
20
+ }
21
+
22
+ const projectDir = path.join(PATHS.projects, projectId);
23
+ if (!isUnderClaudeRoot(projectDir)) {
24
+ return {
25
+ deleted: [],
26
+ skipped: [{ projectId, sessionId: '', reason: 'path escapes ~/.claude' }],
27
+ historyLinesRemoved: 0,
28
+ projectDirRemoved: false,
29
+ };
30
+ }
31
+ if (!fs.existsSync(projectDir)) {
32
+ return {
33
+ deleted: [],
34
+ skipped: [{ projectId, sessionId: '', reason: 'project directory does not exist' }],
35
+ historyLinesRemoved: 0,
36
+ projectDirRemoved: false,
37
+ };
38
+ }
39
+
40
+ const sessionIds: string[] = [];
41
+ for (const ent of fs.readdirSync(projectDir, { withFileTypes: true })) {
42
+ if (ent.isFile() && ent.name.endsWith(JSONL_EXT)) {
43
+ sessionIds.push(ent.name.slice(0, -JSONL_EXT.length));
44
+ }
45
+ }
46
+
47
+ // All-or-nothing precheck: refuse to touch any session if even one is live or
48
+ // recently active. Confirmed by the user — partial deletes leave the project
49
+ // half-cleared, which is more confusing than a clean "try again later".
50
+ const liveMap = buildActiveSessionMap();
51
+ const blockers: SkippedItem[] = [];
52
+ for (const sid of sessionIds) {
53
+ if (liveMap.has(sid)) {
54
+ blockers.push({
55
+ projectId,
56
+ sessionId: sid,
57
+ reason: `live PID ${liveMap.get(sid)} owns this session`,
58
+ });
59
+ continue;
60
+ }
61
+ const jsonlPath = path.join(projectDir, `${sid}${JSONL_EXT}`);
62
+ try {
63
+ if (Date.now() - fs.statSync(jsonlPath).mtimeMs < RECENT_ACTIVITY_WINDOW_MS) {
64
+ blockers.push({
65
+ projectId,
66
+ sessionId: sid,
67
+ reason: 'jsonl modified within the last 5 minutes — could still be in use',
68
+ });
69
+ }
70
+ } catch {
71
+ /* missing file is fine — deleteSessions will skip it */
72
+ }
73
+ }
74
+
75
+ if (blockers.length > 0) {
76
+ return {
77
+ deleted: [],
78
+ skipped: blockers,
79
+ historyLinesRemoved: 0,
80
+ projectDirRemoved: false,
81
+ };
82
+ }
83
+
84
+ const result = await deleteSessions(
85
+ sessionIds.map((sessionId) => ({ projectId, sessionId })),
86
+ );
87
+
88
+ let projectDirRemoved = false;
89
+ if (result.skipped.length === 0) {
90
+ try {
91
+ // Recursive remove also catches any orphan subdirs whose .jsonl was missing.
92
+ fs.rmSync(projectDir, { recursive: true, force: true });
93
+ projectDirRemoved = true;
94
+ } catch {
95
+ /* leave dir for manual cleanup */
96
+ }
97
+ }
98
+
99
+ return { ...result, projectDirRemoved };
100
+ }