dotdo 0.0.1 → 0.0.2

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 (727) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +446 -315
  3. package/dist/ai/index.js +19 -0
  4. package/dist/ai/index.js.map +1 -0
  5. package/dist/ai/template-literals.js +852 -0
  6. package/dist/ai/template-literals.js.map +1 -0
  7. package/dist/api/analytics/router.js +601 -0
  8. package/dist/api/analytics/router.js.map +1 -0
  9. package/dist/api/index.js +158 -0
  10. package/dist/api/index.js.map +1 -0
  11. package/dist/api/middleware/auth-federation.js +573 -0
  12. package/dist/api/middleware/auth-federation.js.map +1 -0
  13. package/dist/api/middleware/auth.js +544 -0
  14. package/dist/api/middleware/auth.js.map +1 -0
  15. package/dist/api/middleware/error-handling.js +176 -0
  16. package/dist/api/middleware/error-handling.js.map +1 -0
  17. package/dist/api/middleware/request-id.js +21 -0
  18. package/dist/api/middleware/request-id.js.map +1 -0
  19. package/dist/api/pages.js +1180 -0
  20. package/dist/api/pages.js.map +1 -0
  21. package/dist/api/routes/api.js +612 -0
  22. package/dist/api/routes/api.js.map +1 -0
  23. package/dist/api/routes/browsers.js +471 -0
  24. package/dist/api/routes/browsers.js.map +1 -0
  25. package/dist/api/routes/do.js +188 -0
  26. package/dist/api/routes/do.js.map +1 -0
  27. package/dist/api/routes/mcp.js +459 -0
  28. package/dist/api/routes/mcp.js.map +1 -0
  29. package/dist/api/routes/obs.js +445 -0
  30. package/dist/api/routes/obs.js.map +1 -0
  31. package/dist/api/routes/openapi.js +794 -0
  32. package/dist/api/routes/openapi.js.map +1 -0
  33. package/dist/api/routes/rpc.js +1103 -0
  34. package/dist/api/routes/rpc.js.map +1 -0
  35. package/dist/api/routes/sandboxes.js +389 -0
  36. package/dist/api/routes/sandboxes.js.map +1 -0
  37. package/dist/api/test-do.js +38 -0
  38. package/dist/api/test-do.js.map +1 -0
  39. package/dist/api/types.js +11 -0
  40. package/dist/api/types.js.map +1 -0
  41. package/dist/cli/bin.js +2 -0
  42. package/dist/cli/main.js +52342 -0
  43. package/dist/db/actions.js +212 -0
  44. package/dist/db/actions.js.map +1 -0
  45. package/dist/db/auth.js +506 -0
  46. package/dist/db/auth.js.map +1 -0
  47. package/dist/db/branches.js +65 -0
  48. package/dist/db/branches.js.map +1 -0
  49. package/dist/db/clickhouse.js +1074 -0
  50. package/dist/db/clickhouse.js.map +1 -0
  51. package/dist/db/dlq.js +39 -0
  52. package/dist/db/dlq.js.map +1 -0
  53. package/dist/db/events.js +28 -0
  54. package/dist/db/events.js.map +1 -0
  55. package/dist/db/exec.js +64 -0
  56. package/dist/db/exec.js.map +1 -0
  57. package/dist/db/files.js +85 -0
  58. package/dist/db/files.js.map +1 -0
  59. package/dist/db/flags.js +24 -0
  60. package/dist/db/flags.js.map +1 -0
  61. package/dist/db/git.js +116 -0
  62. package/dist/db/git.js.map +1 -0
  63. package/dist/db/iceberg/inverted-index.js +862 -0
  64. package/dist/db/iceberg/inverted-index.js.map +1 -0
  65. package/dist/db/iceberg/puffin.js +878 -0
  66. package/dist/db/iceberg/puffin.js.map +1 -0
  67. package/dist/db/iceberg/search-manifest.js +422 -0
  68. package/dist/db/iceberg/search-manifest.js.map +1 -0
  69. package/dist/db/iceberg/types.js +8 -0
  70. package/dist/db/iceberg/types.js.map +1 -0
  71. package/dist/db/index.js +121 -0
  72. package/dist/db/index.js.map +1 -0
  73. package/dist/db/integrations.js +368 -0
  74. package/dist/db/integrations.js.map +1 -0
  75. package/dist/db/json-indexes.js +332 -0
  76. package/dist/db/json-indexes.js.map +1 -0
  77. package/dist/db/linked-accounts.js +287 -0
  78. package/dist/db/linked-accounts.js.map +1 -0
  79. package/dist/db/nouns.js +183 -0
  80. package/dist/db/nouns.js.map +1 -0
  81. package/dist/db/objects.js +170 -0
  82. package/dist/db/objects.js.map +1 -0
  83. package/dist/db/primitives/dag-scheduler/index.js +869 -0
  84. package/dist/db/primitives/dag-scheduler/index.js.map +1 -0
  85. package/dist/db/primitives/exactly-once-context.js +237 -0
  86. package/dist/db/primitives/exactly-once-context.js.map +1 -0
  87. package/dist/db/primitives/index.js +62 -0
  88. package/dist/db/primitives/index.js.map +1 -0
  89. package/dist/db/primitives/keyed-router.js +145 -0
  90. package/dist/db/primitives/keyed-router.js.map +1 -0
  91. package/dist/db/primitives/observability.js +162 -0
  92. package/dist/db/primitives/observability.js.map +1 -0
  93. package/dist/db/primitives/schema-evolution.js +643 -0
  94. package/dist/db/primitives/schema-evolution.js.map +1 -0
  95. package/dist/db/primitives/stateful-operator/index.js +770 -0
  96. package/dist/db/primitives/stateful-operator/index.js.map +1 -0
  97. package/dist/db/primitives/temporal-store.js +306 -0
  98. package/dist/db/primitives/temporal-store.js.map +1 -0
  99. package/dist/db/primitives/typed-column-store.js +1229 -0
  100. package/dist/db/primitives/typed-column-store.js.map +1 -0
  101. package/dist/db/primitives/utils/duration.js +162 -0
  102. package/dist/db/primitives/utils/duration.js.map +1 -0
  103. package/dist/db/primitives/utils/murmur3.js +118 -0
  104. package/dist/db/primitives/utils/murmur3.js.map +1 -0
  105. package/dist/db/primitives/watermark-service.js +136 -0
  106. package/dist/db/primitives/watermark-service.js.map +1 -0
  107. package/dist/db/primitives/window-manager.js +764 -0
  108. package/dist/db/primitives/window-manager.js.map +1 -0
  109. package/dist/db/relationships.js +66 -0
  110. package/dist/db/relationships.js.map +1 -0
  111. package/dist/db/schema-minimal.js +61 -0
  112. package/dist/db/schema-minimal.js.map +1 -0
  113. package/dist/db/search.js +28 -0
  114. package/dist/db/search.js.map +1 -0
  115. package/dist/db/stores.js +1665 -0
  116. package/dist/db/stores.js.map +1 -0
  117. package/dist/db/things.js +297 -0
  118. package/dist/db/things.js.map +1 -0
  119. package/dist/db/vault.js +171 -0
  120. package/dist/db/vault.js.map +1 -0
  121. package/dist/db/verbs.js +102 -0
  122. package/dist/db/verbs.js.map +1 -0
  123. package/dist/do/base.js +48 -0
  124. package/dist/do/base.js.map +1 -0
  125. package/dist/do/bash.js +35 -0
  126. package/dist/do/bash.js.map +1 -0
  127. package/dist/do/fs.js +25 -0
  128. package/dist/do/fs.js.map +1 -0
  129. package/dist/do/full.js +61 -0
  130. package/dist/do/full.js.map +1 -0
  131. package/dist/do/git.js +28 -0
  132. package/dist/do/git.js.map +1 -0
  133. package/dist/do/index.js +52 -0
  134. package/dist/do/index.js.map +1 -0
  135. package/dist/do/tiny.js +31 -0
  136. package/dist/do/tiny.js.map +1 -0
  137. package/dist/lib/DOAuth.js +261 -0
  138. package/dist/lib/DOAuth.js.map +1 -0
  139. package/dist/lib/DODispatcher.js +72 -0
  140. package/dist/lib/DODispatcher.js.map +1 -0
  141. package/dist/lib/Modifier.js +189 -0
  142. package/dist/lib/Modifier.js.map +1 -0
  143. package/dist/lib/StateStorage.js +403 -0
  144. package/dist/lib/StateStorage.js.map +1 -0
  145. package/dist/lib/TypeRegistry.js +122 -0
  146. package/dist/lib/TypeRegistry.js.map +1 -0
  147. package/dist/lib/agent/tools/bash.js +336 -0
  148. package/dist/lib/agent/tools/bash.js.map +1 -0
  149. package/dist/lib/agent/tools/edit.js +157 -0
  150. package/dist/lib/agent/tools/edit.js.map +1 -0
  151. package/dist/lib/agent/tools/glob.js +137 -0
  152. package/dist/lib/agent/tools/glob.js.map +1 -0
  153. package/dist/lib/agent/tools/grep.js +315 -0
  154. package/dist/lib/agent/tools/grep.js.map +1 -0
  155. package/dist/lib/agent/tools/index.js +71 -0
  156. package/dist/lib/agent/tools/index.js.map +1 -0
  157. package/dist/lib/agent/tools/read.js +212 -0
  158. package/dist/lib/agent/tools/read.js.map +1 -0
  159. package/dist/lib/agent/tools/types.js +197 -0
  160. package/dist/lib/agent/tools/types.js.map +1 -0
  161. package/dist/lib/agent/tools/write.js +159 -0
  162. package/dist/lib/agent/tools/write.js.map +1 -0
  163. package/dist/lib/ai/gateway.js +247 -0
  164. package/dist/lib/ai/gateway.js.map +1 -0
  165. package/dist/lib/ai/tool-loop-agent.js +591 -0
  166. package/dist/lib/ai/tool-loop-agent.js.map +1 -0
  167. package/dist/lib/auto-wiring.js +439 -0
  168. package/dist/lib/auto-wiring.js.map +1 -0
  169. package/dist/lib/browse/browserbase.js +163 -0
  170. package/dist/lib/browse/browserbase.js.map +1 -0
  171. package/dist/lib/browse/cloudflare.js +144 -0
  172. package/dist/lib/browse/cloudflare.js.map +1 -0
  173. package/dist/lib/browse/index.js +62 -0
  174. package/dist/lib/browse/index.js.map +1 -0
  175. package/dist/lib/browse/types.js +13 -0
  176. package/dist/lib/browse/types.js.map +1 -0
  177. package/dist/lib/cache/index.js +37 -0
  178. package/dist/lib/cache/index.js.map +1 -0
  179. package/dist/lib/cache/visibility.js +638 -0
  180. package/dist/lib/cache/visibility.js.map +1 -0
  181. package/dist/lib/capabilities.js +268 -0
  182. package/dist/lib/capabilities.js.map +1 -0
  183. package/dist/lib/channels/base.js +106 -0
  184. package/dist/lib/channels/base.js.map +1 -0
  185. package/dist/lib/channels/discord.js +94 -0
  186. package/dist/lib/channels/discord.js.map +1 -0
  187. package/dist/lib/channels/email.js +204 -0
  188. package/dist/lib/channels/email.js.map +1 -0
  189. package/dist/lib/channels/index.js +90 -0
  190. package/dist/lib/channels/index.js.map +1 -0
  191. package/dist/lib/channels/mdxui-chat.js +95 -0
  192. package/dist/lib/channels/mdxui-chat.js.map +1 -0
  193. package/dist/lib/channels/slack-blockkit.js +121 -0
  194. package/dist/lib/channels/slack-blockkit.js.map +1 -0
  195. package/dist/lib/channels/types.js +7 -0
  196. package/dist/lib/channels/types.js.map +1 -0
  197. package/dist/lib/cloudflare/ai.js +654 -0
  198. package/dist/lib/cloudflare/ai.js.map +1 -0
  199. package/dist/lib/cloudflare/index.js +88 -0
  200. package/dist/lib/cloudflare/index.js.map +1 -0
  201. package/dist/lib/cloudflare/kv.js +342 -0
  202. package/dist/lib/cloudflare/kv.js.map +1 -0
  203. package/dist/lib/cloudflare/queues.js +434 -0
  204. package/dist/lib/cloudflare/queues.js.map +1 -0
  205. package/dist/lib/cloudflare/r2.js +604 -0
  206. package/dist/lib/cloudflare/r2.js.map +1 -0
  207. package/dist/lib/cloudflare/vectorize.js +494 -0
  208. package/dist/lib/cloudflare/vectorize.js.map +1 -0
  209. package/dist/lib/cloudflare/workflows.js +569 -0
  210. package/dist/lib/cloudflare/workflows.js.map +1 -0
  211. package/dist/lib/colo/caching.js +196 -0
  212. package/dist/lib/colo/caching.js.map +1 -0
  213. package/dist/lib/colo/detection.js +194 -0
  214. package/dist/lib/colo/detection.js.map +1 -0
  215. package/dist/lib/colo/external-data.js +219 -0
  216. package/dist/lib/colo/external-data.js.map +1 -0
  217. package/dist/lib/colo/globe-data.js +179 -0
  218. package/dist/lib/colo/globe-data.js.map +1 -0
  219. package/dist/lib/colo/index.js +16 -0
  220. package/dist/lib/colo/index.js.map +1 -0
  221. package/dist/lib/decorators.js +37 -0
  222. package/dist/lib/decorators.js.map +1 -0
  223. package/dist/lib/discovery.js +81 -0
  224. package/dist/lib/discovery.js.map +1 -0
  225. package/dist/lib/executors/AgenticFunctionExecutor.js +619 -0
  226. package/dist/lib/executors/AgenticFunctionExecutor.js.map +1 -0
  227. package/dist/lib/executors/BaseFunctionExecutor.js +328 -0
  228. package/dist/lib/executors/BaseFunctionExecutor.js.map +1 -0
  229. package/dist/lib/executors/CascadeExecutor.js +418 -0
  230. package/dist/lib/executors/CascadeExecutor.js.map +1 -0
  231. package/dist/lib/executors/CodeFunctionExecutor.js +904 -0
  232. package/dist/lib/executors/CodeFunctionExecutor.js.map +1 -0
  233. package/dist/lib/executors/GenerativeFunctionExecutor.js +904 -0
  234. package/dist/lib/executors/GenerativeFunctionExecutor.js.map +1 -0
  235. package/dist/lib/executors/HumanFunctionExecutor.js +884 -0
  236. package/dist/lib/executors/HumanFunctionExecutor.js.map +1 -0
  237. package/dist/lib/executors/ParallelStepExecutor.js +308 -0
  238. package/dist/lib/executors/ParallelStepExecutor.js.map +1 -0
  239. package/dist/lib/executors/types.js +12 -0
  240. package/dist/lib/executors/types.js.map +1 -0
  241. package/dist/lib/experiments.js +89 -0
  242. package/dist/lib/experiments.js.map +1 -0
  243. package/dist/lib/flags/store.js +262 -0
  244. package/dist/lib/flags/store.js.map +1 -0
  245. package/dist/lib/functions/FunctionComposition.js +467 -0
  246. package/dist/lib/functions/FunctionComposition.js.map +1 -0
  247. package/dist/lib/functions/FunctionMiddleware.js +457 -0
  248. package/dist/lib/functions/FunctionMiddleware.js.map +1 -0
  249. package/dist/lib/functions/FunctionRegistry.js +426 -0
  250. package/dist/lib/functions/FunctionRegistry.js.map +1 -0
  251. package/dist/lib/functions/createFunction.js +1048 -0
  252. package/dist/lib/functions/createFunction.js.map +1 -0
  253. package/dist/lib/humans/index.js +68 -0
  254. package/dist/lib/humans/index.js.map +1 -0
  255. package/dist/lib/humans/templates.js +117 -0
  256. package/dist/lib/humans/templates.js.map +1 -0
  257. package/dist/lib/identity.js +98 -0
  258. package/dist/lib/identity.js.map +1 -0
  259. package/dist/lib/index.js +9 -0
  260. package/dist/lib/index.js.map +1 -0
  261. package/dist/lib/logging/error-logger.js +163 -0
  262. package/dist/lib/logging/error-logger.js.map +1 -0
  263. package/dist/lib/logging/index.js +160 -0
  264. package/dist/lib/logging/index.js.map +1 -0
  265. package/dist/lib/mixins/bash.js +825 -0
  266. package/dist/lib/mixins/bash.js.map +1 -0
  267. package/dist/lib/mixins/fs.js +648 -0
  268. package/dist/lib/mixins/fs.js.map +1 -0
  269. package/dist/lib/mixins/git.js +1011 -0
  270. package/dist/lib/mixins/git.js.map +1 -0
  271. package/dist/lib/mixins/index.js +29 -0
  272. package/dist/lib/mixins/index.js.map +1 -0
  273. package/dist/lib/mixins/npm.js +662 -0
  274. package/dist/lib/mixins/npm.js.map +1 -0
  275. package/dist/lib/noun-id.js +278 -0
  276. package/dist/lib/noun-id.js.map +1 -0
  277. package/dist/lib/rate-limit/sliding-window.js +148 -0
  278. package/dist/lib/rate-limit/sliding-window.js.map +1 -0
  279. package/dist/lib/rate-limit.js +110 -0
  280. package/dist/lib/rate-limit.js.map +1 -0
  281. package/dist/lib/rpc/bindings.js +548 -0
  282. package/dist/lib/rpc/bindings.js.map +1 -0
  283. package/dist/lib/rpc/index.js +64 -0
  284. package/dist/lib/rpc/index.js.map +1 -0
  285. package/dist/lib/safe-stringify.js +223 -0
  286. package/dist/lib/safe-stringify.js.map +1 -0
  287. package/dist/lib/sandbox/miniflare-sandbox.js +1007 -0
  288. package/dist/lib/sandbox/miniflare-sandbox.js.map +1 -0
  289. package/dist/lib/sqids.js +110 -0
  290. package/dist/lib/sqids.js.map +1 -0
  291. package/dist/lib/sql/adapters/index.js +10 -0
  292. package/dist/lib/sql/adapters/index.js.map +1 -0
  293. package/dist/lib/sql/adapters/node-sql-parser.js +552 -0
  294. package/dist/lib/sql/adapters/node-sql-parser.js.map +1 -0
  295. package/dist/lib/sql/adapters/pgsql-parser.js +1189 -0
  296. package/dist/lib/sql/adapters/pgsql-parser.js.map +1 -0
  297. package/dist/lib/sql/index.js +277 -0
  298. package/dist/lib/sql/index.js.map +1 -0
  299. package/dist/lib/sql/types.js +56 -0
  300. package/dist/lib/sql/types.js.map +1 -0
  301. package/dist/lib/type-classifier.js +126 -0
  302. package/dist/lib/type-classifier.js.map +1 -0
  303. package/dist/lib/utils/html.js +47 -0
  304. package/dist/lib/utils/html.js.map +1 -0
  305. package/dist/lib/validation.js +48 -0
  306. package/dist/lib/validation.js.map +1 -0
  307. package/dist/lib/vault/store.js +411 -0
  308. package/dist/lib/vault/store.js.map +1 -0
  309. package/dist/metrics/hunch.js +739 -0
  310. package/dist/metrics/hunch.js.map +1 -0
  311. package/dist/objects/API.js +302 -0
  312. package/dist/objects/API.js.map +1 -0
  313. package/dist/objects/Agent.js +179 -0
  314. package/dist/objects/Agent.js.map +1 -0
  315. package/dist/objects/AgenticFunctionExecutor.js +8 -0
  316. package/dist/objects/AgenticFunctionExecutor.js.map +1 -0
  317. package/dist/objects/App.js +83 -0
  318. package/dist/objects/App.js.map +1 -0
  319. package/dist/objects/Browser.js +884 -0
  320. package/dist/objects/Browser.js.map +1 -0
  321. package/dist/objects/Business.js +107 -0
  322. package/dist/objects/Business.js.map +1 -0
  323. package/dist/objects/CLI.js +221 -0
  324. package/dist/objects/CLI.js.map +1 -0
  325. package/dist/objects/CodeFunctionExecutor.js +8 -0
  326. package/dist/objects/CodeFunctionExecutor.js.map +1 -0
  327. package/dist/objects/Collection.js +161 -0
  328. package/dist/objects/Collection.js.map +1 -0
  329. package/dist/objects/DO.js +41 -0
  330. package/dist/objects/DO.js.map +1 -0
  331. package/dist/objects/DOBase.js +2309 -0
  332. package/dist/objects/DOBase.js.map +1 -0
  333. package/dist/objects/DOFull.js +1676 -0
  334. package/dist/objects/DOFull.js.map +1 -0
  335. package/dist/objects/DOTiny.js +207 -0
  336. package/dist/objects/DOTiny.js.map +1 -0
  337. package/dist/objects/Directory.js +199 -0
  338. package/dist/objects/Directory.js.map +1 -0
  339. package/dist/objects/Entity.js +413 -0
  340. package/dist/objects/Entity.js.map +1 -0
  341. package/dist/objects/Function.js +116 -0
  342. package/dist/objects/Function.js.map +1 -0
  343. package/dist/objects/Human.js +231 -0
  344. package/dist/objects/Human.js.map +1 -0
  345. package/dist/objects/HumanFunctionExecutor.js +8 -0
  346. package/dist/objects/HumanFunctionExecutor.js.map +1 -0
  347. package/dist/objects/IcebergMetadataDO.js +938 -0
  348. package/dist/objects/IcebergMetadataDO.js.map +1 -0
  349. package/dist/objects/IntegrationsDO.js +1174 -0
  350. package/dist/objects/IntegrationsDO.js.map +1 -0
  351. package/dist/objects/ObservabilityBroadcaster.js +149 -0
  352. package/dist/objects/ObservabilityBroadcaster.js.map +1 -0
  353. package/dist/objects/Package.js +154 -0
  354. package/dist/objects/Package.js.map +1 -0
  355. package/dist/objects/Product.js +193 -0
  356. package/dist/objects/Product.js.map +1 -0
  357. package/dist/objects/SDK.js +152 -0
  358. package/dist/objects/SDK.js.map +1 -0
  359. package/dist/objects/SaaS.js +235 -0
  360. package/dist/objects/SaaS.js.map +1 -0
  361. package/dist/objects/SandboxDO.js +759 -0
  362. package/dist/objects/SandboxDO.js.map +1 -0
  363. package/dist/objects/Service.js +337 -0
  364. package/dist/objects/Service.js.map +1 -0
  365. package/dist/objects/Site.js +80 -0
  366. package/dist/objects/Site.js.map +1 -0
  367. package/dist/objects/Startup.js +479 -0
  368. package/dist/objects/Startup.js.map +1 -0
  369. package/dist/objects/ThingsDO.js +170 -0
  370. package/dist/objects/ThingsDO.js.map +1 -0
  371. package/dist/objects/VectorShardDO.js +648 -0
  372. package/dist/objects/VectorShardDO.js.map +1 -0
  373. package/dist/objects/Worker.js +144 -0
  374. package/dist/objects/Worker.js.map +1 -0
  375. package/dist/objects/Workflow.js +196 -0
  376. package/dist/objects/Workflow.js.map +1 -0
  377. package/dist/objects/WorkflowFactory.js +313 -0
  378. package/dist/objects/WorkflowFactory.js.map +1 -0
  379. package/dist/objects/WorkflowRuntime.js +863 -0
  380. package/dist/objects/WorkflowRuntime.js.map +1 -0
  381. package/dist/objects/circuit-breaker-bulkhead.js +178 -0
  382. package/dist/objects/circuit-breaker-bulkhead.js.map +1 -0
  383. package/dist/objects/createFunction.js +934 -0
  384. package/dist/objects/createFunction.js.map +1 -0
  385. package/dist/objects/index.js +80 -0
  386. package/dist/objects/index.js.map +1 -0
  387. package/dist/objects/lifecycle/Branch.js +275 -0
  388. package/dist/objects/lifecycle/Branch.js.map +1 -0
  389. package/dist/objects/lifecycle/Clone.js +1499 -0
  390. package/dist/objects/lifecycle/Clone.js.map +1 -0
  391. package/dist/objects/lifecycle/Compact.js +237 -0
  392. package/dist/objects/lifecycle/Compact.js.map +1 -0
  393. package/dist/objects/lifecycle/Promote.js +476 -0
  394. package/dist/objects/lifecycle/Promote.js.map +1 -0
  395. package/dist/objects/lifecycle/Shard.js +560 -0
  396. package/dist/objects/lifecycle/Shard.js.map +1 -0
  397. package/dist/objects/lifecycle/index.js +15 -0
  398. package/dist/objects/lifecycle/index.js.map +1 -0
  399. package/dist/objects/lifecycle/types.js +33 -0
  400. package/dist/objects/lifecycle/types.js.map +1 -0
  401. package/dist/objects/mixins/infrastructure.js +171 -0
  402. package/dist/objects/mixins/infrastructure.js.map +1 -0
  403. package/dist/objects/modules/StoresModule.js +153 -0
  404. package/dist/objects/modules/StoresModule.js.map +1 -0
  405. package/dist/objects/persistence/checkpoint-manager.js +606 -0
  406. package/dist/objects/persistence/checkpoint-manager.js.map +1 -0
  407. package/dist/objects/persistence/index.js +72 -0
  408. package/dist/objects/persistence/index.js.map +1 -0
  409. package/dist/objects/persistence/migration-runner.js +562 -0
  410. package/dist/objects/persistence/migration-runner.js.map +1 -0
  411. package/dist/objects/persistence/replication-manager.js +501 -0
  412. package/dist/objects/persistence/replication-manager.js.map +1 -0
  413. package/dist/objects/persistence/tiered-storage-manager.js +595 -0
  414. package/dist/objects/persistence/tiered-storage-manager.js.map +1 -0
  415. package/dist/objects/persistence/types.js +14 -0
  416. package/dist/objects/persistence/types.js.map +1 -0
  417. package/dist/objects/persistence/wal-manager.js +653 -0
  418. package/dist/objects/persistence/wal-manager.js.map +1 -0
  419. package/dist/objects/presets/index.js +20 -0
  420. package/dist/objects/presets/index.js.map +1 -0
  421. package/dist/objects/presets/primitives.js +188 -0
  422. package/dist/objects/presets/primitives.js.map +1 -0
  423. package/dist/objects/primitives/alarm-adapter.js +141 -0
  424. package/dist/objects/primitives/alarm-adapter.js.map +1 -0
  425. package/dist/objects/primitives/index.js +337 -0
  426. package/dist/objects/primitives/index.js.map +1 -0
  427. package/dist/objects/primitives/storage-adapter.js +182 -0
  428. package/dist/objects/primitives/storage-adapter.js.map +1 -0
  429. package/dist/objects/primitives/with-primitives.js +102 -0
  430. package/dist/objects/primitives/with-primitives.js.map +1 -0
  431. package/dist/objects/services/StoreManager.js +227 -0
  432. package/dist/objects/services/StoreManager.js.map +1 -0
  433. package/dist/objects/services/index.js +13 -0
  434. package/dist/objects/services/index.js.map +1 -0
  435. package/dist/objects/transport/auth-layer.js +1451 -0
  436. package/dist/objects/transport/auth-layer.js.map +1 -0
  437. package/dist/objects/transport/capnweb-target.js +355 -0
  438. package/dist/objects/transport/capnweb-target.js.map +1 -0
  439. package/dist/objects/transport/chain.js +441 -0
  440. package/dist/objects/transport/chain.js.map +1 -0
  441. package/dist/objects/transport/handler.js +58 -0
  442. package/dist/objects/transport/handler.js.map +1 -0
  443. package/dist/objects/transport/index.js +53 -0
  444. package/dist/objects/transport/index.js.map +1 -0
  445. package/dist/objects/transport/mcp-server.js +690 -0
  446. package/dist/objects/transport/mcp-server.js.map +1 -0
  447. package/dist/objects/transport/rest-autowire.js +1507 -0
  448. package/dist/objects/transport/rest-autowire.js.map +1 -0
  449. package/dist/objects/transport/rest-router.js +440 -0
  450. package/dist/objects/transport/rest-router.js.map +1 -0
  451. package/dist/objects/transport/rpc-server.js +1536 -0
  452. package/dist/objects/transport/rpc-server.js.map +1 -0
  453. package/dist/objects/transport/shared.js +575 -0
  454. package/dist/objects/transport/shared.js.map +1 -0
  455. package/dist/objects/transport/sync-engine.js +291 -0
  456. package/dist/objects/transport/sync-engine.js.map +1 -0
  457. package/dist/objects/transport/types.js +8 -0
  458. package/dist/objects/transport/types.js.map +1 -0
  459. package/dist/primitives/bashx/src/ast/analyze.js +1472 -0
  460. package/dist/primitives/bashx/src/ast/analyze.js.map +1 -0
  461. package/dist/primitives/bashx/src/ast/parser.js +1488 -0
  462. package/dist/primitives/bashx/src/ast/parser.js.map +1 -0
  463. package/dist/primitives/bashx/src/do/commands/crypto.js +1954 -0
  464. package/dist/primitives/bashx/src/do/commands/crypto.js.map +1 -0
  465. package/dist/primitives/bashx/src/do/commands/data-processing.js +1812 -0
  466. package/dist/primitives/bashx/src/do/commands/data-processing.js.map +1 -0
  467. package/dist/primitives/bashx/src/do/commands/extended-utils.js +804 -0
  468. package/dist/primitives/bashx/src/do/commands/extended-utils.js.map +1 -0
  469. package/dist/primitives/bashx/src/do/commands/math-control.js +1122 -0
  470. package/dist/primitives/bashx/src/do/commands/math-control.js.map +1 -0
  471. package/dist/primitives/bashx/src/do/commands/posix-utils.js +1015 -0
  472. package/dist/primitives/bashx/src/do/commands/posix-utils.js.map +1 -0
  473. package/dist/primitives/bashx/src/do/commands/system-utils.js +687 -0
  474. package/dist/primitives/bashx/src/do/commands/system-utils.js.map +1 -0
  475. package/dist/primitives/bashx/src/do/commands/test-command.js +523 -0
  476. package/dist/primitives/bashx/src/do/commands/test-command.js.map +1 -0
  477. package/dist/primitives/bashx/src/do/commands/text-processing.js +1550 -0
  478. package/dist/primitives/bashx/src/do/commands/text-processing.js.map +1 -0
  479. package/dist/primitives/bashx/src/do/container-executor.js +429 -0
  480. package/dist/primitives/bashx/src/do/container-executor.js.map +1 -0
  481. package/dist/primitives/bashx/src/do/index.js +668 -0
  482. package/dist/primitives/bashx/src/do/index.js.map +1 -0
  483. package/dist/primitives/bashx/src/do/tiered-executor.js +2647 -0
  484. package/dist/primitives/bashx/src/do/tiered-executor.js.map +1 -0
  485. package/dist/primitives/bashx/src/do/worker.js +352 -0
  486. package/dist/primitives/bashx/src/do/worker.js.map +1 -0
  487. package/dist/primitives/bashx/src/types.js +10 -0
  488. package/dist/primitives/bashx/src/types.js.map +1 -0
  489. package/dist/primitives/fsx/core/backend.js +480 -0
  490. package/dist/primitives/fsx/core/backend.js.map +1 -0
  491. package/dist/primitives/fsx/core/constants.js +140 -0
  492. package/dist/primitives/fsx/core/constants.js.map +1 -0
  493. package/dist/primitives/fsx/core/fsx.js +1184 -0
  494. package/dist/primitives/fsx/core/fsx.js.map +1 -0
  495. package/dist/primitives/fsx/core/glob/glob.js +438 -0
  496. package/dist/primitives/fsx/core/glob/glob.js.map +1 -0
  497. package/dist/primitives/fsx/core/glob/index.js +8 -0
  498. package/dist/primitives/fsx/core/glob/index.js.map +1 -0
  499. package/dist/primitives/fsx/core/glob/match.js +392 -0
  500. package/dist/primitives/fsx/core/glob/match.js.map +1 -0
  501. package/dist/primitives/fsx/core/types.js +307 -0
  502. package/dist/primitives/fsx/core/types.js.map +1 -0
  503. package/dist/sandbox/index.js +258 -0
  504. package/dist/sandbox/index.js.map +1 -0
  505. package/dist/sdk/capnweb-compat.js +42 -0
  506. package/dist/sdk/capnweb-compat.js.map +1 -0
  507. package/dist/sdk/client.js +20 -0
  508. package/dist/sdk/client.js.map +1 -0
  509. package/dist/sdk/index.js +17 -0
  510. package/dist/sdk/index.js.map +1 -0
  511. package/dist/snippets/artifacts-config.js +241 -0
  512. package/dist/snippets/artifacts-config.js.map +1 -0
  513. package/dist/snippets/artifacts-ingest.js +832 -0
  514. package/dist/snippets/artifacts-ingest.js.map +1 -0
  515. package/dist/snippets/artifacts-serve.js +1035 -0
  516. package/dist/snippets/artifacts-serve.js.map +1 -0
  517. package/dist/snippets/artifacts-types.js +161 -0
  518. package/dist/snippets/artifacts-types.js.map +1 -0
  519. package/dist/snippets/cache-probe.js +376 -0
  520. package/dist/snippets/cache-probe.js.map +1 -0
  521. package/dist/snippets/cache.js +10 -0
  522. package/dist/snippets/cache.js.map +1 -0
  523. package/dist/snippets/events.js +469 -0
  524. package/dist/snippets/events.js.map +1 -0
  525. package/dist/snippets/index.js +7 -0
  526. package/dist/snippets/index.js.map +1 -0
  527. package/dist/snippets/proxy.js +495 -0
  528. package/dist/snippets/proxy.js.map +1 -0
  529. package/dist/snippets/search.js +1759 -0
  530. package/dist/snippets/search.js.map +1 -0
  531. package/dist/streams/index.js +30 -0
  532. package/dist/streams/index.js.map +1 -0
  533. package/dist/streams/observability.js +68 -0
  534. package/dist/streams/observability.js.map +1 -0
  535. package/dist/types/AI.js +92 -0
  536. package/dist/types/AI.js.map +1 -0
  537. package/dist/types/AIFunction.js +171 -0
  538. package/dist/types/AIFunction.js.map +1 -0
  539. package/dist/types/BrowseVerb.js +89 -0
  540. package/dist/types/BrowseVerb.js.map +1 -0
  541. package/dist/types/Browser.js +31 -0
  542. package/dist/types/Browser.js.map +1 -0
  543. package/dist/types/Chaos.js +15 -0
  544. package/dist/types/Chaos.js.map +1 -0
  545. package/dist/types/CloudflareBindings.js +109 -0
  546. package/dist/types/CloudflareBindings.js.map +1 -0
  547. package/dist/types/Collection.js +50 -0
  548. package/dist/types/Collection.js.map +1 -0
  549. package/dist/types/DO.js +2 -0
  550. package/dist/types/DO.js.map +1 -0
  551. package/dist/types/DOLocation.js +63 -0
  552. package/dist/types/DOLocation.js.map +1 -0
  553. package/dist/types/EventHandler.js +57 -0
  554. package/dist/types/EventHandler.js.map +1 -0
  555. package/dist/types/Experiment.js +33 -0
  556. package/dist/types/Experiment.js.map +1 -0
  557. package/dist/types/Flag.js +57 -0
  558. package/dist/types/Flag.js.map +1 -0
  559. package/dist/types/Lifecycle.js +13 -0
  560. package/dist/types/Lifecycle.js.map +1 -0
  561. package/dist/types/Location.js +169 -0
  562. package/dist/types/Location.js.map +1 -0
  563. package/dist/types/Noun.js +66 -0
  564. package/dist/types/Noun.js.map +1 -0
  565. package/dist/types/SessionEvent.js +194 -0
  566. package/dist/types/SessionEvent.js.map +1 -0
  567. package/dist/types/Thing.js +55 -0
  568. package/dist/types/Thing.js.map +1 -0
  569. package/dist/types/ThingDO.js +153 -0
  570. package/dist/types/ThingDO.js.map +1 -0
  571. package/dist/types/Things.js +2 -0
  572. package/dist/types/Things.js.map +1 -0
  573. package/dist/types/Verb.js +119 -0
  574. package/dist/types/Verb.js.map +1 -0
  575. package/dist/types/WorkflowContext.js +70 -0
  576. package/dist/types/WorkflowContext.js.map +1 -0
  577. package/dist/types/analytics-api.js +13 -0
  578. package/dist/types/analytics-api.js.map +1 -0
  579. package/dist/types/capabilities.js +135 -0
  580. package/dist/types/capabilities.js.map +1 -0
  581. package/dist/types/drizzle.js +12 -0
  582. package/dist/types/drizzle.js.map +1 -0
  583. package/dist/types/event.js +201 -0
  584. package/dist/types/event.js.map +1 -0
  585. package/dist/types/fn.js +12 -0
  586. package/dist/types/fn.js.map +1 -0
  587. package/dist/types/iceberg.js +48 -0
  588. package/dist/types/iceberg.js.map +1 -0
  589. package/dist/types/ids.js +170 -0
  590. package/dist/types/ids.js.map +1 -0
  591. package/dist/types/index.js +41 -0
  592. package/dist/types/index.js.map +1 -0
  593. package/dist/types/introspect.js +54 -0
  594. package/dist/types/introspect.js.map +1 -0
  595. package/dist/types/observability.js +124 -0
  596. package/dist/types/observability.js.map +1 -0
  597. package/dist/types/sync-protocol.js +175 -0
  598. package/dist/types/sync-protocol.js.map +1 -0
  599. package/dist/types/vector.js +13 -0
  600. package/dist/types/vector.js.map +1 -0
  601. package/dist/workflows/ScheduleManager.js +473 -0
  602. package/dist/workflows/ScheduleManager.js.map +1 -0
  603. package/dist/workflows/StepDOBridge.js +149 -0
  604. package/dist/workflows/StepDOBridge.js.map +1 -0
  605. package/dist/workflows/StepResultStorage.js +232 -0
  606. package/dist/workflows/StepResultStorage.js.map +1 -0
  607. package/dist/workflows/WaitForEventManager.js +461 -0
  608. package/dist/workflows/WaitForEventManager.js.map +1 -0
  609. package/dist/workflows/analyzer.js +332 -0
  610. package/dist/workflows/analyzer.js.map +1 -0
  611. package/dist/workflows/compat/activity-router.js +484 -0
  612. package/dist/workflows/compat/activity-router.js.map +1 -0
  613. package/dist/workflows/compat/backends/cloudflare-workflows.js +431 -0
  614. package/dist/workflows/compat/backends/cloudflare-workflows.js.map +1 -0
  615. package/dist/workflows/compat/backends/index.js +14 -0
  616. package/dist/workflows/compat/backends/index.js.map +1 -0
  617. package/dist/workflows/compat/errors/index.js +375 -0
  618. package/dist/workflows/compat/errors/index.js.map +1 -0
  619. package/dist/workflows/compat/index.js +79 -0
  620. package/dist/workflows/compat/index.js.map +1 -0
  621. package/dist/workflows/compat/inngest/index.js +989 -0
  622. package/dist/workflows/compat/inngest/index.js.map +1 -0
  623. package/dist/workflows/compat/qstash/index.js +1263 -0
  624. package/dist/workflows/compat/qstash/index.js.map +1 -0
  625. package/dist/workflows/compat/temporal/activities.js +739 -0
  626. package/dist/workflows/compat/temporal/activities.js.map +1 -0
  627. package/dist/workflows/compat/temporal/child-workflows.js +154 -0
  628. package/dist/workflows/compat/temporal/child-workflows.js.map +1 -0
  629. package/dist/workflows/compat/temporal/client.js +381 -0
  630. package/dist/workflows/compat/temporal/client.js.map +1 -0
  631. package/dist/workflows/compat/temporal/context.js +309 -0
  632. package/dist/workflows/compat/temporal/context.js.map +1 -0
  633. package/dist/workflows/compat/temporal/determinism.js +216 -0
  634. package/dist/workflows/compat/temporal/determinism.js.map +1 -0
  635. package/dist/workflows/compat/temporal/errors.js +128 -0
  636. package/dist/workflows/compat/temporal/errors.js.map +1 -0
  637. package/dist/workflows/compat/temporal/index.js +2464 -0
  638. package/dist/workflows/compat/temporal/index.js.map +1 -0
  639. package/dist/workflows/compat/temporal/saga.js +504 -0
  640. package/dist/workflows/compat/temporal/saga.js.map +1 -0
  641. package/dist/workflows/compat/temporal/signals.js +364 -0
  642. package/dist/workflows/compat/temporal/signals.js.map +1 -0
  643. package/dist/workflows/compat/temporal/storage.js +271 -0
  644. package/dist/workflows/compat/temporal/storage.js.map +1 -0
  645. package/dist/workflows/compat/temporal/timers.js +347 -0
  646. package/dist/workflows/compat/temporal/timers.js.map +1 -0
  647. package/dist/workflows/compat/temporal/types.js +7 -0
  648. package/dist/workflows/compat/temporal/types.js.map +1 -0
  649. package/dist/workflows/compat/temporal/unified-primitives.js +339 -0
  650. package/dist/workflows/compat/temporal/unified-primitives.js.map +1 -0
  651. package/dist/workflows/compat/trigger/index.js +468 -0
  652. package/dist/workflows/compat/trigger/index.js.map +1 -0
  653. package/dist/workflows/compat/utils/index.js +69 -0
  654. package/dist/workflows/compat/utils/index.js.map +1 -0
  655. package/dist/workflows/context/correlation-capability.js +266 -0
  656. package/dist/workflows/context/correlation-capability.js.map +1 -0
  657. package/dist/workflows/context/correlation.js +484 -0
  658. package/dist/workflows/context/correlation.js.map +1 -0
  659. package/dist/workflows/context/experiment.js +289 -0
  660. package/dist/workflows/context/experiment.js.map +1 -0
  661. package/dist/workflows/context/flag.js +244 -0
  662. package/dist/workflows/context/flag.js.map +1 -0
  663. package/dist/workflows/context/foundation.js +648 -0
  664. package/dist/workflows/context/foundation.js.map +1 -0
  665. package/dist/workflows/context/human-base.js +106 -0
  666. package/dist/workflows/context/human-base.js.map +1 -0
  667. package/dist/workflows/context/human.js +368 -0
  668. package/dist/workflows/context/human.js.map +1 -0
  669. package/dist/workflows/context/measure.js +354 -0
  670. package/dist/workflows/context/measure.js.map +1 -0
  671. package/dist/workflows/context/rate-limit.js +358 -0
  672. package/dist/workflows/context/rate-limit.js.map +1 -0
  673. package/dist/workflows/context/user.js +117 -0
  674. package/dist/workflows/context/user.js.map +1 -0
  675. package/dist/workflows/context/vault.js +360 -0
  676. package/dist/workflows/context/vault.js.map +1 -0
  677. package/dist/workflows/data/entity-events/entity-events.js +489 -0
  678. package/dist/workflows/data/entity-events/entity-events.js.map +1 -0
  679. package/dist/workflows/data/experiment/index.js +599 -0
  680. package/dist/workflows/data/experiment/index.js.map +1 -0
  681. package/dist/workflows/data/goal/context.js +558 -0
  682. package/dist/workflows/data/goal/context.js.map +1 -0
  683. package/dist/workflows/data/goal/index.js +32 -0
  684. package/dist/workflows/data/goal/index.js.map +1 -0
  685. package/dist/workflows/data/measure/index.js +840 -0
  686. package/dist/workflows/data/measure/index.js.map +1 -0
  687. package/dist/workflows/data/stream/index.js +1215 -0
  688. package/dist/workflows/data/stream/index.js.map +1 -0
  689. package/dist/workflows/data/track/context.js +883 -0
  690. package/dist/workflows/data/track/context.js.map +1 -0
  691. package/dist/workflows/data/track/index.js +15 -0
  692. package/dist/workflows/data/track/index.js.map +1 -0
  693. package/dist/workflows/data/view/context.js +864 -0
  694. package/dist/workflows/data/view/context.js.map +1 -0
  695. package/dist/workflows/domain.js +93 -0
  696. package/dist/workflows/domain.js.map +1 -0
  697. package/dist/workflows/flag.js +176 -0
  698. package/dist/workflows/flag.js.map +1 -0
  699. package/dist/workflows/flags.js +217 -0
  700. package/dist/workflows/flags.js.map +1 -0
  701. package/dist/workflows/hash.js +209 -0
  702. package/dist/workflows/hash.js.map +1 -0
  703. package/dist/workflows/index.js +50 -0
  704. package/dist/workflows/index.js.map +1 -0
  705. package/dist/workflows/on.js +378 -0
  706. package/dist/workflows/on.js.map +1 -0
  707. package/dist/workflows/pipeline-promise.js +481 -0
  708. package/dist/workflows/pipeline-promise.js.map +1 -0
  709. package/dist/workflows/pipeline-types.js +20 -0
  710. package/dist/workflows/pipeline-types.js.map +1 -0
  711. package/dist/workflows/proxy.js +76 -0
  712. package/dist/workflows/proxy.js.map +1 -0
  713. package/dist/workflows/runtime.js +310 -0
  714. package/dist/workflows/runtime.js.map +1 -0
  715. package/dist/workflows/schedule-builder.js +327 -0
  716. package/dist/workflows/schedule-builder.js.map +1 -0
  717. package/dist/workflows/visibility/index.js +148 -0
  718. package/dist/workflows/visibility/index.js.map +1 -0
  719. package/dist/workflows/visibility/query-parser.js +150 -0
  720. package/dist/workflows/visibility/query-parser.js.map +1 -0
  721. package/dist/workflows/visibility/store.js +223 -0
  722. package/dist/workflows/visibility/store.js.map +1 -0
  723. package/dist/workflows/visibility/types.js +30 -0
  724. package/dist/workflows/visibility/types.js.map +1 -0
  725. package/dist/workflows/workflow.js +53 -0
  726. package/dist/workflows/workflow.js.map +1 -0
  727. package/package.json +279 -46
