daycare-cli 2026.2.26 → 2026.2.27

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 (271) hide show
  1. package/dist/engine/agents/agent.d.ts +2 -0
  2. package/dist/engine/agents/agent.d.ts.map +1 -1
  3. package/dist/engine/agents/agent.js +7 -3
  4. package/dist/engine/agents/agent.js.map +1 -1
  5. package/dist/engine/agents/agentSystem.d.ts +5 -0
  6. package/dist/engine/agents/agentSystem.d.ts.map +1 -1
  7. package/dist/engine/agents/agentSystem.js +16 -1
  8. package/dist/engine/agents/agentSystem.js.map +1 -1
  9. package/dist/engine/agents/agentSystem.spec.js +59 -0
  10. package/dist/engine/agents/agentSystem.spec.js.map +1 -1
  11. package/dist/engine/agents/ops/agentLoopRun.d.ts +0 -2
  12. package/dist/engine/agents/ops/agentLoopRun.d.ts.map +1 -1
  13. package/dist/engine/agents/ops/agentLoopRun.js +4 -7
  14. package/dist/engine/agents/ops/agentLoopRun.js.map +1 -1
  15. package/dist/engine/agents/ops/agentLoopRun.spec.js +21 -24
  16. package/dist/engine/agents/ops/agentLoopRun.spec.js.map +1 -1
  17. package/dist/engine/apps/appExecute.spec.js +2 -10
  18. package/dist/engine/apps/appExecute.spec.js.map +1 -1
  19. package/dist/engine/apps/appInstallToolBuild.js +1 -1
  20. package/dist/engine/apps/appInstallToolBuild.js.map +1 -1
  21. package/dist/engine/apps/appInstallToolBuild.spec.js +1 -5
  22. package/dist/engine/apps/appInstallToolBuild.spec.js.map +1 -1
  23. package/dist/engine/apps/appRuleToolBuild.spec.js +1 -5
  24. package/dist/engine/apps/appRuleToolBuild.spec.js.map +1 -1
  25. package/dist/engine/apps/appToolExecutorBuild.spec.js +1 -5
  26. package/dist/engine/apps/appToolExecutorBuild.spec.js.map +1 -1
  27. package/dist/engine/engine.d.ts.map +1 -1
  28. package/dist/engine/engine.js +10 -0
  29. package/dist/engine/engine.js.map +1 -1
  30. package/dist/engine/friends/usertagGenerate.d.ts +6 -0
  31. package/dist/engine/friends/usertagGenerate.d.ts.map +1 -0
  32. package/dist/engine/friends/usertagGenerate.js +311 -0
  33. package/dist/engine/friends/usertagGenerate.js.map +1 -0
  34. package/dist/engine/friends/usertagGenerate.spec.d.ts +2 -0
  35. package/dist/engine/friends/usertagGenerate.spec.d.ts.map +1 -0
  36. package/dist/engine/friends/usertagGenerate.spec.js +13 -0
  37. package/dist/engine/friends/usertagGenerate.spec.js.map +1 -0
  38. package/dist/engine/modules/executablePrompts/executablePromptExpand.spec.js +1 -5
  39. package/dist/engine/modules/executablePrompts/executablePromptExpand.spec.js.map +1 -1
  40. package/dist/engine/modules/monty/montyPythonTypeFromSchemaRuntime.spec.js +1 -5
  41. package/dist/engine/modules/monty/montyPythonTypeFromSchemaRuntime.spec.js.map +1 -1
  42. package/dist/engine/modules/rlm/rlmExecute.spec.js +1 -5
  43. package/dist/engine/modules/rlm/rlmExecute.spec.js.map +1 -1
  44. package/dist/engine/modules/rlm/rlmRestore.spec.js +1 -5
  45. package/dist/engine/modules/rlm/rlmRestore.spec.js.map +1 -1
  46. package/dist/engine/modules/rlm/rlmTool.spec.js +1 -5
  47. package/dist/engine/modules/rlm/rlmTool.spec.js.map +1 -1
  48. package/dist/engine/modules/say/sayFileResolve.d.ts +4 -5
  49. package/dist/engine/modules/say/sayFileResolve.d.ts.map +1 -1
  50. package/dist/engine/modules/say/sayFileResolve.js +24 -14
  51. package/dist/engine/modules/say/sayFileResolve.js.map +1 -1
  52. package/dist/engine/modules/say/sayFileResolve.spec.js +28 -29
  53. package/dist/engine/modules/say/sayFileResolve.spec.js.map +1 -1
  54. package/dist/engine/modules/toolResolver.spec.js +1 -5
  55. package/dist/engine/modules/toolResolver.spec.js.map +1 -1
  56. package/dist/engine/modules/tools/agentCompactTool.spec.js +1 -5
  57. package/dist/engine/modules/tools/agentCompactTool.spec.js.map +1 -1
  58. package/dist/engine/modules/tools/agentResetTool.spec.js +1 -5
  59. package/dist/engine/modules/tools/agentResetTool.spec.js.map +1 -1
  60. package/dist/engine/modules/tools/background.spec.js +3 -11
  61. package/dist/engine/modules/tools/background.spec.js.map +1 -1
  62. package/dist/engine/modules/tools/channelCreateTool.spec.js +1 -5
  63. package/dist/engine/modules/tools/channelCreateTool.spec.js.map +1 -1
  64. package/dist/engine/modules/tools/channelHistoryTool.spec.js +1 -5
  65. package/dist/engine/modules/tools/channelHistoryTool.spec.js.map +1 -1
  66. package/dist/engine/modules/tools/channelMemberTool.spec.js +1 -5
  67. package/dist/engine/modules/tools/channelMemberTool.spec.js.map +1 -1
  68. package/dist/engine/modules/tools/channelSendTool.spec.js +1 -5
  69. package/dist/engine/modules/tools/channelSendTool.spec.js.map +1 -1
  70. package/dist/engine/modules/tools/friendAddToolBuild.d.ts +7 -0
  71. package/dist/engine/modules/tools/friendAddToolBuild.d.ts.map +1 -0
  72. package/dist/engine/modules/tools/friendAddToolBuild.js +163 -0
  73. package/dist/engine/modules/tools/friendAddToolBuild.js.map +1 -0
  74. package/dist/engine/modules/tools/friendAddToolBuild.spec.d.ts +2 -0
  75. package/dist/engine/modules/tools/friendAddToolBuild.spec.d.ts.map +1 -0
  76. package/dist/engine/modules/tools/friendAddToolBuild.spec.js +151 -0
  77. package/dist/engine/modules/tools/friendAddToolBuild.spec.js.map +1 -0
  78. package/dist/engine/modules/tools/friendRemoveToolBuild.d.ts +7 -0
  79. package/dist/engine/modules/tools/friendRemoveToolBuild.d.ts.map +1 -0
  80. package/dist/engine/modules/tools/friendRemoveToolBuild.js +174 -0
  81. package/dist/engine/modules/tools/friendRemoveToolBuild.js.map +1 -0
  82. package/dist/engine/modules/tools/friendRemoveToolBuild.spec.d.ts +2 -0
  83. package/dist/engine/modules/tools/friendRemoveToolBuild.spec.d.ts.map +1 -0
  84. package/dist/engine/modules/tools/friendRemoveToolBuild.spec.js +172 -0
  85. package/dist/engine/modules/tools/friendRemoveToolBuild.spec.js.map +1 -0
  86. package/dist/engine/modules/tools/friendSendToolBuild.d.ts +7 -0
  87. package/dist/engine/modules/tools/friendSendToolBuild.d.ts.map +1 -0
  88. package/dist/engine/modules/tools/friendSendToolBuild.js +104 -0
  89. package/dist/engine/modules/tools/friendSendToolBuild.js.map +1 -0
  90. package/dist/engine/modules/tools/friendSendToolBuild.spec.d.ts +2 -0
  91. package/dist/engine/modules/tools/friendSendToolBuild.spec.d.ts.map +1 -0
  92. package/dist/engine/modules/tools/friendSendToolBuild.spec.js +120 -0
  93. package/dist/engine/modules/tools/friendSendToolBuild.spec.js.map +1 -0
  94. package/dist/engine/modules/tools/friendShareSubuserToolBuild.d.ts +7 -0
  95. package/dist/engine/modules/tools/friendShareSubuserToolBuild.d.ts.map +1 -0
  96. package/dist/engine/modules/tools/friendShareSubuserToolBuild.js +133 -0
  97. package/dist/engine/modules/tools/friendShareSubuserToolBuild.js.map +1 -0
  98. package/dist/engine/modules/tools/friendShareSubuserToolBuild.spec.d.ts +2 -0
  99. package/dist/engine/modules/tools/friendShareSubuserToolBuild.spec.d.ts.map +1 -0
  100. package/dist/engine/modules/tools/friendShareSubuserToolBuild.spec.js +119 -0
  101. package/dist/engine/modules/tools/friendShareSubuserToolBuild.spec.js.map +1 -0
  102. package/dist/engine/modules/tools/friendUnshareSubuserToolBuild.d.ts +7 -0
  103. package/dist/engine/modules/tools/friendUnshareSubuserToolBuild.d.ts.map +1 -0
  104. package/dist/engine/modules/tools/friendUnshareSubuserToolBuild.js +118 -0
  105. package/dist/engine/modules/tools/friendUnshareSubuserToolBuild.js.map +1 -0
  106. package/dist/engine/modules/tools/friendUnshareSubuserToolBuild.spec.d.ts +2 -0
  107. package/dist/engine/modules/tools/friendUnshareSubuserToolBuild.spec.d.ts.map +1 -0
  108. package/dist/engine/modules/tools/friendUnshareSubuserToolBuild.spec.js +100 -0
  109. package/dist/engine/modules/tools/friendUnshareSubuserToolBuild.spec.js.map +1 -0
  110. package/dist/engine/modules/tools/image-generation.d.ts.map +1 -1
  111. package/dist/engine/modules/tools/image-generation.js +26 -10
  112. package/dist/engine/modules/tools/image-generation.js.map +1 -1
  113. package/dist/engine/modules/tools/image-generation.spec.js +13 -10
  114. package/dist/engine/modules/tools/image-generation.spec.js.map +1 -1
  115. package/dist/engine/modules/tools/mermaid-png.d.ts.map +1 -1
  116. package/dist/engine/modules/tools/mermaid-png.js +16 -11
  117. package/dist/engine/modules/tools/mermaid-png.js.map +1 -1
  118. package/dist/engine/modules/tools/mermaid-png.spec.js +20 -24
  119. package/dist/engine/modules/tools/mermaid-png.spec.js.map +1 -1
  120. package/dist/engine/modules/tools/pdf-process.d.ts.map +1 -1
  121. package/dist/engine/modules/tools/pdf-process.js +10 -38
  122. package/dist/engine/modules/tools/pdf-process.js.map +1 -1
  123. package/dist/engine/modules/tools/pdf-process.spec.js +15 -5
  124. package/dist/engine/modules/tools/pdf-process.spec.js.map +1 -1
  125. package/dist/engine/modules/tools/permanentAgentToolBuild.spec.js +5 -13
  126. package/dist/engine/modules/tools/permanentAgentToolBuild.spec.js.map +1 -1
  127. package/dist/engine/modules/tools/send-file.d.ts.map +1 -1
  128. package/dist/engine/modules/tools/send-file.js +20 -11
  129. package/dist/engine/modules/tools/send-file.js.map +1 -1
  130. package/dist/engine/modules/tools/sendUserMessageTool.spec.js +1 -5
  131. package/dist/engine/modules/tools/sendUserMessageTool.spec.js.map +1 -1
  132. package/dist/engine/modules/tools/sessionHistoryToolBuild.spec.js +1 -2
  133. package/dist/engine/modules/tools/sessionHistoryToolBuild.spec.js.map +1 -1
  134. package/dist/engine/modules/tools/signal.spec.js +1 -5
  135. package/dist/engine/modules/tools/signal.spec.js.map +1 -1
  136. package/dist/engine/modules/tools/signalEventsCsvToolBuild.spec.js +1 -5
  137. package/dist/engine/modules/tools/signalEventsCsvToolBuild.spec.js.map +1 -1
  138. package/dist/engine/modules/tools/signalSubscribeToolBuild.spec.js +1 -5
  139. package/dist/engine/modules/tools/signalSubscribeToolBuild.spec.js.map +1 -1
  140. package/dist/engine/modules/tools/signalUnsubscribeToolBuild.spec.js +1 -5
  141. package/dist/engine/modules/tools/signalUnsubscribeToolBuild.spec.js.map +1 -1
  142. package/dist/engine/modules/tools/skillToolBuild.js +3 -3
  143. package/dist/engine/modules/tools/skillToolBuild.js.map +1 -1
  144. package/dist/engine/modules/tools/skillToolBuild.spec.js +12 -9
  145. package/dist/engine/modules/tools/skillToolBuild.spec.js.map +1 -1
  146. package/dist/engine/modules/tools/subuserConfigureToolBuild.spec.js +1 -2
  147. package/dist/engine/modules/tools/subuserConfigureToolBuild.spec.js.map +1 -1
  148. package/dist/engine/modules/tools/subuserCreateToolBuild.spec.js +1 -2
  149. package/dist/engine/modules/tools/subuserCreateToolBuild.spec.js.map +1 -1
  150. package/dist/engine/modules/tools/subuserListToolBuild.spec.js +1 -2
  151. package/dist/engine/modules/tools/subuserListToolBuild.spec.js.map +1 -1
  152. package/dist/engine/modules/tools/topologyToolBuild.d.ts.map +1 -1
  153. package/dist/engine/modules/tools/topologyToolBuild.js +111 -2
  154. package/dist/engine/modules/tools/topologyToolBuild.js.map +1 -1
  155. package/dist/engine/modules/tools/topologyToolBuild.spec.js +99 -2
  156. package/dist/engine/modules/tools/topologyToolBuild.spec.js.map +1 -1
  157. package/dist/engine/modules/tools/types.d.ts +3 -4
  158. package/dist/engine/modules/tools/types.d.ts.map +1 -1
  159. package/dist/plugins/dashboard/site/404.html +1 -1
  160. package/dist/plugins/dashboard/site/agent.html +1 -1
  161. package/dist/plugins/dashboard/site/agent.txt +1 -1
  162. package/dist/plugins/dashboard/site/agents.html +1 -1
  163. package/dist/plugins/dashboard/site/agents.txt +1 -1
  164. package/dist/plugins/dashboard/site/automations.html +1 -1
  165. package/dist/plugins/dashboard/site/automations.txt +1 -1
  166. package/dist/plugins/dashboard/site/connectors.html +1 -1
  167. package/dist/plugins/dashboard/site/connectors.txt +1 -1
  168. package/dist/plugins/dashboard/site/index.html +1 -1
  169. package/dist/plugins/dashboard/site/index.txt +1 -1
  170. package/dist/plugins/dashboard/site/memory.html +1 -1
  171. package/dist/plugins/dashboard/site/memory.txt +1 -1
  172. package/dist/plugins/dashboard/site/processes.html +1 -1
  173. package/dist/plugins/dashboard/site/processes.txt +1 -1
  174. package/dist/plugins/dashboard/site/providers.html +1 -1
  175. package/dist/plugins/dashboard/site/providers.txt +1 -1
  176. package/dist/plugins/dashboard/site/signals.html +1 -1
  177. package/dist/plugins/dashboard/site/signals.txt +1 -1
  178. package/dist/plugins/dashboard/site/telemetry.html +1 -1
  179. package/dist/plugins/dashboard/site/telemetry.txt +1 -1
  180. package/dist/plugins/dashboard/site/tools.html +1 -1
  181. package/dist/plugins/dashboard/site/tools.txt +1 -1
  182. package/dist/plugins/database/__tests__/plugin.spec.js +4 -2
  183. package/dist/plugins/database/__tests__/plugin.spec.js.map +1 -1
  184. package/dist/plugins/monty-python/tool.spec.js +1 -2
  185. package/dist/plugins/monty-python/tool.spec.js.map +1 -1
  186. package/dist/plugins/shell/processTools.js +1 -1
  187. package/dist/plugins/shell/processTools.js.map +1 -1
  188. package/dist/plugins/shell/processTools.spec.js +2 -3
  189. package/dist/plugins/shell/processTools.spec.js.map +1 -1
  190. package/dist/plugins/shell/tool.d.ts.map +1 -1
  191. package/dist/plugins/shell/tool.js +90 -486
  192. package/dist/plugins/shell/tool.js.map +1 -1
  193. package/dist/plugins/shell/tool.spec.js +11 -20
  194. package/dist/plugins/shell/tool.spec.js.map +1 -1
  195. package/dist/sandbox/sandbox.d.ts +26 -0
  196. package/dist/sandbox/sandbox.d.ts.map +1 -0
  197. package/dist/sandbox/sandbox.js +466 -0
  198. package/dist/sandbox/sandbox.js.map +1 -0
  199. package/dist/sandbox/sandbox.spec.d.ts +2 -0
  200. package/dist/sandbox/sandbox.spec.d.ts.map +1 -0
  201. package/dist/sandbox/sandbox.spec.js +167 -0
  202. package/dist/sandbox/sandbox.spec.js.map +1 -0
  203. package/dist/sandbox/sandboxCanRead.d.ts.map +1 -1
  204. package/dist/sandbox/sandboxCanRead.js +4 -8
  205. package/dist/sandbox/sandboxCanRead.js.map +1 -1
  206. package/dist/sandbox/sandboxCanRead.spec.js +17 -11
  207. package/dist/sandbox/sandboxCanRead.spec.js.map +1 -1
  208. package/dist/sandbox/sandboxFilesystemPolicyBuild.d.ts +1 -1
  209. package/dist/sandbox/sandboxFilesystemPolicyBuild.d.ts.map +1 -1
  210. package/dist/sandbox/sandboxFilesystemPolicyBuild.js +14 -6
  211. package/dist/sandbox/sandboxFilesystemPolicyBuild.js.map +1 -1
  212. package/dist/sandbox/sandboxFilesystemPolicyBuild.spec.js +7 -2
  213. package/dist/sandbox/sandboxFilesystemPolicyBuild.spec.js.map +1 -1
  214. package/dist/sandbox/sandboxReadDenyPathsBuild.d.ts +13 -0
  215. package/dist/sandbox/sandboxReadDenyPathsBuild.d.ts.map +1 -0
  216. package/dist/sandbox/sandboxReadDenyPathsBuild.js +28 -0
  217. package/dist/sandbox/sandboxReadDenyPathsBuild.js.map +1 -0
  218. package/dist/sandbox/sandboxReadDenyPathsBuild.spec.d.ts +2 -0
  219. package/dist/sandbox/sandboxReadDenyPathsBuild.spec.d.ts.map +1 -0
  220. package/dist/sandbox/sandboxReadDenyPathsBuild.spec.js +29 -0
  221. package/dist/sandbox/sandboxReadDenyPathsBuild.spec.js.map +1 -0
  222. package/dist/sandbox/sandboxTypes.d.ts +67 -0
  223. package/dist/sandbox/sandboxTypes.d.ts.map +1 -0
  224. package/dist/sandbox/sandboxTypes.js +2 -0
  225. package/dist/sandbox/sandboxTypes.js.map +1 -0
  226. package/dist/storage/agentsRepository.d.ts +1 -0
  227. package/dist/storage/agentsRepository.d.ts.map +1 -1
  228. package/dist/storage/agentsRepository.js +16 -0
  229. package/dist/storage/agentsRepository.js.map +1 -1
  230. package/dist/storage/agentsRepository.spec.js +45 -0
  231. package/dist/storage/agentsRepository.spec.js.map +1 -1
  232. package/dist/storage/connectionsRepository.d.ts +18 -0
  233. package/dist/storage/connectionsRepository.d.ts.map +1 -0
  234. package/dist/storage/connectionsRepository.js +163 -0
  235. package/dist/storage/connectionsRepository.js.map +1 -0
  236. package/dist/storage/connectionsRepository.spec.d.ts +2 -0
  237. package/dist/storage/connectionsRepository.spec.d.ts.map +1 -0
  238. package/dist/storage/connectionsRepository.spec.js +115 -0
  239. package/dist/storage/connectionsRepository.spec.js.map +1 -0
  240. package/dist/storage/databaseTypes.d.ts +19 -0
  241. package/dist/storage/databaseTypes.d.ts.map +1 -1
  242. package/dist/storage/migrations/20260222_add_usertag_connections.d.ts +7 -0
  243. package/dist/storage/migrations/20260222_add_usertag_connections.d.ts.map +1 -0
  244. package/dist/storage/migrations/20260222_add_usertag_connections.js +32 -0
  245. package/dist/storage/migrations/20260222_add_usertag_connections.js.map +1 -0
  246. package/dist/storage/migrations/20260222_add_usertag_connections.spec.d.ts +2 -0
  247. package/dist/storage/migrations/20260222_add_usertag_connections.spec.d.ts.map +1 -0
  248. package/dist/storage/migrations/20260222_add_usertag_connections.spec.js +55 -0
  249. package/dist/storage/migrations/20260222_add_usertag_connections.spec.js.map +1 -0
  250. package/dist/storage/migrations/_migrations.d.ts.map +1 -1
  251. package/dist/storage/migrations/_migrations.js +3 -1
  252. package/dist/storage/migrations/_migrations.js.map +1 -1
  253. package/dist/storage/storage.d.ts +3 -0
  254. package/dist/storage/storage.d.ts.map +1 -1
  255. package/dist/storage/storage.js +35 -3
  256. package/dist/storage/storage.js.map +1 -1
  257. package/dist/storage/storage.spec.js +1 -0
  258. package/dist/storage/storage.spec.js.map +1 -1
  259. package/dist/storage/usersRepository.d.ts +2 -0
  260. package/dist/storage/usersRepository.d.ts.map +1 -1
  261. package/dist/storage/usersRepository.js +43 -2
  262. package/dist/storage/usersRepository.js.map +1 -1
  263. package/dist/storage/usersRepository.spec.js +9 -2
  264. package/dist/storage/usersRepository.spec.js.map +1 -1
  265. package/dist/types.d.ts +2 -0
  266. package/dist/types.d.ts.map +1 -1
  267. package/dist/types.js +2 -0
  268. package/dist/types.js.map +1 -1
  269. package/package.json +1 -1
  270. /package/dist/plugins/dashboard/site/_next/static/{X_oqQhoSTmj1_qmNPx-r5 → Hr0soHgJ1L7WevXil6GIk}/_buildManifest.js +0 -0
  271. /package/dist/plugins/dashboard/site/_next/static/{X_oqQhoSTmj1_qmNPx-r5 → Hr0soHgJ1L7WevXil6GIk}/_ssgManifest.js +0 -0
