@epiccontext/mcp 0.1.55 → 0.1.57

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 (101) hide show
  1. package/dist/api/client.d.ts +27 -1
  2. package/dist/api/client.d.ts.map +1 -1
  3. package/dist/api/client.js +102 -0
  4. package/dist/api/client.js.map +1 -1
  5. package/dist/cli/commands/add-app.d.ts +9 -0
  6. package/dist/cli/commands/add-app.d.ts.map +1 -0
  7. package/dist/cli/commands/add-app.js +111 -0
  8. package/dist/cli/commands/add-app.js.map +1 -0
  9. package/dist/cli/commands/init.d.ts.map +1 -1
  10. package/dist/cli/commands/init.js +37 -16
  11. package/dist/cli/commands/init.js.map +1 -1
  12. package/dist/cli/commands/pull.d.ts +2 -0
  13. package/dist/cli/commands/pull.d.ts.map +1 -1
  14. package/dist/cli/commands/pull.js +122 -67
  15. package/dist/cli/commands/pull.js.map +1 -1
  16. package/dist/cli/commands/push.d.ts +2 -0
  17. package/dist/cli/commands/push.d.ts.map +1 -1
  18. package/dist/cli/commands/push.js +130 -75
  19. package/dist/cli/commands/push.js.map +1 -1
  20. package/dist/cli/commands/serve.d.ts.map +1 -1
  21. package/dist/cli/commands/serve.js +2 -1
  22. package/dist/cli/commands/serve.js.map +1 -1
  23. package/dist/cli/commands/status.d.ts.map +1 -1
  24. package/dist/cli/commands/status.js +21 -3
  25. package/dist/cli/commands/status.js.map +1 -1
  26. package/dist/cli/commands/validate.d.ts.map +1 -1
  27. package/dist/cli/commands/validate.js +6 -5
  28. package/dist/cli/commands/validate.js.map +1 -1
  29. package/dist/cli/config.d.ts +4 -0
  30. package/dist/cli/config.d.ts.map +1 -1
  31. package/dist/cli/config.js +20 -0
  32. package/dist/cli/config.js.map +1 -1
  33. package/dist/cli/files.d.ts +9 -1
  34. package/dist/cli/files.d.ts.map +1 -1
  35. package/dist/cli/files.js +147 -31
  36. package/dist/cli/files.js.map +1 -1
  37. package/dist/cli/index.d.ts.map +1 -1
  38. package/dist/cli/index.js +12 -0
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/mcp/server.d.ts +1 -0
  41. package/dist/mcp/server.d.ts.map +1 -1
  42. package/dist/mcp/server.js +12 -0
  43. package/dist/mcp/server.js.map +1 -1
  44. package/dist/mcp/tools/list-documents.d.ts +10 -0
  45. package/dist/mcp/tools/list-documents.d.ts.map +1 -0
  46. package/dist/mcp/tools/list-documents.js +86 -0
  47. package/dist/mcp/tools/list-documents.js.map +1 -0
  48. package/dist/mcp/tools/read-document.d.ts +10 -0
  49. package/dist/mcp/tools/read-document.d.ts.map +1 -0
  50. package/dist/mcp/tools/read-document.js +119 -0
  51. package/dist/mcp/tools/read-document.js.map +1 -0
  52. package/dist/mcp/tools/sync-all.d.ts.map +1 -1
  53. package/dist/mcp/tools/sync-all.js +9 -0
  54. package/dist/mcp/tools/sync-all.js.map +1 -1
  55. package/dist/mcp/tools/sync-documents.d.ts +10 -0
  56. package/dist/mcp/tools/sync-documents.d.ts.map +1 -0
  57. package/dist/mcp/tools/sync-documents.js +89 -0
  58. package/dist/mcp/tools/sync-documents.js.map +1 -0
  59. package/dist/mcp/tools/sync-from-app.d.ts.map +1 -1
  60. package/dist/mcp/tools/sync-from-app.js +6 -0
  61. package/dist/mcp/tools/sync-from-app.js.map +1 -1
  62. package/dist/mcp/tools/sync-to-app.d.ts.map +1 -1
  63. package/dist/mcp/tools/sync-to-app.js +6 -0
  64. package/dist/mcp/tools/sync-to-app.js.map +1 -1
  65. package/dist/skills/generator.d.ts.map +1 -1
  66. package/dist/skills/generator.js +98 -5
  67. package/dist/skills/generator.js.map +1 -1
  68. package/dist/sync/deletions.d.ts +31 -0
  69. package/dist/sync/deletions.d.ts.map +1 -0
  70. package/dist/sync/deletions.js +110 -0
  71. package/dist/sync/deletions.js.map +1 -0
  72. package/dist/sync/document-files.d.ts +31 -0
  73. package/dist/sync/document-files.d.ts.map +1 -0
  74. package/dist/sync/document-files.js +98 -0
  75. package/dist/sync/document-files.js.map +1 -0
  76. package/dist/sync/document-manifest.d.ts +22 -0
  77. package/dist/sync/document-manifest.d.ts.map +1 -0
  78. package/dist/sync/document-manifest.js +55 -0
  79. package/dist/sync/document-manifest.js.map +1 -0
  80. package/dist/sync/document-pull.d.ts +16 -0
  81. package/dist/sync/document-pull.d.ts.map +1 -0
  82. package/dist/sync/document-pull.js +149 -0
  83. package/dist/sync/document-pull.js.map +1 -0
  84. package/dist/sync/document-push.d.ts +14 -0
  85. package/dist/sync/document-push.d.ts.map +1 -0
  86. package/dist/sync/document-push.js +107 -0
  87. package/dist/sync/document-push.js.map +1 -0
  88. package/dist/sync/pull.d.ts +4 -0
  89. package/dist/sync/pull.d.ts.map +1 -1
  90. package/dist/sync/pull.js +91 -0
  91. package/dist/sync/pull.js.map +1 -1
  92. package/dist/sync/push.d.ts +4 -0
  93. package/dist/sync/push.d.ts.map +1 -1
  94. package/dist/sync/push.js +44 -1
  95. package/dist/sync/push.js.map +1 -1
  96. package/dist/sync/watcher.d.ts.map +1 -1
  97. package/dist/sync/watcher.js +25 -5
  98. package/dist/sync/watcher.js.map +1 -1
  99. package/dist/types/index.d.ts +127 -0
  100. package/dist/types/index.d.ts.map +1 -1
  101. package/package.json +1 -1
