dotdo 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. package/cli/README.md +238 -0
  2. package/cli/agent.ts +72 -0
  3. package/cli/bin.js +44 -0
  4. package/cli/bin.ts +38 -0
  5. package/cli/build.ts +157 -0
  6. package/cli/commands/auth/login.ts +14 -0
  7. package/cli/commands/auth/logout.ts +6 -0
  8. package/cli/commands/auth/whoami.ts +16 -0
  9. package/cli/commands/deploy-multi.ts +245 -0
  10. package/cli/commands/dev/deploy.ts +100 -0
  11. package/cli/commands/dev/dev.ts +95 -0
  12. package/cli/commands/dev/logs.ts +91 -0
  13. package/cli/commands/dev-local.ts +88 -0
  14. package/cli/commands/do-ops.ts +314 -0
  15. package/cli/commands/index.ts +100 -0
  16. package/cli/commands/init.ts +247 -0
  17. package/cli/commands/introspect/emitter.ts +315 -0
  18. package/cli/commands/introspect/index.ts +193 -0
  19. package/cli/commands/link.ts +598 -0
  20. package/cli/commands/snippets.ts +415 -0
  21. package/cli/commands/tunnel.ts +239 -0
  22. package/cli/device-auth.ts +289 -0
  23. package/cli/fallback.ts +12 -0
  24. package/cli/index.ts +121 -0
  25. package/cli/main.ts +246 -0
  26. package/cli/mcp-stdio.ts +790 -0
  27. package/cli/package.json +62 -0
  28. package/cli/runtime/do-registry.ts +193 -0
  29. package/cli/runtime/embedded-db.ts +344 -0
  30. package/cli/runtime/index.ts +9 -0
  31. package/cli/runtime/miniflare-adapter.ts +162 -0
  32. package/cli/sandbox.ts +82 -0
  33. package/cli/src/args.ts +174 -0
  34. package/cli/src/auth.ts +55 -0
  35. package/cli/src/commands/call.ts +84 -0
  36. package/cli/src/commands/charge.ts +96 -0
  37. package/cli/src/commands/config.ts +115 -0
  38. package/cli/src/commands/email.ts +112 -0
  39. package/cli/src/commands/llm.ts +115 -0
  40. package/cli/src/commands/queue.ts +134 -0
  41. package/cli/src/commands/text.ts +86 -0
  42. package/cli/src/config.ts +185 -0
  43. package/cli/src/output.ts +246 -0
  44. package/cli/src/rpc.ts +192 -0
  45. package/cli/utils/config.ts +282 -0
  46. package/cli/utils/detect.ts +73 -0
  47. package/cli/utils/index.ts +15 -0
  48. package/cli/utils/logger.ts +232 -0
  49. package/dist/ai/template-literals.js +2 -2
  50. package/dist/ai/template-literals.js.map +1 -1
  51. package/dist/api/middleware/auth.js +3 -2
  52. package/dist/api/middleware/auth.js.map +1 -1
  53. package/dist/db/iceberg/inverted-index.js +1 -1
  54. package/dist/db/iceberg/inverted-index.js.map +1 -1
  55. package/dist/db/iceberg/puffin.js.map +1 -1
  56. package/dist/db/json-indexes.js.map +1 -1
  57. package/dist/db/objects.js.map +1 -1
  58. package/dist/db/primitives/dag-scheduler/index.js +1 -1
  59. package/dist/db/primitives/dag-scheduler/index.js.map +1 -1
  60. package/dist/db/primitives/observability.js.map +1 -1
  61. package/dist/db/primitives/schema-evolution.js.map +1 -1
  62. package/dist/db/primitives/temporal-store.js.map +1 -1
  63. package/dist/db/primitives/typed-column-store.js.map +1 -1
  64. package/dist/db/primitives/utils/duration.js.map +1 -1
  65. package/dist/db/primitives/utils/murmur3.js +12 -14
  66. package/dist/db/primitives/utils/murmur3.js.map +1 -1
  67. package/dist/db/primitives/window-manager.js.map +1 -1
  68. package/dist/db/stores.js.map +1 -1
  69. package/dist/db/things.js.map +1 -1
  70. package/dist/lib/DODispatcher.js +2 -2
  71. package/dist/lib/DODispatcher.js.map +1 -1
  72. package/dist/lib/auto-wiring.js.map +1 -1
  73. package/dist/lib/channels/email.js +1 -1
  74. package/dist/lib/channels/email.js.map +1 -1
  75. package/dist/lib/channels/slack-blockkit.js.map +1 -1
  76. package/dist/lib/cloudflare/ai.js +1 -1
  77. package/dist/lib/cloudflare/ai.js.map +1 -1
  78. package/dist/lib/cloudflare/kv.js +1 -1
  79. package/dist/lib/cloudflare/kv.js.map +1 -1
  80. package/dist/lib/cloudflare/r2.js +3 -3
  81. package/dist/lib/cloudflare/r2.js.map +1 -1
  82. package/dist/lib/cloudflare/vectorize.js.map +1 -1
  83. package/dist/lib/cloudflare/workflows.js.map +1 -1
  84. package/dist/lib/executors/AgenticFunctionExecutor.js.map +1 -1
  85. package/dist/lib/executors/CodeFunctionExecutor.js.map +1 -1
  86. package/dist/lib/executors/GenerativeFunctionExecutor.js.map +1 -1
  87. package/dist/lib/executors/HumanFunctionExecutor.js +1 -1
  88. package/dist/lib/executors/HumanFunctionExecutor.js.map +1 -1
  89. package/dist/lib/executors/ParallelStepExecutor.js.map +1 -1
  90. package/dist/lib/experiments.js.map +1 -1
  91. package/dist/lib/flags/store.js.map +1 -1
  92. package/dist/lib/functions/FunctionComposition.js.map +1 -1
  93. package/dist/lib/functions/FunctionMiddleware.js.map +1 -1
  94. package/dist/lib/functions/FunctionRegistry.js.map +1 -1
  95. package/dist/lib/humans/templates.js.map +1 -1
  96. package/dist/lib/identity.js +2 -2
  97. package/dist/lib/identity.js.map +1 -1
  98. package/dist/lib/logging/index.js.map +1 -1
  99. package/dist/lib/mixins/bash.js +1 -73
  100. package/dist/lib/mixins/bash.js.map +1 -1
  101. package/dist/lib/mixins/git.js +0 -5
  102. package/dist/lib/mixins/git.js.map +1 -1
  103. package/dist/lib/mixins/npm.js.map +1 -1
  104. package/dist/lib/noun-id.js.map +1 -1
  105. package/dist/lib/rate-limit/sliding-window.js.map +1 -1
  106. package/dist/lib/rpc/bindings.js.map +1 -1
  107. package/dist/lib/safe-stringify.js.map +1 -1
  108. package/dist/lib/sandbox/miniflare-sandbox.js.map +1 -1
  109. package/dist/lib/sqids.js.map +1 -1
  110. package/dist/lib/sql/adapters/node-sql-parser.js.map +1 -1
  111. package/dist/lib/sql/adapters/pgsql-parser.js +19 -18
  112. package/dist/lib/sql/adapters/pgsql-parser.js.map +1 -1
  113. package/dist/metrics/hunch.js.map +1 -1
  114. package/dist/objects/API.js +1 -1
  115. package/dist/objects/API.js.map +1 -1
  116. package/dist/objects/Agent.js.map +1 -1
  117. package/dist/objects/Browser.js.map +1 -1
  118. package/dist/objects/CLI.js.map +1 -1
  119. package/dist/objects/DOBase.js.map +1 -1
  120. package/dist/objects/DOCache.js +153 -0
  121. package/dist/objects/DOCache.js.map +1 -0
  122. package/dist/objects/DOFull.js.map +1 -1
  123. package/dist/objects/Entity.js.map +1 -1
  124. package/dist/objects/Human.js.map +1 -1
  125. package/dist/objects/IcebergMetadataDO.js.map +1 -1
  126. package/dist/objects/IntegrationsDO.js.map +1 -1
  127. package/dist/objects/ObservabilityBroadcaster.js.map +1 -1
  128. package/dist/objects/Package.js.map +1 -1
  129. package/dist/objects/Product.js +1 -1
  130. package/dist/objects/Product.js.map +1 -1
  131. package/dist/objects/SaaS.js.map +1 -1
  132. package/dist/objects/SandboxDO.js.map +1 -1
  133. package/dist/objects/Service.js.map +1 -1
  134. package/dist/objects/VectorShardDO.js +9 -7
  135. package/dist/objects/VectorShardDO.js.map +1 -1
  136. package/dist/objects/Workflow.js.map +1 -1
  137. package/dist/objects/WorkflowFactory.js.map +1 -1
  138. package/dist/objects/WorkflowRuntime.js.map +1 -1
  139. package/dist/objects/lifecycle/Branch.js.map +1 -1
  140. package/dist/objects/lifecycle/Clone.js +1 -1
  141. package/dist/objects/lifecycle/Clone.js.map +1 -1
  142. package/dist/objects/lifecycle/Compact.js.map +1 -1
  143. package/dist/objects/lifecycle/Shard.js.map +1 -1
  144. package/dist/objects/persistence/checkpoint-manager.js.map +1 -1
  145. package/dist/objects/persistence/migration-runner.js.map +1 -1
  146. package/dist/objects/persistence/replication-manager.js +2 -2
  147. package/dist/objects/persistence/replication-manager.js.map +1 -1
  148. package/dist/objects/persistence/tiered-storage-manager.js.map +1 -1
  149. package/dist/objects/persistence/wal-manager.js.map +1 -1
  150. package/dist/objects/transport/auth-layer.js.map +1 -1
  151. package/dist/objects/transport/chain.js.map +1 -1
  152. package/dist/objects/transport/mcp-server.js +7 -6
  153. package/dist/objects/transport/mcp-server.js.map +1 -1
  154. package/dist/objects/transport/rest-autowire.js +3 -2
  155. package/dist/objects/transport/rest-autowire.js.map +1 -1
  156. package/dist/objects/transport/rest-router.js.map +1 -1
  157. package/dist/objects/transport/rpc-server.js +18 -15
  158. package/dist/objects/transport/rpc-server.js.map +1 -1
  159. package/dist/objects/transport/shared.js +2 -1
  160. package/dist/objects/transport/shared.js.map +1 -1
  161. package/dist/snippets/artifacts-ingest.js.map +1 -1
  162. package/dist/snippets/artifacts-serve.js.map +1 -1
  163. package/dist/snippets/search.js.map +1 -1
  164. package/dist/workflows/ScheduleManager.js.map +1 -1
  165. package/dist/workflows/StepResultStorage.js.map +1 -1
  166. package/dist/workflows/WaitForEventManager.js.map +1 -1
  167. package/dist/workflows/compat/backends/cloudflare-workflows.js.map +1 -1
  168. package/dist/workflows/compat/inngest/index.js.map +1 -1
  169. package/dist/workflows/compat/qstash/index.js.map +1 -1
  170. package/dist/workflows/compat/temporal/client.js.map +1 -1
  171. package/dist/workflows/compat/temporal/index.js.map +1 -1
  172. package/dist/workflows/compat/trigger/index.js.map +1 -1
  173. package/dist/workflows/compat/utils/index.js.map +1 -1
  174. package/dist/workflows/context/correlation.js +2 -2
  175. package/dist/workflows/context/correlation.js.map +1 -1
  176. package/dist/workflows/context/experiment.js +1 -1
  177. package/dist/workflows/context/experiment.js.map +1 -1
  178. package/dist/workflows/context/flag.js +1 -1
  179. package/dist/workflows/context/flag.js.map +1 -1
  180. package/dist/workflows/context/measure.js +1 -1
  181. package/dist/workflows/context/measure.js.map +1 -1
  182. package/dist/workflows/context/rate-limit.js.map +1 -1
  183. package/dist/workflows/data/entity-events/entity-events.js.map +1 -1
  184. package/dist/workflows/data/experiment/index.js.map +1 -1
  185. package/dist/workflows/data/goal/context.js +1 -1
  186. package/dist/workflows/data/goal/context.js.map +1 -1
  187. package/dist/workflows/data/measure/index.js +1 -1
  188. package/dist/workflows/data/measure/index.js.map +1 -1
  189. package/dist/workflows/data/stream/index.js +10 -76
  190. package/dist/workflows/data/stream/index.js.map +1 -1
  191. package/dist/workflows/data/track/context.js.map +1 -1
  192. package/dist/workflows/data/view/context.js.map +1 -1
  193. package/dist/workflows/domain.js.map +1 -1
  194. package/dist/workflows/flags.js +1 -1
  195. package/dist/workflows/flags.js.map +1 -1
  196. package/dist/workflows/hash.js.map +1 -1
  197. package/dist/workflows/on.js +1 -1
  198. package/dist/workflows/on.js.map +1 -1
  199. package/dist/workflows/schedule-builder.js.map +1 -1
  200. package/dist/workflows/visibility/index.js +0 -2
  201. package/dist/workflows/visibility/index.js.map +1 -1
  202. package/dist/workflows/visibility/query-parser.js.map +1 -1
  203. package/package.json +18 -3
  204. package/dist/api/analytics/router.js +0 -601
  205. package/dist/api/analytics/router.js.map +0 -1
  206. package/dist/api/index.js +0 -158
  207. package/dist/api/index.js.map +0 -1
  208. package/dist/api/middleware/error-handling.js +0 -176
  209. package/dist/api/middleware/error-handling.js.map +0 -1
  210. package/dist/api/middleware/request-id.js +0 -21
  211. package/dist/api/middleware/request-id.js.map +0 -1
  212. package/dist/api/pages.js +0 -1180
  213. package/dist/api/pages.js.map +0 -1
  214. package/dist/api/routes/api.js +0 -612
  215. package/dist/api/routes/api.js.map +0 -1
  216. package/dist/api/routes/browsers.js +0 -471
  217. package/dist/api/routes/browsers.js.map +0 -1
  218. package/dist/api/routes/do.js +0 -188
  219. package/dist/api/routes/do.js.map +0 -1
  220. package/dist/api/routes/mcp.js +0 -459
  221. package/dist/api/routes/mcp.js.map +0 -1
  222. package/dist/api/routes/obs.js +0 -445
  223. package/dist/api/routes/obs.js.map +0 -1
  224. package/dist/api/routes/openapi.js +0 -794
  225. package/dist/api/routes/openapi.js.map +0 -1
  226. package/dist/api/routes/rpc.js +0 -1103
  227. package/dist/api/routes/rpc.js.map +0 -1
  228. package/dist/api/routes/sandboxes.js +0 -389
  229. package/dist/api/routes/sandboxes.js.map +0 -1
  230. package/dist/api/test-do.js +0 -38
  231. package/dist/api/test-do.js.map +0 -1
  232. package/dist/api/types.js +0 -11
  233. package/dist/api/types.js.map +0 -1
  234. package/dist/cli/bin.js +0 -2
  235. package/dist/cli/main.js +0 -52342
  236. package/dist/do/bash.js +0 -35
  237. package/dist/do/bash.js.map +0 -1
  238. package/dist/do/fs.js +0 -25
  239. package/dist/do/fs.js.map +0 -1
  240. package/dist/do/full.js +0 -61
  241. package/dist/do/full.js.map +0 -1
  242. package/dist/do/git.js +0 -28
  243. package/dist/do/git.js.map +0 -1
  244. package/dist/do/index.js +0 -52
  245. package/dist/do/index.js.map +0 -1
  246. package/dist/lib/agent/tools/bash.js +0 -336
  247. package/dist/lib/agent/tools/bash.js.map +0 -1
  248. package/dist/lib/agent/tools/edit.js +0 -157
  249. package/dist/lib/agent/tools/edit.js.map +0 -1
  250. package/dist/lib/agent/tools/glob.js +0 -137
  251. package/dist/lib/agent/tools/glob.js.map +0 -1
  252. package/dist/lib/agent/tools/grep.js +0 -315
  253. package/dist/lib/agent/tools/grep.js.map +0 -1
  254. package/dist/lib/agent/tools/index.js +0 -71
  255. package/dist/lib/agent/tools/index.js.map +0 -1
  256. package/dist/lib/agent/tools/read.js +0 -212
  257. package/dist/lib/agent/tools/read.js.map +0 -1
  258. package/dist/lib/agent/tools/types.js +0 -197
  259. package/dist/lib/agent/tools/types.js.map +0 -1
  260. package/dist/lib/agent/tools/write.js +0 -159
  261. package/dist/lib/agent/tools/write.js.map +0 -1
  262. package/dist/lib/mixins/index.js +0 -29
  263. package/dist/lib/mixins/index.js.map +0 -1
  264. package/dist/primitives/bashx/src/ast/analyze.js +0 -1472
  265. package/dist/primitives/bashx/src/ast/analyze.js.map +0 -1
  266. package/dist/primitives/bashx/src/ast/parser.js +0 -1488
  267. package/dist/primitives/bashx/src/ast/parser.js.map +0 -1
  268. package/dist/primitives/bashx/src/do/commands/crypto.js +0 -1954
  269. package/dist/primitives/bashx/src/do/commands/crypto.js.map +0 -1
  270. package/dist/primitives/bashx/src/do/commands/data-processing.js +0 -1812
  271. package/dist/primitives/bashx/src/do/commands/data-processing.js.map +0 -1
  272. package/dist/primitives/bashx/src/do/commands/extended-utils.js +0 -804
  273. package/dist/primitives/bashx/src/do/commands/extended-utils.js.map +0 -1
  274. package/dist/primitives/bashx/src/do/commands/math-control.js +0 -1122
  275. package/dist/primitives/bashx/src/do/commands/math-control.js.map +0 -1
  276. package/dist/primitives/bashx/src/do/commands/posix-utils.js +0 -1015
  277. package/dist/primitives/bashx/src/do/commands/posix-utils.js.map +0 -1
  278. package/dist/primitives/bashx/src/do/commands/system-utils.js +0 -687
  279. package/dist/primitives/bashx/src/do/commands/system-utils.js.map +0 -1
  280. package/dist/primitives/bashx/src/do/commands/test-command.js +0 -523
  281. package/dist/primitives/bashx/src/do/commands/test-command.js.map +0 -1
  282. package/dist/primitives/bashx/src/do/commands/text-processing.js +0 -1550
  283. package/dist/primitives/bashx/src/do/commands/text-processing.js.map +0 -1
  284. package/dist/primitives/bashx/src/do/container-executor.js +0 -429
  285. package/dist/primitives/bashx/src/do/container-executor.js.map +0 -1
  286. package/dist/primitives/bashx/src/do/index.js +0 -668
  287. package/dist/primitives/bashx/src/do/index.js.map +0 -1
  288. package/dist/primitives/bashx/src/do/tiered-executor.js +0 -2647
  289. package/dist/primitives/bashx/src/do/tiered-executor.js.map +0 -1
  290. package/dist/primitives/bashx/src/do/worker.js +0 -352
  291. package/dist/primitives/bashx/src/do/worker.js.map +0 -1
  292. package/dist/primitives/bashx/src/types.js +0 -10
  293. package/dist/primitives/bashx/src/types.js.map +0 -1
  294. package/dist/primitives/fsx/core/backend.js +0 -480
  295. package/dist/primitives/fsx/core/backend.js.map +0 -1
  296. package/dist/primitives/fsx/core/constants.js +0 -140
  297. package/dist/primitives/fsx/core/constants.js.map +0 -1
  298. package/dist/primitives/fsx/core/fsx.js +0 -1184
  299. package/dist/primitives/fsx/core/fsx.js.map +0 -1
  300. package/dist/primitives/fsx/core/glob/glob.js +0 -438
  301. package/dist/primitives/fsx/core/glob/glob.js.map +0 -1
  302. package/dist/primitives/fsx/core/glob/index.js +0 -8
  303. package/dist/primitives/fsx/core/glob/index.js.map +0 -1
  304. package/dist/primitives/fsx/core/glob/match.js +0 -392
  305. package/dist/primitives/fsx/core/glob/match.js.map +0 -1
  306. package/dist/primitives/fsx/core/types.js +0 -307
  307. package/dist/primitives/fsx/core/types.js.map +0 -1
  308. package/dist/sdk/capnweb-compat.js +0 -42
  309. package/dist/sdk/capnweb-compat.js.map +0 -1
  310. package/dist/sdk/client.js +0 -20
  311. package/dist/sdk/client.js.map +0 -1
  312. package/dist/sdk/index.js +0 -17
  313. package/dist/sdk/index.js.map +0 -1
