@ixo/oracle-runtime-workers 0.2.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 (215) hide show
  1. package/README.md +110 -0
  2. package/package.json +77 -0
  3. package/src/attachments/classify.ts +114 -0
  4. package/src/attachments/content-blocks.ts +51 -0
  5. package/src/attachments/download.ts +235 -0
  6. package/src/attachments/extract.ts +241 -0
  7. package/src/attachments/index.ts +84 -0
  8. package/src/attachments/magic.ts +133 -0
  9. package/src/attachments/pipeline.ts +409 -0
  10. package/src/attachments/retention.ts +205 -0
  11. package/src/attachments/route.ts +41 -0
  12. package/src/attachments/sandbox-archive.ts +90 -0
  13. package/src/attachments/sanitize.ts +35 -0
  14. package/src/attachments/types.ts +86 -0
  15. package/src/attachments/view.ts +107 -0
  16. package/src/core/env.ts +200 -0
  17. package/src/core/index.ts +513 -0
  18. package/src/core/llm.ts +842 -0
  19. package/src/core/main-agent-types.ts +123 -0
  20. package/src/core/main-agent.ts +399 -0
  21. package/src/core/manifest.ts +365 -0
  22. package/src/core/meta-tools.ts +232 -0
  23. package/src/core/middlewares/byo-history-sanitizer.ts +165 -0
  24. package/src/core/middlewares/capability-gate.ts +76 -0
  25. package/src/core/middlewares/index.ts +18 -0
  26. package/src/core/middlewares/page-context.ts +98 -0
  27. package/src/core/middlewares/safety-guardrail.ts +117 -0
  28. package/src/core/middlewares/summarization.ts +99 -0
  29. package/src/core/middlewares/tool-repetition-guard.ts +125 -0
  30. package/src/core/middlewares/tool-validation.ts +83 -0
  31. package/src/core/middlewares/work-status.ts +57 -0
  32. package/src/core/openrouter-pricing.ts +124 -0
  33. package/src/core/plugin-loader.ts +192 -0
  34. package/src/core/plugins/index.ts +6 -0
  35. package/src/core/plugins/skills/index.ts +8 -0
  36. package/src/core/plugins/skills/skills-tools.ts +356 -0
  37. package/src/core/plugins/skills/skills.plugin.ts +113 -0
  38. package/src/core/plugins/weather/index.ts +8 -0
  39. package/src/core/plugins/weather/weather-client.ts +153 -0
  40. package/src/core/plugins/weather/weather-middleware.ts +27 -0
  41. package/src/core/plugins/weather/weather-sub-agent.ts +65 -0
  42. package/src/core/plugins/weather/weather-tools.ts +103 -0
  43. package/src/core/plugins/weather/weather.plugin.ts +227 -0
  44. package/src/core/prompt-composer.ts +469 -0
  45. package/src/core/registries.ts +642 -0
  46. package/src/core/runtime-context.ts +619 -0
  47. package/src/core/state.ts +108 -0
  48. package/src/core/sub-agent-fallback.ts +187 -0
  49. package/src/core/subagent-as-tool.ts +322 -0
  50. package/src/core/template.ts +245 -0
  51. package/src/core/utils.ts +246 -0
  52. package/src/core/wrap-plugin-tool.ts +100 -0
  53. package/src/do/ambient.ts +266 -0
  54. package/src/do/contracts.ts +562 -0
  55. package/src/do/debug-timers.ts +120 -0
  56. package/src/do/fresh-stub.ts +32 -0
  57. package/src/do/gateway-retry.ts +73 -0
  58. package/src/do/secrets-adapter.ts +32 -0
  59. package/src/do/size-alerts.ts +76 -0
  60. package/src/do/sse-stream.ts +472 -0
  61. package/src/do/transcript.ts +192 -0
  62. package/src/do/turn-body.ts +84 -0
  63. package/src/do/turn-metadata.ts +146 -0
  64. package/src/do/ucan-service.ts +339 -0
  65. package/src/do/user-oracle-do.ts +3035 -0
  66. package/src/gateway-worker.ts +82 -0
  67. package/src/index.ts +237 -0
  68. package/src/llm/byo-adapter.ts +59 -0
  69. package/src/llm/byo-catalog.ts +520 -0
  70. package/src/llm/byo-client.ts +280 -0
  71. package/src/llm/byo-routes.ts +255 -0
  72. package/src/llm/byo-service.ts +836 -0
  73. package/src/llm/chatgpt-oauth.ts +430 -0
  74. package/src/llm/provider-error.ts +283 -0
  75. package/src/matrix/gateway-do.ts +918 -0
  76. package/src/matrix/ingest.ts +209 -0
  77. package/src/matrix/replay-format.ts +34 -0
  78. package/src/matrix/reply-chain.ts +109 -0
  79. package/src/matrix/room-state-codec.ts +115 -0
  80. package/src/matrix/user-homeserver.ts +106 -0
  81. package/src/matrix/work-status.ts +294 -0
  82. package/src/memory/session-history-indexer.ts +328 -0
  83. package/src/owner-store/ixo-vfs-store.ts +570 -0
  84. package/src/owner-store/matrix-media-store.ts +136 -0
  85. package/src/owner-store/migrating-store.ts +185 -0
  86. package/src/owner-store/owner-copy-errors.ts +175 -0
  87. package/src/owner-store/retry.ts +45 -0
  88. package/src/owner-store/tus-upload.ts +333 -0
  89. package/src/owner-store/types.ts +0 -0
  90. package/src/plugin-api/define-plugin.ts +45 -0
  91. package/src/plugin-api/index.ts +56 -0
  92. package/src/plugin-api/oracle-plugin.ts +145 -0
  93. package/src/plugin-api/tool-helper.ts +82 -0
  94. package/src/plugin-api/types.ts +816 -0
  95. package/src/plugin-api/ucan-errors.ts +16 -0
  96. package/src/plugins/agui/agui-agent.ts +115 -0
  97. package/src/plugins/agui/agui.plugin.ts +148 -0
  98. package/src/plugins/agui/index.ts +2 -0
  99. package/src/plugins/attachments/attachments.plugin.ts +54 -0
  100. package/src/plugins/attachments/index.ts +6 -0
  101. package/src/plugins/attachments/view-attachment-tool.ts +91 -0
  102. package/src/plugins/base64.ts +26 -0
  103. package/src/plugins/composio/composio-tools.ts +365 -0
  104. package/src/plugins/composio/composio-ucan.ts +43 -0
  105. package/src/plugins/composio/composio.plugin.ts +214 -0
  106. package/src/plugins/composio/index.ts +15 -0
  107. package/src/plugins/domain-indexer/domain-indexer-agent.ts +57 -0
  108. package/src/plugins/domain-indexer/domain-indexer-tools.ts +253 -0
  109. package/src/plugins/domain-indexer/domain-indexer.plugin.ts +100 -0
  110. package/src/plugins/domain-indexer/index.ts +3 -0
  111. package/src/plugins/editor/blocknote-bridge.ts +120 -0
  112. package/src/plugins/editor/content-session.ts +331 -0
  113. package/src/plugins/editor/content-tools.ts +686 -0
  114. package/src/plugins/editor/document-model.ts +0 -0
  115. package/src/plugins/editor/editor-access-denied-tool.ts +58 -0
  116. package/src/plugins/editor/editor-agent.ts +34 -0
  117. package/src/plugins/editor/editor-config.ts +64 -0
  118. package/src/plugins/editor/editor-mx.ts +128 -0
  119. package/src/plugins/editor/editor.plugin.ts +143 -0
  120. package/src/plugins/editor/failures.ts +154 -0
  121. package/src/plugins/editor/index.ts +31 -0
  122. package/src/plugins/editor/jsdom-shim.ts +55 -0
  123. package/src/plugins/editor/prompts.ts +59 -0
  124. package/src/plugins/editor/prop-policy.ts +147 -0
  125. package/src/plugins/editor/provider.ts +386 -0
  126. package/src/plugins/editor/room-membership.ts +95 -0
  127. package/src/plugins/editor/standalone-editor-tool.ts +200 -0
  128. package/src/plugins/firecrawl/firecrawl-agent.ts +93 -0
  129. package/src/plugins/firecrawl/firecrawl-tools.ts +220 -0
  130. package/src/plugins/firecrawl/firecrawl.plugin.ts +105 -0
  131. package/src/plugins/firecrawl/index.ts +15 -0
  132. package/src/plugins/flows/action-metadata.ts +3505 -0
  133. package/src/plugins/flows/actions.ts +190 -0
  134. package/src/plugins/flows/edit.ts +314 -0
  135. package/src/plugins/flows/errors.ts +38 -0
  136. package/src/plugins/flows/explain.ts +43 -0
  137. package/src/plugins/flows/flow-doc.ts +111 -0
  138. package/src/plugins/flows/flows.plugin.ts +129 -0
  139. package/src/plugins/flows/forms.ts +330 -0
  140. package/src/plugins/flows/index.ts +2 -0
  141. package/src/plugins/flows/linkage.ts +147 -0
  142. package/src/plugins/flows/port-types.ts +53 -0
  143. package/src/plugins/flows/prompts.ts +65 -0
  144. package/src/plugins/flows/read.ts +392 -0
  145. package/src/plugins/flows/references.ts +66 -0
  146. package/src/plugins/flows/test-support.ts +165 -0
  147. package/src/plugins/flows/tools/authoring.ts +516 -0
  148. package/src/plugins/flows/tools/discovery.ts +119 -0
  149. package/src/plugins/flows/tools/forms.ts +142 -0
  150. package/src/plugins/flows/tools/inspect.ts +165 -0
  151. package/src/plugins/flows/tools/linkage.ts +117 -0
  152. package/src/plugins/flows/tools/settings.ts +184 -0
  153. package/src/plugins/flows/translator.ts +328 -0
  154. package/src/plugins/flows/types.ts +210 -0
  155. package/src/plugins/flows/ydoc-helpers.ts +543 -0
  156. package/src/plugins/index.ts +70 -0
  157. package/src/plugins/mcp-call-timeout.ts +38 -0
  158. package/src/plugins/mcp-tool-adapter.ts +87 -0
  159. package/src/plugins/memory/index.ts +17 -0
  160. package/src/plugins/memory/memory-tools.ts +463 -0
  161. package/src/plugins/memory/memory-ucan.ts +51 -0
  162. package/src/plugins/memory/memory.plugin.ts +122 -0
  163. package/src/plugins/memory/types.ts +147 -0
  164. package/src/plugins/portal/action-log.ts +34 -0
  165. package/src/plugins/portal/index.ts +2 -0
  166. package/src/plugins/portal/portal.plugin.ts +203 -0
  167. package/src/plugins/sandbox/index.ts +34 -0
  168. package/src/plugins/sandbox/sandbox-bridge.ts +295 -0
  169. package/src/plugins/sandbox/sandbox-mcp.ts +127 -0
  170. package/src/plugins/sandbox/sandbox-write-blob.ts +103 -0
  171. package/src/plugins/sandbox/sandbox.plugin.ts +599 -0
  172. package/src/plugins/tasks/index.ts +17 -0
  173. package/src/plugins/tasks/manifest.ts +81 -0
  174. package/src/plugins/tasks/middleware.ts +219 -0
  175. package/src/plugins/tasks/tasks-tools.ts +414 -0
  176. package/src/plugins/tasks/tasks.plugin.ts +74 -0
  177. package/src/plugins/ucan-failure.ts +133 -0
  178. package/src/plugins/user-preferences/index.ts +22 -0
  179. package/src/plugins/user-preferences/schema.ts +31 -0
  180. package/src/plugins/user-preferences/user-preferences-store.ts +172 -0
  181. package/src/plugins/user-preferences/user-preferences-tool.ts +131 -0
  182. package/src/plugins/user-preferences/user-preferences.plugin.ts +137 -0
  183. package/src/plugins/vfs/index.ts +40 -0
  184. package/src/plugins/vfs/vfs-auth.ts +56 -0
  185. package/src/plugins/vfs/vfs-client.ts +655 -0
  186. package/src/plugins/vfs/vfs-content.ts +181 -0
  187. package/src/plugins/vfs/vfs-errors.ts +163 -0
  188. package/src/plugins/vfs/vfs-sandbox-tools.ts +272 -0
  189. package/src/plugins/vfs/vfs-tools.ts +635 -0
  190. package/src/plugins/vfs/vfs.plugin.ts +201 -0
  191. package/src/realtime/frontend-call-registry.ts +163 -0
  192. package/src/realtime/realtime-endpoint.ts +619 -0
  193. package/src/realtime/session-socket-hub.ts +249 -0
  194. package/src/realtime/socket-io-codec.ts +187 -0
  195. package/src/secrets/jwe.ts +74 -0
  196. package/src/secrets/pin-cipher.ts +43 -0
  197. package/src/secrets/secrets-service.ts +319 -0
  198. package/src/shell/app.ts +564 -0
  199. package/src/shell/auth.ts +290 -0
  200. package/src/sqlite/blob-codec.ts +100 -0
  201. package/src/sqlite/blob-compactor.ts +146 -0
  202. package/src/sqlite/cache-config.ts +45 -0
  203. package/src/sqlite/database.ts +643 -0
  204. package/src/sqlite/do-vfs.ts +1485 -0
  205. package/src/sqlite/index.ts +61 -0
  206. package/src/sqlite/serialization.ts +370 -0
  207. package/src/sqlite/sessions-store.ts +311 -0
  208. package/src/sqlite/sqlite-saver.ts +919 -0
  209. package/src/sqlite/vacuum-policy.ts +77 -0
  210. package/src/sqlite/wa-sqlite-loader.ts +123 -0
  211. package/src/sqlite/wasm.d.ts +10 -0
  212. package/src/tasks/schedule.ts +174 -0
  213. package/src/tasks/scheduler.ts +753 -0
  214. package/src/tasks/spec.ts +125 -0
  215. package/src/tasks/store.ts +351 -0