@@ -0,0 +1,149 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { readDocumentManifest, writeDocumentManifest } from "./document-manifest.js";
4
+ import { ensureDocumentsFolderExists, computeLocalPath } from "./document-files.js";
5
+ /**
6
+ * Pull documents from the cloud to the local DOCUMENTS folder.
7
+ * Only downloads new or updated files (delta sync based on timestamps).
8
+ */
9
+ export async function pullDocuments(client, documentsPath, options = {}) {
10
+ ensureDocumentsFolderExists(documentsPath);
11
+ const result = {
12
+ downloaded: 0,
13
+ uploaded: 0,
14
+ skipped: 0,
15
+ deleted: 0,
16
+ errors: [],
17
+ };
18
+ // 1. Get cloud documents
19
+ const cloudData = await client.listDocuments();
20
+ const manifest = readDocumentManifest(documentsPath);
21
+ const manifestMap = new Map(manifest.entries.map((e) => [e.id, e]));
22
+ // 2. Process each cloud document
23
+ for (const cloudDoc of cloudData.documents) {
24
+ const localPath = computeLocalPath(cloudDoc.folderPath || null, cloudDoc.fileName);
25
+ const absolutePath = path.join(documentsPath, localPath);
26
+ // Check max file size
27
+ if (options.maxFileSize && cloudDoc.fileSize > options.maxFileSize) {
28
+ result.skipped++;
29
+ continue;
30
+ }
31
+ const existingEntry = manifestMap.get(cloudDoc.id);
32
+ let needsDownload = false;
33
+ if (!existingEntry) {
34
+ // New document — not in manifest
35
+ needsDownload = true;
36
+ }
37
+ else if (!fs.existsSync(absolutePath)) {
38
+ // In manifest but missing locally — re-download
39
+ needsDownload = true;
40
+ }
41
+ else if (cloudDoc.updatedAt > (existingEntry.cloudUpdatedAt || "")) {
42
+ // Cloud version is newer
43
+ if (options.force) {
44
+ needsDownload = true;
45
+ }
46
+ else {
47
+ // Check if local is also newer (conflict)
48
+ const localMtime = getFileMtime(absolutePath);
49
+ if (localMtime &&
50
+ existingEntry.localUpdatedAt &&
51
+ localMtime > existingEntry.localUpdatedAt) {
52
+ // Both modified — skip unless forced
53
+ result.skipped++;
54
+ continue;
55
+ }
56
+ needsDownload = true;
57
+ }
58
+ }
59
+ else {
60
+ // Already in sync
61
+ result.skipped++;
62
+ continue;
63
+ }
64
+ if (options.dryRun) {
65
+ result.downloaded++;
66
+ continue;
67
+ }
68
+ // Download the file
69
+ try {
70
+ const { data } = await client.downloadDocument(cloudDoc.id);
71
+ // Ensure directory exists
72
+ const dir = path.dirname(absolutePath);
73
+ if (!fs.existsSync(dir)) {
74
+ fs.mkdirSync(dir, { recursive: true });
75
+ }
76
+ // Write atomically: temp file → rename
77
+ const tempPath = absolutePath + ".tmp";
78
+ fs.writeFileSync(tempPath, Buffer.from(data));
79
+ fs.renameSync(tempPath, absolutePath);
80
+ // Update manifest entry
81
+ const entry = {
82
+ id: cloudDoc.id,
83
+ name: cloudDoc.name,
84
+ fileName: cloudDoc.fileName,
85
+ localPath,
86
+ cloudUrl: cloudDoc.fileUrl,
87
+ storagePath: cloudDoc.storagePath,
88
+ mimeType: cloudDoc.mimeType,
89
+ fileSize: cloudDoc.fileSize,
90
+ cloudUpdatedAt: cloudDoc.updatedAt,
91
+ localUpdatedAt: new Date().toISOString(),
92
+ syncStatus: "synced",
93
+ folderId: cloudDoc.folderId,
94
+ folderPath: cloudDoc.folderPath || null,
95
+ };
96
+ // Update in-memory manifest
97
+ const idx = manifest.entries.findIndex((e) => e.id === cloudDoc.id);
98
+ if (idx >= 0) {
99
+ manifest.entries[idx] = entry;
100
+ }
101
+ else {
102
+ manifest.entries.push(entry);
103
+ }
104
+ result.downloaded++;
105
+ }
106
+ catch (error) {
107
+ result.errors.push({
108
+ path: localPath,
109
+ error: error instanceof Error ? error.message : "Download failed",
110
+ });
111
+ }
112
+ }
113
+ // 3. Check for deleted cloud documents (in manifest but not in cloud)
114
+ const cloudIds = new Set(cloudData.documents.map((d) => d.id));
115
+ for (const entry of [...manifest.entries]) {
116
+ if (!cloudIds.has(entry.id)) {
117
+ entry.syncStatus = "deleted_cloud";
118
+ // Optionally remove local file
119
+ const absolutePath = path.join(documentsPath, entry.localPath);
120
+ if (fs.existsSync(absolutePath) && !options.dryRun) {
121
+ try {
122
+ fs.unlinkSync(absolutePath);
123
+ result.deleted++;
124
+ }
125
+ catch {
126
+ // Leave file but mark in manifest
127
+ }
128
+ }
129
+ // Remove from manifest
130
+ manifest.entries = manifest.entries.filter((e) => e.id !== entry.id);
131
+ }
132
+ }
133
+ // 4. Save manifest
134
+ if (!options.dryRun) {
135
+ manifest.lastSyncAt = new Date().toISOString();
136
+ writeDocumentManifest(documentsPath, manifest);
137
+ }
138
+ return result;
139
+ }
140
+ function getFileMtime(filePath) {
141
+ try {
142
+ const stats = fs.statSync(filePath);
143
+ return stats.mtime.toISOString();
144
+ }
145
+ catch {
146
+ return null;
147
+ }
148
+ }
149
+ //# sourceMappingURL=document-pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-pull.js","sourceRoot":"","sources":["../../src/sync/document-pull.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { EpicContextClient } from "../api/client.js";
2
+ import type { DocumentSyncResult } from "../types/index.js";
3
+ export interface DocumentPushOptions {
4
+ /** Preview changes without uploading */
5
+ dryRun?: boolean;
6
+ /** Push only a specific file or folder path */
7
+ path?: string;
8
+ }
9
+ /**
10
+ * Push local documents to the cloud.
11
+ * Only uploads new or modified files (delta sync based on timestamps).
12
+ */
13
+ export declare function pushDocuments(client: EpicContextClient, documentsPath: string, options?: DocumentPushOptions): Promise<DocumentSyncResult>;
14
+ //# sourceMappingURL=document-push.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-push.d.ts","sourceRoot":"","sources":["../../src/sync/document-push.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAEV,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAY3B,MAAM,WAAW,mBAAmB;IAClC,wCAAwC;IACxC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CAoH7B"}
@@ -0,0 +1,107 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { readDocumentManifest, writeDocumentManifest, findEntryByLocalPath, } from "./document-manifest.js";
4
+ import { scanDocumentsFolder, ensureDocumentsFolderExists, getMimeType, } from "./document-files.js";
5
+ /**
6
+ * Push local documents to the cloud.
7
+ * Only uploads new or modified files (delta sync based on timestamps).
8
+ */
9
+ export async function pushDocuments(client, documentsPath, options = {}) {
10
+ ensureDocumentsFolderExists(documentsPath);
11
+ const result = {
12
+ downloaded: 0,
13
+ uploaded: 0,
14
+ skipped: 0,
15
+ deleted: 0,
16
+ errors: [],
17
+ };
18
+ // 1. Scan local files
19
+ let localFiles = scanDocumentsFolder(documentsPath);
20
+ // Filter by path if specified
21
+ if (options.path) {
22
+ const filterPath = options.path.replace(/^\.\//, "");
23
+ localFiles = localFiles.filter((f) => f.relativePath === filterPath ||
24
+ f.relativePath.startsWith(filterPath + "/"));
25
+ }
26
+ // 2. Read manifest
27
+ const manifest = readDocumentManifest(documentsPath);
28
+ // 3. Process each local file
29
+ for (const file of localFiles) {
30
+ const existingEntry = findEntryByLocalPath(manifest, file.relativePath);
31
+ let needsUpload = false;
32
+ if (!existingEntry) {
33
+ // New local file — not in manifest
34
+ needsUpload = true;
35
+ }
36
+ else {
37
+ // Check if local file was modified since last sync
38
+ const localMtime = file.mtime.toISOString();
39
+ if (existingEntry.localUpdatedAt &&
40
+ localMtime > existingEntry.localUpdatedAt) {
41
+ needsUpload = true;
42
+ }
43
+ else {
44
+ result.skipped++;
45
+ continue;
46
+ }
47
+ }
48
+ if (options.dryRun) {
49
+ result.uploaded++;
50
+ continue;
51
+ }
52
+ // Upload the file
53
+ try {
54
+ const fileBuffer = fs.readFileSync(file.absolutePath);
55
+ const mimeType = getMimeType(file.relativePath);
56
+ // Compute folder path from relative path (everything before the filename)
57
+ const folderPath = path.dirname(file.relativePath);
58
+ const fileName = path.basename(file.relativePath);
59
+ const response = await client.uploadDocument(Buffer.from(fileBuffer), {
60
+ fileName,
61
+ mimeType,
62
+ folderPath: folderPath !== "." ? folderPath : undefined,
63
+ name: fileName.replace(/\.[^.]+$/, ""),
64
+ });
65
+ // Extract document info from response
66
+ const doc = response.document;
67
+ // Update manifest entry
68
+ const entry = {
69
+ id: doc?.id || existingEntry?.id || "",
70
+ name: doc?.name || fileName.replace(/\.[^.]+$/, ""),
71
+ fileName,
72
+ localPath: file.relativePath,
73
+ cloudUrl: doc?.file_url || existingEntry?.cloudUrl || "",
74
+ storagePath: doc?.storage_path || existingEntry?.storagePath || "",
75
+ mimeType,
76
+ fileSize: file.size,
77
+ cloudUpdatedAt: doc?.updated_at || new Date().toISOString(),
78
+ localUpdatedAt: file.mtime.toISOString(),
79
+ syncStatus: "synced",
80
+ folderId: doc?.folder_id || null,
81
+ folderPath: folderPath !== "." ? folderPath : null,
82
+ };
83
+ // Update in-memory manifest
84
+ const idx = manifest.entries.findIndex((e) => e.localPath === file.relativePath);
85
+ if (idx >= 0) {
86
+ manifest.entries[idx] = entry;
87
+ }
88
+ else {
89
+ manifest.entries.push(entry);
90
+ }
91
+ result.uploaded++;
92
+ }
93
+ catch (error) {
94
+ result.errors.push({
95
+ path: file.relativePath,
96
+ error: error instanceof Error ? error.message : "Upload failed",
97
+ });
98
+ }
99
+ }
100
+ // 4. Save manifest
101
+ if (!options.dryRun) {
102
+ manifest.lastSyncAt = new Date().toISOString();
103
+ writeDocumentManifest(documentsPath, manifest);
104
+ }
105
+ return result;
106
+ }
107
+ //# sourceMappingURL=document-push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-push.js","sourceRoot":"","sources":["../../src/sync/document-push.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,10 @@ export interface PullResult {
12
12
  skippedPaths: string[];
13
13
  deletedPaths: string[];
14
14
  totalFiles: number;
15
+ /** Number of local files deleted via deletion manifest */
16
+ filesDeletedByManifest?: number;
17
+ /** Paths of files deleted via manifest */
18
+ deletedByManifestPaths?: string[];
15
19
  }
