@cdoing/core 0.1.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 (378) hide show
  1. package/dist/agents/coordinator.d.ts +114 -0
  2. package/dist/agents/coordinator.d.ts.map +1 -0
  3. package/dist/agents/coordinator.js +158 -0
  4. package/dist/agents/coordinator.js.map +1 -0
  5. package/dist/context-providers/clipboard.d.ts +13 -0
  6. package/dist/context-providers/clipboard.d.ts.map +1 -0
  7. package/dist/context-providers/clipboard.js +53 -0
  8. package/dist/context-providers/clipboard.js.map +1 -0
  9. package/dist/context-providers/codebase.d.ts +46 -0
  10. package/dist/context-providers/codebase.d.ts.map +1 -0
  11. package/dist/context-providers/codebase.js +273 -0
  12. package/dist/context-providers/codebase.js.map +1 -0
  13. package/dist/context-providers/diff.d.ts +18 -0
  14. package/dist/context-providers/diff.d.ts.map +1 -0
  15. package/dist/context-providers/diff.js +63 -0
  16. package/dist/context-providers/diff.js.map +1 -0
  17. package/dist/context-providers/docs.d.ts +21 -0
  18. package/dist/context-providers/docs.d.ts.map +1 -0
  19. package/dist/context-providers/docs.js +180 -0
  20. package/dist/context-providers/docs.js.map +1 -0
  21. package/dist/context-providers/file-include.d.ts +13 -0
  22. package/dist/context-providers/file-include.d.ts.map +1 -0
  23. package/dist/context-providers/file-include.js +82 -0
  24. package/dist/context-providers/file-include.js.map +1 -0
  25. package/dist/context-providers/folder.d.ts +19 -0
  26. package/dist/context-providers/folder.d.ts.map +1 -0
  27. package/dist/context-providers/folder.js +130 -0
  28. package/dist/context-providers/folder.js.map +1 -0
  29. package/dist/context-providers/git.d.ts +19 -0
  30. package/dist/context-providers/git.d.ts.map +1 -0
  31. package/dist/context-providers/git.js +74 -0
  32. package/dist/context-providers/git.js.map +1 -0
  33. package/dist/context-providers/index.d.ts +26 -0
  34. package/dist/context-providers/index.d.ts.map +1 -0
  35. package/dist/context-providers/index.js +37 -0
  36. package/dist/context-providers/index.js.map +1 -0
  37. package/dist/context-providers/open-files.d.ts +25 -0
  38. package/dist/context-providers/open-files.d.ts.map +1 -0
  39. package/dist/context-providers/open-files.js +134 -0
  40. package/dist/context-providers/open-files.js.map +1 -0
  41. package/dist/context-providers/problems.d.ts +24 -0
  42. package/dist/context-providers/problems.d.ts.map +1 -0
  43. package/dist/context-providers/problems.js +97 -0
  44. package/dist/context-providers/problems.js.map +1 -0
  45. package/dist/context-providers/registry.d.ts +61 -0
  46. package/dist/context-providers/registry.d.ts.map +1 -0
  47. package/dist/context-providers/registry.js +92 -0
  48. package/dist/context-providers/registry.js.map +1 -0
  49. package/dist/context-providers/terminal.d.ts +25 -0
  50. package/dist/context-providers/terminal.d.ts.map +1 -0
  51. package/dist/context-providers/terminal.js +55 -0
  52. package/dist/context-providers/terminal.js.map +1 -0
  53. package/dist/context-providers/tree.d.ts +29 -0
  54. package/dist/context-providers/tree.d.ts.map +1 -0
  55. package/dist/context-providers/tree.js +172 -0
  56. package/dist/context-providers/tree.js.map +1 -0
  57. package/dist/context-providers/types.d.ts +72 -0
  58. package/dist/context-providers/types.d.ts.map +1 -0
  59. package/dist/context-providers/types.js +10 -0
  60. package/dist/context-providers/types.js.map +1 -0
  61. package/dist/context-providers/url.d.ts +27 -0
  62. package/dist/context-providers/url.d.ts.map +1 -0
  63. package/dist/context-providers/url.js +131 -0
  64. package/dist/context-providers/url.js.map +1 -0
  65. package/dist/effort/index.d.ts +78 -0
  66. package/dist/effort/index.d.ts.map +1 -0
  67. package/dist/effort/index.js +146 -0
  68. package/dist/effort/index.js.map +1 -0
  69. package/dist/hooks/index.d.ts +47 -0
  70. package/dist/hooks/index.d.ts.map +1 -0
  71. package/dist/hooks/index.js +151 -0
  72. package/dist/hooks/index.js.map +1 -0
  73. package/dist/index.d.ts +75 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +152 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/indexing/chunker.d.ts +25 -0
  78. package/dist/indexing/chunker.d.ts.map +1 -0
  79. package/dist/indexing/chunker.js +217 -0
  80. package/dist/indexing/chunker.js.map +1 -0
  81. package/dist/indexing/database.d.ts +49 -0
  82. package/dist/indexing/database.d.ts.map +1 -0
  83. package/dist/indexing/database.js +287 -0
  84. package/dist/indexing/database.js.map +1 -0
  85. package/dist/indexing/index.d.ts +9 -0
  86. package/dist/indexing/index.d.ts.map +1 -0
  87. package/dist/indexing/index.js +13 -0
  88. package/dist/indexing/index.js.map +1 -0
  89. package/dist/indexing/indexer.d.ts +63 -0
  90. package/dist/indexing/indexer.d.ts.map +1 -0
  91. package/dist/indexing/indexer.js +352 -0
  92. package/dist/indexing/indexer.js.map +1 -0
  93. package/dist/indexing/recent-edits-cache.d.ts +77 -0
  94. package/dist/indexing/recent-edits-cache.d.ts.map +1 -0
  95. package/dist/indexing/recent-edits-cache.js +123 -0
  96. package/dist/indexing/recent-edits-cache.js.map +1 -0
  97. package/dist/indexing/types.d.ts +39 -0
  98. package/dist/indexing/types.d.ts.map +1 -0
  99. package/dist/indexing/types.js +6 -0
  100. package/dist/indexing/types.js.map +1 -0
  101. package/dist/mcp/index.d.ts +33 -0
  102. package/dist/mcp/index.d.ts.map +1 -0
  103. package/dist/mcp/index.js +37 -0
  104. package/dist/mcp/index.js.map +1 -0
  105. package/dist/mcp/manager.d.ts +123 -0
  106. package/dist/mcp/manager.d.ts.map +1 -0
  107. package/dist/mcp/manager.js +331 -0
  108. package/dist/mcp/manager.js.map +1 -0
  109. package/dist/oauth.d.ts +33 -0
  110. package/dist/oauth.d.ts.map +1 -0
  111. package/dist/oauth.js +312 -0
  112. package/dist/oauth.js.map +1 -0
  113. package/dist/permissions/index.d.ts +216 -0
  114. package/dist/permissions/index.d.ts.map +1 -0
  115. package/dist/permissions/index.js +938 -0
  116. package/dist/permissions/index.js.map +1 -0
  117. package/dist/plan/index.d.ts +20 -0
  118. package/dist/plan/index.d.ts.map +1 -0
  119. package/dist/plan/index.js +24 -0
  120. package/dist/plan/index.js.map +1 -0
  121. package/dist/plan/manager.d.ts +101 -0
  122. package/dist/plan/manager.d.ts.map +1 -0
  123. package/dist/plan/manager.js +170 -0
  124. package/dist/plan/manager.js.map +1 -0
  125. package/dist/rules/index.d.ts +28 -0
  126. package/dist/rules/index.d.ts.map +1 -0
  127. package/dist/rules/index.js +31 -0
  128. package/dist/rules/index.js.map +1 -0
  129. package/dist/rules/manager.d.ts +77 -0
  130. package/dist/rules/manager.d.ts.map +1 -0
  131. package/dist/rules/manager.js +279 -0
  132. package/dist/rules/manager.js.map +1 -0
  133. package/dist/rules/types.d.ts +34 -0
  134. package/dist/rules/types.d.ts.map +1 -0
  135. package/dist/rules/types.js +9 -0
  136. package/dist/rules/types.js.map +1 -0
  137. package/dist/sandbox/filesystem.d.ts +20 -0
  138. package/dist/sandbox/filesystem.d.ts.map +1 -0
  139. package/dist/sandbox/filesystem.js +141 -0
  140. package/dist/sandbox/filesystem.js.map +1 -0
  141. package/dist/sandbox/index.d.ts +4 -0
  142. package/dist/sandbox/index.d.ts.map +1 -0
  143. package/dist/sandbox/index.js +8 -0
  144. package/dist/sandbox/index.js.map +1 -0
  145. package/dist/sandbox/manager.d.ts +47 -0
  146. package/dist/sandbox/manager.d.ts.map +1 -0
  147. package/dist/sandbox/manager.js +220 -0
  148. package/dist/sandbox/manager.js.map +1 -0
  149. package/dist/sandbox/network.d.ts +14 -0
  150. package/dist/sandbox/network.d.ts.map +1 -0
  151. package/dist/sandbox/network.js +87 -0
  152. package/dist/sandbox/network.js.map +1 -0
  153. package/dist/sandbox/types.d.ts +42 -0
  154. package/dist/sandbox/types.d.ts.map +1 -0
  155. package/dist/sandbox/types.js +25 -0
  156. package/dist/sandbox/types.js.map +1 -0
  157. package/dist/tools/ast-edit.d.ts +57 -0
  158. package/dist/tools/ast-edit.d.ts.map +1 -0
  159. package/dist/tools/ast-edit.js +443 -0
  160. package/dist/tools/ast-edit.js.map +1 -0
  161. package/dist/tools/code-verify.d.ts +8 -0
  162. package/dist/tools/code-verify.d.ts.map +1 -0
  163. package/dist/tools/code-verify.js +159 -0
  164. package/dist/tools/code-verify.js.map +1 -0
  165. package/dist/tools/codebase-search.d.ts +17 -0
  166. package/dist/tools/codebase-search.d.ts.map +1 -0
  167. package/dist/tools/codebase-search.js +104 -0
  168. package/dist/tools/codebase-search.js.map +1 -0
  169. package/dist/tools/file-delete.d.ts +26 -0
  170. package/dist/tools/file-delete.d.ts.map +1 -0
  171. package/dist/tools/file-delete.js +179 -0
  172. package/dist/tools/file-delete.js.map +1 -0
  173. package/dist/tools/file-edit.d.ts +10 -0
  174. package/dist/tools/file-edit.d.ts.map +1 -0
  175. package/dist/tools/file-edit.js +138 -0
  176. package/dist/tools/file-edit.js.map +1 -0
  177. package/dist/tools/file-read.d.ts +12 -0
  178. package/dist/tools/file-read.d.ts.map +1 -0
  179. package/dist/tools/file-read.js +211 -0
  180. package/dist/tools/file-read.js.map +1 -0
  181. package/dist/tools/file-run.d.ts +10 -0
  182. package/dist/tools/file-run.d.ts.map +1 -0
  183. package/dist/tools/file-run.js +179 -0
  184. package/dist/tools/file-run.js.map +1 -0
  185. package/dist/tools/file-write.d.ts +10 -0
  186. package/dist/tools/file-write.d.ts.map +1 -0
  187. package/dist/tools/file-write.js +134 -0
  188. package/dist/tools/file-write.js.map +1 -0
  189. package/dist/tools/glob-search.d.ts +8 -0
  190. package/dist/tools/glob-search.d.ts.map +1 -0
  191. package/dist/tools/glob-search.js +108 -0
  192. package/dist/tools/glob-search.js.map +1 -0
  193. package/dist/tools/grep-search.d.ts +8 -0
  194. package/dist/tools/grep-search.d.ts.map +1 -0
  195. package/dist/tools/grep-search.js +139 -0
  196. package/dist/tools/grep-search.js.map +1 -0
  197. package/dist/tools/list-dir.d.ts +16 -0
  198. package/dist/tools/list-dir.d.ts.map +1 -0
  199. package/dist/tools/list-dir.js +183 -0
  200. package/dist/tools/list-dir.js.map +1 -0
  201. package/dist/tools/multi-edit.d.ts +16 -0
  202. package/dist/tools/multi-edit.d.ts.map +1 -0
  203. package/dist/tools/multi-edit.js +163 -0
  204. package/dist/tools/multi-edit.js.map +1 -0
  205. package/dist/tools/notebook-edit.d.ts +31 -0
  206. package/dist/tools/notebook-edit.d.ts.map +1 -0
  207. package/dist/tools/notebook-edit.js +321 -0
  208. package/dist/tools/notebook-edit.js.map +1 -0
  209. package/dist/tools/registry.d.ts +16 -0
  210. package/dist/tools/registry.d.ts.map +1 -0
  211. package/dist/tools/registry.js +41 -0
  212. package/dist/tools/registry.js.map +1 -0
  213. package/dist/tools/shell-exec.d.ts +12 -0
  214. package/dist/tools/shell-exec.d.ts.map +1 -0
  215. package/dist/tools/shell-exec.js +261 -0
  216. package/dist/tools/shell-exec.js.map +1 -0
  217. package/dist/tools/sub-agent-manager.d.ts +57 -0
  218. package/dist/tools/sub-agent-manager.d.ts.map +1 -0
  219. package/dist/tools/sub-agent-manager.js +153 -0
  220. package/dist/tools/sub-agent-manager.js.map +1 -0
  221. package/dist/tools/sub-agent-status.d.ts +12 -0
  222. package/dist/tools/sub-agent-status.d.ts.map +1 -0
  223. package/dist/tools/sub-agent-status.js +59 -0
  224. package/dist/tools/sub-agent-status.js.map +1 -0
  225. package/dist/tools/sub-agent-terminate.d.ts +12 -0
  226. package/dist/tools/sub-agent-terminate.d.ts.map +1 -0
  227. package/dist/tools/sub-agent-terminate.js +55 -0
  228. package/dist/tools/sub-agent-terminate.js.map +1 -0
  229. package/dist/tools/sub-agent.d.ts +34 -0
  230. package/dist/tools/sub-agent.d.ts.map +1 -0
  231. package/dist/tools/sub-agent.js +140 -0
  232. package/dist/tools/sub-agent.js.map +1 -0
  233. package/dist/tools/system-info.d.ts +24 -0
  234. package/dist/tools/system-info.d.ts.map +1 -0
  235. package/dist/tools/system-info.js +220 -0
  236. package/dist/tools/system-info.js.map +1 -0
  237. package/dist/tools/todo.d.ts +16 -0
  238. package/dist/tools/todo.d.ts.map +1 -0
  239. package/dist/tools/todo.js +144 -0
  240. package/dist/tools/todo.js.map +1 -0
  241. package/dist/tools/types.d.ts +20 -0
  242. package/dist/tools/types.d.ts.map +1 -0
  243. package/dist/tools/types.js +3 -0
  244. package/dist/tools/types.js.map +1 -0
  245. package/dist/tools/view-diff.d.ts +11 -0
  246. package/dist/tools/view-diff.d.ts.map +1 -0
  247. package/dist/tools/view-diff.js +88 -0
  248. package/dist/tools/view-diff.js.map +1 -0
  249. package/dist/tools/view-repo-map.d.ts +18 -0
  250. package/dist/tools/view-repo-map.d.ts.map +1 -0
  251. package/dist/tools/view-repo-map.js +245 -0
  252. package/dist/tools/view-repo-map.js.map +1 -0
  253. package/dist/tools/web-fetch.d.ts +13 -0
  254. package/dist/tools/web-fetch.d.ts.map +1 -0
  255. package/dist/tools/web-fetch.js +106 -0
  256. package/dist/tools/web-fetch.js.map +1 -0
  257. package/dist/tools/web-search.d.ts +10 -0
  258. package/dist/tools/web-search.d.ts.map +1 -0
  259. package/dist/tools/web-search.js +106 -0
  260. package/dist/tools/web-search.js.map +1 -0
  261. package/dist/utils/gitignore.d.ts +10 -0
  262. package/dist/utils/gitignore.d.ts.map +1 -0
  263. package/dist/utils/gitignore.js +104 -0
  264. package/dist/utils/gitignore.js.map +1 -0
  265. package/dist/utils/lazy-apply.d.ts +45 -0
  266. package/dist/utils/lazy-apply.d.ts.map +1 -0
  267. package/dist/utils/lazy-apply.js +164 -0
  268. package/dist/utils/lazy-apply.js.map +1 -0
  269. package/dist/utils/memory.d.ts +36 -0
  270. package/dist/utils/memory.d.ts.map +1 -0
  271. package/dist/utils/memory.js +136 -0
  272. package/dist/utils/memory.js.map +1 -0
  273. package/dist/utils/path-matching.d.ts +24 -0
  274. package/dist/utils/path-matching.d.ts.map +1 -0
  275. package/dist/utils/path-matching.js +116 -0
  276. package/dist/utils/path-matching.js.map +1 -0
  277. package/dist/utils/path-safety.d.ts +13 -0
  278. package/dist/utils/path-safety.d.ts.map +1 -0
  279. package/dist/utils/path-safety.js +54 -0
  280. package/dist/utils/path-safety.js.map +1 -0
  281. package/dist/utils/project-config.d.ts +18 -0
  282. package/dist/utils/project-config.d.ts.map +1 -0
  283. package/dist/utils/project-config.js +76 -0
  284. package/dist/utils/project-config.js.map +1 -0
  285. package/dist/utils/search-match.d.ts +63 -0
  286. package/dist/utils/search-match.d.ts.map +1 -0
  287. package/dist/utils/search-match.js +426 -0
  288. package/dist/utils/search-match.js.map +1 -0
  289. package/dist/utils/shell-paths.d.ts +17 -0
  290. package/dist/utils/shell-paths.d.ts.map +1 -0
  291. package/dist/utils/shell-paths.js +107 -0
  292. package/dist/utils/shell-paths.js.map +1 -0
  293. package/dist/utils/streaming-diff.d.ts +45 -0
  294. package/dist/utils/streaming-diff.d.ts.map +1 -0
  295. package/dist/utils/streaming-diff.js +230 -0
  296. package/dist/utils/streaming-diff.js.map +1 -0
  297. package/dist/utils/todo.d.ts +47 -0
  298. package/dist/utils/todo.d.ts.map +1 -0
  299. package/dist/utils/todo.js +102 -0
  300. package/dist/utils/todo.js.map +1 -0
  301. package/package.json +23 -0
  302. package/src/agents/coordinator.ts +240 -0
  303. package/src/context-providers/clipboard.ts +48 -0
  304. package/src/context-providers/codebase.ts +274 -0
  305. package/src/context-providers/diff.ts +66 -0
  306. package/src/context-providers/docs.ts +160 -0
  307. package/src/context-providers/file-include.ts +54 -0
  308. package/src/context-providers/folder.ts +106 -0
  309. package/src/context-providers/git.ts +72 -0
  310. package/src/context-providers/index.ts +26 -0
  311. package/src/context-providers/open-files.ts +113 -0
  312. package/src/context-providers/problems.ts +100 -0
  313. package/src/context-providers/registry.ts +99 -0
  314. package/src/context-providers/terminal.ts +58 -0
  315. package/src/context-providers/tree.ts +161 -0
  316. package/src/context-providers/types.ts +84 -0
  317. package/src/context-providers/url.ts +138 -0
  318. package/src/effort/index.ts +177 -0
  319. package/src/hooks/index.ts +148 -0
  320. package/src/index.ts +114 -0
  321. package/src/indexing/README.md +267 -0
  322. package/src/indexing/chunker.ts +206 -0
  323. package/src/indexing/database.ts +299 -0
  324. package/src/indexing/index.ts +15 -0
  325. package/src/indexing/indexer.ts +383 -0
  326. package/src/indexing/recent-edits-cache.ts +150 -0
  327. package/src/indexing/types.ts +44 -0
  328. package/src/mcp/index.ts +33 -0
  329. package/src/mcp/manager.ts +385 -0
  330. package/src/oauth.ts +330 -0
  331. package/src/permissions/index.ts +1011 -0
  332. package/src/plan/index.ts +20 -0
  333. package/src/plan/manager.ts +233 -0
  334. package/src/rules/index.ts +28 -0
  335. package/src/rules/manager.ts +276 -0
  336. package/src/rules/types.ts +40 -0
  337. package/src/sandbox/filesystem.ts +135 -0
  338. package/src/sandbox/index.ts +9 -0
  339. package/src/sandbox/manager.ts +213 -0
  340. package/src/sandbox/network.ts +101 -0
  341. package/src/sandbox/types.ts +63 -0
  342. package/src/tools/ast-edit.ts +493 -0
  343. package/src/tools/code-verify.ts +143 -0
  344. package/src/tools/codebase-search.ts +117 -0
  345. package/src/tools/file-delete.ts +155 -0
  346. package/src/tools/file-edit.ts +115 -0
  347. package/src/tools/file-read.ts +195 -0
  348. package/src/tools/file-run.ts +158 -0
  349. package/src/tools/file-write.ts +104 -0
  350. package/src/tools/glob-search.ts +80 -0
  351. package/src/tools/grep-search.ts +120 -0
  352. package/src/tools/list-dir.ts +172 -0
  353. package/src/tools/multi-edit.ts +138 -0
  354. package/src/tools/notebook-edit.ts +342 -0
  355. package/src/tools/registry.ts +43 -0
  356. package/src/tools/shell-exec.ts +251 -0
  357. package/src/tools/sub-agent-manager.ts +183 -0
  358. package/src/tools/sub-agent-status.ts +67 -0
  359. package/src/tools/sub-agent-terminate.ts +62 -0
  360. package/src/tools/sub-agent.ts +162 -0
  361. package/src/tools/system-info.ts +248 -0
  362. package/src/tools/todo.ts +149 -0
  363. package/src/tools/types.ts +21 -0
  364. package/src/tools/view-diff.ts +99 -0
  365. package/src/tools/view-repo-map.ts +249 -0
  366. package/src/tools/web-fetch.ts +118 -0
  367. package/src/tools/web-search.ts +129 -0
  368. package/src/utils/gitignore.ts +73 -0
  369. package/src/utils/lazy-apply.ts +189 -0
  370. package/src/utils/memory.ts +124 -0
  371. package/src/utils/path-matching.ts +84 -0
  372. package/src/utils/path-safety.ts +19 -0
  373. package/src/utils/project-config.ts +41 -0
  374. package/src/utils/search-match.ts +495 -0
  375. package/src/utils/shell-paths.ts +79 -0
  376. package/src/utils/streaming-diff.ts +260 -0
  377. package/src/utils/todo.ts +115 -0
  378. package/tsconfig.json +18 -0
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Lazy Apply — LLM-assisted placeholder expansion for file edits.
3
+ *
4
+ * When an LLM generates code with placeholder markers like:
5
+ * // ... existing code ...
6
+ * // ... rest of the function ...
7
+ * # ... remaining imports ...
8
+ *
9
+ * This module detects those placeholders and expands them by preserving
10
+ * the corresponding original code sections. This allows LLMs to make
11
+ * targeted edits without reproducing entire files.
12
+ *
13
+ * Three strategies:
14
+ * 1. Deterministic — match anchors (lines before/after placeholder) against
15
+ * original content and splice in the preserved region
16
+ * 2. Unified diff — if the new content is a diff, apply it directly
17
+ * 3. Streaming — process token-by-token as LLM generates, expanding in real-time
18
+ */
19
+
20
+ /**
21
+ * Common placeholder patterns used by LLMs to indicate "keep existing code here".
22
+ * Matches patterns like:
23
+ * // ... existing code ...
24
+ * // ... rest of the function ...
25
+ * # ... remaining imports ...
26
+ * /* ... keep existing ... * /
27
+ * // [existing code]
28
+ * // (rest remains the same)
29
+ */
30
+ const PLACEHOLDER_PATTERNS = [
31
+ // Comment-style with ellipsis: // ... existing code ...
32
+ /^(\s*)(?:\/\/|#|--|\/\*|\*|<!--)\s*\.{2,}\s*(existing|remaining|rest|keep|same|unchanged|other|previous).*$/i,
33
+ // Comment-style with brackets: // [existing code]
34
+ /^(\s*)(?:\/\/|#|--|\/\*|\*|<!--)\s*\[(?:existing|remaining|rest|keep|same|unchanged|other|previous).*\].*$/i,
35
+ // Comment-style with parens: // (rest remains the same)
36
+ /^(\s*)(?:\/\/|#|--|\/\*|\*|<!--)\s*\((?:existing|remaining|rest|keep|same|unchanged|other|previous).*\).*$/i,
37
+ // Bare ellipsis comment: // ...
38
+ /^(\s*)(?:\/\/|#|--|\/\*|\*|<!--)\s*\.{3,}\s*(?:\*\/|-->)?\s*$/,
39
+ ];
40
+
41
+ export interface LazyApplyResult {
42
+ content: string;
43
+ placeholdersExpanded: number;
44
+ strategy: "deterministic" | "none";
45
+ }
46
+
47
+ /**
48
+ * Check if a line is a placeholder marker.
49
+ */
50
+ export function isPlaceholderLine(line: string): boolean {
51
+ return PLACEHOLDER_PATTERNS.some((p) => p.test(line));
52
+ }
53
+
54
+ /**
55
+ * Detect if content contains any placeholder markers.
56
+ */
57
+ export function hasPlaceholders(content: string): boolean {
58
+ return content.split("\n").some(isPlaceholderLine);
59
+ }
60
+
61
+ /**
62
+ * Expand placeholders in newContent by referencing originalContent.
63
+ *
64
+ * Algorithm:
65
+ * 1. Split both contents into lines
66
+ * 2. Walk through newContent lines
67
+ * 3. When a placeholder line is found:
68
+ * a. Use anchor lines (the non-placeholder lines before and after) to locate
69
+ * the corresponding region in the original file
70
+ * b. Splice in the original lines between the anchors
71
+ * 4. Return the expanded content
72
+ */
73
+ export function expandPlaceholders(
74
+ originalContent: string,
75
+ newContent: string,
76
+ ): LazyApplyResult {
77
+ const newLines = newContent.split("\n");
78
+
79
+ if (!newLines.some(isPlaceholderLine)) {
80
+ return { content: newContent, placeholdersExpanded: 0, strategy: "none" };
81
+ }
82
+
83
+ const originalLines = originalContent.split("\n");
84
+ const result: string[] = [];
85
+ let placeholdersExpanded = 0;
86
+ let i = 0;
87
+
88
+ while (i < newLines.length) {
89
+ if (!isPlaceholderLine(newLines[i])) {
90
+ result.push(newLines[i]);
91
+ i++;
92
+ continue;
93
+ }
94
+
95
+ // Found a placeholder — find anchor lines before and after
96
+ const anchorBefore = findAnchorBefore(result);
97
+ const anchorAfter = findAnchorAfter(newLines, i);
98
+
99
+ // Locate the region in original content between these anchors
100
+ const region = findOriginalRegion(originalLines, anchorBefore, anchorAfter);
101
+
102
+ if (region) {
103
+ // Splice in the original lines
104
+ for (let r = region.start; r < region.end; r++) {
105
+ result.push(originalLines[r]);
106
+ }
107
+ placeholdersExpanded++;
108
+ } else {
109
+ // Couldn't find region — keep placeholder as a comment so it's visible
110
+ result.push(newLines[i]);
111
+ }
112
+
113
+ i++;
114
+ }
115
+
116
+ return {
117
+ content: result.join("\n"),
118
+ placeholdersExpanded,
119
+ strategy: placeholdersExpanded > 0 ? "deterministic" : "none",
120
+ };
121
+ }
122
+
123
+ /**
124
+ * Find the last non-empty, non-placeholder line from the result so far.
125
+ */
126
+ function findAnchorBefore(resultSoFar: string[]): string | null {
127
+ for (let i = resultSoFar.length - 1; i >= 0; i--) {
128
+ const line = resultSoFar[i].trim();
129
+ if (line && !isPlaceholderLine(resultSoFar[i])) {
130
+ return resultSoFar[i];
131
+ }
132
+ }
133
+ return null;
134
+ }
135
+
136
+ /**
137
+ * Find the next non-empty, non-placeholder line after position i.
138
+ */
139
+ function findAnchorAfter(lines: string[], fromIndex: number): string | null {
140
+ for (let i = fromIndex + 1; i < lines.length; i++) {
141
+ const line = lines[i].trim();
142
+ if (line && !isPlaceholderLine(lines[i])) {
143
+ return lines[i];
144
+ }
145
+ }
146
+ return null;
147
+ }
148
+
149
+ /**
150
+ * Find the region in originalLines between anchorBefore and anchorAfter.
151
+ * Returns the line range (exclusive end) of original lines to preserve.
152
+ */
153
+ function findOriginalRegion(
154
+ originalLines: string[],
155
+ anchorBefore: string | null,
156
+ anchorAfter: string | null,
157
+ ): { start: number; end: number } | null {
158
+ let startIdx = 0;
159
+ let endIdx = originalLines.length;
160
+
161
+ // Find where anchorBefore occurs in original
162
+ if (anchorBefore !== null) {
163
+ const beforeTrimmed = anchorBefore.trim();
164
+ for (let i = 0; i < originalLines.length; i++) {
165
+ if (originalLines[i].trim() === beforeTrimmed) {
166
+ startIdx = i + 1; // Start after the anchor
167
+ break;
168
+ }
169
+ }
170
+ }
171
+
172
+ // Find where anchorAfter occurs in original (searching from startIdx)
173
+ if (anchorAfter !== null) {
174
+ const afterTrimmed = anchorAfter.trim();
175
+ for (let i = startIdx; i < originalLines.length; i++) {
176
+ if (originalLines[i].trim() === afterTrimmed) {
177
+ endIdx = i; // End before the anchor
178
+ break;
179
+ }
180
+ }
181
+ }
182
+
183
+ // Validate we found a sensible region
184
+ if (startIdx >= endIdx) {
185
+ return null;
186
+ }
187
+
188
+ return { start: startIdx, end: endIdx };
189
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Memory System — persistent memory across sessions.
3
+ *
4
+ * Stores key-value memories in ~/.cdoing/memory.json
5
+ * The agent can save, recall, and forget memories.
6
+ */
7
+
8
+ import * as fs from "fs";
9
+ import * as path from "path";
10
+ import * as os from "os";
11
+
12
+ const MEMORY_DIR = path.join(os.homedir(), ".cdoing");
13
+ const MEMORY_FILE = path.join(MEMORY_DIR, "memory.json");
14
+
15
+ export interface MemoryEntry {
16
+ key: string;
17
+ value: string;
18
+ category: "user" | "project" | "preference" | "context";
19
+ createdAt: string;
20
+ updatedAt: string;
21
+ }
22
+
23
+ export class MemoryStore {
24
+ private memories: MemoryEntry[] = [];
25
+
26
+ constructor() {
27
+ this.load();
28
+ }
29
+
30
+ private load(): void {
31
+ try {
32
+ if (fs.existsSync(MEMORY_FILE)) {
33
+ const data = JSON.parse(fs.readFileSync(MEMORY_FILE, "utf-8"));
34
+ this.memories = Array.isArray(data.memories) ? data.memories : [];
35
+ }
36
+ } catch {
37
+ this.memories = [];
38
+ }
39
+ }
40
+
41
+ private save(): void {
42
+ if (!fs.existsSync(MEMORY_DIR)) fs.mkdirSync(MEMORY_DIR, { recursive: true });
43
+ fs.writeFileSync(
44
+ MEMORY_FILE,
45
+ JSON.stringify({ memories: this.memories }, null, 2),
46
+ "utf-8"
47
+ );
48
+ }
49
+
50
+ /** Save or update a memory */
51
+ set(key: string, value: string, category: MemoryEntry["category"] = "context"): void {
52
+ const now = new Date().toISOString();
53
+ const existing = this.memories.find((m) => m.key === key);
54
+ if (existing) {
55
+ existing.value = value;
56
+ existing.updatedAt = now;
57
+ existing.category = category;
58
+ } else {
59
+ this.memories.push({ key, value, category, createdAt: now, updatedAt: now });
60
+ }
61
+ this.save();
62
+ }
63
+
64
+ /** Get a specific memory */
65
+ get(key: string): string | null {
66
+ const entry = this.memories.find((m) => m.key === key);
67
+ return entry?.value || null;
68
+ }
69
+
70
+ /** Search memories by keyword */
71
+ search(query: string): MemoryEntry[] {
72
+ const q = query.toLowerCase();
73
+ return this.memories.filter(
74
+ (m) => m.key.toLowerCase().includes(q) || m.value.toLowerCase().includes(q)
75
+ );
76
+ }
77
+
78
+ /** Get all memories */
79
+ getAll(): ReadonlyArray<MemoryEntry> {
80
+ return this.memories;
81
+ }
82
+
83
+ /** Get memories by category */
84
+ getByCategory(category: MemoryEntry["category"]): MemoryEntry[] {
85
+ return this.memories.filter((m) => m.category === category);
86
+ }
87
+
88
+ /** Delete a memory */
89
+ forget(key: string): boolean {
90
+ const index = this.memories.findIndex((m) => m.key === key);
91
+ if (index === -1) return false;
92
+ this.memories.splice(index, 1);
93
+ this.save();
94
+ return true;
95
+ }
96
+
97
+ /** Clear all memories */
98
+ clear(): void {
99
+ this.memories = [];
100
+ this.save();
101
+ }
102
+
103
+ /** Format memories for inclusion in system prompt */
104
+ formatForPrompt(): string {
105
+ if (this.memories.length === 0) return "";
106
+
107
+ const byCategory = new Map<string, MemoryEntry[]>();
108
+ for (const m of this.memories) {
109
+ const list = byCategory.get(m.category) || [];
110
+ list.push(m);
111
+ byCategory.set(m.category, list);
112
+ }
113
+
114
+ const parts: string[] = [];
115
+ for (const [category, entries] of byCategory) {
116
+ parts.push(`## ${category}`);
117
+ for (const e of entries) {
118
+ parts.push(`- **${e.key}**: ${e.value}`);
119
+ }
120
+ }
121
+
122
+ return parts.join("\n");
123
+ }
124
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Path Matching Utilities — shared by permissions and sandbox systems.
3
+ *
4
+ * Supports path specifier prefixes:
5
+ * //abs/path → absolute from filesystem root
6
+ * ~/rel/path → relative to home directory
7
+ * /proj/path → relative to project root
8
+ * ./rel/path → relative to current working directory
9
+ * rel/path → relative to current working directory
10
+ */
11
+
12
+ import * as path from "path";
13
+ import * as os from "os";
14
+
15
+ const HOME_DIR = os.homedir();
16
+
17
+ /**
18
+ * Resolve a specifier to an absolute base path for matching.
19
+ */
20
+ export function resolveSpecifierBase(specifier: string, projectDir: string, cwd: string): string {
21
+ if (specifier.startsWith("//")) {
22
+ return path.normalize("/" + specifier.substring(2));
23
+ }
24
+ if (specifier.startsWith("~/")) {
25
+ return path.join(HOME_DIR, specifier.substring(2));
26
+ }
27
+ if (specifier.startsWith("/")) {
28
+ return path.join(projectDir, specifier.substring(1));
29
+ }
30
+ if (specifier.startsWith("./")) {
31
+ return path.join(cwd, specifier.substring(2));
32
+ }
33
+ return path.join(cwd, specifier);
34
+ }
35
+
36
+ /** Glob match: * matches single directory segment, ** matches recursively. */
37
+ export function pathGlob(filePath: string, pattern: string): boolean {
38
+ if (!pattern.includes("*")) {
39
+ return filePath === pattern || filePath.startsWith(pattern + path.sep);
40
+ }
41
+ const patParts = pattern.split(path.sep);
42
+ const fileParts = filePath.split(path.sep);
43
+ return matchPathParts(fileParts, patParts, 0, 0);
44
+ }
45
+
46
+ export function matchPathParts(fp: string[], pp: string[], fi: number, pi: number): boolean {
47
+ while (pi < pp.length) {
48
+ if (pp[pi] === "**") {
49
+ for (let k = fi; k <= fp.length; k++) {
50
+ if (matchPathParts(fp, pp, k, pi + 1)) return true;
51
+ }
52
+ return false;
53
+ }
54
+ if (fi >= fp.length) return false;
55
+ if (!matchSegment(fp[fi], pp[pi])) return false;
56
+ fi++;
57
+ pi++;
58
+ }
59
+ return fi === fp.length;
60
+ }
61
+
62
+ export function matchSegment(name: string, pat: string): boolean {
63
+ if (!pat.includes("*")) return name === pat;
64
+ const rx = "^" + pat.split("*").map(escapeRegex).join("[^/]*") + "$";
65
+ return new RegExp(rx).test(name);
66
+ }
67
+
68
+ function escapeRegex(s: string): string {
69
+ return s.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
70
+ }
71
+
72
+ /**
73
+ * Match a file path against a specifier, resolving the specifier relative
74
+ * to the project directory and current working directory.
75
+ */
76
+ export function matchPath(
77
+ filePath: string,
78
+ specifier: string,
79
+ projectDir: string,
80
+ cwd: string,
81
+ ): boolean {
82
+ const base = resolveSpecifierBase(specifier, projectDir, cwd);
83
+ return pathGlob(filePath, base);
84
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Path Safety — resolves user-provided paths to absolute paths.
3
+ *
4
+ * Access control is handled by the permission system (allow/deny rules)
5
+ * and the sandbox system (filesystem restrictions when enabled).
6
+ * This utility only normalizes paths — it does NOT restrict access.
7
+ */
8
+
9
+ import * as path from "path";
10
+
11
+ /**
12
+ * Resolve a user-provided path to an absolute, normalized path.
13
+ * Relative paths are resolved against the working directory.
14
+ */
15
+ export function safePath(userPath: string, workingDir: string): string {
16
+ return path.isAbsolute(userPath)
17
+ ? path.resolve(userPath)
18
+ : path.resolve(workingDir, userPath);
19
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Project Config — reads .cdoing/config.md for project-specific instructions.
3
+ * Similar to Claude Code's CLAUDE.md system.
4
+ *
5
+ * Looks for config in these locations (in order):
6
+ * 1. .cdoing/config.md (project-specific)
7
+ * 2. CDOING.md (project root alternative)
8
+ */
9
+
10
+ import * as fs from "fs";
11
+ import * as path from "path";
12
+
13
+ const CONFIG_FILES = [
14
+ ".cdoing/config.md",
15
+ "CDOING.md",
16
+ ];
17
+
18
+ /**
19
+ * Load project configuration from the working directory.
20
+ * Returns the content of the first config file found, or null.
21
+ */
22
+ export function loadProjectConfig(workingDir: string): string | null {
23
+ for (const file of CONFIG_FILES) {
24
+ const filePath = path.join(workingDir, file);
25
+ try {
26
+ if (fs.existsSync(filePath)) {
27
+ return fs.readFileSync(filePath, "utf-8").trim();
28
+ }
29
+ } catch {
30
+ // skip unreadable files
31
+ }
32
+ }
33
+ return null;
34
+ }
35
+
36
+ /**
37
+ * Get the path where project config would be stored.
38
+ */
39
+ export function getProjectConfigPath(workingDir: string): string {
40
+ return path.join(workingDir, ".cdoing", "config.md");
41
+ }