@@ -0,0 +1,82 @@
1
+ /* eslint-disable no-console -- console IS the logger on Workers (Logs/observability). */
2
+ /**
3
+ * Entry for a deployment that runs the Matrix gateway as its OWN Worker
4
+ * script (`@ixo/oracle-runtime-workers/gateway`).
5
+ *
6
+ * Every Durable Object of one script shares that script's isolate on a
7
+ * server, and an isolate has a 128 MB heap. In the single-script layout the
8
+ * gateway (matrix-js-sdk, the crypto wasm, the sync store — tens of MB that
9
+ * never go away) sits in the same heap as every user object on that server,
10
+ * so a user's flush or import spike can reset the gateway and vice versa.
11
+ * With the gateway in a second script it gets its own isolate and its own
12
+ * budget; the user script's isolate holds only user objects.
13
+ *
14
+ * The two scripts talk over cross-script Durable Object bindings
15
+ * (`script_name` in the wrangler config): the shell's `MATRIX_GATEWAY`
16
+ * binding points at this script's class, this script's `USER_ORACLE`
17
+ * binding points back at the shell script's user class. RPC is identical
18
+ * either way, so nothing in the objects changes — this entry only exports
19
+ * the class and a keep-alive cron. This module deliberately imports nothing
20
+ * from the agent side (`core/`, `plugins/`), so the gateway bundle carries no
21
+ * LangChain, no MCP clients and no editor code.
22
+ */
23
+ import type { OracleWorkerEnv } from './do/contracts';
24
+ import { MatrixGatewayDO } from './matrix/gateway-do';
25
+
26
+ export { MatrixGatewayDO } from './matrix/gateway-do';
27
+
28
+ export interface GatewayWorker {
29
+ fetch: (
30
+ request: Request,
31
+ env: OracleWorkerEnv,
32
+ ctx: ExecutionContext,
33
+ ) => Promise<Response>;
34
+ scheduled: (
35
+ event: ScheduledController,
36
+ env: OracleWorkerEnv,
37
+ ctx: ExecutionContext,
38
+ ) => Promise<void>;
39
+ MatrixGatewayDO: typeof MatrixGatewayDO;
40
+ }
41
+
42
+ function gatewayStub(env: OracleWorkerEnv) {
43
+ return env.MATRIX_GATEWAY.get(env.MATRIX_GATEWAY.idFromName(env.ORACLE_DID));
44
+ }
45
+
46
+ /**
47
+ * Build the gateway script's handlers. The script needs no public route
48
+ * (`workers_dev: false` is fine): the shell reaches the gateway through the
49
+ * binding, and `/matrix/status`, `/debug/matrix/*` stay on the shell. The
50
+ * fetch handler answers `/health` for a deployment that does get a route
51
+ * and 404s everything else; the cron is the keep-alive safety net, same as
52
+ * the single-script layout's.
53
+ */
54
+ export function createGatewayWorker(): GatewayWorker {
55
+ return {
56
+ MatrixGatewayDO,
57
+ fetch: async (request, env, ctx) => {
58
+ const { pathname } = new URL(request.url);
59
+ if (
60
+ request.method === 'GET' &&
61
+ (pathname === '/' || pathname === '/health')
62
+ ) {
63
+ ctx.waitUntil(
64
+ gatewayStub(env)
65
+ .ensureStarted()
66
+ .catch((err) =>
67
+ console.error('[matrix] ensureStarted failed', err),
68
+ ),
69
+ );
70
+ return Response.json({
71
+ ok: true,
72
+ role: 'matrix-gateway',
73
+ oracleDid: env.ORACLE_DID,
74
+ });
75
+ }
76
+ return new Response('Not found', { status: 404 });
77
+ },
78
+ scheduled: async (_event, env) => {
79
+ await gatewayStub(env).ensureStarted();
80
+ },
81
+ };
82
+ }
package/src/index.ts ADDED
@@ -0,0 +1,237 @@
1
+ /* eslint-disable no-console -- console IS the logger on Workers (Logs/observability). */
2
+ /**
3
+ * @ixo/oracle-runtime-workers — QiForge oracles on Cloudflare Workers.
4
+ *
5
+ * An oracle is a Worker whose entry does:
6
+ *
7
+ * const oracle = createOracleWorker({ config, plugins: [new WeatherPlugin()] });
8
+ * export const { UserOracleDO, MatrixGatewayDO } = oracle;
9
+ * export default oracle; // { fetch, scheduled }
10
+ *
11
+ * plus a `wrangler.jsonc` declaring the two Durable Object bindings
12
+ * (`USER_ORACLE` → `UserOracleDO`, `MATRIX_GATEWAY` → `MatrixGatewayDO`,
13
+ * both `new_sqlite_classes`) and the crypto-wasm alias. See
14
+ * `apps/qiforge-workers-example`.
15
+ */
16
+ import {
17
+ createRuntimeCore,
18
+ listModels,
19
+ type RuntimeCoreOptions,
20
+ type RuntimeCore,
21
+ } from './core';
22
+ import type { OraclePlugin } from './plugin-api';
23
+ import type { OracleConfig } from './plugin-api/types';
24
+ import type { OracleWorkerEnv } from './do/contracts';
25
+ import {
26
+ createUserOracleDO,
27
+ type OracleWorkerHooks,
28
+ } from './do/user-oracle-do';
29
+ import { MatrixGatewayDO } from './matrix/gateway-do';
30
+ import { createShell, gateway, type PluginRoute } from './shell/app';
31
+ import type { RouteExclusion } from './shell/auth';
32
+
33
+ export * from './plugin-api';
34
+ export * from './plugins';
35
+ export * from './do/contracts';
36
+ export type { OwnerStore } from './owner-store/types';
37
+ export { MigratingOwnerStore } from './owner-store/migrating-store';
38
+ export { IxoVfsOwnerStore } from './owner-store/ixo-vfs-store';
39
+ export { MatrixMediaOwnerStore } from './owner-store/matrix-media-store';
40
+ export { MatrixGatewayDO } from './matrix/gateway-do';
41
+ export {
42
+ createUserOracleDO,
43
+ type OracleWorkerHooks,
44
+ } from './do/user-oracle-do';
45
+ export { createShell } from './shell/app';
46
+ export { authenticate } from './shell/auth';
47
+ export {
48
+ createRuntimeCore,
49
+ createMainAgent,
50
+ createLlmAdapter,
51
+ buildModelListing,
52
+ fetchOpenRouterPrices,
53
+ listModelCatalog,
54
+ listModels,
55
+ MODEL_CATALOG,
56
+ WeatherPlugin,
57
+ SkillsPlugin,
58
+ type RuntimeCore,
59
+ type RuntimeCoreOptions,
60
+ } from './core';
61
+ export {
62
+ NEBIUS_BASE_URL,
63
+ NEBIUS_MODEL_MAP,
64
+ langsmithEnvFromWorkerEnv,
65
+ llmEnvFromWorkerEnv,
66
+ resolveLangsmithTracing,
67
+ type LangsmithTracingDecision,
68
+ type LangsmithTracingEnv,
69
+ type LlmProvider,
70
+ type ResolveLangsmithTracingArgs,
71
+ } from './core/llm';
72
+
73
+ // --- per-room JWE secrets ---------------------------------------------------
74
+ export { decryptJwe, encryptJwe, parseJwk, type JWK } from './secrets/jwe';
75
+ export { decryptWithPin } from './secrets/pin-cipher';
76
+ export {
77
+ RUNTIME_PUBLIC_KEY_ID,
78
+ WorkersSecretsService,
79
+ type SecretIndexEntry,
80
+ type SecretsGateway,
81
+ type WorkersSecretsServiceOptions,
82
+ } from './secrets/secrets-service';
83
+ export { createSecretsAdapter } from './do/secrets-adapter';
84
+
85
+ // --- bring-your-own-credential LLMs ----------------------------------------
86
+ export * from './llm/byo-catalog';
87
+ export { createByoLlmAdapter, type ByoTurnResolution } from './llm/byo-adapter';
88
+ export {
89
+ ANTHROPIC_OPENAI_COMPAT_BASE_URL,
90
+ CHATGPT_BACKEND_BASE_URL,
91
+ DEEPSEEK_BASE_URL,
92
+ GEMINI_OPENAI_COMPAT_BASE_URL,
93
+ createByoChatModel,
94
+ type CreateByoChatModelArgs,
95
+ } from './llm/byo-client';
96
+ export {
97
+ WorkersByoService,
98
+ type ByoCredentialMap,
99
+ type ByoProviderStatus,
100
+ type ByoSecretsBackend,
101
+ type ByoStateStore,
102
+ type ByoTurnState,
103
+ type WorkersByoServiceOptions,
104
+ } from './llm/byo-service';
105
+ export { handleByoRequest } from './llm/byo-routes';
106
+ export {
107
+ BYO_FALLBACK_KIND,
108
+ buildByoFallbackNotice,
109
+ type ByoFallbackNoticePayload,
110
+ type ByoFallbackReason,
111
+ } from './llm/provider-error';
112
+ export {
113
+ CHATGPT_REDIRECT_URI,
114
+ ChatGptOAuthError,
115
+ DEFAULT_CHATGPT_CLIENT_ID,
116
+ DEVICE_VERIFICATION_URL,
117
+ TOKEN_REFRESH_SKEW_MS,
118
+ buildAuthorizeUrl,
119
+ createOAuthState,
120
+ createPkcePair,
121
+ exchangeAuthorizationCode,
122
+ pollDeviceToken,
123
+ refreshChatGptTokens,
124
+ startDeviceAuthorization,
125
+ type DeviceAuthorization,
126
+ type DevicePollResult,
127
+ type PkcePair,
128
+ } from './llm/chatgpt-oauth';
129
+
130
+ export interface CreateOracleWorkerOptions {
131
+ config: OracleConfig;
132
+ plugins?: OraclePlugin[];
133
+ features?: RuntimeCoreOptions['features'];
134
+ /** Extra host routes mounted on the shell. */
135
+ routes?: PluginRoute[];
136
+ /** Host routes exempt from UCAN auth. */
137
+ authExcludedRoutes?: RouteExclusion[];
138
+ /**
139
+ * Overrides for the model catalog exposed on `GET /models`. Default: the
140
+ * curated catalog with live OpenRouter prices (`listModels`).
141
+ */
142
+ listModels?: (env: OracleWorkerEnv) => unknown | Promise<unknown>;
143
+ /**
144
+ * Host hooks for the per-turn agent build — the Node runtime's
145
+ * `opts.hooks.getRoomTitle` / `safetyModel`, resolved per turn against the
146
+ * user object's ambient services.
147
+ */
148
+ hooks?: OracleWorkerHooks;
149
+ }
150
+
151
+ export interface OracleWorker {
152
+ fetch: (
153
+ request: Request,
154
+ env: OracleWorkerEnv,
155
+ ctx: ExecutionContext,
156
+ ) => Promise<Response>;
157
+ scheduled: (
158
+ event: ScheduledController,
159
+ env: OracleWorkerEnv,
160
+ ctx: ExecutionContext,
161
+ ) => Promise<void>;
162
+ UserOracleDO: ReturnType<typeof createUserOracleDO>;
163
+ MatrixGatewayDO: typeof MatrixGatewayDO;
164
+ /** Resolve (and memoize per isolate) the runtime core for an env. */
165
+ core: (env: OracleWorkerEnv) => RuntimeCore;
166
+ }
167
+
168
+ export function createOracleWorker(
169
+ opts: CreateOracleWorkerOptions,
170
+ ): OracleWorker {
171
+ // One core per isolate per env object. Isolates are reused across requests
172
+ // (cheap), evicted under pressure (rebuilt on demand) — same lifetime the
173
+ // Node runtime's boot caches had, minus the process.
174
+ const cores = new WeakMap<object, RuntimeCore>();
175
+ const coreFor = (env: OracleWorkerEnv): RuntimeCore => {
176
+ let core = cores.get(env);
177
+ if (!core) {
178
+ core = createRuntimeCore({
179
+ config: opts.config,
180
+ plugins: opts.plugins ?? [],
181
+ features: opts.features,
182
+ env,
183
+ logger: console,
184
+ });
185
+ cores.set(env, core);
186
+ }
187
+ return core;
188
+ };
189
+
190
+ const apps = new WeakMap<object, ReturnType<typeof createShell>>();
191
+ const appFor = (env: OracleWorkerEnv) => {
192
+ let app = apps.get(env);
193
+ if (!app) {
194
+ const core = coreFor(env);
195
+ app = createShell({
196
+ routes: [...core.pluginRoutes, ...(opts.routes ?? [])],
197
+ authExcludedRoutes: [
198
+ ...core.authExcludedRoutes,
199
+ ...(opts.authExcludedRoutes ?? []),
200
+ ],
201
+ listModels: opts.listModels ?? ((e) => listModels(e)),
202
+ banner: {
203
+ name: opts.config.name,
204
+ description: opts.config.description,
205
+ },
206
+ });
207
+ apps.set(env, app);
208
+ }
209
+ return app;
210
+ };
211
+
212
+ const UserOracleDO = createUserOracleDO({
213
+ core: coreFor,
214
+ ...(opts.hooks ? { hooks: opts.hooks } : {}),
215
+ });
216
+
217
+ return {
218
+ UserOracleDO,
219
+ MatrixGatewayDO,
220
+ core: coreFor,
221
+ fetch: async (request, env, ctx) => {
222
+ // Make sure the Matrix bot is running; the call is idempotent and cheap
223
+ // once started. Done in the background so it never delays a request.
224
+ ctx.waitUntil(
225
+ gateway(env)
226
+ .ensureStarted()
227
+ .catch((err) => console.error('[matrix] ensureStarted failed', err)),
228
+ );
229
+ return appFor(env).fetch(request, env, ctx);
230
+ },
231
+ scheduled: async (_event, env) => {
232
+ // Cron safety net: if the gateway's keep-alive loop ever died, this
233
+ // restarts it. Declare a `triggers.crons` entry (e.g. every 5 minutes).
234
+ await gateway(env).ensureStarted();
235
+ },
236
+ };
237
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Request-scoped LLM adapter for BYO turns — the Workers port of the Node
3
+ * runtime's `llm/byo-adapter.ts`.
4
+ *
5
+ * The host swaps this in for `ambient.llm` on turns where the user has an
6
+ * active BYO credential, so every downstream consumer — the main model,
7
+ * sub-agents, plugin tools reading `rtCtx.llm`, and middlewares —
8
+ * transparently runs on the user's provider. Roles the provider cannot serve
9
+ * (embedding everywhere, vision on DeepSeek) fall through to the platform
10
+ * adapter, so those stay platform-paid.
11
+ *
12
+ * The credential is captured in this closure only; it never appears on the
13
+ * request context, graph state, or trace metadata.
14
+ */
15
+
16
+ import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
17
+ import type { ChatOpenAIFields, Logger, ModelRole } from '../plugin-api/types';
18
+ import type { LlmAdapter } from '../core/runtime-context';
19
+ import { byoModelForRole, type ByoCredential } from './byo-catalog';
20
+ import { createByoChatModel, type ChatGptBackendConfig } from './byo-client';
21
+
22
+ export interface ByoTurnResolution {
23
+ credential: ByoCredential;
24
+ /** Provider-native id serving the `main` role this turn. */
25
+ mainModelId: string;
26
+ /** ChatGPT lane only: backend/proxy the requests go to. */
27
+ chatGptBackend?: ChatGptBackendConfig;
28
+ }
29
+
30
+ export function createByoLlmAdapter(
31
+ platform: LlmAdapter,
32
+ turn: ByoTurnResolution,
33
+ logger?: Logger,
34
+ ): LlmAdapter {
35
+ return {
36
+ get(role: ModelRole, params?: ChatOpenAIFields): BaseChatModel {
37
+ const modelId = byoModelForRole(
38
+ turn.credential.provider,
39
+ role,
40
+ turn.mainModelId,
41
+ );
42
+ if (modelId === null) {
43
+ // Role not served by this provider — platform model, platform key.
44
+ return platform.get(role, params);
45
+ }
46
+ // Strip a caller-supplied `model` (for `main` it carries the `byo:` id,
47
+ // which is not a wire id) — the translated id wins.
48
+ const { model: _model, ...rest } = params ?? {};
49
+ return createByoChatModel({
50
+ credential: turn.credential,
51
+ modelId,
52
+ role,
53
+ chatGptBackend: turn.chatGptBackend,
54
+ params: rest,
55
+ logger,
56
+ });
57
+ },
58
+ };
59
+ }