16
20
  /**
17
21
  * Pull from cloud to local CONTEXT folder
@@ -1 +1 @@
1
- {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/sync/pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,iBAAiB,EACzB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAqErB"}
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/sync/pull.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAWrD,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,0CAA0C;IAC1C,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,iBAAiB,EACzB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAwHrB"}
package/dist/sync/pull.js CHANGED
@@ -1,4 +1,7 @@
1
+ import fs from "fs";
2
+ import path from "path";
1
3
  import { writeContextFolder, ensureContextFolder, deleteOrphanedLocalFiles } from "../cli/files.js";
4
+ import { readDeletionManifest, writeDeletionManifest, mergeDeletionManifests, pruneOldDeletions, } from "./deletions.js";
2
5
  /**
3
6
  * Pull from cloud to local CONTEXT folder
4
7
  * By default, skips files where local version is newer than cloud version
@@ -51,6 +54,48 @@ export async function pullFromCloud(client, contextPath, options = {}) {
51
54
  }
52
55
  }
53
56
  }
57
+ // Process deletion manifest: merge cloud deletions with local manifest,
58
+ // then delete matching local files
59
+ let filesDeletedByManifest = 0;
60
+ const deletedByManifestPaths = [];
61
+ const cloudDeletions = response.deletions || [];
62
+ if (cloudDeletions.length > 0 || readDeletionManifest(contextPath).deletions.length > 0) {
63
+ const localManifest = readDeletionManifest(contextPath);
64
+ const cloudManifest = {
65
+ version: 1,
66
+ deletions: cloudDeletions,
67
+ };
68
+ // Merge cloud deletions into local manifest
69
+ let merged = mergeDeletionManifests(localManifest, cloudManifest);
70
+ // Handle restorations: if a block key appears in files[] AND in the manifest,
71
+ // the block was restored — remove it from the manifest
72
+ const activeFileKeys = new Set();
73
+ for (const file of response.files) {
74
+ // Extract key from file path (last segment without .md)
75
+ const fileName = file.path.split("/").pop();
76
+ if (fileName && fileName.endsWith(".md") && fileName.toLowerCase() !== "readme.md") {
77
+ activeFileKeys.add(fileName.replace(/\.md$/, ""));
78
+ }
79
+ }
80
+ const restoredEntries = merged.deletions.filter((d) => activeFileKeys.has(d.key));
81
+ if (restoredEntries.length > 0) {
82
+ merged = {
83
+ version: 1,
84
+ deletions: merged.deletions.filter((d) => !activeFileKeys.has(d.key)),
85
+ };
86
+ }
87
+ // Delete local files matching deletion entries
88
+ for (const deletion of merged.deletions) {
89
+ const deleted = deleteLocalFileForBlock(contextPath, deletion.key, deletion.section);
90
+ if (deleted) {
91
+ filesDeletedByManifest++;
92
+ deletedByManifestPaths.push(deleted);
93
+ }
94
+ }
95
+ // Prune old entries and write back
96
+ const pruned = pruneOldDeletions(merged);
97
+ writeDeletionManifest(contextPath, pruned);
98
+ }
54
99
  return {
55
100
  success: true,
56
101
  filesWritten: written,
@@ -59,6 +104,52 @@ export async function pullFromCloud(client, contextPath, options = {}) {
59
104
  skippedPaths,
60
105
  deletedPaths,
61
106
  totalFiles: filesToWrite.length,
107
+ filesDeletedByManifest,
108
+ deletedByManifestPaths,
62
109
  };
63
110
  }
111
+ /**
112
+ * Find and delete a local file matching a block key in a section folder.
113
+ * Searches recursively within the section folder for {key}.md.
114
+ * Returns the relative path of the deleted file, or null if not found.
115
+ */
116
+ function deleteLocalFileForBlock(contextPath, key, section) {
117
+ // Convert section type to folder name (underscores → hyphens)
118
+ const sectionFolder = section.replace(/_/g, "-");
119
+ const sectionPath = path.join(contextPath, sectionFolder);
120
+ if (!fs.existsSync(sectionPath)) {
121
+ // Also try with the original section name (no conversion)
122
+ const altPath = path.join(contextPath, section);
123
+ if (!fs.existsSync(altPath)) {
124
+ return null;
125
+ }
126
+ return searchAndDelete(altPath, contextPath, key);
127
+ }
128
+ return searchAndDelete(sectionPath, contextPath, key);
129
+ }
130
+ /**
131
+ * Recursively search for {key}.md in a directory and delete it.
132
+ */
133
+ function searchAndDelete(dirPath, contextPath, key) {
134
+ const targetFilename = `${key}.md`;
135
+ try {
136
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
137
+ for (const entry of entries) {
138
+ const fullPath = path.join(dirPath, entry.name);
139
+ if (entry.isFile() && entry.name === targetFilename) {
140
+ fs.unlinkSync(fullPath);
141
+ return path.relative(contextPath, fullPath);
142
+ }
143
+ if (entry.isDirectory() && !entry.name.startsWith(".")) {
144
+ const result = searchAndDelete(fullPath, contextPath, key);
145
+ if (result)
146
+ return result;
147
+ }
148
+ }
149
+ }
150
+ catch {
151
+ // Non-fatal: directory read or delete failed
152
+ }
153
+ return null;
154
+ }
64
155
  //# sourceMappingURL=pull.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/sync/pull.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAkBpG;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAyB,EACzB,WAAmB,EACnB,UAAuB,EAAE;IAEzB,+BAA+B;IAC/B,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAEjC,0BAA0B;IAC1B,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;IAE5C,wEAAwE;IACxE,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,YAAY,EAAE,CAAC;YACf,YAAY,EAAE,CAAC;YACf,YAAY,EAAE,CAAC;YACf,YAAY,EAAE,EAAE;YAChB,YAAY,EAAE,EAAE;YAChB,UAAU,EAAE,CAAC;SACd,CAAC;IACJ,CAAC;IAED,iCAAiC;IACjC,IAAI,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC;IAClC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACzC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,OAAQ,CAAC,CACpC,CAAC;IACJ,CAAC;IAED,8BAA8B;IAC9B,2DAA2D;IAC3D,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,kBAAkB,CAC3D,WAAW,EACX,YAAY,EACZ,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CACzB,CAAC;IAEF,yDAAyD;IACzD,kFAAkF;IAClF,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,YAAY,GAAa,EAAE,CAAC;IAEhC,IAAI,OAAO,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;QACnC,wDAAwD;QACxD,oDAAoD;QACpD,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACrB,+EAA+E;YAC/E,2DAA2D;YAC3D,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAC7C,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAC3C,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAC9C,CAAC;YAEF,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5B,MAAM,YAAY,GAAG,wBAAwB,CAAC,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAC3E,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC;gBACpC,YAAY,GAAG,YAAY,CAAC,YAAY,CAAC;YAC3C,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI;QACb,YAAY,EAAE,OAAO;QACrB,YAAY,EAAE,OAAO;QACrB,YAAY;QACZ,YAAY;QACZ,YAAY;QACZ,UAAU,EAAE,YAAY,CAAC,MAAM;KAChC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/sync/pull.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,10 @@ export interface PushResult {