@@ -1,25 +1,10 @@
1
- import { promises as fs } from "node:fs";
2
- import os from "node:os";
3
1
  import path from "node:path";
4
2
  import { Type } from "@sinclair/typebox";
5
3
  import { toolExecutionResultOutcomeWithTyped, toolMessageTextExtract } from "../../engine/modules/tools/toolReturnOutcome.js";
6
- import { resolveWorkspacePath } from "../../engine/permissions.js";
7
- import { isWithinSecure, openSecure } from "../../sandbox/pathResolveSecure.js";
8
- import { runInSandbox } from "../../sandbox/runtime.js";
9
- import { sandboxAllowedDomainsResolve } from "../../sandbox/sandboxAllowedDomainsResolve.js";
10
- import { sandboxAllowedDomainsValidate } from "../../sandbox/sandboxAllowedDomainsValidate.js";
11
- import { sandboxCanRead } from "../../sandbox/sandboxCanRead.js";
12
- import { sandboxCanWrite } from "../../sandbox/sandboxCanWrite.js";
13
- import { sandboxFilesystemPolicyBuild } from "../../sandbox/sandboxFilesystemPolicyBuild.js";
14
- import { envNormalize } from "../../util/envNormalize.js";
15
4
  import { stringTruncateTail } from "../../utils/stringTruncateTail.js";