@@ -0,0 +1,1550 @@
1
+ /**
2
+ * Text Processing Commands Implementation
3
+ *
4
+ * Implements sed, awk, diff, patch, tee, and xargs commands
5
+ * for native Tier 1 execution in bashx.
6
+ *
7
+ * @module bashx/do/commands/text-processing
8
+ */
9
+ // ============================================================================
10
+ // SHARED UTILITIES
11
+ // ============================================================================
12
+ /**
13
+ * LRU cache for compiled regular expressions.
14
+ * Improves performance when the same pattern is used multiple times.
15
+ */
16
+ class RegexCache {
17
+ cache = new Map();
18
+ maxSize;
19
+ constructor(maxSize = 100) {
20
+ this.maxSize = maxSize;
21
+ }
22
+ /**
23
+ * Get or compile a regex pattern with caching
24
+ * @param pattern - The regex pattern string
25
+ * @param flags - Optional regex flags
26
+ * @returns Compiled RegExp object
27
+ */
28
+ get(pattern, flags = '') {
29
+ const key = `${pattern}:${flags}`;
30
+ let regex = this.cache.get(key);
31
+ if (!regex) {
32
+ regex = new RegExp(pattern, flags);
33
+ // Evict oldest entry if cache is full
34
+ if (this.cache.size >= this.maxSize) {
35
+ const firstKey = this.cache.keys().next().value;
36
+ if (firstKey)
37
+ this.cache.delete(firstKey);
38
+ }
39
+ this.cache.set(key, regex);
40
+ }
41
+ return regex;
42
+ }
43
+ /**
44
+ * Clear the cache
45
+ */
46
+ clear() {
47
+ this.cache.clear();
48
+ }
49
+ }
50
+ // Global regex cache instance
51
+ const regexCache = new RegexCache();
52
+ /**
53
+ * Split input text into lines, handling trailing newlines consistently.
54
+ * @param text - Input text to split
55
+ * @returns Array of lines (without trailing empty line from split)
56
+ */
57
+ function splitLines(text) {
58
+ const lines = text.split('\n');
59
+ const hasTrailingNewline = text.endsWith('\n');
60
+ if (hasTrailingNewline && lines[lines.length - 1] === '') {
61
+ lines.pop();
62
+ }
63
+ return lines;
64
+ }
65
+ /**
66
+ * Escape special regex characters in a string.
67
+ * @param str - String to escape
68
+ * @returns Escaped string safe for use in regex
69
+ */
70
+ function escapeRegex(str) {
71
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
72
+ }
73
+ /**
74
+ * Evaluate simple arithmetic expressions safely (Workers-compatible).
75
+ * @param left - Left operand
76
+ * @param op - Operator (+, -, *, /)
77
+ * @param right - Right operand
78
+ * @returns Result of the operation
79
+ */
80
+ function evalArithmetic(left, op, right) {
81
+ switch (op) {
82
+ case '+': return left + right;
83
+ case '-': return left - right;
84
+ case '*': return left * right;
85
+ case '/': return right !== 0 ? left / right : 0;
86
+ default: return left;
87
+ }
88
+ }
89
+ /**
90
+ * Parse sed command arguments
91
+ */
92
+ function parseSedArgs(args) {
93
+ const options = {
94
+ expressions: [],
95
+ };
96
+ const files = [];
97
+ let script = '';
98
+ let i = 0;
99
+ while (i < args.length) {
100
+ const arg = args[i];
101
+ if (arg === '-n') {
102
+ options.quiet = true;
103
+ i++;
104
+ }
105
+ else if (arg === '-E' || arg === '-r') {
106
+ options.extended = true;
107
+ i++;
108
+ }
109
+ else if (arg === '-i') {
110
+ options.inPlace = true;
111
+ i++;
112
+ }
113
+ else if (arg.startsWith('-i')) {
114
+ options.inPlace = true;
115
+ options.inPlaceSuffix = arg.slice(2);
116
+ i++;
117
+ }
118
+ else if (arg === '-e') {
119
+ i++;
120
+ if (i < args.length) {
121
+ options.expressions.push(args[i]);
122
+ i++;
123
+ }
124
+ }
125
+ else if (arg.startsWith('-')) {
126
+ // Skip unknown options
127
+ i++;
128
+ }
129
+ else if (!script && options.expressions.length === 0) {
130
+ script = arg;
131
+ i++;
132
+ }
133
+ else {
134
+ files.push(arg);
135
+ i++;
136
+ }
137
+ }
138
+ return { options, script, files };
139
+ }
140
+ /**
141
+ * Parse a sed substitution command (s/pattern/replacement/flags).
142
+ * Supports various delimiters and converts sed regex syntax to JavaScript.
143
+ *
144
+ * @param script - The sed substitution command (e.g., 's/foo/bar/g')
145
+ * @returns Parsed substitution object or null if not a valid substitution
146
+ */
147
+ function parseSedSubstitution(script) {
148
+ // Match s/pattern/replacement/flags with various delimiters
149
+ const delimMatch = script.match(/^s(.)/);
150
+ if (!delimMatch)
151
+ return null;
152
+ const delim = delimMatch[1];
153
+ const escapedDelim = escapeRegex(delim);
154
+ const regex = regexCache.get(`^s${escapedDelim}((?:[^${escapedDelim}\\\\]|\\\\.)*)${escapedDelim}((?:[^${escapedDelim}\\\\]|\\\\.)*)${escapedDelim}([gip]*)$`);
155
+ const match = script.match(regex);
156
+ if (!match)
157
+ return null;
158
+ const [, pattern, replacement, flags] = match;
159
+ const global = flags.includes('g');
160
+ const ignoreCase = flags.includes('i');
161
+ // Convert sed regex to JavaScript regex
162
+ // Replace sed escape sequences with JS equivalents
163
+ // \\( -> ( (grouping in sed basic regex)
164
+ // \\) -> ) (grouping in sed basic regex)
165
+ // Note: In patterns, \1 stays as \1 for backreferences (JS regex uses \1 in pattern)
166
+ // Only in replacements, \1 becomes $1 (JS uses $1 in replacement strings)
167
+ let jsPattern = pattern
168
+ .replace(/\\\(/g, '(')
169
+ .replace(/\\\)/g, ')');
170
+ let jsReplacement = replacement
171
+ .replace(/\\1/g, '$1')
172
+ .replace(/\\2/g, '$2')
173
+ .replace(/\\3/g, '$3')
174
+ .replace(/\\4/g, '$4')
175
+ .replace(/\\5/g, '$5')
176
+ .replace(/\\6/g, '$6')
177
+ .replace(/\\7/g, '$7')
178
+ .replace(/\\8/g, '$8')
179
+ .replace(/\\9/g, '$9');
180
+ const regexFlags = ignoreCase ? 'i' : '';
181
+ return {
182
+ pattern: new RegExp(jsPattern, regexFlags),
183
+ replacement: jsReplacement,
184
+ global,
185
+ };
186
+ }
187
+ /**
188
+ * Parse sed print command (Np or N,Mp where N,M are line numbers)
189
+ */
190
+ function parseSedPrint(script) {
191
+ // Match patterns like '5p', '2,4p', '$p', '1,$p'
192
+ const match = script.match(/^(\d+|\$)(?:,(\d+|\$))?p$/);
193
+ if (!match)
194
+ return null;
195
+ const start = match[1] === '$' ? '$' : parseInt(match[1], 10);
196
+ const end = match[2] ? (match[2] === '$' ? '$' : parseInt(match[2], 10)) : undefined;
197
+ return { start, end };
198
+ }
199
+ /**
200
+ * Parse sed delete command (Nd or N,Md or /pattern/d)
201
+ */
202
+ function parseSedDelete(script) {
203
+ // Match pattern delete like /^a/d
204
+ const patternMatch = script.match(/^\/(.+)\/d$/);
205
+ if (patternMatch) {
206
+ return { pattern: new RegExp(patternMatch[1]) };
207
+ }
208
+ // Match line range delete like '2d' or '1,10d'
209
+ const rangeMatch = script.match(/^(\d+)(?:,(\d+))?d$/);
210
+ if (rangeMatch) {
211
+ return {
212
+ start: parseInt(rangeMatch[1], 10),
213
+ end: rangeMatch[2] ? parseInt(rangeMatch[2], 10) : undefined,
214
+ };
215
+ }
216
+ return null;
217
+ }
218
+ /**
219
+ * Execute sed (stream editor) command.
220
+ *
221
+ * Supports substitution (s/pattern/replacement/flags), line printing with -n and p,
222
+ * line deletion with d, and multiple -e expressions.
223
+ *
224
+ * @param args - Command arguments (e.g., ['-e', 's/foo/bar/', '/path/to/file'])
225
+ * @param input - Input text to process (used when no file is specified)
226
+ * @param fs - Optional filesystem capability for in-place editing
227
+ * @returns Object with stdout, stderr, and exitCode
228
+ *
229
+ * @example
230
+ * // Basic substitution
231
+ * executeSed(['s/hello/world/g'], 'hello hello')
232
+ * // => { stdout: 'world world\n', stderr: '', exitCode: 0 }
233
+ */
234
+ export function executeSed(args, input, _fs) {
235
+ const { options, script, files: _files } = parseSedArgs(args);
236
+ void _files; // Reserved for future file input support
237
+ const scripts = options.expressions.length > 0 ? options.expressions : [script];
238
+ // If files provided, we'd need to read from fs - for now just use input
239
+ let content = input;
240
+ const processLine = (line, lineNum, totalLines) => {
241
+ let result = line;
242
+ for (const s of scripts) {
243
+ if (result === null)
244
+ break;
245
+ // Try substitution
246
+ const sub = parseSedSubstitution(s);
247
+ if (sub) {
248
+ if (sub.global) {
249
+ result = result.replace(new RegExp(sub.pattern.source, sub.pattern.flags + 'g'), sub.replacement);
250
+ }
251
+ else {
252
+ result = result.replace(sub.pattern, sub.replacement);
253
+ }
254
+ continue;
255
+ }
256
+ // Try print (only relevant when -n is used)
257
+ const print = parseSedPrint(s);
258
+ if (print && options.quiet) {
259
+ const startLine = print.start === '$' ? totalLines : print.start;
260
+ const endLine = print.end === undefined ? startLine : (print.end === '$' ? totalLines : print.end);
261
+ if (lineNum < startLine || lineNum > endLine) {
262
+ result = null;
263
+ }
264
+ continue;
265
+ }
266
+ // Try delete
267
+ const del = parseSedDelete(s);
268
+ if (del) {
269
+ if (del.pattern) {
270
+ if (del.pattern.test(result)) {
271
+ result = null;
272
+ }
273
+ }
274
+ else if (del.start !== undefined) {
275
+ const endLine = del.end ?? del.start;
276
+ if (lineNum >= del.start && lineNum <= endLine) {
277
+ result = null;
278
+ }
279
+ }
280
+ continue;
281
+ }
282
+ }
283
+ return result;
284
+ };
285
+ const lines = splitLines(content);
286
+ const totalLines = lines.length;
287
+ const outputLines = [];
288
+ for (let i = 0; i < lines.length; i++) {
289
+ const result = processLine(lines[i], i + 1, totalLines);
290
+ if (result !== null) {
291
+ outputLines.push(result);
292
+ }
293
+ }
294
+ let stdout = outputLines.join('\n');
295
+ if (outputLines.length > 0) {
296
+ stdout += '\n';
297
+ }
298
+ return { stdout, stderr: '', exitCode: 0 };
299
+ }
300
+ /**
301
+ * Parse awk command arguments
302
+ */
303
+ function parseAwkArgs(args) {
304
+ const options = {
305
+ fieldSeparator: /\s+/.source, // Default: whitespace
306
+ outputFieldSeparator: ' ',
307
+ outputRecordSeparator: '\n',
308
+ };
309
+ const files = [];
310
+ let program = '';
311
+ let i = 0;
312
+ while (i < args.length) {
313
+ const arg = args[i];
314
+ if (arg === '-F') {
315
+ i++;
316
+ if (i < args.length) {
317
+ let sep = args[i];
318
+ // Remove quotes if present
319
+ if ((sep.startsWith("'") && sep.endsWith("'")) || (sep.startsWith('"') && sep.endsWith('"'))) {
320
+ sep = sep.slice(1, -1);
321
+ }
322
+ options.fieldSeparator = sep.replace(/\\t/g, '\t');
323
+ i++;
324
+ }
325
+ }
326
+ else if (arg.startsWith('-F')) {
327
+ let sep = arg.slice(2);
328
+ // Remove quotes if present
329
+ if ((sep.startsWith("'") && sep.endsWith("'")) || (sep.startsWith('"') && sep.endsWith('"'))) {
330
+ sep = sep.slice(1, -1);
331
+ }
332
+ options.fieldSeparator = sep.replace(/\\t/g, '\t');
333
+ i++;
334
+ }
335
+ else if (arg.startsWith('-')) {
336
+ // Skip unknown options
337
+ i++;
338
+ }
339
+ else if (!program) {
340
+ program = arg;
341
+ i++;
342
+ }
343
+ else {
344
+ files.push(arg);
345
+ i++;
346
+ }
347
+ }
348
+ return { options, program, files };
349
+ }
350
+ /**
351
+ * Parse an awk program into its components
352
+ */
353
+ function parseAwkProgram(program) {
354
+ const result = {};
355
+ // Extract BEGIN block
356
+ const beginMatch = program.match(/BEGIN\s*\{([^}]*)\}/i);
357
+ if (beginMatch) {
358
+ result.begin = beginMatch[1].trim();
359
+ program = program.replace(beginMatch[0], '');
360
+ }
361
+ // Extract END block
362
+ const endMatch = program.match(/END\s*\{([^}]*)\}/i);
363
+ if (endMatch) {
364
+ result.end = endMatch[1].trim();
365
+ program = program.replace(endMatch[0], '');
366
+ }
367
+ // Parse main pattern/action
368
+ program = program.trim();
369
+ if (program) {
370
+ // Match pattern { action } or just { action } or just condition
371
+ const patternActionMatch = program.match(/^(\/[^/]+\/|[^{]+)?\s*\{([^}]*)\}$/);
372
+ if (patternActionMatch) {
373
+ result.main = {
374
+ pattern: patternActionMatch[1]?.trim(),
375
+ action: patternActionMatch[2].trim(),
376
+ };
377
+ }
378
+ else if (program.startsWith('{') && program.endsWith('}')) {
379
+ result.main = {
380
+ action: program.slice(1, -1).trim(),
381
+ };
382
+ }
383
+ else {
384
+ // Just a condition like NR==5 - implicit print
385
+ result.main = {
386
+ pattern: program,
387
+ action: 'print',
388
+ };
389
+ }
390
+ }
391
+ return result;
392
+ }
393
+ /**
394
+ * Evaluate an awk expression
395
+ */
396
+ function evaluateAwkExpression(expr, fields, variables, options) {
397
+ // Replace field references $1, $2, $NF, $0
398
+ let result = expr;
399
+ // Replace $NF with last field
400
+ result = result.replace(/\$NF/g, fields[fields.length - 1] || '');
401
+ // Replace $0 with full line
402
+ result = result.replace(/\$0/g, fields.join(options.outputFieldSeparator));
403
+ // Replace $n with nth field (1-indexed)
404
+ result = result.replace(/\$(\d+)/g, (_, n) => fields[parseInt(n, 10) - 1] || '');
405
+ // Replace NR, NF, FS, OFS
406
+ result = result.replace(/\bNR\b/g, String(variables.NR));
407
+ result = result.replace(/\bNF\b/g, String(fields.length));
408
+ result = result.replace(/\bFS\b/g, String(variables.FS));
409
+ result = result.replace(/\bOFS\b/g, String(variables.OFS));
410
+ // Replace user-defined variables (after built-in ones)
411
+ // Use word boundary to match whole variable names
412
+ for (const [varName, varValue] of Object.entries(variables)) {
413
+ if (!['NR', 'NF', 'FS', 'OFS'].includes(varName)) {
414
+ // Word boundary - matches before/after word characters
415
+ // /sum -> matches sum, sum/count -> matches both sum and count
416
+ result = result.replace(new RegExp(`(?<![a-zA-Z_])${varName}(?![a-zA-Z0-9_])`, 'g'), String(varValue));
417
+ }
418
+ }
419
+ // Handle arithmetic expressions like sum/count or 100/4
420
+ // Use the shared evalArithmetic helper (Workers-compatible, no eval/Function)
421
+ result = result.trim();
422
+ const arithMatch = result.match(/^([\d.]+)\s*([+\-*/])\s*([\d.]+)$/);
423
+ if (arithMatch) {
424
+ const [, leftStr, op, rightStr] = arithMatch;
425
+ const left = parseFloat(leftStr);
426
+ const right = parseFloat(rightStr);
427
+ if (!isNaN(left) && !isNaN(right)) {
428
+ result = String(evalArithmetic(left, op, right));
429
+ }
430
+ }
431
+ return result;
432
+ }
433
+ /**
434
+ * Execute an awk action
435
+ */
436
+ function executeAwkAction(action, fields, variables, options) {
437
+ const outputParts = [];
438
+ let hasPrintf = false;
439
+ // Split multiple statements by semicolon
440
+ const statements = action.split(/;/).map(s => s.trim()).filter(Boolean);
441
+ for (const stmt of statements) {
442
+ // Handle print statement
443
+ if (stmt.startsWith('print')) {
444
+ const printArgs = stmt.slice(5).trim();
445
+ if (!printArgs) {
446
+ // print with no args prints $0
447
+ outputParts.push(fields.join(options.outputFieldSeparator));
448
+ }
449
+ else {
450
+ // Parse print arguments
451
+ const parts = [];
452
+ // Handle printf-style
453
+ if (stmt.startsWith('printf')) {
454
+ hasPrintf = true;
455
+ const printfMatch = stmt.match(/printf\s+"([^"]*)"(?:\s*,\s*(.+))?/);
456
+ if (printfMatch) {
457
+ let format = printfMatch[1].replace(/\\n/g, '\n').replace(/\\t/g, '\t');
458
+ const argsStr = printfMatch[2];
459
+ if (argsStr) {
460
+ const args = argsStr.split(/\s*,\s*/).map(a => evaluateAwkExpression(a.trim(), fields, variables, options));
461
+ let argIndex = 0;
462
+ format = format.replace(/%(-?\d*\.?\d*)?([sdxef])/g, (_match, _width, type) => {
463
+ const val = args[argIndex++] || '';
464
+ if (type === 'd') {
465
+ return String(parseInt(val, 10) || 0);
466
+ }
467
+ return val;
468
+ });
469
+ }
470
+ outputParts.push(format);
471
+ }
472
+ continue;
473
+ }
474
+ // Regular print with comma-separated values
475
+ // Handle expressions like $1, $3 or $1 $3 (space = OFS, comma = OFS)
476
+ const argParts = printArgs.split(/\s*,\s*/);
477
+ for (const part of argParts) {
478
+ const evaluated = evaluateAwkExpression(part, fields, variables, options);
479
+ parts.push(evaluated);
480
+ }
481
+ outputParts.push(parts.join(options.outputFieldSeparator));
482
+ }
483
+ }
484
+ // Handle if statements (must come before general assignment check)
485
+ else if (stmt.startsWith('if')) {
486
+ const ifMatch = stmt.match(/if\s*\(([^)]+)\)\s*(\w+)\s*=\s*(.+)/);
487
+ if (ifMatch) {
488
+ const [, condition, varName, value] = ifMatch;
489
+ const condResult = evaluateAwkCondition(condition, fields, variables, options);
490
+ if (condResult) {
491
+ const evaluated = evaluateAwkExpression(value, fields, variables, options);
492
+ variables[varName] = parseFloat(evaluated) || evaluated;
493
+ }
494
+ }
495
+ }
496
+ // Handle variable increment (count++)
497
+ else if (stmt.match(/(\w+)\+\+/)) {
498
+ const match = stmt.match(/(\w+)\+\+/);
499
+ if (match) {
500
+ variables[match[1]] = (Number(variables[match[1]]) || 0) + 1;
501
+ }
502
+ }
503
+ // Handle variable assignments (after if statement check)
504
+ else if (stmt.includes('=') && !stmt.includes('==')) {
505
+ const assignMatch = stmt.match(/(\w+)\s*([+\-*/]?=)\s*(.+)/);
506
+ if (assignMatch) {
507
+ const [, varName, op, valueExpr] = assignMatch;
508
+ const evaluated = evaluateAwkExpression(valueExpr, fields, variables, options);
509
+ const numValue = parseFloat(evaluated) || 0;
510
+ if (op === '=') {
511
+ variables[varName] = numValue;
512
+ }
513
+ else if (op === '+=') {
514
+ variables[varName] = (Number(variables[varName]) || 0) + numValue;
515
+ }
516
+ else if (op === '-=') {
517
+ variables[varName] = (Number(variables[varName]) || 0) - numValue;
518
+ }
519
+ else if (op === '*=') {
520
+ variables[varName] = (Number(variables[varName]) || 0) * numValue;
521
+ }
522
+ else if (op === '/=') {
523
+ variables[varName] = (Number(variables[varName]) || 0) / numValue;
524
+ }
525
+ }
526
+ }
527
+ }
528
+ // For printf, join without additional separators since printf controls its own newlines
529
+ // For regular print, use ORS as separator
530
+ const output = hasPrintf
531
+ ? outputParts.join('')
532
+ : outputParts.join(options.outputRecordSeparator);
533
+ return { output, isPrintf: hasPrintf };
534
+ }
535
+ /**
536
+ * Evaluate an awk condition
537
+ */
538
+ function evaluateAwkCondition(condition, fields, variables, options) {
539
+ condition = condition.trim();
540
+ // Handle compound conditions with && first (lower precedence than comparison operators)
541
+ if (condition.includes('&&')) {
542
+ const parts = condition.split(/\s*&&\s*/);
543
+ return parts.every(part => evaluateAwkCondition(part.trim(), fields, variables, options));
544
+ }
545
+ // Handle compound conditions with ||
546
+ if (condition.includes('||')) {
547
+ const parts = condition.split(/\s*\|\|\s*/);
548
+ return parts.some(part => evaluateAwkCondition(part.trim(), fields, variables, options));
549
+ }
550
+ // Handle regex pattern /pattern/
551
+ if (condition.startsWith('/') && condition.endsWith('/')) {
552
+ const pattern = condition.slice(1, -1);
553
+ const line = fields.join(options.outputFieldSeparator);
554
+ return new RegExp(pattern).test(line);
555
+ }
556
+ // Handle negated regex !/pattern/
557
+ if (condition.startsWith('!/') && condition.endsWith('/')) {
558
+ const pattern = condition.slice(2, -1);
559
+ const line = fields.join(options.outputFieldSeparator);
560
+ return !new RegExp(pattern).test(line);
561
+ }
562
+ // Handle comparisons like NR==5, $1>10, etc.
563
+ const compMatch = condition.match(/(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)/);
564
+ if (compMatch) {
565
+ const [, left, op, right] = compMatch;
566
+ const leftVal = evaluateAwkExpression(left.trim(), fields, variables, options);
567
+ const rightVal = evaluateAwkExpression(right.trim(), fields, variables, options);
568
+ const leftNum = parseFloat(leftVal);
569
+ const rightNum = parseFloat(rightVal);
570
+ const useNumeric = !isNaN(leftNum) && !isNaN(rightNum);
571
+ switch (op) {
572
+ case '==': return useNumeric ? leftNum === rightNum : leftVal === rightVal;
573
+ case '!=': return useNumeric ? leftNum !== rightNum : leftVal !== rightVal;
574
+ case '>=': return useNumeric ? leftNum >= rightNum : leftVal >= rightVal;
575
+ case '<=': return useNumeric ? leftNum <= rightNum : leftVal <= rightVal;
576
+ case '>': return useNumeric ? leftNum > rightNum : leftVal > rightVal;
577
+ case '<': return useNumeric ? leftNum < rightNum : leftVal < rightVal;
578
+ }
579
+ }
580
+ // Default: truthy check
581
+ const evaluated = evaluateAwkExpression(condition, fields, variables, options);
582
+ return Boolean(evaluated);
583
+ }
584
+ /**
585
+ * Execute awk (pattern scanning and processing) command.
586
+ *
587
+ * Supports field extraction ($1, $2, $NF), pattern matching, BEGIN/END blocks,
588
+ * custom field separators (-F), variables, arithmetic, and control flow.
589
+ *
590
+ * @param args - Command arguments (e.g., ['-F:', '{print $1}', '/path/to/file'])
591
+ * @param input - Input text to process
592
+ * @returns Object with stdout, stderr, and exitCode
593
+ *
594
+ * @example
595
+ * // Print first field
596
+ * executeAwk(['{print $1}'], 'hello world')
597
+ * // => { stdout: 'hello\n', stderr: '', exitCode: 0 }
598
+ *
599
+ * @example
600
+ * // Sum a column
601
+ * executeAwk(['{sum+=$1} END {print sum}'], '10\n20\n30')
602
+ * // => { stdout: '60\n', stderr: '', exitCode: 0 }
603
+ */
604
+ export function executeAwk(args, input) {
605
+ const { options, program } = parseAwkArgs(args);
606
+ const parsed = parseAwkProgram(program);
607
+ const variables = {
608
+ NR: 0,
609
+ NF: 0,
610
+ FS: options.fieldSeparator,
611
+ OFS: options.outputFieldSeparator,
612
+ };
613
+ const output = [];
614
+ // Execute BEGIN block
615
+ if (parsed.begin) {
616
+ // Parse OFS/ORS assignments in BEGIN
617
+ const ofsMatch = parsed.begin.match(/OFS\s*=\s*"([^"]*)"/);
618
+ if (ofsMatch) {
619
+ options.outputFieldSeparator = ofsMatch[1];
620
+ variables.OFS = ofsMatch[1];
621
+ }
622
+ const orsMatch = parsed.begin.match(/ORS\s*=\s*"([^"]*)"/);
623
+ if (orsMatch) {
624
+ options.outputRecordSeparator = orsMatch[1];
625
+ }
626
+ // Initialize variables
627
+ const varMatches = parsed.begin.matchAll(/(\w+)\s*=\s*(\d+)/g);
628
+ for (const match of varMatches) {
629
+ variables[match[1]] = parseInt(match[2], 10);
630
+ }
631
+ }
632
+ // Process input lines
633
+ const lines = splitLines(input);
634
+ for (let i = 0; i < lines.length; i++) {
635
+ const line = lines[i];
636
+ variables.NR = i + 1;
637
+ // Split into fields using cached regex
638
+ const fieldSep = options.fieldSeparator === /\s+/.source
639
+ ? /\s+/
640
+ : regexCache.get(escapeRegex(options.fieldSeparator));
641
+ const fields = ['', ...line.split(fieldSep)]; // $0 is handled specially, but fields[1] = $1
642
+ fields[0] = line; // $0 is the whole line
643
+ variables.NF = fields.length - 1;
644
+ if (parsed.main) {
645
+ // Check pattern if present
646
+ let shouldExecute = true;
647
+ if (parsed.main.pattern) {
648
+ shouldExecute = evaluateAwkCondition(parsed.main.pattern, fields.slice(1), variables, options);
649
+ }
650
+ if (shouldExecute) {
651
+ const result = executeAwkAction(parsed.main.action, fields.slice(1), variables, options);
652
+ if (result.output) {
653
+ output.push(result);
654
+ }
655
+ }
656
+ }
657
+ }
658
+ // Execute END block
659
+ if (parsed.end) {
660
+ const fields = [''];
661
+ const result = executeAwkAction(parsed.end, fields, variables, options);
662
+ if (result.output) {
663
+ output.push(result);
664
+ }
665
+ }
666
+ // Build final output - printf handles its own newlines, print uses ORS
667
+ let stdout = '';
668
+ for (let i = 0; i < output.length; i++) {
669
+ const item = output[i];
670
+ stdout += item.output;
671
+ // Only add ORS after non-printf outputs that don't already end with newline
672
+ if (!item.isPrintf && !item.output.endsWith('\n')) {
673
+ stdout += options.outputRecordSeparator;
674
+ }
675
+ }
676
+ // Add final ORS if needed (for non-empty output not ending in newline)
677
+ if (stdout.length > 0 && !stdout.endsWith('\n') && options.outputRecordSeparator === '\n') {
678
+ stdout += '\n';
679
+ }
680
+ return { stdout, stderr: '', exitCode: 0 };
681
+ }
682
+ /**
683
+ * Myers diff algorithm - find shortest edit script
684
+ */
685
+ function myersDiff(oldLines, newLines) {
686
+ const n = oldLines.length;
687
+ const m = newLines.length;
688
+ const max = n + m;
689
+ const v = { 1: 0 };
690
+ const trace = [];
691
+ // Find the shortest edit script
692
+ outer: for (let d = 0; d <= max; d++) {
693
+ trace.push({ ...v });
694
+ for (let k = -d; k <= d; k += 2) {
695
+ let x;
696
+ if (k === -d || (k !== d && v[k - 1] < v[k + 1])) {
697
+ x = v[k + 1];
698
+ }
699
+ else {
700
+ x = v[k - 1] + 1;
701
+ }
702
+ let y = x - k;
703
+ while (x < n && y < m && oldLines[x] === newLines[y]) {
704
+ x++;
705
+ y++;
706
+ }
707
+ v[k] = x;
708
+ if (x >= n && y >= m) {
709
+ break outer;
710
+ }
711
+ }
712
+ }
713
+ // Backtrack to find the path
714
+ const edits = [];
715
+ let x = n;
716
+ let y = m;
717
+ for (let d = trace.length - 1; d >= 0; d--) {
718
+ const vPrev = trace[d];
719
+ const k = x - y;
720
+ let prevK;
721
+ if (k === -d || (k !== d && vPrev[k - 1] < vPrev[k + 1])) {
722
+ prevK = k + 1;
723
+ }
724
+ else {
725
+ prevK = k - 1;
726
+ }
727
+ const prevX = vPrev[prevK];
728
+ const prevY = prevX - prevK;
729
+ // Add equal lines (diagonal moves)
730
+ while (x > prevX && y > prevY) {
731
+ x--;
732
+ y--;
733
+ edits.unshift({ type: 'equal', oldIdx: x, newIdx: y });
734
+ }
735
+ if (d > 0) {
736
+ if (x === prevX) {
737
+ // Insert
738
+ y--;
739
+ edits.unshift({ type: 'insert', newIdx: y });
740
+ }
741
+ else {
742
+ // Delete
743
+ x--;
744
+ edits.unshift({ type: 'delete', oldIdx: x });
745
+ }
746
+ }
747
+ }
748
+ return edits;
749
+ }
750
+ /**
751
+ * Format diff in normal format
752
+ */
753
+ function formatNormalDiff(oldLines, newLines, edits) {
754
+ const output = [];
755
+ let i = 0;
756
+ while (i < edits.length) {
757
+ const edit = edits[i];
758
+ if (edit.type === 'equal') {
759
+ i++;
760
+ continue;
761
+ }
762
+ // Collect consecutive changes
763
+ const changes = [];
764
+ while (i < edits.length && edits[i].type !== 'equal') {
765
+ changes.push(edits[i]);
766
+ i++;
767
+ }
768
+ const deletes = changes.filter(c => c.type === 'delete');
769
+ const inserts = changes.filter(c => c.type === 'insert');
770
+ if (deletes.length > 0 && inserts.length > 0) {
771
+ // Change
772
+ const oldStart = deletes[0].oldIdx + 1;
773
+ const oldEnd = deletes[deletes.length - 1].oldIdx + 1;
774
+ const newStart = inserts[0].newIdx + 1;
775
+ const newEnd = inserts[inserts.length - 1].newIdx + 1;
776
+ const oldRange = oldStart === oldEnd ? `${oldStart}` : `${oldStart},${oldEnd}`;
777
+ const newRange = newStart === newEnd ? `${newStart}` : `${newStart},${newEnd}`;
778
+ output.push(`${oldRange}c${newRange}`);
779
+ for (const d of deletes) {
780
+ output.push(`< ${oldLines[d.oldIdx]}`);
781
+ }
782
+ output.push('---');
783
+ for (const ins of inserts) {
784
+ output.push(`> ${newLines[ins.newIdx]}`);
785
+ }
786
+ }
787
+ else if (deletes.length > 0) {
788
+ // Delete
789
+ const oldStart = deletes[0].oldIdx + 1;
790
+ const oldEnd = deletes[deletes.length - 1].oldIdx + 1;
791
+ const newPos = (deletes[0].oldIdx || 0);
792
+ const oldRange = oldStart === oldEnd ? `${oldStart}` : `${oldStart},${oldEnd}`;
793
+ output.push(`${oldRange}d${newPos}`);
794
+ for (const d of deletes) {
795
+ output.push(`< ${oldLines[d.oldIdx]}`);
796
+ }
797
+ }
798
+ else if (inserts.length > 0) {
799
+ // Add
800
+ const oldPos = inserts[0].newIdx;
801
+ const newStart = inserts[0].newIdx + 1;
802
+ const newEnd = inserts[inserts.length - 1].newIdx + 1;
803
+ const newRange = newStart === newEnd ? `${newStart}` : `${newStart},${newEnd}`;
804
+ output.push(`${oldPos}a${newRange}`);
805
+ for (const ins of inserts) {
806
+ output.push(`> ${newLines[ins.newIdx]}`);
807
+ }
808
+ }
809
+ }
810
+ return output.length > 0 ? output.join('\n') + '\n' : '';
811
+ }
812
+ /**
813
+ * Format diff in unified format
814
+ */
815
+ function formatUnifiedDiff(file1Path, file2Path, oldLines, newLines, edits, contextLines = 3) {
816
+ const output = [];
817
+ output.push(`--- ${file1Path}`);
818
+ output.push(`+++ ${file2Path}`);
819
+ // Group edits into hunks
820
+ const hunks = [];
821
+ let currentHunk = null;
822
+ let contextBuffer = [];
823
+ let oldLineNum = 0;
824
+ let newLineNum = 0;
825
+ for (const edit of edits) {
826
+ if (edit.type === 'equal') {
827
+ const line = oldLines[edit.oldIdx];
828
+ if (currentHunk) {
829
+ currentHunk.lines.push({ type: 'context', line });
830
+ currentHunk.oldCount++;
831
+ currentHunk.newCount++;
832
+ contextBuffer.push(line);
833
+ if (contextBuffer.length > contextLines * 2) {
834
+ // End current hunk
835
+ // Remove trailing context beyond limit
836
+ while (currentHunk.lines.length > 0 &&
837
+ currentHunk.lines[currentHunk.lines.length - 1].type === 'context' &&
838
+ contextBuffer.length > contextLines) {
839
+ currentHunk.lines.pop();
840
+ currentHunk.oldCount--;
841
+ currentHunk.newCount--;
842
+ contextBuffer.shift();
843
+ }
844
+ hunks.push(currentHunk);
845
+ currentHunk = null;
846
+ contextBuffer = [line];
847
+ }
848
+ }
849
+ else {
850
+ contextBuffer.push(line);
851
+ if (contextBuffer.length > contextLines) {
852
+ contextBuffer.shift();
853
+ }
854
+ }
855
+ oldLineNum++;
856
+ newLineNum++;
857
+ }
858
+ else {
859
+ if (!currentHunk) {
860
+ // Start new hunk with leading context
861
+ currentHunk = {
862
+ oldStart: Math.max(1, oldLineNum - contextBuffer.length + 1),
863
+ oldCount: contextBuffer.length,
864
+ newStart: Math.max(1, newLineNum - contextBuffer.length + 1),
865
+ newCount: contextBuffer.length,
866
+ lines: contextBuffer.map(l => ({ type: 'context', line: l })),
867
+ };
868
+ contextBuffer = [];
869
+ }
870
+ if (edit.type === 'delete') {
871
+ currentHunk.lines.push({ type: 'delete', line: oldLines[edit.oldIdx] });
872
+ currentHunk.oldCount++;
873
+ oldLineNum++;
874
+ }
875
+ else {
876
+ currentHunk.lines.push({ type: 'add', line: newLines[edit.newIdx] });
877
+ currentHunk.newCount++;
878
+ newLineNum++;
879
+ }
880
+ }
881
+ }
882
+ if (currentHunk) {
883
+ // Remove trailing context beyond limit
884
+ while (currentHunk.lines.length > 0 &&
885
+ currentHunk.lines[currentHunk.lines.length - 1].type === 'context') {
886
+ const lastNonContext = currentHunk.lines.slice().reverse().findIndex(l => l.type !== 'context');
887
+ if (lastNonContext === -1)
888
+ break;
889
+ const contextAfter = lastNonContext;
890
+ if (contextAfter > contextLines) {
891
+ currentHunk.lines.pop();
892
+ currentHunk.oldCount--;
893
+ currentHunk.newCount--;
894
+ }
895
+ else {
896
+ break;
897
+ }
898
+ }
899
+ hunks.push(currentHunk);
900
+ }
901
+ // Format hunks
902
+ for (const hunk of hunks) {
903
+ output.push(`@@ -${hunk.oldStart},${hunk.oldCount} +${hunk.newStart},${hunk.newCount} @@`);
904
+ for (const line of hunk.lines) {
905
+ if (line.type === 'context') {
906
+ output.push(` ${line.line}`);
907
+ }
908
+ else if (line.type === 'delete') {
909
+ output.push(`-${line.line}`);
910
+ }
911
+ else {
912
+ output.push(`+${line.line}`);
913
+ }
914
+ }
915
+ }
916
+ return output.join('\n') + '\n';
917
+ }
918
+ /**
919
+ * Format diff in context format
920
+ */
921
+ function formatContextDiff(file1Path, file2Path, oldLines, newLines, edits) {
922
+ const output = [];
923
+ output.push(`*** ${file1Path}`);
924
+ output.push(`--- ${file2Path}`);
925
+ output.push('***************');
926
+ // For simplicity, output entire file as one hunk
927
+ output.push(`*** 1,${oldLines.length} ****`);
928
+ for (let i = 0; i < oldLines.length; i++) {
929
+ const edit = edits.find(e => e.oldIdx === i && (e.type === 'equal' || e.type === 'delete'));
930
+ if (edit?.type === 'delete') {
931
+ output.push(`! ${oldLines[i]}`);
932
+ }
933
+ else if (edit?.type === 'equal') {
934
+ // Check if there's a change at this position
935
+ const hasChange = edits.some(e => e.type === 'insert' && e.newIdx === edit.newIdx);
936
+ if (hasChange) {
937
+ output.push(`! ${oldLines[i]}`);
938
+ }
939
+ else {
940
+ output.push(` ${oldLines[i]}`);
941
+ }
942
+ }
943
+ }
944
+ output.push(`--- 1,${newLines.length} ----`);
945
+ for (let i = 0; i < newLines.length; i++) {
946
+ const edit = edits.find(e => e.newIdx === i && (e.type === 'equal' || e.type === 'insert'));
947
+ if (edit?.type === 'insert') {
948
+ output.push(`! ${newLines[i]}`);
949
+ }
950
+ else if (edit?.type === 'equal') {
951
+ // Check if there's a change at this position
952
+ const hasChange = edits.some(e => e.type === 'delete' && e.oldIdx === edit.oldIdx);
953
+ if (hasChange) {
954
+ output.push(`! ${newLines[i]}`);
955
+ }
956
+ else {
957
+ output.push(` ${newLines[i]}`);
958
+ }
959
+ }
960
+ }
961
+ return output.join('\n') + '\n';
962
+ }
963
+ /**
964
+ * Parse diff command arguments
965
+ * @internal Reserved for future CLI diff support
966
+ */
967
+ export function parseDiffArgs(args) {
968
+ const options = {};
969
+ const files = [];
970
+ for (const arg of args) {
971
+ if (arg === '-u' || arg === '--unified') {
972
+ options.unified = true;
973
+ }
974
+ else if (arg === '-c' || arg === '--context') {
975
+ options.context = true;
976
+ }
977
+ else if (arg.startsWith('-U')) {
978
+ options.unified = true;
979
+ options.contextLines = parseInt(arg.slice(2), 10);
980
+ }
981
+ else if (arg.startsWith('-C')) {
982
+ options.context = true;
983
+ options.contextLines = parseInt(arg.slice(2), 10);
984
+ }
985
+ else if (!arg.startsWith('-')) {
986
+ files.push(arg);
987
+ }
988
+ }
989
+ return { options, files };
990
+ }
991
+ /**
992
+ * Execute diff (file comparison) command.
993
+ *
994
+ * Compares two text files and outputs the differences. Implements Myers diff
995
+ * algorithm for efficient comparison. Supports normal, unified (-u), and
996
+ * context (-c) output formats.
997
+ *
998
+ * @param file1Content - Content of the first (original) file
999
+ * @param file2Content - Content of the second (new) file
1000
+ * @param file1Path - Path of the first file (for output headers)
1001
+ * @param file2Path - Path of the second file (for output headers)
1002
+ * @param options - Diff options (unified, context, contextLines)
1003
+ * @returns Object with stdout (diff output), stderr, and exitCode (0 if same, 1 if different)
1004
+ *
1005
+ * @example
1006
+ * // Unified diff format
1007
+ * executeDiff('line1\n', 'line1\nline2\n', 'a.txt', 'b.txt', { unified: true })
1008
+ */
1009
+ export function executeDiff(file1Content, file2Content, file1Path, file2Path, options = {}) {
1010
+ const oldLines = file1Content.split('\n');
1011
+ const newLines = file2Content.split('\n');
1012
+ // Remove trailing empty lines from split
1013
+ if (file1Content.endsWith('\n') && oldLines[oldLines.length - 1] === '') {
1014
+ oldLines.pop();
1015
+ }
1016
+ if (file2Content.endsWith('\n') && newLines[newLines.length - 1] === '') {
1017
+ newLines.pop();
1018
+ }
1019
+ // Check if files are identical
1020
+ if (file1Content === file2Content) {
1021
+ return { stdout: '', stderr: '', exitCode: 0 };
1022
+ }
1023
+ const edits = myersDiff(oldLines, newLines);
1024
+ let stdout;
1025
+ if (options.unified) {
1026
+ stdout = formatUnifiedDiff(file1Path, file2Path, oldLines, newLines, edits, options.contextLines);
1027
+ }
1028
+ else if (options.context) {
1029
+ stdout = formatContextDiff(file1Path, file2Path, oldLines, newLines, edits);
1030
+ }
1031
+ else {
1032
+ stdout = formatNormalDiff(oldLines, newLines, edits);
1033
+ }
1034
+ return { stdout, stderr: '', exitCode: stdout ? 1 : 0 };
1035
+ }
1036
+ /**
1037
+ * Parse a unified diff patch
1038
+ */
1039
+ function parseUnifiedPatch(patchContent) {
1040
+ const patches = [];
1041
+ const lines = patchContent.split('\n');
1042
+ let current = null;
1043
+ let currentHunk = null;
1044
+ for (let i = 0; i < lines.length; i++) {
1045
+ const line = lines[i];
1046
+ // File header
1047
+ if (line.startsWith('--- ')) {
1048
+ if (current) {
1049
+ if (currentHunk) {
1050
+ current.hunks.push(currentHunk);
1051
+ }
1052
+ patches.push(current);
1053
+ }
1054
+ current = { oldFile: line.slice(4).split('\t')[0], newFile: '', hunks: [] };
1055
+ currentHunk = null;
1056
+ }
1057
+ else if (line.startsWith('+++ ') && current) {
1058
+ current.newFile = line.slice(4).split('\t')[0];
1059
+ }
1060
+ // Hunk header
1061
+ else if (line.startsWith('@@') && current) {
1062
+ if (currentHunk) {
1063
+ current.hunks.push(currentHunk);
1064
+ }
1065
+ const match = line.match(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
1066
+ if (match) {
1067
+ currentHunk = {
1068
+ oldStart: parseInt(match[1], 10),
1069
+ oldCount: parseInt(match[2] || '1', 10),
1070
+ newStart: parseInt(match[3], 10),
1071
+ newCount: parseInt(match[4] || '1', 10),
1072
+ lines: [],
1073
+ };
1074
+ }
1075
+ }
1076
+ // Hunk content
1077
+ else if (currentHunk) {
1078
+ if (line.startsWith(' ')) {
1079
+ currentHunk.lines.push({ type: 'context', content: line.slice(1) });
1080
+ }
1081
+ else if (line.startsWith('-')) {
1082
+ currentHunk.lines.push({ type: 'delete', content: line.slice(1) });
1083
+ }
1084
+ else if (line.startsWith('+')) {
1085
+ currentHunk.lines.push({ type: 'add', content: line.slice(1) });
1086
+ }
1087
+ }
1088
+ }
1089
+ if (current) {
1090
+ if (currentHunk) {
1091
+ current.hunks.push(currentHunk);
1092
+ }
1093
+ patches.push(current);
1094
+ }
1095
+ return patches;
1096
+ }
1097
+ /**
1098
+ * Apply a patch to content
1099
+ */
1100
+ function applyPatch(original, patch, options) {
1101
+ const lines = original.split('\n');
1102
+ if (original.endsWith('\n') && lines[lines.length - 1] === '') {
1103
+ lines.pop();
1104
+ }
1105
+ let offset = 0;
1106
+ for (const hunk of patch.hunks) {
1107
+ const startLine = hunk.oldStart - 1 + offset;
1108
+ // Verify context matches (simple check)
1109
+ let contextMatches = true;
1110
+ let lineIdx = startLine;
1111
+ for (const hunkLine of hunk.lines) {
1112
+ if (options.reverse) {
1113
+ if (hunkLine.type === 'add') {
1114
+ if (lines[lineIdx] !== hunkLine.content) {
1115
+ contextMatches = false;
1116
+ break;
1117
+ }
1118
+ lineIdx++;
1119
+ }
1120
+ else if (hunkLine.type === 'context') {
1121
+ if (lines[lineIdx] !== hunkLine.content) {
1122
+ contextMatches = false;
1123
+ break;
1124
+ }
1125
+ lineIdx++;
1126
+ }
1127
+ }
1128
+ else {
1129
+ if (hunkLine.type === 'delete' || hunkLine.type === 'context') {
1130
+ if (lines[lineIdx] !== hunkLine.content) {
1131
+ contextMatches = false;
1132
+ break;
1133
+ }
1134
+ lineIdx++;
1135
+ }
1136
+ }
1137
+ }
1138
+ if (!contextMatches) {
1139
+ // Check if already applied (for forward patch) or already reversed
1140
+ let alreadyApplied = true;
1141
+ lineIdx = startLine;
1142
+ for (const hunkLine of hunk.lines) {
1143
+ if (options.reverse) {
1144
+ if (hunkLine.type === 'delete') {
1145
+ if (lines[lineIdx] !== hunkLine.content) {
1146
+ alreadyApplied = false;
1147
+ break;
1148
+ }
1149
+ lineIdx++;
1150
+ }
1151
+ else if (hunkLine.type === 'context') {
1152
+ if (lines[lineIdx] !== hunkLine.content) {
1153
+ alreadyApplied = false;
1154
+ break;
1155
+ }
1156
+ lineIdx++;
1157
+ }
1158
+ }
1159
+ else {
1160
+ if (hunkLine.type === 'add' || hunkLine.type === 'context') {
1161
+ if (lines[lineIdx] !== hunkLine.content) {
1162
+ alreadyApplied = false;
1163
+ break;
1164
+ }
1165
+ lineIdx++;
1166
+ }
1167
+ }
1168
+ }
1169
+ if (alreadyApplied) {
1170
+ return { result: original, success: false, message: 'Reversed (or previously applied) patch detected!' };
1171
+ }
1172
+ return { result: original, success: false, message: 'Hunk failed to apply' };
1173
+ }
1174
+ if (options.dryRun) {
1175
+ continue;
1176
+ }
1177
+ // Apply the hunk
1178
+ const newLines = [];
1179
+ let deleteCount = 0;
1180
+ let addCount = 0;
1181
+ for (const hunkLine of hunk.lines) {
1182
+ if (options.reverse) {
1183
+ if (hunkLine.type === 'delete') {
1184
+ newLines.push(hunkLine.content);
1185
+ addCount++;
1186
+ }
1187
+ else if (hunkLine.type === 'add') {
1188
+ deleteCount++;
1189
+ }
1190
+ else {
1191
+ newLines.push(hunkLine.content);
1192
+ }
1193
+ }
1194
+ else {
1195
+ if (hunkLine.type === 'add') {
1196
+ newLines.push(hunkLine.content);
1197
+ addCount++;
1198
+ }
1199
+ else if (hunkLine.type === 'delete') {
1200
+ deleteCount++;
1201
+ }
1202
+ else {
1203
+ newLines.push(hunkLine.content);
1204
+ }
1205
+ }
1206
+ }
1207
+ const contextAndDelete = hunk.lines.filter(l => options.reverse ? (l.type === 'context' || l.type === 'add') : (l.type === 'context' || l.type === 'delete')).length;
1208
+ lines.splice(startLine, contextAndDelete, ...newLines);
1209
+ offset += addCount - deleteCount;
1210
+ }
1211
+ let result = lines.join('\n');
1212
+ if (lines.length > 0) {
1213
+ result += '\n';
1214
+ }
1215
+ return { result, success: true, message: `patching file ${patch.newFile}` };
1216
+ }
1217
+ /**
1218
+ * Strip path prefix
1219
+ */
1220
+ function stripPathPrefix(path, level) {
1221
+ if (level === 0)
1222
+ return path;
1223
+ const parts = path.split('/');
1224
+ return parts.slice(level).join('/');
1225
+ }
1226
+ /**
1227
+ * Parse patch command arguments
1228
+ * @internal Reserved for future CLI patch support
1229
+ */
1230
+ export function parsePatchArgs(args) {
1231
+ const options = { stripLevel: 0 };
1232
+ let patchFile;
1233
+ for (let i = 0; i < args.length; i++) {
1234
+ const arg = args[i];
1235
+ if (arg === '-R' || arg === '--reverse') {
1236
+ options.reverse = true;
1237
+ }
1238
+ else if (arg === '--dry-run') {
1239
+ options.dryRun = true;
1240
+ }
1241
+ else if (arg.startsWith('-p')) {
1242
+ options.stripLevel = parseInt(arg.slice(2), 10);
1243
+ }
1244
+ else if (arg === '-i') {
1245
+ i++;
1246
+ if (i < args.length) {
1247
+ patchFile = args[i];
1248
+ }
1249
+ }
1250
+ else if (!arg.startsWith('-')) {
1251
+ patchFile = arg;
1252
+ }
1253
+ }
1254
+ return { options, patchFile };
1255
+ }
1256
+ /**
1257
+ * Execute patch (apply diffs) command.
1258
+ *
1259
+ * Applies a unified diff patch to content. Supports reverse patching (-R),
1260
+ * dry-run mode (--dry-run), and path stripping (-p).
1261
+ *
1262
+ * @param original - Original file content to patch
1263
+ * @param patchContent - The patch content (unified diff format)
1264
+ * @param options - Patch options (reverse, dryRun, stripLevel)
1265
+ * @returns Object with stdout, stderr, exitCode, and optionally result (patched content)
1266
+ *
1267
+ * @example
1268
+ * // Apply a patch
1269
+ * const patch = '--- a.txt\n+++ b.txt\n@@ -1,1 +1,2 @@\n line1\n+line2\n'
1270
+ * executePatch('line1\n', patch, { dryRun: true })
1271
+ */
1272
+ export function executePatch(original, patchContent, options = {}) {
1273
+ const patches = parseUnifiedPatch(patchContent);
1274
+ if (patches.length === 0) {
1275
+ return { stdout: '', stderr: 'No valid patches found', exitCode: 1 };
1276
+ }
1277
+ const patch = patches[0];
1278
+ const targetFile = stripPathPrefix(patch.newFile, options.stripLevel || 0);
1279
+ const { result, success, message } = applyPatch(original, patch, options);
1280
+ if (!success) {
1281
+ return { stdout: '', stderr: message, exitCode: 1 };
1282
+ }
1283
+ const action = options.dryRun ? 'checking' : 'patching';
1284
+ return {
1285
+ stdout: `${action} file ${targetFile}\n`,
1286
+ stderr: '',
1287
+ exitCode: 0,
1288
+ result: options.dryRun ? original : result,
1289
+ };
1290
+ }
1291
+ /**
1292
+ * Parse tee command arguments
1293
+ */
1294
+ function parseTeeArgs(args) {
1295
+ const options = { append: false };
1296
+ const files = [];
1297
+ for (const arg of args) {
1298
+ if (arg === '-a' || arg === '--append') {
1299
+ options.append = true;
1300
+ }
1301
+ else if (!arg.startsWith('-')) {
1302
+ files.push(arg);
1303
+ }
1304
+ }
1305
+ return { options, files };
1306
+ }
1307
+ /**
1308
+ * Execute tee (write to multiple outputs) command.
1309
+ *
1310
+ * Reads from input and writes to both stdout and specified files.
1311
+ * Supports append mode (-a).
1312
+ *
1313
+ * @param input - Input text to process
1314
+ * @param args - Command arguments (e.g., ['-a', 'file1.txt', 'file2.txt'])
1315
+ * @param fs - Optional filesystem capability for file writing
1316
+ * @returns Promise resolving to object with stdout, stderr, and exitCode
1317
+ *
1318
+ * @example
1319
+ * // Write to files while passing through
1320
+ * await executeTee('hello\n', ['output.txt'], fs)
1321
+ * // => { stdout: 'hello\n', stderr: '', exitCode: 0 }
1322
+ */
1323
+ export async function executeTee(input, args, fs) {
1324
+ const { options, files } = parseTeeArgs(args);
1325
+ // Write to files if fs is available
1326
+ if (fs && files.length > 0) {
1327
+ for (const file of files) {
1328
+ try {
1329
+ if (options.append) {
1330
+ const existing = await fs.exists(file) ? await fs.read(file, { encoding: 'utf-8' }) : '';
1331
+ await fs.write(file, existing + input);
1332
+ }
1333
+ else {
1334
+ await fs.write(file, input);
1335
+ }
1336
+ }
1337
+ catch (error) {
1338
+ // Continue with other files
1339
+ }
1340
+ }
1341
+ }
1342
+ // Always output to stdout
1343
+ return { stdout: input, stderr: '', exitCode: 0 };
1344
+ }
1345
+ /**
1346
+ * Parse xargs command arguments
1347
+ */
1348
+ function parseXargsArgs(args) {
1349
+ const options = {};
1350
+ const command = [];
1351
+ let foundCommand = false;
1352
+ for (let i = 0; i < args.length; i++) {
1353
+ const arg = args[i];
1354
+ if (foundCommand) {
1355
+ command.push(arg);
1356
+ continue;
1357
+ }
1358
+ if (arg === '-n') {
1359
+ i++;
1360
+ if (i < args.length) {
1361
+ options.maxArgs = parseInt(args[i], 10);
1362
+ }
1363
+ }
1364
+ else if (arg.startsWith('-n')) {
1365
+ options.maxArgs = parseInt(arg.slice(2), 10);
1366
+ }
1367
+ else if (arg === '-d') {
1368
+ i++;
1369
+ if (i < args.length) {
1370
+ options.delimiter = args[i];
1371
+ }
1372
+ }
1373
+ else if (arg === '-0') {
1374
+ options.delimiter = '\0';
1375
+ }
1376
+ else if (arg === '-I') {
1377
+ i++;
1378
+ if (i < args.length) {
1379
+ options.placeholder = args[i];
1380
+ }
1381
+ }
1382
+ else if (arg.startsWith('-I')) {
1383
+ options.placeholder = arg.slice(2);
1384
+ }
1385
+ else if (arg === '-P') {
1386
+ i++;
1387
+ if (i < args.length) {
1388
+ options.parallel = parseInt(args[i], 10);
1389
+ }
1390
+ }
1391
+ else if (arg === '-p') {
1392
+ options.prompt = true;
1393
+ }
1394
+ else if (arg === '-s') {
1395
+ i++;
1396
+ if (i < args.length) {
1397
+ options.maxChars = parseInt(args[i], 10);
1398
+ }
1399
+ }
1400
+ else if (!arg.startsWith('-')) {
1401
+ foundCommand = true;
1402
+ command.push(arg);
1403
+ }
1404
+ }
1405
+ return { options, command };
1406
+ }
1407
+ /**
1408
+ * Split input into arguments for xargs
1409
+ */
1410
+ function splitXargsInput(input, delimiter) {
1411
+ if (delimiter === '\0') {
1412
+ return input.split('\0').filter(Boolean);
1413
+ }
1414
+ if (delimiter) {
1415
+ return input.split(delimiter).filter(Boolean);
1416
+ }
1417
+ // Default: split on whitespace and newlines
1418
+ return input.split(/[\s\n]+/).filter(Boolean);
1419
+ }
1420
+ /**
1421
+ * Execute xargs (build and execute command lines) command.
1422
+ *
1423
+ * Builds and executes command lines from standard input. Supports:
1424
+ * - -n (max arguments per command)
1425
+ * - -I (placeholder replacement)
1426
+ * - -0 (null delimiter for filenames with spaces)
1427
+ * - -P (parallel execution)
1428
+ * - -s (max command length)
1429
+ *
1430
+ * @param input - Input containing arguments (one per line or whitespace-separated)
1431
+ * @param args - Command arguments (e.g., ['-n', '1', 'echo'])
1432
+ * @param executor - Function to execute subcommands
1433
+ * @returns Promise resolving to object with stdout, stderr, and exitCode
1434
+ *
1435
+ * @example
1436
+ * // Process one argument at a time
1437
+ * await executeXargs('a\nb\nc', ['-n', '1', 'echo'], cmd => exec(cmd))
1438
+ * // => { stdout: 'a\nb\nc\n', stderr: '', exitCode: 0 }
1439
+ */
1440
+ export async function executeXargs(input, args, executor) {
1441
+ const { options, command } = parseXargsArgs(args);
1442
+ // Default command is echo
1443
+ const baseCommand = command.length > 0 ? command : ['echo'];
1444
+ // Parse input into arguments
1445
+ const inputArgs = splitXargsInput(input, options.delimiter);
1446
+ if (inputArgs.length === 0) {
1447
+ // Run once with no args
1448
+ const cmd = baseCommand.join(' ');
1449
+ return executor(cmd);
1450
+ }
1451
+ const outputs = [];
1452
+ const errors = [];
1453
+ let exitCode = 0;
1454
+ if (options.placeholder) {
1455
+ // -I mode: run command once per input line, replacing placeholder
1456
+ for (const arg of inputArgs) {
1457
+ const cmdWithArg = baseCommand.map(c => c.replace(new RegExp(options.placeholder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), arg)).join(' ');
1458
+ if (options.prompt) {
1459
+ outputs.push(`${baseCommand[0]} ${arg}?...`);
1460
+ }
1461
+ const result = await executor(cmdWithArg);
1462
+ if (result.stdout)
1463
+ outputs.push(result.stdout.replace(/\n$/, ''));
1464
+ if (result.stderr)
1465
+ errors.push(result.stderr);
1466
+ if (result.exitCode !== 0)
1467
+ exitCode = 123;
1468
+ }
1469
+ }
1470
+ else if (options.maxArgs) {
1471
+ // -n mode: run command with maxArgs arguments at a time
1472
+ for (let i = 0; i < inputArgs.length; i += options.maxArgs) {
1473
+ const batch = inputArgs.slice(i, i + options.maxArgs);
1474
+ const cmd = [...baseCommand, ...batch].join(' ');
1475
+ const result = await executor(cmd);
1476
+ if (result.stdout)
1477
+ outputs.push(result.stdout.replace(/\n$/, ''));
1478
+ if (result.stderr)
1479
+ errors.push(result.stderr);
1480
+ if (result.exitCode !== 0)
1481
+ exitCode = 123;
1482
+ }
1483
+ }
1484
+ else if (options.maxChars) {
1485
+ // -s mode: limit total command line length
1486
+ let currentBatch = [];
1487
+ let currentLen = baseCommand.join(' ').length;
1488
+ for (const arg of inputArgs) {
1489
+ if (currentLen + arg.length + 1 > options.maxChars && currentBatch.length > 0) {
1490
+ const cmd = [...baseCommand, ...currentBatch].join(' ');
1491
+ const result = await executor(cmd);
1492
+ if (result.stdout)
1493
+ outputs.push(result.stdout.replace(/\n$/, ''));
1494
+ if (result.stderr)
1495
+ errors.push(result.stderr);
1496
+ if (result.exitCode !== 0)
1497
+ exitCode = 123;
1498
+ currentBatch = [];
1499
+ currentLen = baseCommand.join(' ').length;
1500
+ }
1501
+ currentBatch.push(arg);
1502
+ currentLen += arg.length + 1;
1503
+ }
1504
+ if (currentBatch.length > 0) {
1505
+ const cmd = [...baseCommand, ...currentBatch].join(' ');
1506
+ const result = await executor(cmd);
1507
+ if (result.stdout)
1508
+ outputs.push(result.stdout.replace(/\n$/, ''));
1509
+ if (result.stderr)
1510
+ errors.push(result.stderr);
1511
+ if (result.exitCode !== 0)
1512
+ exitCode = 123;
1513
+ }
1514
+ }
1515
+ else {
1516
+ // Default: all args in one command
1517
+ const cmd = [...baseCommand, ...inputArgs].join(' ');
1518
+ if (options.prompt) {
1519
+ outputs.push(`${baseCommand[0]} ${inputArgs.join(' ')}?...`);
1520
+ }
1521
+ const result = await executor(cmd);
1522
+ if (result.stdout)
1523
+ outputs.push(result.stdout.replace(/\n$/, ''));
1524
+ if (result.stderr)
1525
+ errors.push(result.stderr);
1526
+ exitCode = result.exitCode;
1527
+ }
1528
+ let stdout = outputs.join('\n');
1529
+ if (outputs.length > 0)
1530
+ stdout += '\n';
1531
+ return { stdout, stderr: errors.join('\n'), exitCode };
1532
+ }
1533
+ // ============================================================================
1534
+ // Exports for TieredExecutor integration
1535
+ // ============================================================================
1536
+ export const TEXT_PROCESSING_COMMANDS = new Set(['sed', 'awk', 'diff', 'patch', 'tee', 'xargs']);
1537
+ /**
1538
+ * Check if a command is a text processing command handled by this module.
1539
+ *
1540
+ * @param cmd - Command name to check
1541
+ * @returns True if the command is handled by this module
1542
+ *
1543
+ * @example
1544
+ * isTextProcessingCommand('sed') // => true
1545
+ * isTextProcessingCommand('ls') // => false
1546
+ */
1547
+ export function isTextProcessingCommand(cmd) {
1548
+ return TEXT_PROCESSING_COMMANDS.has(cmd);
1549
+ }
1550
+ //# sourceMappingURL=text-processing.js.map