13
13
  result: SyncResult;
14
14
  /** Blocks that exist in cloud but not locally - would be deleted with deleteOrphans */
15
15
  potentialOrphans?: number;
16
+ /** Number of blocks archived via deletion manifest */
17
+ archivedByManifest?: number;
18
+ /** Number of deletions auto-detected from missing local files */
19
+ autoDetectedDeletions?: number;
16
20
  }
17
21
  /**
18
22
  * Push local CONTEXT folder to cloud
@@ -1 +1 @@
1
- {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/sync/push.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,WAAW,GAAG,aAAa,CAAC;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,uFAAuF;IACvF,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,iBAAiB,EACzB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CA2CrB"}
1
+ {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/sync/push.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAQrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,WAAW,GAAG,aAAa,CAAC;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,uFAAuF;IACvF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sDAAsD;IACtD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iEAAiE;IACjE,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,iBAAiB,EACzB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAgGrB"}
package/dist/sync/push.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { readContextFolder } from "../cli/files.js";
2
+ import { readDeletionManifest, writeDeletionManifest, addDeletion, pruneOldDeletions, } from "./deletions.js";
2
3
  /**
3
4
  * Push local CONTEXT folder to cloud
4
5
  */
@@ -24,7 +25,9 @@ export async function pushToCloud(client, contextPath, options = {}) {
24
25
  if (options.path) {
25
26
  filesToSync = files.filter((f) => f.path.startsWith(options.path));
26
27
  }
27
- // Import to cloud
28
+ // Read the local deletion manifest to send alongside files
29
+ const manifest = readDeletionManifest(contextPath);
30
+ // Import to cloud with deletions
28
31
  // SAFETY: deleteOrphans defaults to FALSE to prevent accidental data loss
29
32
  // in collaborative environments. Users must explicitly pass --delete-orphans
30
33
  // to remove blocks that don't exist in their local folder.
@@ -32,12 +35,52 @@ export async function pushToCloud(client, contextPath, options = {}) {
32
35
  dryRun: options.dryRun,
33
36
  conflictResolution: options.conflictResolution ?? "folder_wins",
34
37
  deleteOrphans: options.deleteOrphans ?? false,
38
+ deletions: manifest.deletions,
35
39
  });