@@ -1,188 +0,0 @@
1
- import { Hono } from 'hono';
2
- // Default timeout for DO fetch calls (30 seconds)
3
- const DO_FETCH_TIMEOUT_MS = 30000;
4
- /**
5
- * Create a structured error response for DO fetch failures
6
- */
7
- function createDOErrorResponse(code, message, context) {
8
- return {
9
- error: {
10
- code,
11
- message,
12
- ...(context && { context }),
13
- },
14
- };
15
- }
16
- /**
17
- * Wrap a fetch call with timeout
18
- */
19
- async function fetchWithTimeout(stub, request, timeoutMs = DO_FETCH_TIMEOUT_MS) {
20
- const controller = new AbortController();
21
- const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
22
- try {
23
- // Clone request with abort signal
24
- // Need to use duplex: 'half' in Node.js environments when body is a ReadableStream
25
- const hasBody = request.method !== 'GET' && request.method !== 'HEAD' && request.body;
26
- const requestWithSignal = new Request(request.url, {
27
- method: request.method,
28
- headers: request.headers,
29
- body: hasBody ? request.body : undefined,
30
- signal: controller.signal,
31
- // @ts-expect-error - duplex is required for Node.js but not in types
32
- duplex: hasBody ? 'half' : undefined,
33
- });
34
- return await stub.fetch(requestWithSignal);
35
- }
36
- finally {
37
- clearTimeout(timeoutId);
38
- }
39
- }
40
- /**
41
- * DO Router - Routes requests to individual Durable Object instances
42
- *
43
- * Pattern: /:doClass/:id/*
44
- *
45
- * This router forwards requests to specific DO instances based on:
46
- * - doClass: The DO namespace binding name (e.g., 'DO', 'TEST_DO', 'BROWSER_DO')
47
- * - id: The identifier used with idFromName() to get the DO instance
48
- * - *: The remaining path to forward to the DO
49
- *
50
- * Example:
51
- * GET /DO/user-123/profile
52
- * -> Gets DO namespace 'DO' from env
53
- * -> Gets stub via idFromName('user-123')
54
- * -> Forwards request with path '/profile' to the DO
55
- */
56
- export const doRoutes = new Hono();
57
- /**
58
- * Route all HTTP methods to DO instances
59
- *
60
- * Matches: /:doClass/:id, /:doClass/:id/, /:doClass/:id/*
61
- */
62
- doRoutes.all('/:doClass/:id/*', async (c) => {
63
- const { doClass, id } = c.req.param();
64
- const requestId = c.req.header('x-request-id') || crypto.randomUUID();
65
- const source = `${doClass}/${id}`;
66
- // Get DO namespace binding by class name
67
- const namespace = c.env[doClass];
68
- if (!namespace || typeof namespace.idFromName !== 'function') {
69
- return c.json({ error: { code: 'NOT_FOUND', message: `Unknown DO class: ${doClass}` } }, 404);
70
- }
71
- // Get DO stub using idFromName
72
- const doId = namespace.idFromName(id);
73
- const stub = namespace.get(doId);
74
- // Rewrite path: remove /:doClass/:id prefix
75
- // Original path: /DO/user-123/some/path -> DO receives: /some/path
76
- const originalPath = c.req.path;
77
- const prefixPattern = new RegExp(`^/${doClass}/${encodeURIComponent(id)}`);
78
- const rewrittenPath = originalPath.replace(prefixPattern, '') || '/';
79
- // Build the URL for the DO request
80
- const url = new URL(c.req.url);
81
- url.pathname = rewrittenPath;
82
- // Forward request to DO with original headers and body, wrapped in try-catch
83
- try {
84
- // Need to use duplex: 'half' in Node.js environments when body is a ReadableStream
85
- const hasBody = c.req.method !== 'GET' && c.req.method !== 'HEAD';
86
- const request = new Request(url.toString(), {
87
- method: c.req.method,
88
- headers: c.req.raw.headers,
89
- body: hasBody ? c.req.raw.body : undefined,
90
- // @ts-expect-error - duplex is required for Node.js but not in types
91
- duplex: hasBody ? 'half' : undefined,
92
- });
93
- const response = await fetchWithTimeout(stub, request);
94
- // Handle non-JSON error responses from DO
95
- if (!response.ok) {
96
- const contentType = response.headers.get('content-type') || '';
97
- if (!contentType.includes('application/json')) {
98
- const text = await response.text();
99
- return c.json(createDOErrorResponse('DO_ERROR', text || 'Unknown error', {
100
- source,
101
- requestId,
102
- }), response.status);
103
- }
104
- }
105
- return response;
106
- }
107
- catch (error) {
108
- const errorMessage = error instanceof Error ? error.message : String(error);
109
- // Check for timeout (AbortError)
110
- if (error instanceof Error && error.name === 'AbortError') {
111
- return c.json(createDOErrorResponse('DO_FETCH_TIMEOUT', 'Request to Durable Object timed out', {
112
- source,
113
- requestId,
114
- originalError: errorMessage,
115
- }), 504);
116
- }
117
- // Generic DO fetch error
118
- return c.json(createDOErrorResponse('DO_FETCH_ERROR', 'Failed to communicate with Durable Object', {
119
- source,
120
- requestId,
121
- originalError: errorMessage,
122
- }), 502);
123
- }
124
- });
125
- /**
126
- * Handle requests without wildcard path (e.g., /DO/user-123)
127
- * Routes to the root path of the DO instance
128
- */
129
- doRoutes.all('/:doClass/:id', async (c) => {
130
- const { doClass, id } = c.req.param();
131
- const requestId = c.req.header('x-request-id') || crypto.randomUUID();
132
- const source = `${doClass}/${id}`;
133
- // Get DO namespace binding by class name
134
- const namespace = c.env[doClass];
135
- if (!namespace || typeof namespace.idFromName !== 'function') {
136
- return c.json({ error: { code: 'NOT_FOUND', message: `Unknown DO class: ${doClass}` } }, 404);
137
- }
138
- // Get DO stub using idFromName
139
- const doId = namespace.idFromName(id);
140
- const stub = namespace.get(doId);
141
- // Build the URL for the DO request (root path)
142
- const url = new URL(c.req.url);
143
- url.pathname = '/';
144
- // Forward request to DO with original headers and body, wrapped in try-catch
145
- try {
146
- // Need to use duplex: 'half' in Node.js environments when body is a ReadableStream
147
- const hasBody = c.req.method !== 'GET' && c.req.method !== 'HEAD';
148
- const request = new Request(url.toString(), {
149
- method: c.req.method,
150
- headers: c.req.raw.headers,
151
- body: hasBody ? c.req.raw.body : undefined,
152
- // @ts-expect-error - duplex is required for Node.js but not in types
153
- duplex: hasBody ? 'half' : undefined,
154
- });
155
- const response = await fetchWithTimeout(stub, request);
156
- // Handle non-JSON error responses from DO
157
- if (!response.ok) {
158
- const contentType = response.headers.get('content-type') || '';
159
- if (!contentType.includes('application/json')) {
160
- const text = await response.text();
161
- return c.json(createDOErrorResponse('DO_ERROR', text || 'Unknown error', {
162
- source,
163
- requestId,
164
- }), response.status);
165
- }
166
- }
167
- return response;
168
- }
169
- catch (error) {
170
- const errorMessage = error instanceof Error ? error.message : String(error);
171
- // Check for timeout (AbortError)
172
- if (error instanceof Error && error.name === 'AbortError') {
173
- return c.json(createDOErrorResponse('DO_FETCH_TIMEOUT', 'Request to Durable Object timed out', {
174
- source,
175
- requestId,
176
- originalError: errorMessage,
177
- }), 504);
178
- }
179
- // Generic DO fetch error
180
- return c.json(createDOErrorResponse('DO_FETCH_ERROR', 'Failed to communicate with Durable Object', {
181
- source,
182
- requestId,
183
- originalError: errorMessage,
184
- }), 502);
185
- }
186
- });
187
- export default doRoutes;
188
- //# sourceMappingURL=do.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"do.js","sourceRoot":"","sources":["../../../api/routes/do.ts"],"names":[],"mappings":"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"}
@@ -1,459 +0,0 @@
1
- import { Hono } from 'hono';
2
- /**
3
- * MCP HTTP Streamable Transport Handler
4
- *
5
- * Implements JSON-RPC 2.0 over HTTP with SSE for server-initiated notifications.
6
- *
7
- * Routes:
8
- * - POST /mcp: Handle JSON-RPC requests
9
- * - GET /mcp: SSE stream for server-initiated notifications
10
- * - DELETE /mcp: Terminate session
11
- */
12
- // Session storage (in-memory for now, should use DO in production)
13
- const sessions = new Map();
14
- // Track deleted sessions to prevent re-creation
15
- const deletedSessions = new Set();
16
- // Default tools available in all sessions
17
- const defaultTools = [
18
- {
19
- name: 'echo',
20
- description: 'Echo back the input message',
21
- inputSchema: {
22
- type: 'object',
23
- properties: {
24
- message: { type: 'string' },
25
- },
26
- required: ['message'],
27
- },
28
- },
29
- {
30
- name: 'create_thing',
31
- description: 'Create a new thing',
32
- inputSchema: {
33
- type: 'object',
34
- properties: {
35
- type: { type: 'string' },
36
- data: { type: 'object' },
37
- },
38
- required: ['type', 'data'],
39
- },
40
- },
41
- {
42
- name: 'delete_thing',
43
- description: 'Delete a thing by ID',
44
- inputSchema: {
45
- type: 'object',
46
- properties: {
47
- id: { type: 'string' },
48
- },
49
- required: ['id'],
50
- },
51
- },
52
- {
53
- name: 'throw_error',
54
- description: 'A tool that throws an internal error (for testing)',
55
- inputSchema: {
56
- type: 'object',
57
- properties: {},
58
- },
59
- },
60
- ];
61
- // Pre-populate a test session for testing purposes
62
- const testSession = {
63
- id: 'test-session-1',
64
- createdAt: new Date(),
65
- lastAccessedAt: new Date(),
66
- lastActivity: new Date(),
67
- tools: new Map(defaultTools.map((t) => [t.name, t])),
68
- resources: new Map(),
69
- clientInfo: { name: 'test-client', version: '1.0.0' },
70
- capabilities: {},
71
- subscriptions: [],
72
- };
73
- sessions.set('test-session-1', testSession);
74
- export function createMcpSession() {
75
- const id = crypto.randomUUID();
76
- const now = new Date();
77
- const session = {
78
- id,
79
- createdAt: now,
80
- lastAccessedAt: now,
81
- lastActivity: now,
82
- tools: new Map(defaultTools.map((t) => [t.name, t])),
83
- resources: new Map(),
84
- clientInfo: undefined,
85
- capabilities: {},
86
- subscriptions: [],
87
- };
88
- sessions.set(id, session);
89
- return session;
90
- }
91
- export function getMcpSession(sessionId) {
92
- // Don't return deleted sessions (except test-session-1 which is auto-created)
93
- if (deletedSessions.has(sessionId) && sessionId !== 'test-session-1') {
94
- return undefined;
95
- }
96
- // Ensure test session exists (for testing purposes)
97
- // This is auto-created for tests that use a hardcoded session ID
98
- if (sessionId === 'test-session-1' && !sessions.has('test-session-1')) {
99
- const now = new Date();
100
- sessions.set('test-session-1', {
101
- id: 'test-session-1',
102
- createdAt: now,
103
- lastAccessedAt: now,
104
- lastActivity: now,
105
- tools: new Map(defaultTools.map((t) => [t.name, t])),
106
- resources: new Map(),
107
- clientInfo: { name: 'test-client', version: '1.0.0' },
108
- capabilities: {},
109
- subscriptions: [],
110
- });
111
- // Also remove from deleted set if it was there
112
- deletedSessions.delete('test-session-1');
113
- }
114
- return sessions.get(sessionId);
115
- }
116
- export function deleteMcpSession(sessionId) {
117
- const existed = sessions.delete(sessionId);
118
- if (existed) {
119
- deletedSessions.add(sessionId);
120
- }
121
- return existed;
122
- }
123
- // Standard JSON-RPC error codes
124
- const JSON_RPC_ERRORS = {
125
- PARSE_ERROR: -32700,
126
- INVALID_REQUEST: -32600,
127
- METHOD_NOT_FOUND: -32601,
128
- INVALID_PARAMS: -32602,
129
- INTERNAL_ERROR: -32603,
130
- };
131
- function jsonRpcError(id, code, message, data) {
132
- return {
133
- jsonrpc: '2.0',
134
- id,
135
- error: { code, message, data },
136
- };
137
- }
138
- function jsonRpcSuccess(id, result) {
139
- return {
140
- jsonrpc: '2.0',
141
- id,
142
- result,
143
- };
144
- }
145
- export async function handleMcpRequest(request, session) {
146
- const method = request.method;
147
- // OPTIONS: CORS preflight
148
- if (method === 'OPTIONS') {
149
- return new Response(null, {
150
- status: 204,
151
- headers: {
152
- 'Access-Control-Allow-Methods': 'GET, POST, DELETE, OPTIONS',
153
- 'Access-Control-Allow-Headers': 'Content-Type, Mcp-Session-Id',
154
- 'Access-Control-Max-Age': '86400',
155
- },
156
- });
157
- }
158
- // GET: SSE stream for notifications
159
- if (method === 'GET') {
160
- const sessionId = request.headers.get('mcp-session-id') || request.headers.get('Mcp-Session-Id');
161
- if (!sessionId) {
162
- return new Response(JSON.stringify(jsonRpcError(null, JSON_RPC_ERRORS.INVALID_REQUEST, 'Missing Mcp-Session-Id header')), {
163
- status: 400,
164
- headers: { 'Content-Type': 'application/json' },
165
- });
166
- }
167
- const existingSession = getMcpSession(sessionId);
168
- if (!existingSession) {
169
- return new Response(JSON.stringify(jsonRpcError(null, JSON_RPC_ERRORS.INVALID_REQUEST, 'Session not found')), {
170
- status: 404,
171
- headers: { 'Content-Type': 'application/json' },
172
- });
173
- }
174
- // Return SSE stream
175
- const stream = new ReadableStream({
176
- start(controller) {
177
- // Send initial keep-alive comment
178
- controller.enqueue(new TextEncoder().encode(': keep-alive\n\n'));
179
- },
180
- });
181
- return new Response(stream, {
182
- status: 200,
183
- headers: {
184
- 'Content-Type': 'text/event-stream',
185
- 'Cache-Control': 'no-cache',
186
- Connection: 'keep-alive',
187
- 'Mcp-Session-Id': sessionId,
188
- },
189
- });
190
- }
191
- // DELETE: Terminate session
192
- if (method === 'DELETE') {
193
- const sessionId = request.headers.get('mcp-session-id') || request.headers.get('Mcp-Session-Id');
194
- if (!sessionId) {
195
- return new Response(JSON.stringify(jsonRpcError(null, JSON_RPC_ERRORS.INVALID_REQUEST, 'Missing Mcp-Session-Id header')), {
196
- status: 400,
197
- headers: { 'Content-Type': 'application/json' },
198
- });
199
- }
200
- const deleted = deleteMcpSession(sessionId);
201
- if (!deleted) {
202
- return new Response(JSON.stringify(jsonRpcError(null, JSON_RPC_ERRORS.INVALID_REQUEST, 'Session not found')), {
203
- status: 404,
204
- headers: { 'Content-Type': 'application/json' },
205
- });
206
- }
207
- return new Response(null, { status: 204 });
208
- }
209
- // Only POST allowed beyond this point
210
- if (method !== 'POST') {
211
- return new Response(JSON.stringify(jsonRpcError(null, JSON_RPC_ERRORS.INVALID_REQUEST, 'Method not allowed')), {
212
- status: 405,
213
- headers: {
214
- 'Content-Type': 'application/json',
215
- Allow: 'GET, POST, DELETE',
216
- },
217
- });
218
- }
219
- // Check Content-Type for POST
220
- const contentType = request.headers.get('content-type');
221
- if (!contentType || !contentType.includes('application/json')) {
222
- return new Response(JSON.stringify(jsonRpcError(null, JSON_RPC_ERRORS.INVALID_REQUEST, 'Content-Type must be application/json')), {
223
- status: 415,
224
- headers: { 'Content-Type': 'application/json' },
225
- });
226
- }
227
- let body;
228
- try {
229
- body = (await request.json());
230
- }
231
- catch {
232
- return new Response(JSON.stringify(jsonRpcError(null, JSON_RPC_ERRORS.PARSE_ERROR, 'Parse error')), {
233
- status: 200, // JSON-RPC errors use 200
234
- headers: { 'Content-Type': 'application/json' },
235
- });
236
- }
237
- // Get or create session
238
- let sessionId = request.headers.get('mcp-session-id') || request.headers.get('Mcp-Session-Id');
239
- let currentSession = sessionId ? getMcpSession(sessionId) : undefined;
240
- // Handle batch requests
241
- const requests = Array.isArray(body) ? body : [body];
242
- const responses = [];
243
- const responseHeaders = {
244
- 'Content-Type': 'application/json',
245
- };
246
- // Track if all requests are notifications
247
- let allNotifications = true;
248
- for (const req of requests) {
249
- // Validate JSON-RPC format
250
- if (req.jsonrpc !== '2.0') {
251
- responses.push(jsonRpcError(req.id ?? null, JSON_RPC_ERRORS.INVALID_REQUEST, 'Invalid JSON-RPC version'));
252
- allNotifications = false;
253
- continue;
254
- }
255
- // Notifications have no id - no response expected
256
- if (req.id === undefined) {
257
- // Process notification but don't add to responses
258
- continue;
259
- }
260
- allNotifications = false;
261
- // Check params type - must be object or undefined
262
- if (req.params !== undefined && (typeof req.params !== 'object' || req.params === null || Array.isArray(req.params))) {
263
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.INVALID_PARAMS, 'Invalid params: must be an object'));
264
- continue;
265
- }
266
- // Check session for non-initialize methods
267
- if (req.method !== 'initialize' && req.method !== 'ping') {
268
- if (sessionId && !currentSession) {
269
- // Session was provided but not found - return HTTP 404
270
- return new Response(JSON.stringify(jsonRpcError(req.id, JSON_RPC_ERRORS.INVALID_REQUEST, 'Session not found')), {
271
- status: 404,
272
- headers: { 'Content-Type': 'application/json' },
273
- });
274
- }
275
- }
276
- // Handle MCP methods
277
- switch (req.method) {
278
- case 'initialize': {
279
- if (!currentSession) {
280
- currentSession = createMcpSession();
281
- sessionId = currentSession.id;
282
- }
283
- responses.push(jsonRpcSuccess(req.id, {
284
- protocolVersion: '2024-11-05',
285
- capabilities: {
286
- tools: { listChanged: true },
287
- resources: { subscribe: true, listChanged: true },
288
- prompts: { listChanged: true },
289
- },
290
- serverInfo: {
291
- name: 'dotdo-mcp-server',
292
- version: '0.1.0',
293
- },
294
- }));
295
- break;
296
- }
297
- case 'tools/list': {
298
- if (!currentSession) {
299
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.INVALID_REQUEST, 'Session not initialized'));
300
- continue;
301
- }
302
- responses.push(jsonRpcSuccess(req.id, {
303
- tools: Array.from(currentSession.tools.values()),
304
- }));
305
- break;
306
- }
307
- case 'tools/call': {
308
- if (!currentSession) {
309
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.INVALID_REQUEST, 'Session not initialized'));
310
- continue;
311
- }
312
- const params = req.params;
313
- if (!params?.name) {
314
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.INVALID_PARAMS, 'Missing tool name'));
315
- continue;
316
- }
317
- const tool = currentSession.tools.get(params.name);
318
- if (!tool) {
319
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.METHOD_NOT_FOUND, `Tool not found: ${params.name}`));
320
- continue;
321
- }
322
- // Validate required arguments
323
- const toolArgs = params.arguments || {};
324
- const requiredFields = Array.isArray(tool.inputSchema?.required) ? tool.inputSchema.required : [];
325
- if (requiredFields.length > 0) {
326
- const missingFields = requiredFields.filter((field) => !(field in toolArgs));
327
- if (missingFields.length > 0) {
328
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.INVALID_PARAMS, `Missing required arguments: ${missingFields.join(', ')}`));
329
- continue;
330
- }
331
- }
332
- // Execute tool based on name
333
- try {
334
- let resultText;
335
- let isError = false;
336
- switch (params.name) {
337
- case 'echo':
338
- resultText = `Echo: ${toolArgs.message || ''}`;
339
- break;
340
- case 'create_thing':
341
- resultText = JSON.stringify({ created: true, type: toolArgs.type, data: toolArgs.data });
342
- break;
343
- case 'delete_thing':
344
- // Simulate not found for non-existent ID
345
- if (!toolArgs.id || toolArgs.id === 'non-existent-id') {
346
- resultText = 'Thing not found';
347
- isError = true;
348
- }
349
- else {
350
- resultText = JSON.stringify({ deleted: true, id: toolArgs.id });
351
- }
352
- break;
353
- case 'throw_error':
354
- // Throw internal error
355
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.INTERNAL_ERROR, 'Internal server error'));
356
- continue;
357
- default:
358
- resultText = `Tool ${params.name} executed`;
359
- }
360
- responses.push(jsonRpcSuccess(req.id, {
361
- content: [{ type: 'text', text: resultText }],
362
- isError: isError ? true : undefined,
363
- }));
364
- }
365
- catch (error) {
366
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.INTERNAL_ERROR, String(error)));
367
- }
368
- break;
369
- }
370
- case 'resources/list': {
371
- if (!currentSession) {
372
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.INVALID_REQUEST, 'Session not initialized'));
373
- continue;
374
- }
375
- responses.push(jsonRpcSuccess(req.id, {
376
- resources: Array.from(currentSession.resources.values()),
377
- }));
378
- break;
379
- }
380
- case 'resources/read': {
381
- if (!currentSession) {
382
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.INVALID_REQUEST, 'Session not initialized'));
383
- continue;
384
- }
385
- const params = req.params;
386
- if (!params?.uri) {
387
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.INVALID_PARAMS, 'Missing resource URI'));
388
- continue;
389
- }
390
- responses.push(jsonRpcSuccess(req.id, {
391
- contents: [{ uri: params.uri, mimeType: 'text/plain', text: '' }],
392
- }));
393
- break;
394
- }
395
- case 'ping': {
396
- responses.push(jsonRpcSuccess(req.id, {}));
397
- break;
398
- }
399
- case 'prompts/list': {
400
- if (!currentSession) {
401
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.INVALID_REQUEST, 'Session not initialized'));
402
- continue;
403
- }
404
- responses.push(jsonRpcSuccess(req.id, {
405
- prompts: [],
406
- }));
407
- break;
408
- }
409
- case 'prompts/get': {
410
- if (!currentSession) {
411
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.INVALID_REQUEST, 'Session not initialized'));
412
- continue;
413
- }
414
- const params = req.params;
415
- if (!params?.name) {
416
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.INVALID_PARAMS, 'Missing prompt name'));
417
- continue;
418
- }
419
- responses.push(jsonRpcSuccess(req.id, {
420
- messages: [{ role: 'user', content: { type: 'text', text: `Prompt: ${params.name}` } }],
421
- }));
422
- break;
423
- }
424
- case 'resources/subscribe':
425
- case 'resources/unsubscribe': {
426
- if (!currentSession) {
427
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.INVALID_REQUEST, 'Session not initialized'));
428
- continue;
429
- }
430
- responses.push(jsonRpcSuccess(req.id, {}));
431
- break;
432
- }
433
- default:
434
- responses.push(jsonRpcError(req.id, JSON_RPC_ERRORS.METHOD_NOT_FOUND, `Method not found: ${req.method}`));
435
- }
436
- }
437
- // If all requests were notifications, return 204
438
- if (allNotifications && responses.length === 0) {
439
- return new Response(null, { status: 204 });
440
- }
441
- // If session was created/used, include it in response headers
442
- if (currentSession) {
443
- responseHeaders['Mcp-Session-Id'] = currentSession.id;
444
- }
445
- // Return single response or batch
446
- const responseBody = Array.isArray(body) ? responses : responses[0];
447
- return new Response(JSON.stringify(responseBody), {
448
- status: 200,
449
- headers: responseHeaders,
450
- });
451
- }
452
- // Hono route handler
453
- export const mcpRoutes = new Hono();
454
- mcpRoutes.all('/', async (c) => {
455
- const response = await handleMcpRequest(c.req.raw);
456
- return response;
457
- });
458
- export default mcpRoutes;
459
- //# sourceMappingURL=mcp.js.map