orbitx 0.2.4 → 0.2.6

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 (171) hide show
  1. package/dist/core/ai-provider.d.ts +9 -1
  2. package/dist/core/ai-provider.d.ts.map +1 -1
  3. package/dist/core/ai-provider.js.map +1 -1
  4. package/dist/core/anthropic-provider.d.ts +1 -1
  5. package/dist/core/anthropic-provider.d.ts.map +1 -1
  6. package/dist/core/anthropic-provider.js +71 -62
  7. package/dist/core/anthropic-provider.js.map +1 -1
  8. package/dist/core/base-agent.d.ts +2 -0
  9. package/dist/core/base-agent.d.ts.map +1 -1
  10. package/dist/core/base-agent.js +27 -4
  11. package/dist/core/base-agent.js.map +1 -1
  12. package/dist/core/deepseek-provider.d.ts +1 -1
  13. package/dist/core/deepseek-provider.d.ts.map +1 -1
  14. package/dist/core/deepseek-provider.js +49 -50
  15. package/dist/core/deepseek-provider.js.map +1 -1
  16. package/dist/core/mcp-fs-storage.d.ts.map +1 -1
  17. package/dist/core/mcp-fs-storage.js +2 -1
  18. package/dist/core/mcp-fs-storage.js.map +1 -1
  19. package/dist/core/ollama-provider.d.ts +1 -1
  20. package/dist/core/ollama-provider.d.ts.map +1 -1
  21. package/dist/core/ollama-provider.js +47 -34
  22. package/dist/core/ollama-provider.js.map +1 -1
  23. package/dist/core/openai-provider.d.ts +1 -1
  24. package/dist/core/openai-provider.d.ts.map +1 -1
  25. package/dist/core/openai-provider.js +42 -43
  26. package/dist/core/openai-provider.js.map +1 -1
  27. package/dist/core/retry.d.ts +1 -1
  28. package/dist/core/retry.d.ts.map +1 -1
  29. package/dist/core/retry.js +5 -1
  30. package/dist/core/retry.js.map +1 -1
  31. package/dist/tests/core/mcp-computer.test.js +26 -23
  32. package/dist/tests/core/mcp-computer.test.js.map +1 -1
  33. package/dist/tests/core/mcp-connection.test.js +23 -21
  34. package/dist/tests/core/mcp-connection.test.js.map +1 -1
  35. package/dist/tests/core/mcp-ipc-connection.test.js +30 -28
  36. package/dist/tests/core/mcp-ipc-connection.test.js.map +1 -1
  37. package/dist/tests/core/mcp-ws-connection.test.js +31 -30
  38. package/dist/tests/core/mcp-ws-connection.test.js.map +1 -1
  39. package/dist/tests/index.d.ts +27 -0
  40. package/dist/tests/index.d.ts.map +1 -1
  41. package/dist/tests/index.js +27 -0
  42. package/dist/tests/index.js.map +1 -1
  43. package/dist/tests/tools/agent/agent-tools.test.js +149 -147
  44. package/dist/tests/tools/agent/agent-tools.test.js.map +1 -1
  45. package/dist/tests/tools/bash/fixtures.d.ts +16 -0
  46. package/dist/tests/tools/bash/fixtures.d.ts.map +1 -0
  47. package/dist/tests/tools/bash/fixtures.js +22 -0
  48. package/dist/tests/tools/bash/fixtures.js.map +1 -0
  49. package/dist/tests/tools/bash/kill-tree.d.ts +21 -0
  50. package/dist/tests/tools/bash/kill-tree.d.ts.map +1 -0
  51. package/dist/tests/tools/bash/kill-tree.js +47 -0
  52. package/dist/tests/tools/bash/kill-tree.js.map +1 -0
  53. package/dist/tests/tools/bash/list.test.d.ts +2 -0
  54. package/dist/tests/tools/bash/list.test.d.ts.map +1 -0
  55. package/dist/tests/tools/bash/list.test.js +43 -0
  56. package/dist/tests/tools/bash/list.test.js.map +1 -0
  57. package/dist/tests/tools/bash/logs.test.d.ts +2 -0
  58. package/dist/tests/tools/bash/logs.test.d.ts.map +1 -0
  59. package/dist/tests/tools/bash/logs.test.js +48 -0
  60. package/dist/tests/tools/bash/logs.test.js.map +1 -0
  61. package/dist/tests/tools/bash/run.test.d.ts +2 -0
  62. package/dist/tests/tools/bash/run.test.d.ts.map +1 -0
  63. package/dist/tests/tools/bash/run.test.js +53 -0
  64. package/dist/tests/tools/bash/run.test.js.map +1 -0
  65. package/dist/tests/tools/bash/terminate.test.d.ts +2 -0
  66. package/dist/tests/tools/bash/terminate.test.d.ts.map +1 -0
  67. package/dist/tests/tools/bash/terminate.test.js +60 -0
  68. package/dist/tests/tools/bash/terminate.test.js.map +1 -0
  69. package/dist/tests/tools/bash/wait.test.d.ts +2 -0
  70. package/dist/tests/tools/bash/wait.test.d.ts.map +1 -0
  71. package/dist/tests/tools/bash/wait.test.js +45 -0
  72. package/dist/tests/tools/bash/wait.test.js.map +1 -0
  73. package/dist/tests/tools/bash/write-input.test.d.ts +2 -0
  74. package/dist/tests/tools/bash/write-input.test.d.ts.map +1 -0
  75. package/dist/tests/tools/bash/write-input.test.js +65 -0
  76. package/dist/tests/tools/bash/write-input.test.js.map +1 -0
  77. package/dist/tests/tools/browser/browser-tools.test.d.ts +2 -0
  78. package/dist/tests/tools/browser/browser-tools.test.d.ts.map +1 -0
  79. package/dist/tests/tools/browser/browser-tools.test.js +36 -0
  80. package/dist/tests/tools/browser/browser-tools.test.js.map +1 -0
  81. package/dist/tests/tools/fs/create-dir.test.d.ts +2 -0
  82. package/dist/tests/tools/fs/create-dir.test.d.ts.map +1 -0
  83. package/dist/tests/tools/fs/create-dir.test.js +37 -0
  84. package/dist/tests/tools/fs/create-dir.test.js.map +1 -0
  85. package/dist/tests/tools/fs/delete.test.d.ts +2 -0
  86. package/dist/tests/tools/fs/delete.test.d.ts.map +1 -0
  87. package/dist/tests/tools/fs/delete.test.js +69 -0
  88. package/dist/tests/tools/fs/delete.test.js.map +1 -0
  89. package/dist/tests/tools/fs/edit-file.test.d.ts +2 -0
  90. package/dist/tests/tools/fs/edit-file.test.d.ts.map +1 -0
  91. package/dist/tests/tools/fs/edit-file.test.js +103 -0
  92. package/dist/tests/tools/fs/edit-file.test.js.map +1 -0
  93. package/dist/tests/tools/fs/list-dir.test.d.ts +2 -0
  94. package/dist/tests/tools/fs/list-dir.test.d.ts.map +1 -0
  95. package/dist/tests/tools/fs/list-dir.test.js +65 -0
  96. package/dist/tests/tools/fs/list-dir.test.js.map +1 -0
  97. package/dist/tests/tools/fs/move.test.d.ts +2 -0
  98. package/dist/tests/tools/fs/move.test.d.ts.map +1 -0
  99. package/dist/tests/tools/fs/move.test.js +47 -0
  100. package/dist/tests/tools/fs/move.test.js.map +1 -0
  101. package/dist/tests/tools/fs/read-file.test.d.ts +2 -0
  102. package/dist/tests/tools/fs/read-file.test.d.ts.map +1 -0
  103. package/dist/tests/tools/fs/read-file.test.js +52 -0
  104. package/dist/tests/tools/fs/read-file.test.js.map +1 -0
  105. package/dist/tests/tools/fs/stat.test.d.ts +2 -0
  106. package/dist/tests/tools/fs/stat.test.d.ts.map +1 -0
  107. package/dist/tests/tools/fs/stat.test.js +43 -0
  108. package/dist/tests/tools/fs/stat.test.js.map +1 -0
  109. package/dist/tests/tools/fs/write-file.test.d.ts +2 -0
  110. package/dist/tests/tools/fs/write-file.test.d.ts.map +1 -0
  111. package/dist/tests/tools/fs/write-file.test.js +53 -0
  112. package/dist/tests/tools/fs/write-file.test.js.map +1 -0
  113. package/dist/tests/tools/present/add.test.d.ts +2 -0
  114. package/dist/tests/tools/present/add.test.d.ts.map +1 -0
  115. package/dist/tests/tools/present/add.test.js +51 -0
  116. package/dist/tests/tools/present/add.test.js.map +1 -0
  117. package/dist/tests/tools/present/clear.test.d.ts +2 -0
  118. package/dist/tests/tools/present/clear.test.d.ts.map +1 -0
  119. package/dist/tests/tools/present/clear.test.js +44 -0
  120. package/dist/tests/tools/present/clear.test.js.map +1 -0
  121. package/dist/tests/tools/present/get-list.test.d.ts +2 -0
  122. package/dist/tests/tools/present/get-list.test.d.ts.map +1 -0
  123. package/dist/tests/tools/present/get-list.test.js +50 -0
  124. package/dist/tests/tools/present/get-list.test.js.map +1 -0
  125. package/dist/tests/tools/question-answer/question-answer.test.d.ts +2 -0
  126. package/dist/tests/tools/question-answer/question-answer.test.d.ts.map +1 -0
  127. package/dist/tests/tools/question-answer/question-answer.test.js +34 -0
  128. package/dist/tests/tools/question-answer/question-answer.test.js.map +1 -0
  129. package/dist/tests/tools/todo/check-task.test.d.ts +2 -0
  130. package/dist/tests/tools/todo/check-task.test.d.ts.map +1 -0
  131. package/dist/tests/tools/todo/check-task.test.js +42 -0
  132. package/dist/tests/tools/todo/check-task.test.js.map +1 -0
  133. package/dist/tests/tools/todo/create-list.test.d.ts +2 -0
  134. package/dist/tests/tools/todo/create-list.test.d.ts.map +1 -0
  135. package/dist/tests/tools/todo/create-list.test.js +32 -0
  136. package/dist/tests/tools/todo/create-list.test.js.map +1 -0
  137. package/dist/tests/tools/todo/create-task.test.d.ts +2 -0
  138. package/dist/tests/tools/todo/create-task.test.d.ts.map +1 -0
  139. package/dist/tests/tools/todo/create-task.test.js +53 -0
  140. package/dist/tests/tools/todo/create-task.test.js.map +1 -0
  141. package/dist/tests/tools/todo/get-list.test.d.ts +2 -0
  142. package/dist/tests/tools/todo/get-list.test.d.ts.map +1 -0
  143. package/dist/tests/tools/todo/get-list.test.js +38 -0
  144. package/dist/tests/tools/todo/get-list.test.js.map +1 -0
  145. package/dist/tests/tools/todo/get-lists.test.d.ts +2 -0
  146. package/dist/tests/tools/todo/get-lists.test.d.ts.map +1 -0
  147. package/dist/tests/tools/todo/get-lists.test.js +29 -0
  148. package/dist/tests/tools/todo/get-lists.test.js.map +1 -0
  149. package/dist/tests/tools/todo/remove-list.test.d.ts +2 -0
  150. package/dist/tests/tools/todo/remove-list.test.d.ts.map +1 -0
  151. package/dist/tests/tools/todo/remove-list.test.js +41 -0
  152. package/dist/tests/tools/todo/remove-list.test.js.map +1 -0
  153. package/dist/tests/tools/todo/remove-task.test.d.ts +2 -0
  154. package/dist/tests/tools/todo/remove-task.test.d.ts.map +1 -0
  155. package/dist/tests/tools/todo/remove-task.test.js +45 -0
  156. package/dist/tests/tools/todo/remove-task.test.js.map +1 -0
  157. package/dist/tests/tools/utils/delay.test.js +26 -24
  158. package/dist/tests/tools/utils/delay.test.js.map +1 -1
  159. package/dist/tests/tools/utils/get-current-time.test.js +43 -41
  160. package/dist/tests/tools/utils/get-current-time.test.js.map +1 -1
  161. package/dist/tests/tools/utils/read-image.test.d.ts +2 -0
  162. package/dist/tests/tools/utils/read-image.test.d.ts.map +1 -0
  163. package/dist/tests/tools/utils/read-image.test.js +54 -0
  164. package/dist/tests/tools/utils/read-image.test.js.map +1 -0
  165. package/dist/tools/browser/session-manager.d.ts.map +1 -1
  166. package/dist/tools/browser/session-manager.js +16 -3
  167. package/dist/tools/browser/session-manager.js.map +1 -1
  168. package/docs/agents.md +7 -1
  169. package/docs/mcp-architecture.md +1 -1
  170. package/docs/providers.md +5 -1
  171. package/package.json +1 -1