40
+ // Auto-detect local deletions from potentialOrphans:
41
+ // If the server reports blocks that exist in cloud but not locally,
42
+ // these are likely files the user deleted. Add them to the manifest
43
+ // and send a follow-up request to archive them.
44
+ let autoDetectedDeletions = 0;
45
+ const orphans = response.result.potentialOrphans;
46
+ if (!options.dryRun && orphans && orphans.length > 0 && !options.path) {
47
+ // Build set of already-known deletions
48
+ const knownDeletions = new Set(manifest.deletions.map((d) => `${d.section}:${d.key}`));
49
+ const newDeletions = orphans.filter((o) => !knownDeletions.has(`${o.sectionType}:${o.key}`));
50
+ if (newDeletions.length > 0) {
51
+ // Add newly detected deletions to the manifest
52
+ for (const orphan of newDeletions) {
53
+ addDeletion(contextPath, {
54
+ key: orphan.key,
55
+ section: orphan.sectionType,
56
+ source: "local",
57
+ });
58
+ }
59
+ autoDetectedDeletions = newDeletions.length;
60
+ // Send follow-up import with only the new deletions to archive them
61
+ const updatedManifest = readDeletionManifest(contextPath);
62
+ await client.importFiles([], {
63
+ dryRun: false,
64
+ conflictResolution: options.conflictResolution ?? "folder_wins",
65
+ deletions: updatedManifest.deletions,
66
+ });
67
+ }
68
+ }
69
+ // Prune old entries (>30 days) and write back
70
+ if (!options.dryRun) {
71
+ const currentManifest = readDeletionManifest(contextPath);
72
+ const pruned = pruneOldDeletions(currentManifest);
73
+ if (pruned.deletions.length !== currentManifest.deletions.length) {
74
+ writeDeletionManifest(contextPath, pruned);
75
+ }
76
+ }
36
77
  return {
37
78
  success: response.success,
38
79
  dryRun: response.dryRun,
39
80
  filesProcessed: filesToSync.length,
40
81
  result: response.result,
82
+ archivedByManifest: response.result.deleted,
83
+ autoDetectedDeletions,
41
84
  };