16
5
  const READ_MAX_LINES = 2000;
17
6
  const READ_MAX_BYTES = 50 * 1024;
18
- const MAX_EXEC_BUFFER = 1_000_000;
19
7
  const MAX_EXEC_STREAM_OUTPUT_CHARS = 8_000;
20
- const DEFAULT_EXEC_TIMEOUT = 30_000;
21
- const UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
22
- const NARROW_NO_BREAK_SPACE = "\u202F";
23
8
  const editItemSchema = Type.Object({
24
9
  search: Type.String({ minLength: 1 }),
25
10
  replace: Type.String(),
@@ -45,7 +30,6 @@ const execSchema = Type.Object({
45
30
  cwd: Type.Optional(Type.String({ minLength: 1 })),
46
31
  timeoutMs: Type.Optional(Type.Number({ minimum: 100, maximum: 300_000 })),
47
32
  env: Type.Optional(envSchema),
48
- home: Type.Optional(Type.String({ minLength: 1 })),
49
33
  packageManagers: Type.Optional(Type.Array(Type.Union([
50
34
  Type.Literal("dart"),
51
35
  Type.Literal("dotnet"),
@@ -86,13 +70,38 @@ export function buildWorkspaceReadTool() {
86
70
  returns: shellReturns,
87
71
  execute: async (args, toolContext, toolCall) => {
88
72
  const payload = args;
89
- const workingDir = toolContext.permissions.workingDir;
90
- if (!workingDir) {
91
- throw new Error("Workspace is not configured.");
73
+ const readResult = await toolContext.sandbox.read({
74
+ path: payload.path,
75
+ offset: payload.offset,
76
+ limit: payload.limit
77
+ });
78
+ if (readResult.type === "image") {
79
+ const text = `Read image file: ${readResult.displayPath} [${readResult.mimeType}]`;
80
+ const toolMessage = buildToolMessage(toolCall, text, false, {
81
+ action: "read",
82
+ path: readResult.displayPath,
83
+ bytes: readResult.bytes,
84
+ mimeType: readResult.mimeType
85
+ });
86
+ toolMessage.content = [
87
+ { type: "text", text },
88
+ { type: "image", data: readResult.content.toString("base64"), mimeType: readResult.mimeType }
89
+ ];
90
+ return toolExecutionResultOutcomeWithTyped(toolMessage, shellResultBuild(toolMessage, "read"));
92
91
  }
93
- const targetPath = await resolveReadInputPath(payload.path, workingDir);
94
- const resolved = await resolveReadPathSecure(toolContext.permissions, targetPath);
95
- return handleReadSecure(resolved, payload.path, payload.offset, payload.limit, workingDir, toolCall);
92
+ if (readResult.type !== "text") {
93
+ throw new Error("Path is not a text or image file.");
94
+ }
95
+ const toolMessage = buildToolMessage(toolCall, readResult.content, false, {
96
+ action: "read",
97
+ path: readResult.displayPath,
98
+ bytes: readResult.bytes,
99
+ truncated: readResult.truncated,
100
+ truncatedBy: readResult.truncatedBy,
101
+ offset: payload.offset ?? null,
102
+ limit: payload.limit ?? null
103
+ });
104
+ return toolExecutionResultOutcomeWithTyped(toolMessage, shellResultBuild(toolMessage, "read"));
96
105
  }
97
106
  };
98
107
  }
@@ -106,13 +115,19 @@ export function buildWorkspaceWriteTool() {
106
115
  returns: shellReturns,
107
116
  execute: async (args, toolContext, toolCall) => {
108
117
  const payload = args;
109
- const workingDir = toolContext.permissions.workingDir;
110
- if (!workingDir) {
111
- throw new Error("Workspace is not configured.");
112
- }
113
- ensureAbsolutePath(payload.path);
114
- const resolved = await resolveWritePathSecure(toolContext.permissions, payload.path);
115
- return handleWriteSecure(resolved, payload.content, payload.append ?? false, workingDir, toolCall);
118
+ const writeResult = await toolContext.sandbox.write({
119
+ path: payload.path,
120
+ content: payload.content,
121
+ append: payload.append ?? false
122
+ });
123
+ const text = `${payload.append ? "Appended" : "Wrote"} ${writeResult.bytes} bytes to ${writeResult.sandboxPath}.`;
124
+ const toolMessage = buildToolMessage(toolCall, text, false, {
125
+ action: "write",
126
+ path: writeResult.sandboxPath,
127
+ bytes: writeResult.bytes,
128
+ append: payload.append ?? false
129
+ });
130
+ return toolExecutionResultOutcomeWithTyped(toolMessage, shellResultBuild(toolMessage, "write"));
116
131
  }
117
132
  };
118
133
  }
@@ -126,13 +141,33 @@ export function buildWorkspaceEditTool() {
126
141
  returns: shellReturns,
127
142
  execute: async (args, toolContext, toolCall) => {
128
143
  const payload = args;
129
- const workingDir = toolContext.permissions.workingDir;
130
- if (!workingDir) {
131
- throw new Error("Workspace is not configured.");
132
- }
133
144
  ensureAbsolutePath(payload.path);
134
- const resolved = await resolveWritePathSecure(toolContext.permissions, payload.path);
135
- return handleEditSecure(resolved, payload.edits, workingDir, toolCall);
145
+ const readResult = await toolContext.sandbox.read({ path: payload.path, raw: true });
146
+ if (readResult.type !== "text") {
147
+ throw new Error("Path is not a text file.");
148
+ }
149
+ let updated = readResult.content;
150
+ const counts = [];
151
+ for (const edit of payload.edits) {
152
+ const { next, count } = applyEdit(updated, edit);
153
+ if (count === 0) {
154
+ const preview = edit.search.length > 80 ? `${edit.search.slice(0, 77)}...` : edit.search;
155
+ throw new Error(`Edit not applied: "${preview}" not found.`);
156
+ }
157
+ counts.push(count);
158
+ updated = next;
159
+ }
160
+ await toolContext.sandbox.write({ path: payload.path, content: updated });
161
+ const summary = counts
162
+ .map((count, index) => `edit ${index + 1}: ${count} replacement${count === 1 ? "" : "s"}`)
163
+ .join(", ");
164
+ const text = `Updated ${readResult.displayPath} (${summary}).`;
165
+ const toolMessage = buildToolMessage(toolCall, text, false, {
166
+ action: "edit",
167
+ path: readResult.displayPath,
168
+ edits: counts
169
+ });
170
+ return toolExecutionResultOutcomeWithTyped(toolMessage, shellResultBuild(toolMessage, "edit"));
136
171
  }
137
172
  };
138
173
  }
@@ -140,230 +175,34 @@ export function buildExecTool() {
140
175
  return {
141
176
  tool: {
142
177
  name: "exec",
143
- description: "Execute a shell command inside the agent workspace (or a subdirectory). The cwd, if provided, must be an absolute path that resolves inside the workspace. Exec uses the caller's granted write directories and global read access with a protected deny-list. Optional home (absolute path within allowed write directories) remaps HOME and related env vars for sandboxed execution. Optional packageManagers language presets auto-allow ecosystem hosts (dart/dotnet/go/java/node/php/python/ruby/rust). Optional allowedDomains enables outbound access to specific domains (supports subdomain wildcards like *.example.com, no global wildcard). Returns stdout/stderr and failure details.",
178
+ description: "Execute a shell command inside the agent workspace (or a subdirectory). The cwd, if provided, must resolve inside the workspace. Exec uses the caller's granted write directories and global read access with a protected deny-list. Optional packageManagers language presets auto-allow ecosystem hosts (dart/dotnet/go/java/node/php/python/ruby/rust). Optional allowedDomains enables outbound access to specific domains (supports subdomain wildcards like *.example.com, no global wildcard). Returns stdout/stderr and failure details.",
144
179
  parameters: execSchema
145
180
  },
146
181
  returns: shellReturns,
147
182
  execute: async (args, toolContext, toolCall) => {
148
183
  const payload = args;
149
- const workingDir = toolContext.permissions.workingDir;
150
- if (!workingDir) {
151
- throw new Error("Workspace is not configured.");
152
- }
153
- const permissions = resolveExecPermissions(toolContext.permissions);
154
- if (payload.cwd) {
155
- ensureAbsolutePath(payload.cwd);
156
- }
157
- if (payload.home) {
158
- ensureAbsolutePath(payload.home);
159
- }
160
- const cwd = payload.cwd ? resolveWorkspacePath(workingDir, payload.cwd) : workingDir;
161
- const home = payload.home ? await resolveWritePathSecure(permissions, payload.home) : undefined;
162
- const allowedDomains = sandboxAllowedDomainsResolve(payload.allowedDomains, payload.packageManagers);
163
- const domainIssues = sandboxAllowedDomainsValidate(allowedDomains);
164
- if (domainIssues.length > 0) {
165
- throw new Error(domainIssues.join(" "));
166
- }
167
- const envOverrides = envNormalize(payload.env);
168
- const env = envOverrides ? { ...process.env, ...envOverrides } : process.env;
169
- const timeout = payload.timeoutMs ?? DEFAULT_EXEC_TIMEOUT;
170
- const sandboxConfig = buildSandboxConfig(permissions, allowedDomains);
171
- try {
172
- const result = await runInSandbox(payload.command, sandboxConfig, {
173
- cwd,
174
- env,
175
- home,
176
- timeoutMs: timeout,
177
- maxBufferBytes: MAX_EXEC_BUFFER
178
- });
179
- const stdout = toText(result.stdout);
180
- const stderr = toText(result.stderr);
181
- const text = formatExecOutput(stdout, stderr, false);
182
- const toolMessage = buildToolMessage(toolCall, text, false, {
183
- cwd: path.relative(workingDir, cwd) || "."
184
- });
185
- return toolExecutionResultOutcomeWithTyped(toolMessage, shellResultBuild(toolMessage, "exec"));
186
- }
187
- catch (error) {
188
- const execError = error;
189
- const stdout = toText(execError.stdout);
190
- const stderr = toText(execError.stderr);
191
- const text = formatExecOutput(stdout, stderr, true);
192
- const toolMessage = buildToolMessage(toolCall, text, true, {
193
- cwd: path.relative(workingDir, cwd) || ".",
194
- exitCode: execError.code ?? null,
195
- signal: execError.signal ?? null
196
- });
197
- return toolExecutionResultOutcomeWithTyped(toolMessage, shellResultBuild(toolMessage, "exec"));
198
- }
184
+ const workingDir = toolContext.sandbox.workingDir;
185
+ const result = await toolContext.sandbox.exec({
186
+ command: payload.command,
187
+ cwd: payload.cwd,
188
+ timeoutMs: payload.timeoutMs,
189
+ env: payload.env,
190
+ packageManagers: payload.packageManagers,
191
+ allowedDomains: payload.allowedDomains
192
+ });
193
+ const text = formatExecOutput(result.stdout, result.stderr, result.failed);
194
+ const toolMessage = buildToolMessage(toolCall, text, result.failed, {
195
+ cwd: path.relative(workingDir, result.cwd) || ".",
196
+ exitCode: result.exitCode,
197
+ signal: result.signal
198
+ });
199
+ return toolExecutionResultOutcomeWithTyped(toolMessage, shellResultBuild(toolMessage, "exec"));
199
200
  }
200
201
  };
201
202
  }
202
- /**
203
- * Secure read handler that uses lstat + openSecure to prevent TOCTOU attacks.
204
- * The path has already been securely resolved (symlinks followed, containment verified).
205
- */
206
- async function handleReadSecure(resolvedPath, requestedPath, offset, limit, workingDir, toolCall) {
207
- // Use lstat to check file type without following symlinks
208
- const stats = await fs.lstat(resolvedPath);
209
- if (stats.isSymbolicLink()) {
210
- throw new Error("Cannot read symbolic link directly.");
211
- }
212
- if (!stats.isFile()) {
213
- throw new Error("Path is not a file.");
214
- }
215
- const displayPath = formatDisplayPath(workingDir, resolvedPath);
216
- const mimeType = await detectSupportedImageMimeTypeFromFile(resolvedPath);
217
- if (mimeType) {
218
- const imageBuffer = await readBinaryFileSecure(resolvedPath);
219
- const text = `Read image file: ${displayPath} [${mimeType}]`;
220
- const toolMessage = buildToolMessage(toolCall, text, false, {
221
- action: "read",
222
- path: displayPath,
223
- bytes: stats.size,
224
- mimeType
225
- });
226
- toolMessage.content = [
227
- { type: "text", text },
228
- { type: "image", data: imageBuffer.toString("base64"), mimeType }
229
- ];
230
- return toolExecutionResultOutcomeWithTyped(toolMessage, shellResultBuild(toolMessage, "read"));
231
- }
232
- const textContent = await readTextFileSecure(resolvedPath);
233
- const allLines = textContent.split("\n");
234
- const totalFileLines = allLines.length;
235
- const startLine = offset ? Math.max(0, offset - 1) : 0;
236
- const startLineDisplay = startLine + 1;
237
- if (startLine >= allLines.length) {
238
- throw new Error(`Offset ${offset} is beyond end of file (${allLines.length} lines total)`);
239
- }
240
- let selectedContent;
241
- let userLimitedLines;
242
- if (limit !== undefined) {
243
- const endLine = Math.min(startLine + limit, allLines.length);
244
- selectedContent = allLines.slice(startLine, endLine).join("\n");
245
- userLimitedLines = endLine - startLine;
246
- }
247
- else {
248
- selectedContent = allLines.slice(startLine).join("\n");
249
- }
250
- const truncation = truncateHead(selectedContent);
251
- let outputText;
252
- if (truncation.firstLineExceedsLimit) {
253
- const firstLineSize = formatSize(Buffer.byteLength(allLines[startLine] ?? "", "utf8"));
254
- outputText = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize(READ_MAX_BYTES)} limit. Use bash: sed -n '${startLineDisplay}p' ${requestedPath} | head -c ${READ_MAX_BYTES}]`;
255
- }
256
- else if (truncation.truncated) {
257
- const endLineDisplay = startLineDisplay + truncation.outputLines - 1;
258
- const nextOffset = endLineDisplay + 1;
259
- outputText = truncation.content;
260
- if (truncation.truncatedBy === "lines") {
261
- outputText += `\n\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue.]`;
262
- }
263
- else {
264
- outputText += `\n\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(READ_MAX_BYTES)} limit). Use offset=${nextOffset} to continue.]`;
265
- }
266
- }
267
- else if (userLimitedLines !== undefined && startLine + userLimitedLines < allLines.length) {
268
- const remaining = allLines.length - (startLine + userLimitedLines);
269
- const nextOffset = startLine + userLimitedLines + 1;
270
- outputText = `${truncation.content}\n\n[${remaining} more lines in file. Use offset=${nextOffset} to continue.]`;
271
- }
272
- else {
273
- outputText = truncation.content;
274
- }
275
- const toolMessage = buildToolMessage(toolCall, outputText, false, {
276
- action: "read",
277
- path: displayPath,
278
- bytes: stats.size,
279
- truncated: truncation.truncated,
280
- truncatedBy: truncation.truncatedBy,
281
- offset: offset ?? null,
282
- limit: limit ?? null
283
- });
284
- return toolExecutionResultOutcomeWithTyped(toolMessage, shellResultBuild(toolMessage, "read"));
285
- }
286
- /**
287
- * Secure write handler that prevents TOCTOU attacks.
288
- * The path has already been securely resolved (symlinks followed, containment verified).
289
- */
290
- async function handleWriteSecure(resolvedPath, content, append, workingDir, toolCall) {
291
- await fs.mkdir(path.dirname(resolvedPath), { recursive: true });
292
- // Check if target is a symlink before writing
293
- try {
294
- const stats = await fs.lstat(resolvedPath);
295
- if (stats.isSymbolicLink()) {
296
- throw new Error("Cannot write to symbolic link.");
297
- }
298
- }
299
- catch (error) {
300
- // File doesn't exist yet - OK for write operations
301
- if (error.code !== "ENOENT") {
302
- throw error;
303
- }
304
- }
305
- // Use atomic file operations via file handle
306
- const flags = append ? "a" : "w";
307
- const handle = await fs.open(resolvedPath, flags);
308
- try {
309
- await handle.writeFile(content, "utf8");
310
- }
311
- finally {
312
- await handle.close();
313
- }
314
- const bytes = Buffer.byteLength(content, "utf8");
315
- const displayPath = formatDisplayPath(workingDir, resolvedPath);
316
- const text = `${append ? "Appended" : "Wrote"} ${bytes} bytes to ${displayPath}.`;
317
- const toolMessage = buildToolMessage(toolCall, text, false, {
318
- action: "write",
319
- path: displayPath,
320
- bytes,
321
- append
322
- });
323
- return toolExecutionResultOutcomeWithTyped(toolMessage, shellResultBuild(toolMessage, "write"));
324
- }
325
- /**
326
- * Secure edit handler that prevents TOCTOU attacks.
327
- * Uses file handle to ensure atomic read-modify-write operations.
328
- */
329
- async function handleEditSecure(resolvedPath, edits, workingDir, toolCall) {
330
- // Check if target is a symlink
331
- const stats = await fs.lstat(resolvedPath);
332
- if (stats.isSymbolicLink()) {
333
- throw new Error("Cannot edit symbolic link.");
334
- }
335
- // Open with r+ for read-modify-write atomicity
336
- const handle = await fs.open(resolvedPath, "r+");
337
- try {
338
- const original = await handle.readFile("utf8");
339
- let updated = original;
340
- const counts = [];
341
- for (const edit of edits) {
342
- const { next, count } = applyEdit(updated, edit);
343
- if (count === 0) {
344
- const preview = edit.search.length > 80 ? `${edit.search.slice(0, 77)}...` : edit.search;
345
- throw new Error(`Edit not applied: "${preview}" not found.`);
346
- }
347
- counts.push(count);
348
- updated = next;
349
- }
350
- // Truncate and write from beginning
351
- await handle.truncate(0);
352
- await handle.write(updated, 0, "utf8");
353
- const displayPath = formatDisplayPath(workingDir, resolvedPath);
354
- const summary = counts
355
- .map((count, index) => `edit ${index + 1}: ${count} replacement${count === 1 ? "" : "s"}`)
356
- .join(", ");
357
- const text = `Updated ${displayPath} (${summary}).`;
358
- const toolMessage = buildToolMessage(toolCall, text, false, {
359
- action: "edit",
360
- path: displayPath,
361
- edits: counts
362
- });
363
- return toolExecutionResultOutcomeWithTyped(toolMessage, shellResultBuild(toolMessage, "edit"));
364
- }
365
- finally {
366
- await handle.close();
203
+ function ensureAbsolutePath(target) {
204
+ if (!path.isAbsolute(target)) {
205
+ throw new Error("Path must be absolute.");
367
206
  }
368
207
  }
369
208
  function applyEdit(input, edit) {
@@ -429,12 +268,6 @@ function detailNumberGet(details, key) {
429
268
  const value = details[key];
430
269
  return typeof value === "number" && Number.isFinite(value) ? value : undefined;
431
270
  }
432
- function toText(value) {
433
- if (!value) {
434
- return "";
435
- }
436
- return typeof value === "string" ? value : value.toString("utf8");
437
- }
438
271
  export function formatExecOutput(stdout, stderr, failed) {
439
272
  const parts = [];
440
273
  const stdoutPart = formatExecStream("stdout", stdout);
@@ -457,233 +290,4 @@ function formatExecStream(stream, value) {
457
290
  const text = stringTruncateTail(value.trimEnd(), MAX_EXEC_STREAM_OUTPUT_CHARS, stream);
458
291
  return `${stream}:\n${text}`;
459
292
  }
460
- async function readTextFileSecure(resolvedPath) {
461
- const handle = await openSecure(resolvedPath, "r");
462
- try {
463
- return await handle.readFile("utf8");
464
- }
465
- finally {
466
- await handle.close();
467
- }
468
- }
469
- async function readBinaryFileSecure(resolvedPath) {
470
- const handle = await openSecure(resolvedPath, "r");
471
- try {
472
- return await handle.readFile();
473
- }
474
- finally {
475
- await handle.close();
476
- }
477
- }
478
- async function detectSupportedImageMimeTypeFromFile(resolvedPath) {
479
- const handle = await openSecure(resolvedPath, "r");
480
- try {
481
- const header = Buffer.alloc(16);
482
- const { bytesRead } = await handle.read(header, 0, header.length, 0);
483
- if (bytesRead === 0) {
484
- return null;
485
- }
486
- return detectSupportedImageMimeTypeFromHeader(header.subarray(0, bytesRead));
487
- }
488
- finally {
489
- await handle.close();
490
- }
491
- }
492
- function detectSupportedImageMimeTypeFromHeader(header) {
493
- if (header.length >= 3 && header[0] === 0xff && header[1] === 0xd8 && header[2] === 0xff) {
494
- return "image/jpeg";
495
- }
496
- if (header.length >= 8 &&
497
- header[0] === 0x89 &&
498
- header[1] === 0x50 &&
499
- header[2] === 0x4e &&
500
- header[3] === 0x47 &&
501
- header[4] === 0x0d &&
502
- header[5] === 0x0a &&
503
- header[6] === 0x1a &&
504
- header[7] === 0x0a) {
505
- return "image/png";
506
- }
507
- if (header.length >= 6) {
508
- const signature = header.subarray(0, 6).toString("ascii");
509
- if (signature === "GIF87a" || signature === "GIF89a") {
510
- return "image/gif";
511
- }
512
- }
513
- if (header.length >= 12 &&
514
- header.subarray(0, 4).toString("ascii") === "RIFF" &&
515
- header.subarray(8, 12).toString("ascii") === "WEBP") {
516
- return "image/webp";
517
- }
518
- return null;
519
- }
520
- function formatSize(bytes) {
521
- if (bytes < 1024) {
522
- return `${bytes}B`;
523
- }
524
- if (bytes < 1024 * 1024) {
525
- return `${(bytes / 1024).toFixed(1)}KB`;
526
- }
527
- return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
528
- }
529
- function truncateHead(content) {
530
- const totalBytes = Buffer.byteLength(content, "utf8");
531
- const lines = content.split("\n");
532
- const totalLines = lines.length;
533
- if (totalLines <= READ_MAX_LINES && totalBytes <= READ_MAX_BYTES) {
534
- return {
535
- content,
536
- truncated: false,
537
- truncatedBy: null,
538
- totalLines,
539
- totalBytes,
540
- outputLines: totalLines,
541
- outputBytes: totalBytes,
542
- lastLinePartial: false,
543
- firstLineExceedsLimit: false
544
- };
545
- }
546
- const firstLineBytes = Buffer.byteLength(lines[0] ?? "", "utf8");
547
- if (firstLineBytes > READ_MAX_BYTES) {
548
- return {
549
- content: "",
550
- truncated: true,
551
- truncatedBy: "bytes",
552
- totalLines,
553
- totalBytes,
554
- outputLines: 0,
555
- outputBytes: 0,
556
- lastLinePartial: false,
557
- firstLineExceedsLimit: true
558
- };
559
- }
560
- const outputLines = [];
561
- let outputBytes = 0;
562
- let truncatedBy = "lines";
563
- for (let index = 0; index < lines.length && index < READ_MAX_LINES; index++) {
564
- const line = lines[index] ?? "";
565
- const lineBytes = Buffer.byteLength(line, "utf8") + (index > 0 ? 1 : 0);
566
- if (outputBytes + lineBytes > READ_MAX_BYTES) {
567
- truncatedBy = "bytes";
568
- break;
569
- }
570
- outputLines.push(line);
571
- outputBytes += lineBytes;
572
- }
573
- if (outputLines.length >= READ_MAX_LINES && outputBytes <= READ_MAX_BYTES) {
574
- truncatedBy = "lines";
575
- }
576
- const outputContent = outputLines.join("\n");
577
- return {
578
- content: outputContent,
579
- truncated: true,
580
- truncatedBy,
581
- totalLines,
582
- totalBytes,
583
- outputLines: outputLines.length,
584
- outputBytes: Buffer.byteLength(outputContent, "utf8"),
585
- lastLinePartial: false,
586
- firstLineExceedsLimit: false
587
- };
588
- }
589
- function normalizeReadPathUnicodeSpaces(value) {
590
- return value.replace(UNICODE_SPACES, " ");
591
- }
592
- function normalizeReadPathAtPrefix(value) {
593
- return value.startsWith("@") ? value.slice(1) : value;
594
- }
595
- function normalizeReadPathInput(rawPath) {
596
- const normalized = normalizeReadPathUnicodeSpaces(normalizeReadPathAtPrefix(rawPath));
597
- if (normalized === "~") {
598
- return os.homedir();
599
- }
600
- if (normalized.startsWith("~/")) {
601
- return os.homedir() + normalized.slice(1);
602
- }
603
- return normalized;
604
- }
605
- async function pathExists(target) {
606
- try {
607
- await fs.access(target);
608
- return true;
609
- }
610
- catch {
611
- return false;
612
- }
613
- }
614
- function readPathTryMacOSScreenshotVariant(target) {
615
- return target.replace(/ (AM|PM)\./g, `${NARROW_NO_BREAK_SPACE}$1.`);
616
- }
617
- function readPathTryNfdVariant(target) {
618
- return target.normalize("NFD");
619
- }
620
- function readPathTryCurlyQuoteVariant(target) {
621
- return target.replace(/'/g, "\u2019");
622
- }
623
- /**
624
- * Resolves a read path with compatibility fallbacks for common macOS screenshot naming variants.
625
- */
626
- async function resolveReadInputPath(rawPath, workingDir) {
627
- const normalized = normalizeReadPathInput(rawPath);
628
- const resolved = path.isAbsolute(normalized) ? normalized : path.resolve(workingDir, normalized);
629
- if (await pathExists(resolved)) {
630
- return resolved;
631
- }
632
- const amPmVariant = readPathTryMacOSScreenshotVariant(resolved);
633
- if (amPmVariant !== resolved && (await pathExists(amPmVariant))) {
634
- return amPmVariant;
635
- }
636
- const nfdVariant = readPathTryNfdVariant(resolved);
637
- if (nfdVariant !== resolved && (await pathExists(nfdVariant))) {
638
- return nfdVariant;
639
- }
640
- const curlyVariant = readPathTryCurlyQuoteVariant(resolved);
641
- if (curlyVariant !== resolved && (await pathExists(curlyVariant))) {
642
- return curlyVariant;
643
- }
644
- const nfdCurlyVariant = readPathTryCurlyQuoteVariant(nfdVariant);
645
- if (nfdCurlyVariant !== resolved && (await pathExists(nfdCurlyVariant))) {
646
- return nfdCurlyVariant;
647
- }
648
- return resolved;
649
- }
650
- function ensureAbsolutePath(target) {
651
- if (!path.isAbsolute(target)) {
652
- throw new Error("Path must be absolute.");
653
- }
654
- }
655
- async function resolveWritePathSecure(permissions, target) {
656
- return sandboxCanWrite(permissions, target);
657
- }
658
- async function resolveReadPathSecure(permissions, target) {
659
- return sandboxCanRead(permissions, target);
660
- }
661
- function formatDisplayPath(workingDir, target) {
662
- if (isWithinSecure(workingDir, target)) {
663
- return path.relative(workingDir, target) || ".";
664
- }
665
- return target;
666
- }
667
- function buildSandboxConfig(permissions, allowedDomains) {
668
- const filesystem = sandboxFilesystemPolicyBuild({
669
- writeDirs: permissions.writeDirs,
670
- workingDir: permissions.workingDir
671
- });
672
- return {
673
- filesystem,
674
- network: {
675
- allowedDomains,
676
- deniedDomains: []
677
- },
678
- enableWeakerNestedSandbox: true
679
- };
680
- }
681
- function resolveExecPermissions(currentPermissions) {
682
- const readDirs = currentPermissions.readDirs ? [...currentPermissions.readDirs] : undefined;
683
- return {
684
- workingDir: currentPermissions.workingDir,
685
- writeDirs: [...currentPermissions.writeDirs],
686
- ...(readDirs ? { readDirs } : {})
687
- };
688
- }
689
293
  //# sourceMappingURL=tool.js.map