@@ -0,0 +1,36 @@
1
+ import { test, describe } from "node:test";
2
+ /**
3
+ * Browser tool tests are pending — a codebase issue, not a test-writing one.
4
+ * `npm test` runs via tsx (not a `tsc` build), and tsx/esbuild wraps every
5
+ * nested named function/arrow with a `__name(fn, "name")` helper. Puppeteer's
6
+ * page.evaluate() serializes its callback via Function.prototype.toString()
7
+ * and runs the source inside an isolated browser context that has no access
8
+ * to that helper, so any evaluate() callback carrying a leaked `__name(...)`
9
+ * call throws `ReferenceError: __name is not defined` inside the page. See
10
+ * src/tools/browser/evaluate-safe.ts for the existing (partial) workaround —
11
+ * not every browser tool's page.evaluate() call goes through it yet, so
12
+ * real tests here would fail on tsx even though the tools work fine from a
13
+ * compiled `tsc` build. These are left as node:test TODOs (not
14
+ * skipped/deleted) so the gap stays visible in `npm test` output until
15
+ * that's sorted out and real tests get written, following the same
16
+ * MCPClient/MCPServer/MCPConnection pattern used by every other tools/*
17
+ * test (see src/tests/tools/utils/delay.test.ts).
18
+ */
19
+ describe("browser (pending — puppeteer issue)", () => {
20
+ test.todo("BrowserCreateSessionTool: opens a session at a url and returns a sessionId");
21
+ test.todo("BrowserRemoveSessionTool: closes a session and removes it from browser-get-sessions");
22
+ test.todo("BrowserGetSessionsTool: reflects open sessions and stops listing removed ones");
23
+ test.todo("BrowserNavigateTool: navigates an existing session to a new url");
24
+ test.todo("BrowserConsoleTool: captures console messages logged by the page");
25
+ test.todo("BrowserInjectTool: evaluates javascript in the page and returns its result");
26
+ test.todo("BrowserReadTool: outlines the page and tags interactive elements with ref ids, paginates via continueRef");
27
+ test.todo("BrowserClickTool: clicks a clickable element by ref");
28
+ test.todo("BrowserFillTool: types into a fillable element by ref, including submitOnEnter for forms with no submit button");
29
+ test.todo("BrowserSubmitFormTool: submits a form by its form ref");
30
+ test.todo("BrowserScrollInfoTool: reports scrollable length and current scroll position");
31
+ test.todo("BrowserScrollTool: scrolls the page to a given vertical position");
32
+ test.todo("BrowserNetworkStatusTool: reports idle/loading network status");
33
+ test.todo("BrowserNetworkTool: logs network requests, filterable by resource type");
34
+ test.todo("BrowserScreenshotTool: returns an image tool-output (viewport and fullPage)");
35
+ });
36
+ //# sourceMappingURL=browser-tools.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-tools.test.js","sourceRoot":"","sources":["../../../../src/tests/tools/browser/browser-tools.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE3C;;;;;;;;;;;;;;;;GAgBG;AACH,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;IACjD,IAAI,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;IACxF,IAAI,CAAC,IAAI,CAAC,qFAAqF,CAAC,CAAC;IACjG,IAAI,CAAC,IAAI,CAAC,+EAA+E,CAAC,CAAC;IAC3F,IAAI,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;IAC7E,IAAI,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;IAC9E,IAAI,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;IACxF,IAAI,CAAC,IAAI,CAAC,0GAA0G,CAAC,CAAC;IACtH,IAAI,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;IACjE,IAAI,CAAC,IAAI,CAAC,gHAAgH,CAAC,CAAC;IAC5H,IAAI,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;IACnE,IAAI,CAAC,IAAI,CAAC,8EAA8E,CAAC,CAAC;IAC1F,IAAI,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;IAC9E,IAAI,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;IAC3E,IAAI,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC;IACpF,IAAI,CAAC,IAAI,CAAC,6EAA6E,CAAC,CAAC;AAC7F,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=create-dir.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-dir.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/tools/fs/create-dir.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ import { test, before, after, describe } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, rmSync, existsSync, statSync } from "fs";
4
+ import { tmpdir } from "os";
5
+ import { join } from "path";
6
+ import { FsCreateDirTool, MCPClient, MCPConnection, MCPServer } from "../../../index.js";
7
+ describe("fs/create-dir", () => {
8
+ let mcpConnection;
9
+ let mcpClient;
10
+ let mcpServer;
11
+ let tmpDir;
12
+ before(async () => {
13
+ tmpDir = mkdtempSync(join(tmpdir(), "orbitx-fs-create-dir-"));
14
+ mcpConnection = new MCPConnection();
15
+ mcpClient = new MCPClient("1234", mcpConnection);
16
+ mcpServer = new MCPServer(mcpConnection);
17
+ mcpServer.registerTool(FsCreateDirTool());
18
+ });
19
+ after(async () => {
20
+ mcpConnection?.close();
21
+ rmSync(tmpDir, { recursive: true, force: true });
22
+ });
23
+ test("FsCreateDirTool: creates a directory including missing parents", async () => {
24
+ const path = join(tmpDir, "a", "b", "c");
25
+ const result = await mcpClient.callTool("fs-create-dir", { path });
26
+ assert.strictEqual(result.output.message, "success");
27
+ assert.ok(existsSync(path));
28
+ assert.ok(statSync(path).isDirectory());
29
+ });
30
+ test("FsCreateDirTool: creating an already-existing directory is a no-op success", async () => {
31
+ const path = join(tmpDir, "already-there");
32
+ await mcpClient.callTool("fs-create-dir", { path });
33
+ const result = await mcpClient.callTool("fs-create-dir", { path });
34
+ assert.strictEqual(result.output.message, "success");
35
+ });
36
+ });
37
+ //# sourceMappingURL=create-dir.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-dir.test.js","sourceRoot":"","sources":["../../../../src/tests/tools/fs/create-dir.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEzF,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC3B,IAAI,aAAwC,CAAC;IAC7C,IAAI,SAAoB,CAAC;IACzB,IAAI,SAAoB,CAAC;IACzB,IAAI,MAAc,CAAC;IAEnB,MAAM,CAAC,KAAK,IAAI,EAAE;QACd,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,uBAAuB,CAAC,CAAC,CAAC;QAE9D,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;QACpC,SAAS,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QACjD,SAAS,GAAG,IAAI,SAAS,CAAC,aAAa,CAAC,CAAC;QACzC,SAAS,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,KAAK,IAAI,EAAE;QACb,aAAa,EAAE,KAAK,EAAE,CAAC;QACvB,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAEnE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACrD,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;QAC1F,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QAC3C,MAAM,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAEpD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACnE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=delete.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/tools/fs/delete.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,69 @@
1
+ import { test, before, after, describe } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, rmSync, writeFileSync, mkdirSync, existsSync } from "fs";
4
+ import { tmpdir } from "os";
5
+ import { join } from "path";
6
+ import { FsDeleteTool, MCPClient, MCPConnection, MCPServer } from "../../../index.js";
7
+ describe("fs/delete", () => {
8
+ let mcpConnection;
9
+ let mcpClient;
10
+ let mcpServer;
11
+ let tmpDir;
12
+ before(async () => {
13
+ tmpDir = mkdtempSync(join(tmpdir(), "orbitx-fs-delete-"));
14
+ mcpConnection = new MCPConnection();
15
+ mcpClient = new MCPClient("1234", mcpConnection);
16
+ mcpServer = new MCPServer(mcpConnection);
17
+ mcpServer.registerTool(FsDeleteTool());
18
+ });
19
+ after(async () => {
20
+ mcpConnection?.close();
21
+ rmSync(tmpDir, { recursive: true, force: true });
22
+ });
23
+ test("FsDeleteTool: deletes a file", async () => {
24
+ const path = join(tmpDir, "file.txt");
25
+ writeFileSync(path, "x");
26
+ const result = await mcpClient.callTool("fs-delete", { path });
27
+ assert.strictEqual(result.output.message, "success");
28
+ assert.strictEqual(result.output.type, "file");
29
+ assert.strictEqual(existsSync(path), false);
30
+ });
31
+ test("FsDeleteTool: a directory without recursive:true fails even when it's empty", async () => {
32
+ // Node's fs.rm requires recursive:true for ANY directory target, not
33
+ // just non-empty ones — it always throws ERR_FS_EISDIR otherwise.
34
+ const path = join(tmpDir, "empty-dir");
35
+ mkdirSync(path);
36
+ const result = await mcpClient.callTool("fs-delete", { path });
37
+ assert.ok(result.output.error, "should fail without recursive:true even on an empty directory");
38
+ assert.ok(existsSync(path), "directory should still exist");
39
+ });
40
+ test("FsDeleteTool: recursive:true deletes an empty directory", async () => {
41
+ const path = join(tmpDir, "empty-dir-recursive");
42
+ mkdirSync(path);
43
+ const result = await mcpClient.callTool("fs-delete", { path, recursive: true });
44
+ assert.strictEqual(result.output.message, "success");
45
+ assert.strictEqual(result.output.type, "directory");
46
+ assert.strictEqual(existsSync(path), false);
47
+ });
48
+ test("FsDeleteTool: a non-empty directory without recursive:true fails", async () => {
49
+ const path = join(tmpDir, "non-empty-dir");
50
+ mkdirSync(path);
51
+ writeFileSync(join(path, "inner.txt"), "x");
52
+ const result = await mcpClient.callTool("fs-delete", { path });
53
+ assert.ok(result.output.error, "should fail without recursive:true on a non-empty directory");
54
+ assert.ok(existsSync(path), "directory should still exist");
55
+ });
56
+ test("FsDeleteTool: recursive:true deletes a directory and everything inside it", async () => {
57
+ const path = join(tmpDir, "recursive-dir");
58
+ mkdirSync(path);
59
+ writeFileSync(join(path, "inner.txt"), "x");
60
+ const result = await mcpClient.callTool("fs-delete", { path, recursive: true });
61
+ assert.strictEqual(result.output.message, "success");
62
+ assert.strictEqual(existsSync(path), false);
63
+ });
64
+ test("FsDeleteTool: a missing path surfaces a descriptive error", async () => {
65
+ const result = await mcpClient.callTool("fs-delete", { path: join(tmpDir, "nope") });
66
+ assert.match(result.output.error, /no file or directory found at/);
67
+ });
68
+ });
69
+ //# sourceMappingURL=delete.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.test.js","sourceRoot":"","sources":["../../../../src/tests/tools/fs/delete.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC/E,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEtF,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACvB,IAAI,aAAwC,CAAC;IAC7C,IAAI,SAAoB,CAAC;IACzB,IAAI,SAAoB,CAAC;IACzB,IAAI,MAAc,CAAC;IAEnB,MAAM,CAAC,KAAK,IAAI,EAAE;QACd,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;QAE1D,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;QACpC,SAAS,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QACjD,SAAS,GAAG,IAAI,SAAS,CAAC,aAAa,CAAC,CAAC;QACzC,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,KAAK,IAAI,EAAE;QACb,aAAa,EAAE,KAAK,EAAE,CAAC;QACvB,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACtC,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAEzB,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAE/D,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACrD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/C,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,qEAAqE;QACrE,kEAAkE;QAClE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACvC,SAAS,CAAC,IAAI,CAAC,CAAC;QAEhB,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAE/D,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,+DAA+D,CAAC,CAAC;QAChG,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,8BAA8B,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;QACjD,SAAS,CAAC,IAAI,CAAC,CAAC;QAEhB,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEhF,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACrD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACpD,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QAC3C,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,GAAG,CAAC,CAAC;QAE5C,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAE/D,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,6DAA6D,CAAC,CAAC;QAC9F,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,8BAA8B,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QAC3C,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,GAAG,CAAC,CAAC;QAE5C,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEhF,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACrD,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QAErF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,+BAA+B,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=edit-file.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit-file.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/tools/fs/edit-file.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,103 @@
1
+ import { test, before, after, beforeEach, describe } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, rmSync, writeFileSync, readFileSync } from "fs";
4
+ import { tmpdir } from "os";
5
+ import { join } from "path";
6
+ import { FsEditFileTool, MCPClient, MCPConnection, MCPServer } from "../../../index.js";
7
+ describe("fs/edit-file", () => {
8
+ let mcpConnection;
9
+ let mcpClient;
10
+ let mcpServer;
11
+ let tmpDir;
12
+ let filePath;
13
+ before(async () => {
14
+ tmpDir = mkdtempSync(join(tmpdir(), "orbitx-fs-edit-"));
15
+ filePath = join(tmpDir, "file.txt");
16
+ mcpConnection = new MCPConnection();
17
+ mcpClient = new MCPClient("1234", mcpConnection);
18
+ mcpServer = new MCPServer(mcpConnection);
19
+ mcpServer.registerTool(FsEditFileTool());
20
+ });
21
+ after(async () => {
22
+ mcpConnection?.close();
23
+ rmSync(tmpDir, { recursive: true, force: true });
24
+ });
25
+ beforeEach(() => {
26
+ writeFileSync(filePath, "line1\nline2\nline3");
27
+ });
28
+ test("FsEditFileTool: replaces a line range with new content", async () => {
29
+ const result = await mcpClient.callTool("fs-edit-file", {
30
+ path: filePath,
31
+ offsetLine: 2,
32
+ limitLine: 1,
33
+ content: "replaced",
34
+ });
35
+ assert.strictEqual(result.output.message, "success");
36
+ assert.strictEqual(result.output.removedLines, 1);
37
+ assert.strictEqual(result.output.insertedLines, 1);
38
+ assert.strictEqual(readFileSync(filePath, "utf-8"), "line1\nreplaced\nline3");
39
+ });
40
+ test("FsEditFileTool: limitLine 0 inserts before offsetLine without deleting anything", async () => {
41
+ const result = await mcpClient.callTool("fs-edit-file", {
42
+ path: filePath,
43
+ offsetLine: 2,
44
+ limitLine: 0,
45
+ content: "inserted",
46
+ });
47
+ assert.strictEqual(result.output.removedLines, 0);
48
+ assert.strictEqual(readFileSync(filePath, "utf-8"), "line1\ninserted\nline2\nline3");
49
+ });
50
+ test("FsEditFileTool: offsetLine totalLines+1 appends at the end of the file", async () => {
51
+ await mcpClient.callTool("fs-edit-file", {
52
+ path: filePath,
53
+ offsetLine: 4,
54
+ limitLine: 0,
55
+ content: "line4",
56
+ });
57
+ assert.strictEqual(readFileSync(filePath, "utf-8"), "line1\nline2\nline3\nline4");
58
+ });
59
+ test("FsEditFileTool: empty content just deletes the range", async () => {
60
+ await mcpClient.callTool("fs-edit-file", {
61
+ path: filePath,
62
+ offsetLine: 2,
63
+ limitLine: 1,
64
+ content: "",
65
+ });
66
+ assert.strictEqual(readFileSync(filePath, "utf-8"), "line1\nline3");
67
+ });
68
+ test("FsEditFileTool: offsetLine past the end of the file surfaces a descriptive error", async () => {
69
+ const result = await mcpClient.callTool("fs-edit-file", {
70
+ path: filePath,
71
+ offsetLine: 10,
72
+ limitLine: 0,
73
+ content: "x",
74
+ });
75
+ assert.match(result.output.error, /past end of file/);
76
+ });
77
+ test("FsEditFileTool: invalid offsetLine/limitLine are rejected", async () => {
78
+ const badOffset = await mcpClient.callTool("fs-edit-file", {
79
+ path: filePath,
80
+ offsetLine: 0,
81
+ limitLine: 1,
82
+ content: "x",
83
+ });
84
+ assert.match(badOffset.output.error, /offsetLine is 1-indexed/);
85
+ const badLimit = await mcpClient.callTool("fs-edit-file", {
86
+ path: filePath,
87
+ offsetLine: 1,
88
+ limitLine: -1,
89
+ content: "x",
90
+ });
91
+ assert.match(badLimit.output.error, /limitLine must be a non-negative number/);
92
+ });
93
+ test("FsEditFileTool: a missing file surfaces a descriptive error", async () => {
94
+ const result = await mcpClient.callTool("fs-edit-file", {
95
+ path: join(tmpDir, "missing.txt"),
96
+ offsetLine: 1,
97
+ limitLine: 0,
98
+ content: "x",
99
+ });
100
+ assert.match(result.output.error, /no file found at/);
101
+ });
102
+ });
103
+ //# sourceMappingURL=edit-file.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit-file.test.js","sourceRoot":"","sources":["../../../../src/tests/tools/fs/edit-file.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAExF,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC1B,IAAI,aAAwC,CAAC;IAC7C,IAAI,SAAoB,CAAC;IACzB,IAAI,SAAoB,CAAC;IACzB,IAAI,MAAc,CAAC;IACnB,IAAI,QAAgB,CAAC;IAErB,MAAM,CAAC,KAAK,IAAI,EAAE;QACd,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;QACxD,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAEpC,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;QACpC,SAAS,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QACjD,SAAS,GAAG,IAAI,SAAS,CAAC,aAAa,CAAC,CAAC;QACzC,SAAS,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,KAAK,IAAI,EAAE;QACb,aAAa,EAAE,KAAK,EAAE,CAAC;QACvB,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,GAAG,EAAE;QACZ,aAAa,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE;YACpD,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,UAAU;SACtB,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACrD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;QACnD,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,wBAAwB,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iFAAiF,EAAE,KAAK,IAAI,EAAE;QAC/F,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE;YACpD,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,UAAU;SACtB,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,+BAA+B,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE;YACrC,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO;SACnB,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,4BAA4B,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE;YACrC,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,EAAE;SACd,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,cAAc,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,kFAAkF,EAAE,KAAK,IAAI,EAAE;QAChG,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE;YACpD,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE;YACd,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,GAAG;SACf,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE;YACvD,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,GAAG;SACf,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,yBAAyB,CAAC,CAAC;QAEhE,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE;YACtD,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,CAAC,CAAC;YACb,OAAO,EAAE,GAAG;SACf,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,yCAAyC,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE;YACpD,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC;YACjC,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,GAAG;SACf,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=list-dir.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-dir.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/tools/fs/list-dir.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,65 @@
1
+ import { test, before, after, describe } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from "fs";
4
+ import { tmpdir } from "os";
5
+ import { join } from "path";
6
+ import { FsListDirTool, MCPClient, MCPConnection, MCPServer } from "../../../index.js";
7
+ describe("fs/list-dir", () => {
8
+ let mcpConnection;
9
+ let mcpClient;
10
+ let mcpServer;
11
+ let tmpDir;
12
+ before(async () => {
13
+ tmpDir = mkdtempSync(join(tmpdir(), "orbitx-fs-list-"));
14
+ writeFileSync(join(tmpDir, "a.txt"), "a");
15
+ writeFileSync(join(tmpDir, "b.txt"), "bb");
16
+ mkdirSync(join(tmpDir, "sub"));
17
+ writeFileSync(join(tmpDir, "sub", "c.txt"), "ccc");
18
+ mkdirSync(join(tmpDir, "node_modules"));
19
+ writeFileSync(join(tmpDir, "node_modules", "pkg.js"), "ignored");
20
+ mcpConnection = new MCPConnection();
21
+ mcpClient = new MCPClient("1234", mcpConnection);
22
+ mcpServer = new MCPServer(mcpConnection);
23
+ mcpServer.registerTool(FsListDirTool());
24
+ });
25
+ after(async () => {
26
+ mcpConnection?.close();
27
+ rmSync(tmpDir, { recursive: true, force: true });
28
+ });
29
+ test("FsListDirTool: lists top-level entries only by default", async () => {
30
+ const result = await mcpClient.callTool("fs-list-dir", { path: tmpDir });
31
+ const names = result.output.result.map((e) => e.name).sort();
32
+ assert.deepStrictEqual(names, ["a.txt", "b.txt", "node_modules", "sub"]);
33
+ assert.strictEqual(result.output.totalResult, 4);
34
+ });
35
+ test("FsListDirTool: recursive:true walks subdirectories but tags default-excluded dirs and skips their contents", async () => {
36
+ const result = await mcpClient.callTool("fs-list-dir", { path: tmpDir, recursive: true });
37
+ const entries = result.output.result;
38
+ const names = entries.map((e) => e.name).sort();
39
+ assert.ok(names.includes("c.txt"), "should recurse into 'sub' and find c.txt");
40
+ assert.ok(!names.includes("pkg.js"), "should not recurse into node_modules by default");
41
+ const nodeModulesEntry = entries.find((e) => e.name === "node_modules");
42
+ assert.strictEqual(nodeModulesEntry.excluded, true);
43
+ });
44
+ test("FsListDirTool: excludeDirs overrides which directories are skipped during recursion", async () => {
45
+ const result = await mcpClient.callTool("fs-list-dir", { path: tmpDir, recursive: true, excludeDirs: ["sub"] });
46
+ const names = result.output.result.map((e) => e.name);
47
+ assert.ok(!names.includes("c.txt"), "sub's contents should be skipped when excluded explicitly");
48
+ assert.ok(names.includes("pkg.js"), "node_modules should be walked since it's no longer excluded");
49
+ });
50
+ test("FsListDirTool: pages through entries using offsetResult/limitResult", async () => {
51
+ const result = await mcpClient.callTool("fs-list-dir", { path: tmpDir, offsetResult: 1, limitResult: 2 });
52
+ assert.strictEqual(result.output.result.length, 2);
53
+ assert.strictEqual(result.output.offsetResult, 1);
54
+ assert.strictEqual(result.output.totalResult, 4);
55
+ });
56
+ test("FsListDirTool: a missing directory surfaces a descriptive error", async () => {
57
+ const result = await mcpClient.callTool("fs-list-dir", { path: join(tmpDir, "missing") });
58
+ assert.match(result.output.error, /no directory found at/);
59
+ });
60
+ test("FsListDirTool: listing a file path surfaces a descriptive error", async () => {
61
+ const result = await mcpClient.callTool("fs-list-dir", { path: join(tmpDir, "a.txt") });
62
+ assert.match(result.output.error, /is a file, not a directory/);
63
+ });
64
+ });
65
+ //# sourceMappingURL=list-dir.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-dir.test.js","sourceRoot":"","sources":["../../../../src/tests/tools/fs/list-dir.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEvF,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IACzB,IAAI,aAAwC,CAAC;IAC7C,IAAI,SAAoB,CAAC;IACzB,IAAI,SAAoB,CAAC;IACzB,IAAI,MAAc,CAAC;IAEnB,MAAM,CAAC,KAAK,IAAI,EAAE;QACd,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;QACxD,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;QAC1C,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;QAC3C,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QAC/B,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC;QACnD,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;QACxC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC;QAEjE,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;QACpC,SAAS,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QACjD,SAAS,GAAG,IAAI,SAAS,CAAC,aAAa,CAAC,CAAC;QACzC,SAAS,CAAC,YAAY,CAAC,aAAa,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,KAAK,IAAI,EAAE;QACb,aAAa,EAAE,KAAK,EAAE,CAAC;QACvB,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAEzE,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QAClE,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC;QACzE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,4GAA4G,EAAE,KAAK,IAAI,EAAE;QAC1H,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE1F,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;QACrC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QACrD,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,0CAA0C,CAAC,CAAC;QAC/E,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,iDAAiD,CAAC,CAAC;QAExF,MAAM,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;QAC7E,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,qFAAqF,EAAE,KAAK,IAAI,EAAE;QACnG,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAEhH,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC3D,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,2DAA2D,CAAC,CAAC;QACjG,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,6DAA6D,CAAC,CAAC;IACvG,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC;QAE1G,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACnD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;QAE1F,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,uBAAuB,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QAExF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,4BAA4B,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=move.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"move.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/tools/fs/move.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,47 @@
1
+ import { test, before, after, describe } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, rmSync, writeFileSync, existsSync, readFileSync } from "fs";
4
+ import { tmpdir } from "os";
5
+ import { join } from "path";
6
+ import { FsMoveTool, MCPClient, MCPConnection, MCPServer } from "../../../index.js";
7
+ describe("fs/move", () => {
8
+ let mcpConnection;
9
+ let mcpClient;
10
+ let mcpServer;
11
+ let tmpDir;
12
+ before(async () => {
13
+ tmpDir = mkdtempSync(join(tmpdir(), "orbitx-fs-move-"));
14
+ mcpConnection = new MCPConnection();
15
+ mcpClient = new MCPClient("1234", mcpConnection);
16
+ mcpServer = new MCPServer(mcpConnection);
17
+ mcpServer.registerTool(FsMoveTool());
18
+ });
19
+ after(async () => {
20
+ mcpConnection?.close();
21
+ rmSync(tmpDir, { recursive: true, force: true });
22
+ });
23
+ test("FsMoveTool: renames/moves a file", async () => {
24
+ const from = join(tmpDir, "source.txt");
25
+ const to = join(tmpDir, "dest.txt");
26
+ writeFileSync(from, "content");
27
+ const result = await mcpClient.callTool("fs-move", { from, to });
28
+ assert.strictEqual(result.output.message, "success");
29
+ assert.strictEqual(existsSync(from), false);
30
+ assert.strictEqual(readFileSync(to, "utf-8"), "content");
31
+ });
32
+ test("FsMoveTool: creates missing parent directories of the destination", async () => {
33
+ const from = join(tmpDir, "source2.txt");
34
+ const to = join(tmpDir, "nested", "deep", "dest2.txt");
35
+ writeFileSync(from, "content2");
36
+ await mcpClient.callTool("fs-move", { from, to });
37
+ assert.strictEqual(readFileSync(to, "utf-8"), "content2");
38
+ });
39
+ test("FsMoveTool: a missing source surfaces a descriptive error", async () => {
40
+ const result = await mcpClient.callTool("fs-move", {
41
+ from: join(tmpDir, "missing.txt"),
42
+ to: join(tmpDir, "dest3.txt"),
43
+ });
44
+ assert.match(result.output.error, /no file or directory found at/);
45
+ });
46
+ });
47
+ //# sourceMappingURL=move.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"move.test.js","sourceRoot":"","sources":["../../../../src/tests/tools/fs/move.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=read-file.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-file.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/tools/fs/read-file.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,52 @@
1
+ import { test, before, after, describe } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from "fs";
4
+ import { tmpdir } from "os";
5
+ import { join } from "path";
6
+ import { FsReadFileTool, MCPClient, MCPConnection, MCPServer } from "../../../index.js";
7
+ describe("fs/read-file", () => {
8
+ let mcpConnection;
9
+ let mcpClient;
10
+ let mcpServer;
11
+ let tmpDir;
12
+ before(async () => {
13
+ tmpDir = mkdtempSync(join(tmpdir(), "orbitx-fs-read-"));
14
+ writeFileSync(join(tmpDir, "file.txt"), "line1\nline2\nline3\nline4\nline5");
15
+ mkdirSync(join(tmpDir, "adir"));
16
+ mcpConnection = new MCPConnection();
17
+ mcpClient = new MCPClient("1234", mcpConnection);
18
+ mcpServer = new MCPServer(mcpConnection);
19
+ mcpServer.registerTool(FsReadFileTool());
20
+ });
21
+ after(async () => {
22
+ mcpConnection?.close();
23
+ rmSync(tmpDir, { recursive: true, force: true });
24
+ });
25
+ test("FsReadFileTool: reads a whole file by default", async () => {
26
+ const result = await mcpClient.callTool("fs-read-file", { path: join(tmpDir, "file.txt") });
27
+ assert.strictEqual(result.output.content, "line1\nline2\nline3\nline4\nline5");
28
+ assert.strictEqual(result.output.totalLines, 5);
29
+ assert.strictEqual(result.output.startLine, 1);
30
+ assert.strictEqual(result.output.endLine, 5);
31
+ });
32
+ test("FsReadFileTool: pages through a file using offsetLine/limitLine", async () => {
33
+ const result = await mcpClient.callTool("fs-read-file", {
34
+ path: join(tmpDir, "file.txt"),
35
+ offsetLine: 2,
36
+ limitLine: 2,
37
+ });
38
+ assert.strictEqual(result.output.content, "line2\nline3");
39
+ assert.strictEqual(result.output.startLine, 2);
40
+ assert.strictEqual(result.output.endLine, 3);
41
+ assert.strictEqual(result.output.totalLines, 5);
42
+ });
43
+ test("FsReadFileTool: a missing file surfaces a descriptive error", async () => {
44
+ const result = await mcpClient.callTool("fs-read-file", { path: join(tmpDir, "missing.txt") });
45
+ assert.match(result.output.error, /no file found at/);
46
+ });
47
+ test("FsReadFileTool: reading a directory surfaces a descriptive error", async () => {
48
+ const result = await mcpClient.callTool("fs-read-file", { path: join(tmpDir, "adir") });
49
+ assert.match(result.output.error, /is a directory, not a file/);
50
+ });
51
+ });
52
+ //# sourceMappingURL=read-file.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-file.test.js","sourceRoot":"","sources":["../../../../src/tests/tools/fs/read-file.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stat.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/tools/fs/stat.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,43 @@
1
+ import { test, before, after, describe } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from "fs";
4
+ import { tmpdir } from "os";
5
+ import { join } from "path";
6
+ import { FsStatTool, MCPClient, MCPConnection, MCPServer } from "../../../index.js";
7
+ describe("fs/stat", () => {
8
+ let mcpConnection;
9
+ let mcpClient;
10
+ let mcpServer;
11
+ let tmpDir;
12
+ before(async () => {
13
+ tmpDir = mkdtempSync(join(tmpdir(), "orbitx-fs-stat-"));
14
+ writeFileSync(join(tmpDir, "file.txt"), "hello");
15
+ mkdirSync(join(tmpDir, "adir"));
16
+ mcpConnection = new MCPConnection();
17
+ mcpClient = new MCPClient("1234", mcpConnection);
18
+ mcpServer = new MCPServer(mcpConnection);
19
+ mcpServer.registerTool(FsStatTool());
20
+ });
21
+ after(async () => {
22
+ mcpConnection?.close();
23
+ rmSync(tmpDir, { recursive: true, force: true });
24
+ });
25
+ test("FsStatTool: reports type/size/timestamps for an existing file", async () => {
26
+ const result = await mcpClient.callTool("fs-stat", { path: join(tmpDir, "file.txt") });
27
+ assert.strictEqual(result.output.exists, true);
28
+ assert.strictEqual(result.output.type, "file");
29
+ assert.strictEqual(result.output.size, Buffer.byteLength("hello"));
30
+ assert.ok(!Number.isNaN(new Date(result.output.modifiedAt).getTime()));
31
+ assert.ok(!Number.isNaN(new Date(result.output.createdAt).getTime()));
32
+ });
33
+ test("FsStatTool: reports type 'directory' for a directory", async () => {
34
+ const result = await mcpClient.callTool("fs-stat", { path: join(tmpDir, "adir") });
35
+ assert.strictEqual(result.output.exists, true);
36
+ assert.strictEqual(result.output.type, "directory");
37
+ });
38
+ test("FsStatTool: a missing path returns exists:false instead of throwing", async () => {
39
+ const result = await mcpClient.callTool("fs-stat", { path: join(tmpDir, "missing") });
40
+ assert.deepStrictEqual(result.output, { exists: false });
41
+ });
42
+ });
43
+ //# sourceMappingURL=stat.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat.test.js","sourceRoot":"","sources":["../../../../src/tests/tools/fs/stat.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=write-file.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-file.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/tools/fs/write-file.test.ts"],"names":[],"mappings":""}