42
85
  }
43
86
  //# sourceMappingURL=push.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/sync/push.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAmBpD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAyB,EACzB,WAAmB,EACnB,UAAuB,EAAE;IAEzB,uBAAuB;IACvB,MAAM,KAAK,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAE7C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;YAC/B,cAAc,EAAE,CAAC;YACjB,MAAM,EAAE;gBACN,OAAO,EAAE,CAAC;gBACV,OAAO,EAAE,CAAC;gBACV,OAAO,EAAE,CAAC;gBACV,SAAS,EAAE,EAAE;gBACb,MAAM,EAAE,EAAE;aACX;SACF,CAAC;IACJ,CAAC;IAED,8BAA8B;IAC9B,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC/B,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAK,CAAC,CACjC,CAAC;IACJ,CAAC;IAED,kBAAkB;IAClB,0EAA0E;IAC1E,6EAA6E;IAC7E,2DAA2D;IAC3D,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE;QACrD,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,aAAa;QAC/D,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,KAAK;KAC9C,CAAC,CAAC;IAEH,OAAO;QACL,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,cAAc,EAAE,WAAW,CAAC,MAAM;QAClC,MAAM,EAAE,QAAQ,CAAC,MAAM;KACxB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/sync/push.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,WAAW,EACX,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAuBxB;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAyB,EACzB,WAAmB,EACnB,UAAuB,EAAE;IAEzB,uBAAuB;IACvB,MAAM,KAAK,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAE7C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;YAC/B,cAAc,EAAE,CAAC;YACjB,MAAM,EAAE;gBACN,OAAO,EAAE,CAAC;gBACV,OAAO,EAAE,CAAC;gBACV,OAAO,EAAE,CAAC;gBACV,SAAS,EAAE,EAAE;gBACb,MAAM,EAAE,EAAE;aACX;SACF,CAAC;IACJ,CAAC;IAED,8BAA8B;IAC9B,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC/B,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAK,CAAC,CACjC,CAAC;IACJ,CAAC;IAED,2DAA2D;IAC3D,MAAM,QAAQ,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAEnD,iCAAiC;IACjC,0EAA0E;IAC1E,6EAA6E;IAC7E,2DAA2D;IAC3D,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE;QACrD,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,aAAa;QAC/D,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,KAAK;QAC7C,SAAS,EAAE,QAAQ,CAAC,SAAS;KAC9B,CAAC,CAAC;IAEH,qDAAqD;IACrD,oEAAoE;IACpE,oEAAoE;IACpE,gDAAgD;IAChD,IAAI,qBAAqB,GAAG,CAAC,CAAC;IAC9B,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,gBAAgB,CAAC;IAEjD,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACtE,uCAAuC;QACvC,MAAM,cAAc,GAAG,IAAI,GAAG,CAC5B,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,CACvD,CAAC;QAEF,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CACjC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,CACxD,CAAC;QAEF,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,+CAA+C;YAC/C,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;gBAClC,WAAW,CAAC,WAAW,EAAE;oBACvB,GAAG,EAAE,MAAM,CAAC,GAAG;oBACf,OAAO,EAAE,MAAM,CAAC,WAAW;oBAC3B,MAAM,EAAE,OAAO;iBAChB,CAAC,CAAC;YACL,CAAC;YACD,qBAAqB,GAAG,YAAY,CAAC,MAAM,CAAC;YAE5C,oEAAoE;YACpE,MAAM,eAAe,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;YAC1D,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE;gBAC3B,MAAM,EAAE,KAAK;gBACb,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,aAAa;gBAC/D,SAAS,EAAE,eAAe,CAAC,SAAS;aACrC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,8CAA8C;IAC9C,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,eAAe,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,iBAAiB,CAAC,eAAe,CAAC,CAAC;QAClD,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,eAAe,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YACjE,qBAAqB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,cAAc,EAAE,WAAW,CAAC,MAAM;QAClC,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO;QAC3C,qBAAqB;KACtB,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/sync/watcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC/E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD;AAED;;GAEG;AACH,qBAAa,WAAW;IAOpB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IAPhB,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,SAAS,CAAS;gBAGhB,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,aAAa;IAG/B;;OAEG;IACH,KAAK,IAAI,IAAI;IAsBb;;OAEG;IACH,IAAI,IAAI,IAAI;IASZ;;OAEG;IACH,OAAO,CAAC,YAAY;IAiBpB;;OAEG;IACH,OAAO,CAAC,YAAY;IAUpB;;OAEG;YACW,qBAAqB;CAyBpC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,aAAa,GACpB,WAAW,CAIb"}
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/sync/watcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAI1D,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC/E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD;AAED;;GAEG;AACH,qBAAa,WAAW;IAOpB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IAPhB,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,SAAS,CAAS;gBAGhB,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,aAAa;IAG/B;;OAEG;IACH,KAAK,IAAI,IAAI;IAsBb;;OAEG;IACH,IAAI,IAAI,IAAI;IASZ;;OAEG;IACH,OAAO,CAAC,YAAY;IAoCpB;;OAEG;IACH,OAAO,CAAC,YAAY;IAUpB;;OAEG;YACW,qBAAqB;CAyBpC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,aAAa,GACpB,WAAW,CAIb"}
@@ -1,5 +1,7 @@
1
1
  import chokidar from "chokidar";
