@animus-labs/cortex 0.2.0

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 (293) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +73 -0
  3. package/dist/budget-guard.d.ts +75 -0
  4. package/dist/budget-guard.d.ts.map +1 -0
  5. package/dist/budget-guard.js +142 -0
  6. package/dist/budget-guard.js.map +1 -0
  7. package/dist/compaction/compaction.d.ts +99 -0
  8. package/dist/compaction/compaction.d.ts.map +1 -0
  9. package/dist/compaction/compaction.js +302 -0
  10. package/dist/compaction/compaction.js.map +1 -0
  11. package/dist/compaction/failsafe.d.ts +57 -0
  12. package/dist/compaction/failsafe.d.ts.map +1 -0
  13. package/dist/compaction/failsafe.js +135 -0
  14. package/dist/compaction/failsafe.js.map +1 -0
  15. package/dist/compaction/index.d.ts +381 -0
  16. package/dist/compaction/index.d.ts.map +1 -0
  17. package/dist/compaction/index.js +979 -0
  18. package/dist/compaction/index.js.map +1 -0
  19. package/dist/compaction/microcompaction.d.ts +219 -0
  20. package/dist/compaction/microcompaction.d.ts.map +1 -0
  21. package/dist/compaction/microcompaction.js +536 -0
  22. package/dist/compaction/microcompaction.js.map +1 -0
  23. package/dist/compaction/observational/buffering.d.ts +225 -0
  24. package/dist/compaction/observational/buffering.d.ts.map +1 -0
  25. package/dist/compaction/observational/buffering.js +354 -0
  26. package/dist/compaction/observational/buffering.js.map +1 -0
  27. package/dist/compaction/observational/constants.d.ts +70 -0
  28. package/dist/compaction/observational/constants.d.ts.map +1 -0
  29. package/dist/compaction/observational/constants.js +507 -0
  30. package/dist/compaction/observational/constants.js.map +1 -0
  31. package/dist/compaction/observational/index.d.ts +219 -0
  32. package/dist/compaction/observational/index.d.ts.map +1 -0
  33. package/dist/compaction/observational/index.js +641 -0
  34. package/dist/compaction/observational/index.js.map +1 -0
  35. package/dist/compaction/observational/observer.d.ts +97 -0
  36. package/dist/compaction/observational/observer.d.ts.map +1 -0
  37. package/dist/compaction/observational/observer.js +424 -0
  38. package/dist/compaction/observational/observer.js.map +1 -0
  39. package/dist/compaction/observational/recall-tool.d.ts +27 -0
  40. package/dist/compaction/observational/recall-tool.d.ts.map +1 -0
  41. package/dist/compaction/observational/recall-tool.js +93 -0
  42. package/dist/compaction/observational/recall-tool.js.map +1 -0
  43. package/dist/compaction/observational/reflector.d.ts +94 -0
  44. package/dist/compaction/observational/reflector.d.ts.map +1 -0
  45. package/dist/compaction/observational/reflector.js +167 -0
  46. package/dist/compaction/observational/reflector.js.map +1 -0
  47. package/dist/compaction/observational/types.d.ts +271 -0
  48. package/dist/compaction/observational/types.d.ts.map +1 -0
  49. package/dist/compaction/observational/types.js +15 -0
  50. package/dist/compaction/observational/types.js.map +1 -0
  51. package/dist/context-manager.d.ts +134 -0
  52. package/dist/context-manager.d.ts.map +1 -0
  53. package/dist/context-manager.js +170 -0
  54. package/dist/context-manager.js.map +1 -0
  55. package/dist/cortex-agent.d.ts +1020 -0
  56. package/dist/cortex-agent.d.ts.map +1 -0
  57. package/dist/cortex-agent.js +3589 -0
  58. package/dist/cortex-agent.js.map +1 -0
  59. package/dist/error-classifier.d.ts +48 -0
  60. package/dist/error-classifier.d.ts.map +1 -0
  61. package/dist/error-classifier.js +152 -0
  62. package/dist/error-classifier.js.map +1 -0
  63. package/dist/event-bridge.d.ts +166 -0
  64. package/dist/event-bridge.d.ts.map +1 -0
  65. package/dist/event-bridge.js +381 -0
  66. package/dist/event-bridge.js.map +1 -0
  67. package/dist/index.d.ts +55 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +57 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/mcp-client.d.ts +119 -0
  72. package/dist/mcp-client.d.ts.map +1 -0
  73. package/dist/mcp-client.js +474 -0
  74. package/dist/mcp-client.js.map +1 -0
  75. package/dist/model-wrapper.d.ts +58 -0
  76. package/dist/model-wrapper.d.ts.map +1 -0
  77. package/dist/model-wrapper.js +86 -0
  78. package/dist/model-wrapper.js.map +1 -0
  79. package/dist/noop-logger.d.ts +4 -0
  80. package/dist/noop-logger.d.ts.map +1 -0
  81. package/dist/noop-logger.js +8 -0
  82. package/dist/noop-logger.js.map +1 -0
  83. package/dist/prompt-diagnostics.d.ts +47 -0
  84. package/dist/prompt-diagnostics.d.ts.map +1 -0
  85. package/dist/prompt-diagnostics.js +230 -0
  86. package/dist/prompt-diagnostics.js.map +1 -0
  87. package/dist/provider-manager.d.ts +224 -0
  88. package/dist/provider-manager.d.ts.map +1 -0
  89. package/dist/provider-manager.js +563 -0
  90. package/dist/provider-manager.js.map +1 -0
  91. package/dist/provider-registry.d.ts +115 -0
  92. package/dist/provider-registry.d.ts.map +1 -0
  93. package/dist/provider-registry.js +305 -0
  94. package/dist/provider-registry.js.map +1 -0
  95. package/dist/schema-converter.d.ts +20 -0
  96. package/dist/schema-converter.d.ts.map +1 -0
  97. package/dist/schema-converter.js +48 -0
  98. package/dist/schema-converter.js.map +1 -0
  99. package/dist/skill-preprocessor.d.ts +46 -0
  100. package/dist/skill-preprocessor.d.ts.map +1 -0
  101. package/dist/skill-preprocessor.js +237 -0
  102. package/dist/skill-preprocessor.js.map +1 -0
  103. package/dist/skill-registry.d.ts +107 -0
  104. package/dist/skill-registry.d.ts.map +1 -0
  105. package/dist/skill-registry.js +330 -0
  106. package/dist/skill-registry.js.map +1 -0
  107. package/dist/skill-tool.d.ts +54 -0
  108. package/dist/skill-tool.d.ts.map +1 -0
  109. package/dist/skill-tool.js +88 -0
  110. package/dist/skill-tool.js.map +1 -0
  111. package/dist/sub-agent-manager.d.ts +90 -0
  112. package/dist/sub-agent-manager.d.ts.map +1 -0
  113. package/dist/sub-agent-manager.js +192 -0
  114. package/dist/sub-agent-manager.js.map +1 -0
  115. package/dist/token-estimator.d.ts +23 -0
  116. package/dist/token-estimator.d.ts.map +1 -0
  117. package/dist/token-estimator.js +27 -0
  118. package/dist/token-estimator.js.map +1 -0
  119. package/dist/tool-contract.d.ts +68 -0
  120. package/dist/tool-contract.d.ts.map +1 -0
  121. package/dist/tool-contract.js +35 -0
  122. package/dist/tool-contract.js.map +1 -0
  123. package/dist/tool-result-persistence.d.ts +89 -0
  124. package/dist/tool-result-persistence.d.ts.map +1 -0
  125. package/dist/tool-result-persistence.js +152 -0
  126. package/dist/tool-result-persistence.js.map +1 -0
  127. package/dist/tools/bash/index.d.ts +71 -0
  128. package/dist/tools/bash/index.d.ts.map +1 -0
  129. package/dist/tools/bash/index.js +485 -0
  130. package/dist/tools/bash/index.js.map +1 -0
  131. package/dist/tools/bash/interactive.d.ts +47 -0
  132. package/dist/tools/bash/interactive.d.ts.map +1 -0
  133. package/dist/tools/bash/interactive.js +262 -0
  134. package/dist/tools/bash/interactive.js.map +1 -0
  135. package/dist/tools/bash/safety.d.ts +149 -0
  136. package/dist/tools/bash/safety.d.ts.map +1 -0
  137. package/dist/tools/bash/safety.js +1116 -0
  138. package/dist/tools/bash/safety.js.map +1 -0
  139. package/dist/tools/edit.d.ts +57 -0
  140. package/dist/tools/edit.d.ts.map +1 -0
  141. package/dist/tools/edit.js +310 -0
  142. package/dist/tools/edit.js.map +1 -0
  143. package/dist/tools/glob.d.ts +34 -0
  144. package/dist/tools/glob.d.ts.map +1 -0
  145. package/dist/tools/glob.js +268 -0
  146. package/dist/tools/glob.js.map +1 -0
  147. package/dist/tools/grep.d.ts +53 -0
  148. package/dist/tools/grep.d.ts.map +1 -0
  149. package/dist/tools/grep.js +673 -0
  150. package/dist/tools/grep.js.map +1 -0
  151. package/dist/tools/index.d.ts +62 -0
  152. package/dist/tools/index.d.ts.map +1 -0
  153. package/dist/tools/index.js +52 -0
  154. package/dist/tools/index.js.map +1 -0
  155. package/dist/tools/read.d.ts +43 -0
  156. package/dist/tools/read.d.ts.map +1 -0
  157. package/dist/tools/read.js +459 -0
  158. package/dist/tools/read.js.map +1 -0
  159. package/dist/tools/runtime.d.ts +62 -0
  160. package/dist/tools/runtime.d.ts.map +1 -0
  161. package/dist/tools/runtime.js +116 -0
  162. package/dist/tools/runtime.js.map +1 -0
  163. package/dist/tools/shared/cwd-tracker.d.ts +32 -0
  164. package/dist/tools/shared/cwd-tracker.d.ts.map +1 -0
  165. package/dist/tools/shared/cwd-tracker.js +44 -0
  166. package/dist/tools/shared/cwd-tracker.js.map +1 -0
  167. package/dist/tools/shared/edit-history.d.ts +55 -0
  168. package/dist/tools/shared/edit-history.d.ts.map +1 -0
  169. package/dist/tools/shared/edit-history.js +72 -0
  170. package/dist/tools/shared/edit-history.js.map +1 -0
  171. package/dist/tools/shared/edit-matcher.d.ts +83 -0
  172. package/dist/tools/shared/edit-matcher.d.ts.map +1 -0
  173. package/dist/tools/shared/edit-matcher.js +359 -0
  174. package/dist/tools/shared/edit-matcher.js.map +1 -0
  175. package/dist/tools/shared/file-mutation-lock.d.ts +22 -0
  176. package/dist/tools/shared/file-mutation-lock.d.ts.map +1 -0
  177. package/dist/tools/shared/file-mutation-lock.js +35 -0
  178. package/dist/tools/shared/file-mutation-lock.js.map +1 -0
  179. package/dist/tools/shared/gitignore.d.ts +17 -0
  180. package/dist/tools/shared/gitignore.d.ts.map +1 -0
  181. package/dist/tools/shared/gitignore.js +59 -0
  182. package/dist/tools/shared/gitignore.js.map +1 -0
  183. package/dist/tools/shared/pdf-extractor.d.ts +96 -0
  184. package/dist/tools/shared/pdf-extractor.d.ts.map +1 -0
  185. package/dist/tools/shared/pdf-extractor.js +196 -0
  186. package/dist/tools/shared/pdf-extractor.js.map +1 -0
  187. package/dist/tools/shared/read-registry.d.ts +66 -0
  188. package/dist/tools/shared/read-registry.d.ts.map +1 -0
  189. package/dist/tools/shared/read-registry.js +65 -0
  190. package/dist/tools/shared/read-registry.js.map +1 -0
  191. package/dist/tools/shared/safe-env.d.ts +18 -0
  192. package/dist/tools/shared/safe-env.d.ts.map +1 -0
  193. package/dist/tools/shared/safe-env.js +70 -0
  194. package/dist/tools/shared/safe-env.js.map +1 -0
  195. package/dist/tools/sub-agent.d.ts +91 -0
  196. package/dist/tools/sub-agent.d.ts.map +1 -0
  197. package/dist/tools/sub-agent.js +89 -0
  198. package/dist/tools/sub-agent.js.map +1 -0
  199. package/dist/tools/task-output.d.ts +38 -0
  200. package/dist/tools/task-output.d.ts.map +1 -0
  201. package/dist/tools/task-output.js +186 -0
  202. package/dist/tools/task-output.js.map +1 -0
  203. package/dist/tools/tool-search/index.d.ts +40 -0
  204. package/dist/tools/tool-search/index.d.ts.map +1 -0
  205. package/dist/tools/tool-search/index.js +110 -0
  206. package/dist/tools/tool-search/index.js.map +1 -0
  207. package/dist/tools/tool-search/registry.d.ts +82 -0
  208. package/dist/tools/tool-search/registry.d.ts.map +1 -0
  209. package/dist/tools/tool-search/registry.js +238 -0
  210. package/dist/tools/tool-search/registry.js.map +1 -0
  211. package/dist/tools/undo-edit.d.ts +51 -0
  212. package/dist/tools/undo-edit.d.ts.map +1 -0
  213. package/dist/tools/undo-edit.js +231 -0
  214. package/dist/tools/undo-edit.js.map +1 -0
  215. package/dist/tools/web-fetch/cache.d.ts +49 -0
  216. package/dist/tools/web-fetch/cache.d.ts.map +1 -0
  217. package/dist/tools/web-fetch/cache.js +89 -0
  218. package/dist/tools/web-fetch/cache.js.map +1 -0
  219. package/dist/tools/web-fetch/index.d.ts +53 -0
  220. package/dist/tools/web-fetch/index.d.ts.map +1 -0
  221. package/dist/tools/web-fetch/index.js +513 -0
  222. package/dist/tools/web-fetch/index.js.map +1 -0
  223. package/dist/tools/write.d.ts +59 -0
  224. package/dist/tools/write.d.ts.map +1 -0
  225. package/dist/tools/write.js +316 -0
  226. package/dist/tools/write.js.map +1 -0
  227. package/dist/types.d.ts +881 -0
  228. package/dist/types.d.ts.map +1 -0
  229. package/dist/types.js +16 -0
  230. package/dist/types.js.map +1 -0
  231. package/dist/working-tags.d.ts +44 -0
  232. package/dist/working-tags.d.ts.map +1 -0
  233. package/dist/working-tags.js +103 -0
  234. package/dist/working-tags.js.map +1 -0
  235. package/package.json +87 -0
  236. package/src/budget-guard.ts +170 -0
  237. package/src/compaction/compaction.ts +386 -0
  238. package/src/compaction/failsafe.ts +185 -0
  239. package/src/compaction/index.ts +1199 -0
  240. package/src/compaction/microcompaction.ts +709 -0
  241. package/src/compaction/observational/buffering.ts +430 -0
  242. package/src/compaction/observational/constants.ts +532 -0
  243. package/src/compaction/observational/index.ts +837 -0
  244. package/src/compaction/observational/observer.ts +510 -0
  245. package/src/compaction/observational/recall-tool.ts +130 -0
  246. package/src/compaction/observational/reflector.ts +221 -0
  247. package/src/compaction/observational/types.ts +343 -0
  248. package/src/context-manager.ts +237 -0
  249. package/src/cortex-agent.ts +4297 -0
  250. package/src/error-classifier.ts +199 -0
  251. package/src/event-bridge.ts +508 -0
  252. package/src/index.ts +292 -0
  253. package/src/mcp-client.ts +582 -0
  254. package/src/model-wrapper.ts +128 -0
  255. package/src/noop-logger.ts +9 -0
  256. package/src/prompt-diagnostics.ts +296 -0
  257. package/src/provider-manager.ts +823 -0
  258. package/src/provider-registry.ts +386 -0
  259. package/src/schema-converter.ts +51 -0
  260. package/src/skill-preprocessor.ts +314 -0
  261. package/src/skill-registry.ts +378 -0
  262. package/src/skill-tool.ts +130 -0
  263. package/src/sub-agent-manager.ts +236 -0
  264. package/src/token-estimator.ts +26 -0
  265. package/src/tool-contract.ts +113 -0
  266. package/src/tool-result-persistence.ts +197 -0
  267. package/src/tools/bash/index.ts +633 -0
  268. package/src/tools/bash/interactive.ts +302 -0
  269. package/src/tools/bash/safety.ts +1297 -0
  270. package/src/tools/edit.ts +422 -0
  271. package/src/tools/glob.ts +330 -0
  272. package/src/tools/grep.ts +819 -0
  273. package/src/tools/index.ts +110 -0
  274. package/src/tools/read.ts +580 -0
  275. package/src/tools/runtime.ts +173 -0
  276. package/src/tools/shared/cwd-tracker.ts +50 -0
  277. package/src/tools/shared/edit-history.ts +96 -0
  278. package/src/tools/shared/edit-matcher.ts +457 -0
  279. package/src/tools/shared/file-mutation-lock.ts +40 -0
  280. package/src/tools/shared/gitignore.ts +61 -0
  281. package/src/tools/shared/pdf-extractor.ts +290 -0
  282. package/src/tools/shared/read-registry.ts +93 -0
  283. package/src/tools/shared/safe-env.ts +82 -0
  284. package/src/tools/sub-agent.ts +171 -0
  285. package/src/tools/task-output.ts +236 -0
  286. package/src/tools/tool-search/index.ts +167 -0
  287. package/src/tools/tool-search/registry.ts +278 -0
  288. package/src/tools/undo-edit.ts +314 -0
  289. package/src/tools/web-fetch/cache.ts +112 -0
  290. package/src/tools/web-fetch/index.ts +604 -0
  291. package/src/tools/write.ts +385 -0
  292. package/src/types.ts +1057 -0
  293. package/src/working-tags.ts +118 -0
@@ -0,0 +1,316 @@
1
+ /**
2
+ * Write tool: create a new file or overwrite an existing file.
3
+ *
4
+ * Enforces the read-before-write contract via ReadRegistry.
5
+ * Performs atomic writes (write to temp, then rename) to prevent
6
+ * partial writes on crash. Creates parent directories as needed.
7
+ *
8
+ * Reference: docs/cortex/tools/write.md
9
+ */
10
+ import * as fs from 'node:fs';
11
+ import * as path from 'node:path';
12
+ import * as crypto from 'node:crypto';
13
+ import { Type } from 'typebox';
14
+ import { attachRuntimeAwareTool } from './runtime.js';
15
+ // ---------------------------------------------------------------------------
16
+ // Schema
17
+ // ---------------------------------------------------------------------------
18
+ export const WriteParams = Type.Object({
19
+ file_path: Type.String({ description: 'Absolute path to the file to write (must be absolute, not relative)' }),
20
+ content: Type.String({ description: 'The full content to write to the file' }),
21
+ });
22
+ // ---------------------------------------------------------------------------
23
+ // Helpers
24
+ // ---------------------------------------------------------------------------
25
+ /**
26
+ * Compute a safe line-level diff between two strings.
27
+ *
28
+ * This intentionally emits at most one changed hunk. The UI only needs a
29
+ * compact, deterministic summary of the mutation, not a minimal diff.
30
+ */
31
+ export function computeDiff(oldContent, newContent) {
32
+ const oldLines = oldContent.split('\n');
33
+ const newLines = newContent.split('\n');
34
+ let prefix = 0;
35
+ while (prefix < oldLines.length &&
36
+ prefix < newLines.length &&
37
+ oldLines[prefix] === newLines[prefix]) {
38
+ prefix += 1;
39
+ }
40
+ if (prefix === oldLines.length && prefix === newLines.length) {
41
+ return [];
42
+ }
43
+ let oldSuffix = oldLines.length - 1;
44
+ let newSuffix = newLines.length - 1;
45
+ while (oldSuffix >= prefix &&
46
+ newSuffix >= prefix &&
47
+ oldLines[oldSuffix] === newLines[newSuffix]) {
48
+ oldSuffix -= 1;
49
+ newSuffix -= 1;
50
+ }
51
+ const removedLines = oldSuffix >= prefix
52
+ ? oldLines.slice(prefix, oldSuffix + 1).map((line) => `-${line}`)
53
+ : [];
54
+ const addedLines = newSuffix >= prefix
55
+ ? newLines.slice(prefix, newSuffix + 1).map((line) => `+${line}`)
56
+ : [];
57
+ return [{
58
+ oldStart: prefix + 1,
59
+ oldLines: removedLines.length,
60
+ newStart: prefix + 1,
61
+ newLines: addedLines.length,
62
+ lines: [...removedLines, ...addedLines],
63
+ }];
64
+ }
65
+ // ---------------------------------------------------------------------------
66
+ // Tool factory
67
+ // ---------------------------------------------------------------------------
68
+ export function createWriteTool(config) {
69
+ const readRegistry = config.runtime?.readRegistry ?? config.readRegistry;
70
+ const editHistory = config.runtime?.editHistory ?? config.editHistory;
71
+ if (!readRegistry) {
72
+ throw new Error('createWriteTool requires either runtime or readRegistry');
73
+ }
74
+ const fileMutationLock = config.runtime?.fileMutationLock ?? config.fileMutationLock;
75
+ const tool = {
76
+ name: 'Write',
77
+ description: 'Create a new file or overwrite an existing file on the local filesystem. ' +
78
+ 'If the file already exists, you MUST Read it before using this tool. The write will be rejected if an existing file has not been read first.',
79
+ parameters: WriteParams,
80
+ async execute(params) {
81
+ const filePath = path.resolve(params.file_path);
82
+ const newContent = params.content;
83
+ // Check if file exists (before acquiring lock)
84
+ let fileExists = false;
85
+ try {
86
+ const stat = await fs.promises.stat(filePath);
87
+ fileExists = stat.isFile();
88
+ }
89
+ catch {
90
+ // File does not exist - that's fine for creation
91
+ }
92
+ // Acquire per-file mutation lock (serializes concurrent same-file writes)
93
+ const release = fileMutationLock ? await fileMutationLock.acquire(filePath) : undefined;
94
+ try {
95
+ let originalContent = null;
96
+ // Re-check existence after acquiring lock (another tool may have created/deleted it)
97
+ try {
98
+ const stat = await fs.promises.stat(filePath);
99
+ fileExists = stat.isFile();
100
+ }
101
+ catch {
102
+ fileExists = false;
103
+ }
104
+ // Enforce read-before-write for existing files
105
+ if (fileExists && !readRegistry.hasBeenRead(filePath)) {
106
+ return {
107
+ content: [{ type: 'text', text: 'You must Read this file before overwriting it.' }],
108
+ details: {
109
+ filePath,
110
+ isCreate: false,
111
+ bytesWritten: 0,
112
+ diff: null,
113
+ originalContent: null,
114
+ },
115
+ };
116
+ }
117
+ // Mtime freshness check: reject if file changed on disk since last Read.
118
+ // Using strict greater-than (not !==) to tolerate Windows/cloud-sync
119
+ // quirks where mtime can go backwards without a real modification.
120
+ // When mtime does indicate a change, fall back to a content-hash
121
+ // comparison (only possible for full reads) so formatter-style
122
+ // touches that don't change bytes still allow the write.
123
+ let originalBuffer;
124
+ if (fileExists) {
125
+ const readState = readRegistry.getState(filePath);
126
+ if (readState) {
127
+ const currentStat = await fs.promises.stat(filePath);
128
+ if (currentStat.mtimeMs > readState.timestamp) {
129
+ let contentUnchanged = false;
130
+ if (readState.contentHash) {
131
+ try {
132
+ originalBuffer = await fs.promises.readFile(filePath);
133
+ const currentHash = crypto.createHash('sha256')
134
+ .update(originalBuffer).digest('hex');
135
+ contentUnchanged = currentHash === readState.contentHash;
136
+ }
137
+ catch {
138
+ // If we can't read, fall through to the rejection path.
139
+ }
140
+ }
141
+ if (!contentUnchanged) {
142
+ readRegistry.invalidate(filePath);
143
+ return {
144
+ content: [{
145
+ type: 'text',
146
+ text: 'File was modified since last Read. Read the file again before overwriting it.',
147
+ }],
148
+ details: {
149
+ filePath,
150
+ isCreate: false,
151
+ bytesWritten: 0,
152
+ diff: null,
153
+ originalContent: null,
154
+ },
155
+ };
156
+ }
157
+ }
158
+ }
159
+ }
160
+ // Read original content for diff (existing files only). Reuse the
161
+ // buffer from the content-hash check if we already loaded it.
162
+ if (fileExists) {
163
+ try {
164
+ originalContent = originalBuffer
165
+ ? originalBuffer.toString('utf8')
166
+ : await fs.promises.readFile(filePath, 'utf8');
167
+ }
168
+ catch {
169
+ // If we can't read for diff, continue without it
170
+ }
171
+ }
172
+ // Create parent directories
173
+ const parentDir = path.dirname(filePath);
174
+ try {
175
+ await fs.promises.mkdir(parentDir, { recursive: true });
176
+ }
177
+ catch (err) {
178
+ const code = err.code;
179
+ if (code === 'EACCES') {
180
+ return {
181
+ content: [{ type: 'text', text: `Cannot create directory: ${parentDir}` }],
182
+ details: {
183
+ filePath,
184
+ isCreate: !fileExists,
185
+ bytesWritten: 0,
186
+ diff: null,
187
+ originalContent,
188
+ },
189
+ };
190
+ }
191
+ throw err;
192
+ }
193
+ // Atomic write: write to temp file, then rename
194
+ const tempPath = path.join(parentDir, `.write-${crypto.randomUUID()}.tmp`);
195
+ try {
196
+ await fs.promises.writeFile(tempPath, newContent, 'utf8');
197
+ try {
198
+ await fs.promises.rename(tempPath, filePath);
199
+ }
200
+ catch {
201
+ // Rename may fail on Windows if target is open. Fall back to direct write.
202
+ await fs.promises.writeFile(filePath, newContent, 'utf8');
203
+ // Clean up temp file
204
+ try {
205
+ await fs.promises.unlink(tempPath);
206
+ }
207
+ catch {
208
+ // Ignore cleanup errors
209
+ }
210
+ }
211
+ }
212
+ catch (err) {
213
+ // Clean up temp file on error
214
+ try {
215
+ await fs.promises.unlink(tempPath);
216
+ }
217
+ catch {
218
+ // Ignore cleanup errors
219
+ }
220
+ const code = err.code;
221
+ if (code === 'EACCES') {
222
+ return {
223
+ content: [{ type: 'text', text: `Permission denied: ${filePath}` }],
224
+ details: {
225
+ filePath,
226
+ isCreate: !fileExists,
227
+ bytesWritten: 0,
228
+ diff: null,
229
+ originalContent,
230
+ },
231
+ };
232
+ }
233
+ if (code === 'ENOSPC') {
234
+ return {
235
+ content: [{ type: 'text', text: `Disk full. Cannot write to: ${filePath}` }],
236
+ details: {
237
+ filePath,
238
+ isCreate: !fileExists,
239
+ bytesWritten: 0,
240
+ diff: null,
241
+ originalContent,
242
+ },
243
+ };
244
+ }
245
+ if (code === 'ENAMETOOLONG') {
246
+ return {
247
+ content: [{ type: 'text', text: `Path exceeds system limit: ${filePath}` }],
248
+ details: {
249
+ filePath,
250
+ isCreate: !fileExists,
251
+ bytesWritten: 0,
252
+ diff: null,
253
+ originalContent,
254
+ },
255
+ };
256
+ }
257
+ throw err;
258
+ }
259
+ // Refresh read state: the agent's own write is authoritative knowledge
260
+ // of current file contents, so subsequent mutations don't require a re-read.
261
+ // We record the new mtime and a content hash of what we just wrote so
262
+ // external modifications still trigger the freshness check above.
263
+ // Also capture an EditHistory snapshot (when enabled) so UndoEdit
264
+ // can restore the prior state — including the "file didn't exist"
265
+ // case, where undo means deleting what Write just created.
266
+ try {
267
+ const postStat = await fs.promises.stat(filePath);
268
+ const postHash = crypto.createHash('sha256')
269
+ .update(newContent, 'utf8').digest('hex');
270
+ readRegistry.markRead(filePath, {
271
+ timestamp: postStat.mtimeMs,
272
+ contentHash: postHash,
273
+ });
274
+ editHistory?.record(filePath, {
275
+ originalContent,
276
+ postMutationMtimeMs: postStat.mtimeMs,
277
+ postMutationContentHash: postHash,
278
+ source: 'Write',
279
+ });
280
+ }
281
+ catch {
282
+ readRegistry.invalidate(filePath);
283
+ }
284
+ const bytesWritten = Buffer.byteLength(newContent, 'utf8');
285
+ const isCreate = !fileExists;
286
+ // Compute diff for updates
287
+ const diff = originalContent !== null ? computeDiff(originalContent, newContent) : null;
288
+ const verb = isCreate ? 'Created' : 'Updated';
289
+ return {
290
+ content: [{ type: 'text', text: `${verb} ${filePath} (${bytesWritten} bytes)` }],
291
+ details: {
292
+ filePath,
293
+ isCreate,
294
+ bytesWritten,
295
+ diff,
296
+ originalContent,
297
+ },
298
+ };
299
+ }
300
+ finally {
301
+ release?.();
302
+ }
303
+ },
304
+ };
305
+ return attachRuntimeAwareTool(tool, {
306
+ toolKind: 'Write',
307
+ cloneForRuntime: (runtime) => createWriteTool({
308
+ ...config,
309
+ runtime,
310
+ readRegistry: runtime.readRegistry,
311
+ fileMutationLock: runtime.fileMutationLock,
312
+ editHistory: runtime.editHistory,
313
+ }),
314
+ });
315
+ }
316
+ //# sourceMappingURL=write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"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"}