2
+ import path from "path";
2
3
  import { pushToCloud } from "./push.js";
4
+ import { addDeletion } from "./deletions.js";
3
5
  /**
4
6
  * File watcher for auto-syncing CONTEXT folder changes (local → cloud only)
5
7
  */
@@ -51,18 +53,36 @@ export class FileWatcher {
51
53
  /**
52
54
  * Handle a file change event
53
55
  */
54
- handleChange(event, path) {
56
+ handleChange(event, filePath) {
55
57
  // Only watch markdown files
56
- if (!path.endsWith(".md")) {
58
+ if (!filePath.endsWith(".md")) {
57
59
  return;
58
60
  }
59
61
  // Skip README and AI-GUIDE
60
- const filename = path.split("/").pop()?.toLowerCase();
62
+ const filename = filePath.split("/").pop()?.toLowerCase();
61
63
  if (filename === "readme.md" || filename === "ai-guide.md") {
62
64
  return;
63
65
  }
64
- this.config.onChange?.(event, path);
65
- this.pendingChanges.add(path);
66
+ // When a file is deleted (unlink), record it in the deletion manifest
67
+ // so the next push will propagate the deletion to the cloud
68
+ if (event === "unlink") {
69
+ const relativePath = path.relative(this.config.contextPath, filePath);
70
+ const parts = relativePath.split(path.sep);
71
+ // Section is the first directory (e.g., "product", "brand", "development")
72
+ const section = parts[0]?.replace(/-/g, "_");
73
+ // Key is the filename without .md
74
+ const key = path.basename(filePath, ".md");
75
+ if (section && key) {
76
+ try {
77
+ addDeletion(this.config.contextPath, { key, section, source: "local" });
78
+ }
79
+ catch {
80
+ // Non-fatal: manifest write failed, deletion won't propagate automatically
81
+ }
82
+ }
83
+ }
84
+ this.config.onChange?.(event, filePath);
85
+ this.pendingChanges.add(filePath);
66
86
  this.scheduleSync();
67
87
  }
68
88
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/sync/watcher.ts"],"names":[],"mappings":"AAAA,OAAO,QAA4B,MAAM,UAAU,CAAC;AAEpD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAYxC;;GAEG;AACH,MAAM,OAAO,WAAW;IAOZ;IACA;IAPF,OAAO,GAAqB,IAAI,CAAC;IACjC,cAAc,GAAgB,IAAI,GAAG,EAAE,CAAC;IACxC,WAAW,GAA0B,IAAI,CAAC;IAC1C,SAAS,GAAG,KAAK,CAAC;IAE1B,YACU,MAAyB,EACzB,MAAqB;QADrB,WAAM,GAAN,MAAM,CAAmB;QACzB,WAAM,GAAN,MAAM,CAAe;IAC5B,CAAC;IAEJ;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;YACrD,OAAO,EAAE;gBACP,eAAe,EAAE,WAAW;gBAC5B,cAAc;gBACd,qDAAqD;gBACrD,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe;aAC/B;YACD,UAAU,EAAE,IAAI;YAChB,aAAa,EAAE,IAAI;YACnB,gBAAgB,EAAE;gBAChB,kBAAkB,EAAE,IAAI;gBACxB,YAAY,EAAE,GAAG;aAClB;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO;aACT,EAAE,CAAC,KAAK,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;aACnE,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;aACzE,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC/E,CAAC;IAED;;OAEG;IACH,IAAI;QACF,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC/B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,KAAa,EAAE,IAAY;QAC9C,4BAA4B;QAC5B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO;QACT,CAAC;QAED,2BAA2B;QAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,CAAC;QACtD,IAAI,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;YAC3D,OAAO;QACT,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACjC,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC,GAAG,EAAE;YACjC,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC/B,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,qBAAqB;QACjC,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACrD,OAAO;QACT,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAChD,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAE5B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;gBACrE,kBAAkB,EAAE,aAAa;aAClC,CAAC,CAAC;YAEH,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACnB,KAAK,EAAE,OAAO,CAAC,MAAM;gBACrB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;gBAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;aAC/B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,KAAc,CAAC,CAAC;QACxC,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAyB,EACzB,MAAqB;IAErB,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChD,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/sync/watcher.ts"],"names":[],"mappings":"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"}