auramaxx 1.0.0-alpha.4

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 (363) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +112 -0
  3. package/bin/aurawallet.js +121 -0
  4. package/docs/ADAPTERS.md +467 -0
  5. package/docs/API.md +2679 -0
  6. package/docs/APPS.md +198 -0
  7. package/docs/ARCHITECTURE.md +350 -0
  8. package/docs/AUTH.md +698 -0
  9. package/docs/BEST-PRACTICES.md +121 -0
  10. package/docs/CLI.md +61 -0
  11. package/docs/DEVELOPING-APPS.md +452 -0
  12. package/docs/EXTENSION.md +97 -0
  13. package/docs/JOBS.md +33 -0
  14. package/docs/MCP.md +76 -0
  15. package/docs/PROTOCOL.md +142 -0
  16. package/docs/SETUP.md +219 -0
  17. package/docs/WORKSPACE.md +672 -0
  18. package/docs/agent-auth.md +63 -0
  19. package/docs/aura-file.md +48 -0
  20. package/docs/credentials.md +53 -0
  21. package/docs/external/getting-started.md +65 -0
  22. package/docs/external/overview.md +45 -0
  23. package/docs/external/use-cases.md +48 -0
  24. package/docs/external/why-aura.md +35 -0
  25. package/docs/jobs/connect-agent.md +77 -0
  26. package/docs/jobs/migrate-from-dotenv.md +79 -0
  27. package/docs/jobs/recover-from-lockout.md +72 -0
  28. package/docs/jobs/secure-ci.md +63 -0
  29. package/docs/oauth2.md +42 -0
  30. package/docs/passkeys.md +60 -0
  31. package/docs/security.md +540 -0
  32. package/docs/specs/aura-open-protocol.md +61 -0
  33. package/docs/specs/aura-provider-plugin.md +24 -0
  34. package/docs/specs/aura-registry-model.md +31 -0
  35. package/docs/specs/fixtures/invalid-bad-key.aura +1 -0
  36. package/docs/specs/fixtures/invalid-bad-unicode-escape.aura +1 -0
  37. package/docs/specs/fixtures/invalid-duplicate-key.aura +2 -0
  38. package/docs/specs/fixtures/valid-basic.aura +4 -0
  39. package/docs/specs/fixtures/valid-provider-ref.aura +1 -0
  40. package/docs/specs/fixtures/valid-quoted-escapes.aura +2 -0
  41. package/docs/templates/RELEASE_NOTES_TEMPLATE.md +22 -0
  42. package/docs/totp.md +40 -0
  43. package/docs/wallet/AI.md +508 -0
  44. package/docs/wallet/DEVELOPING-STRATEGIES.md +713 -0
  45. package/docs/wallet/README.md +47 -0
  46. package/docs/wallet/STRATEGY.md +89 -0
  47. package/next.config.ts +21 -0
  48. package/package.json +151 -0
  49. package/postcss.config.mjs +8 -0
  50. package/prisma/migrations/20260214170000_baseline/migration.sql +511 -0
  51. package/prisma/migrations/20260216214537_add_passkey_model/migration.sql +18 -0
  52. package/prisma/migrations/20260217150500_add_credential_access_audit/migration.sql +31 -0
  53. package/prisma/migrations/migration_lock.toml +3 -0
  54. package/prisma/schema.prisma +447 -0
  55. package/public/logo-chevron.svg +31 -0
  56. package/public/logo-concentric.svg +31 -0
  57. package/public/logo-crosshatch.svg +39 -0
  58. package/public/logo-dashed.svg +39 -0
  59. package/public/logo-horizontal.svg +31 -0
  60. package/public/logo-m56.svg +64 -0
  61. package/public/logo.webp +0 -0
  62. package/scripts/add-app.js +245 -0
  63. package/scripts/init.sh +57 -0
  64. package/scripts/migrate-apikeys-to-credentials.ts +35 -0
  65. package/scripts/sandbox-agent-flow.sh +235 -0
  66. package/scripts/sandbox.sh +175 -0
  67. package/scripts/validate-job-docs.mjs +125 -0
  68. package/server/abi/SwapHelper.json +438 -0
  69. package/server/cli/approval.ts +447 -0
  70. package/server/cli/commands/app.ts +204 -0
  71. package/server/cli/commands/cron.ts +24 -0
  72. package/server/cli/commands/doctor.ts +1007 -0
  73. package/server/cli/commands/env.ts +456 -0
  74. package/server/cli/commands/init.ts +752 -0
  75. package/server/cli/commands/mcp.ts +125 -0
  76. package/server/cli/commands/restore.ts +314 -0
  77. package/server/cli/commands/shell-hook.ts +468 -0
  78. package/server/cli/commands/start.ts +62 -0
  79. package/server/cli/commands/status.ts +59 -0
  80. package/server/cli/commands/stop.ts +14 -0
  81. package/server/cli/commands/token.ts +180 -0
  82. package/server/cli/commands/unlock.ts +49 -0
  83. package/server/cli/commands/vault.ts +417 -0
  84. package/server/cli/index.ts +328 -0
  85. package/server/cli/lib/aura-parser.ts +64 -0
  86. package/server/cli/lib/credential-create.ts +74 -0
  87. package/server/cli/lib/credential-resolve.ts +254 -0
  88. package/server/cli/lib/dotenv-migrate.ts +116 -0
  89. package/server/cli/lib/dotenv-parser.ts +146 -0
  90. package/server/cli/lib/http.ts +91 -0
  91. package/server/cli/lib/init-steps.ts +76 -0
  92. package/server/cli/lib/local-agent-trust.ts +45 -0
  93. package/server/cli/lib/process.ts +136 -0
  94. package/server/cli/lib/prompt.ts +85 -0
  95. package/server/cli/lib/theme.ts +240 -0
  96. package/server/cli/socket.ts +570 -0
  97. package/server/cli/transport-client.ts +50 -0
  98. package/server/cron/index.ts +137 -0
  99. package/server/cron/job.ts +31 -0
  100. package/server/cron/jobs/balance-sync.ts +436 -0
  101. package/server/cron/jobs/incoming-scan.ts +506 -0
  102. package/server/cron/jobs/native-price.ts +70 -0
  103. package/server/cron/jobs/orphan-cleanup.ts +40 -0
  104. package/server/cron/jobs/strategy-runner.ts +175 -0
  105. package/server/cron/scheduler.ts +125 -0
  106. package/server/index.ts +406 -0
  107. package/server/lib/adapters/factory.ts +110 -0
  108. package/server/lib/adapters/index.ts +19 -0
  109. package/server/lib/adapters/router.ts +297 -0
  110. package/server/lib/adapters/telegram.ts +645 -0
  111. package/server/lib/adapters/types.ts +89 -0
  112. package/server/lib/adapters/webhook.ts +95 -0
  113. package/server/lib/address.ts +49 -0
  114. package/server/lib/agent-auth/contracts.ts +1194 -0
  115. package/server/lib/agent-profiles.ts +328 -0
  116. package/server/lib/ai.ts +285 -0
  117. package/server/lib/api-registry/contracts.ts +86 -0
  118. package/server/lib/api-registry/validation.ts +172 -0
  119. package/server/lib/apikey-migration.ts +189 -0
  120. package/server/lib/app-installer.ts +505 -0
  121. package/server/lib/app-tokens.ts +247 -0
  122. package/server/lib/auth.ts +314 -0
  123. package/server/lib/batch.ts +242 -0
  124. package/server/lib/cold.ts +874 -0
  125. package/server/lib/config.ts +381 -0
  126. package/server/lib/credential-access-audit.ts +85 -0
  127. package/server/lib/credential-access-policy.ts +110 -0
  128. package/server/lib/credential-health.ts +343 -0
  129. package/server/lib/credential-import.ts +487 -0
  130. package/server/lib/credential-scope.ts +87 -0
  131. package/server/lib/credential-shares.ts +190 -0
  132. package/server/lib/credential-transport.ts +342 -0
  133. package/server/lib/credential-vault.ts +77 -0
  134. package/server/lib/credentials.ts +333 -0
  135. package/server/lib/crypto.ts +8 -0
  136. package/server/lib/db.ts +15 -0
  137. package/server/lib/defaults.ts +366 -0
  138. package/server/lib/dex/index.ts +80 -0
  139. package/server/lib/dex/relay.ts +235 -0
  140. package/server/lib/dex/types.ts +59 -0
  141. package/server/lib/dex/uniswap.ts +370 -0
  142. package/server/lib/e2e-agent/artifacts.ts +36 -0
  143. package/server/lib/e2e-agent/contracts.ts +112 -0
  144. package/server/lib/e2e-agent/validation.ts +135 -0
  145. package/server/lib/encrypt.ts +128 -0
  146. package/server/lib/error.ts +20 -0
  147. package/server/lib/events.ts +205 -0
  148. package/server/lib/hot.ts +357 -0
  149. package/server/lib/key-fingerprint.ts +28 -0
  150. package/server/lib/logger.ts +331 -0
  151. package/server/lib/network.ts +137 -0
  152. package/server/lib/notifications.ts +219 -0
  153. package/server/lib/oauth2-refresh.ts +241 -0
  154. package/server/lib/oursecret.ts +54 -0
  155. package/server/lib/passkey-credential.ts +360 -0
  156. package/server/lib/passkey.ts +68 -0
  157. package/server/lib/permissions.ts +248 -0
  158. package/server/lib/pino.ts +24 -0
  159. package/server/lib/policy-preview.ts +138 -0
  160. package/server/lib/price.ts +338 -0
  161. package/server/lib/prices.ts +34 -0
  162. package/server/lib/project-scope.ts +239 -0
  163. package/server/lib/resolve-action.ts +427 -0
  164. package/server/lib/resolve.ts +36 -0
  165. package/server/lib/sessions.ts +632 -0
  166. package/server/lib/solana/connection.ts +26 -0
  167. package/server/lib/solana/jupiter.ts +128 -0
  168. package/server/lib/solana/transfer.ts +108 -0
  169. package/server/lib/solana/wallet.ts +136 -0
  170. package/server/lib/strategy/emits.ts +21 -0
  171. package/server/lib/strategy/engine.ts +1305 -0
  172. package/server/lib/strategy/executor.ts +115 -0
  173. package/server/lib/strategy/hook-context.ts +158 -0
  174. package/server/lib/strategy/hooks.ts +990 -0
  175. package/server/lib/strategy/index.ts +28 -0
  176. package/server/lib/strategy/installer.ts +305 -0
  177. package/server/lib/strategy/loader.ts +256 -0
  178. package/server/lib/strategy/message.ts +235 -0
  179. package/server/lib/strategy/repository.ts +218 -0
  180. package/server/lib/strategy/session-logger.ts +693 -0
  181. package/server/lib/strategy/sources.ts +288 -0
  182. package/server/lib/strategy/state.ts +189 -0
  183. package/server/lib/strategy/templates.ts +403 -0
  184. package/server/lib/strategy/tick.ts +404 -0
  185. package/server/lib/strategy/types.ts +230 -0
  186. package/server/lib/swap.ts +3 -0
  187. package/server/lib/temp.ts +86 -0
  188. package/server/lib/token-metadata.ts +86 -0
  189. package/server/lib/token-safety.ts +200 -0
  190. package/server/lib/token-search.ts +444 -0
  191. package/server/lib/totp.ts +194 -0
  192. package/server/lib/transactions.ts +123 -0
  193. package/server/lib/transport.ts +75 -0
  194. package/server/lib/txhistory/decoder.ts +262 -0
  195. package/server/lib/txhistory/enricher.ts +652 -0
  196. package/server/lib/txhistory/index.ts +391 -0
  197. package/server/lib/txhistory/signatures.ts +59 -0
  198. package/server/lib/verified-summary.ts +421 -0
  199. package/server/mcp/profile-policy.ts +30 -0
  200. package/server/mcp/server.ts +619 -0
  201. package/server/mcp/tools.ts +523 -0
  202. package/server/middleware/auth.ts +119 -0
  203. package/server/middleware/requestLogger.ts +84 -0
  204. package/server/routes/actions.ts +459 -0
  205. package/server/routes/adapters.ts +703 -0
  206. package/server/routes/addressbook.ts +113 -0
  207. package/server/routes/ai.ts +34 -0
  208. package/server/routes/apikeys.ts +295 -0
  209. package/server/routes/apps.ts +601 -0
  210. package/server/routes/auth.ts +457 -0
  211. package/server/routes/backup.ts +340 -0
  212. package/server/routes/batch.ts +270 -0
  213. package/server/routes/bookmarks.ts +162 -0
  214. package/server/routes/credential-shares.ts +198 -0
  215. package/server/routes/credential-vaults.ts +154 -0
  216. package/server/routes/credentials.ts +1290 -0
  217. package/server/routes/dashboard.ts +71 -0
  218. package/server/routes/defaults.ts +124 -0
  219. package/server/routes/fund.ts +229 -0
  220. package/server/routes/import.ts +352 -0
  221. package/server/routes/launch.ts +665 -0
  222. package/server/routes/lock.ts +54 -0
  223. package/server/routes/logs.ts +68 -0
  224. package/server/routes/nuke.ts +111 -0
  225. package/server/routes/passkey-credentials.ts +99 -0
  226. package/server/routes/passkey.ts +346 -0
  227. package/server/routes/portfolio.ts +217 -0
  228. package/server/routes/price.ts +63 -0
  229. package/server/routes/resolve.ts +31 -0
  230. package/server/routes/security.ts +45 -0
  231. package/server/routes/send-evm.ts +241 -0
  232. package/server/routes/send-solana.ts +281 -0
  233. package/server/routes/send.ts +178 -0
  234. package/server/routes/setup.ts +210 -0
  235. package/server/routes/strategy.ts +894 -0
  236. package/server/routes/swap-evm.ts +353 -0
  237. package/server/routes/swap-solana.ts +177 -0
  238. package/server/routes/swap.ts +356 -0
  239. package/server/routes/token.ts +247 -0
  240. package/server/routes/unlock.ts +403 -0
  241. package/server/routes/wallet-assets.ts +361 -0
  242. package/server/routes/wallet-transactions.ts +515 -0
  243. package/server/routes/wallet.ts +710 -0
  244. package/server/types.ts +146 -0
  245. package/skills/aurawallet/SKILL.md +739 -0
  246. package/skills/aurawallet-setup/SKILL.md +74 -0
  247. package/skills/security-review/SKILL.md +148 -0
  248. package/src/app/api/agent-requests/route.ts +30 -0
  249. package/src/app/api/apps/install/route.ts +126 -0
  250. package/src/app/api/apps/manifests/route.ts +16 -0
  251. package/src/app/api/apps/static/[...path]/route.ts +57 -0
  252. package/src/app/api/events/route.ts +92 -0
  253. package/src/app/api/page.tsx +212 -0
  254. package/src/app/api/workspace/[id]/apps/[wid]/route.ts +119 -0
  255. package/src/app/api/workspace/[id]/apps/route.ts +81 -0
  256. package/src/app/api/workspace/[id]/export/route.ts +67 -0
  257. package/src/app/api/workspace/[id]/route.ts +168 -0
  258. package/src/app/api/workspace/auth.ts +34 -0
  259. package/src/app/api/workspace/config/route.ts +106 -0
  260. package/src/app/api/workspace/import/route.ts +127 -0
  261. package/src/app/api/workspace/route.ts +116 -0
  262. package/src/app/app/page.tsx +2122 -0
  263. package/src/app/apple-icon.png +0 -0
  264. package/src/app/docs/page.tsx +178 -0
  265. package/src/app/favicon.ico +0 -0
  266. package/src/app/globals.css +572 -0
  267. package/src/app/health/page.tsx +5 -0
  268. package/src/app/hello/page.tsx +15 -0
  269. package/src/app/icon.png +0 -0
  270. package/src/app/layout.tsx +34 -0
  271. package/src/app/page.tsx +986 -0
  272. package/src/app/providers.tsx +90 -0
  273. package/src/app/share/[token]/page.tsx +295 -0
  274. package/src/components/ChainSelector.tsx +144 -0
  275. package/src/components/HumanActionBar.tsx +695 -0
  276. package/src/components/NotificationDrawer.tsx +129 -0
  277. package/src/components/apps/AgentKeysApp.tsx +490 -0
  278. package/src/components/apps/App.tsx +153 -0
  279. package/src/components/apps/AppGrid.tsx +15 -0
  280. package/src/components/apps/DetailedAddressDrawer.tsx +325 -0
  281. package/src/components/apps/DraggableApp.tsx +562 -0
  282. package/src/components/apps/IFrameApp.tsx +73 -0
  283. package/src/components/apps/LogsApp.tsx +360 -0
  284. package/src/components/apps/SendApp.tsx +394 -0
  285. package/src/components/apps/SetupWizardApp.tsx +1004 -0
  286. package/src/components/apps/SystemDefaultsApp.tsx +845 -0
  287. package/src/components/apps/ThirdPartyApp.tsx +428 -0
  288. package/src/components/apps/TokenApp.tsx +319 -0
  289. package/src/components/apps/TransactionsApp.tsx +438 -0
  290. package/src/components/apps/WalletDetailApp.tsx +1505 -0
  291. package/src/components/apps/index.ts +13 -0
  292. package/src/components/design-system/Button.tsx +53 -0
  293. package/src/components/design-system/ChainIndicator.tsx +65 -0
  294. package/src/components/design-system/ChainSelector.tsx +137 -0
  295. package/src/components/design-system/ConfirmationModal.tsx +106 -0
  296. package/src/components/design-system/ConfirmationPopover.tsx +81 -0
  297. package/src/components/design-system/Drawer.tsx +123 -0
  298. package/src/components/design-system/FilterDropdown.tsx +72 -0
  299. package/src/components/design-system/Modal.tsx +206 -0
  300. package/src/components/design-system/Popover.tsx +142 -0
  301. package/src/components/design-system/TextInput.tsx +85 -0
  302. package/src/components/design-system/Toggle.tsx +58 -0
  303. package/src/components/design-system/index.ts +11 -0
  304. package/src/components/docs/DocsThemeToggle.tsx +49 -0
  305. package/src/components/health/CredentialHealthDashboard.tsx +214 -0
  306. package/src/components/icons/ChainIcons.tsx +72 -0
  307. package/src/components/layout/AppStoreDrawer.tsx +369 -0
  308. package/src/components/layout/ContentArea.tsx +21 -0
  309. package/src/components/layout/TabBar.tsx +278 -0
  310. package/src/components/layout/WalletSidebar.tsx +1033 -0
  311. package/src/components/layout/index.ts +4 -0
  312. package/src/components/marketing/AuraWalletSpecOverlay.tsx +635 -0
  313. package/src/components/marketing/DeviceMorphExperience.tsx +216 -0
  314. package/src/components/vault/ApiKeysConsole.tsx +1080 -0
  315. package/src/components/vault/AuditConsole.tsx +584 -0
  316. package/src/components/vault/CredentialDetail.tsx +455 -0
  317. package/src/components/vault/CredentialEmpty.tsx +55 -0
  318. package/src/components/vault/CredentialField.tsx +361 -0
  319. package/src/components/vault/CredentialForm.tsx +1212 -0
  320. package/src/components/vault/CredentialList.tsx +165 -0
  321. package/src/components/vault/CredentialRow.tsx +97 -0
  322. package/src/components/vault/CredentialShareModal.tsx +178 -0
  323. package/src/components/vault/CredentialVault.tsx +754 -0
  324. package/src/components/vault/CredentialWalletWidget.tsx +103 -0
  325. package/src/components/vault/ImportCredentialsModal.tsx +515 -0
  326. package/src/components/vault/LargeTypeModal.tsx +64 -0
  327. package/src/components/vault/PasswordGenerator.tsx +224 -0
  328. package/src/components/vault/TOTPDisplay.tsx +123 -0
  329. package/src/components/vault/VaultSidebar.tsx +413 -0
  330. package/src/components/vault/types.ts +54 -0
  331. package/src/context/AuthContext.tsx +337 -0
  332. package/src/context/PriceContext.tsx +113 -0
  333. package/src/context/ThemeContext.tsx +164 -0
  334. package/src/context/WebSocketContext.tsx +269 -0
  335. package/src/context/WorkspaceContext.tsx +668 -0
  336. package/src/hooks/index.ts +3 -0
  337. package/src/hooks/useAgentActions.ts +368 -0
  338. package/src/hooks/useBalance.ts +103 -0
  339. package/src/hooks/useBalances.ts +129 -0
  340. package/src/instrumentation.ts +12 -0
  341. package/src/lib/api.ts +449 -0
  342. package/src/lib/app-loader.ts +148 -0
  343. package/src/lib/app-registry.ts +178 -0
  344. package/src/lib/app-sdk.ts +157 -0
  345. package/src/lib/audit-console-adapter.ts +151 -0
  346. package/src/lib/auth-client.ts +75 -0
  347. package/src/lib/config.ts +74 -0
  348. package/src/lib/crypto.ts +112 -0
  349. package/src/lib/db.ts +21 -0
  350. package/src/lib/docs.ts +390 -0
  351. package/src/lib/events.ts +361 -0
  352. package/src/lib/pino.ts +24 -0
  353. package/src/lib/theme-handlers.ts +168 -0
  354. package/src/lib/theme.ts +351 -0
  355. package/src/lib/tokenData.ts +378 -0
  356. package/src/lib/vault-crypto.ts +129 -0
  357. package/src/lib/websocket-server.ts +302 -0
  358. package/src/lib/websocket-setup.ts +79 -0
  359. package/src/lib/wordlist.ts +2050 -0
  360. package/src/lib/workspace-handlers.ts +285 -0
  361. package/start.sh +80 -0
  362. package/tailwind.config.ts +99 -0
  363. package/tsconfig.json +42 -0
@@ -0,0 +1,297 @@
1
+ /**
2
+ * ApprovalRouter — connects to WebSocket, fans out events to adapters.
3
+ *
4
+ * Calls resolve and message logic directly as an in-process trusted
5
+ * component, without fabricating admin tokens or making HTTP requests
6
+ * to itself.
7
+ */
8
+
9
+ import { WebSocket } from 'ws';
10
+ import { resolveAction } from '../resolve-action';
11
+ import { handleAppMessage, enqueueAppMessage, waitForQueuedAppMessage } from '../strategy/engine';
12
+ import { getDefaultSync } from '../defaults';
13
+ import type {
14
+ ApprovalAdapter,
15
+ AdapterContext,
16
+ ActionNotification,
17
+ ActionResolution,
18
+ ResolveOptions,
19
+ ResolveResult,
20
+ } from './types';
21
+ import { getErrorMessage } from '../error';
22
+
23
+ export class ApprovalRouter {
24
+ private adapters: ApprovalAdapter[] = [];
25
+ private ws: WebSocket | null = null;
26
+ private reconnectTimeout: NodeJS.Timeout | null = null;
27
+ private isRunning = false;
28
+ private serverUrl: string;
29
+ private defaultAppCache: string | null | undefined = undefined;
30
+
31
+ constructor(serverUrl: string) {
32
+ this.serverUrl = serverUrl;
33
+ }
34
+
35
+ /** Register an adapter to receive events */
36
+ registerAdapter(adapter: ApprovalAdapter): void {
37
+ this.adapters.push(adapter);
38
+ }
39
+
40
+ /** Start the router: connect WS, fetch pending, start adapters */
41
+ async start(): Promise<void> {
42
+ if (process.env.NODE_ENV === 'test') return;
43
+
44
+ if (this.adapters.length === 0) {
45
+ console.log('[adapters] No adapters registered, skipping start');
46
+ return;
47
+ }
48
+
49
+ this.isRunning = true;
50
+
51
+ // Build adapter context
52
+ const ctx: AdapterContext = {
53
+ resolve: (actionId, approved, opts) => this.resolve(actionId, approved, opts),
54
+ serverUrl: this.serverUrl,
55
+ sendMessage: (appId, text, onProgress, adapter) => this.sendMessage(appId, text, onProgress, adapter),
56
+ resolveApp: (targetApp) => this.resolveApp(targetApp),
57
+ };
58
+
59
+ // Start all adapters
60
+ for (const adapter of this.adapters) {
61
+ try {
62
+ await adapter.start(ctx);
63
+ console.log(`[adapters] Started adapter: ${adapter.name}`);
64
+ } catch (err) {
65
+ const msg = getErrorMessage(err);
66
+ console.error(`[adapters] Failed to start adapter ${adapter.name}:`, msg);
67
+ }
68
+ }
69
+
70
+ // Connect to WebSocket for live events
71
+ this.connectWebSocket();
72
+
73
+ // Fetch any existing pending actions
74
+ await this.fetchPendingActions();
75
+
76
+ console.log(`[adapters] Router started with ${this.adapters.length} adapter(s)`);
77
+ }
78
+
79
+ /** Stop the router and all adapters */
80
+ async stop(): Promise<void> {
81
+ this.isRunning = false;
82
+
83
+ if (this.reconnectTimeout) {
84
+ clearTimeout(this.reconnectTimeout);
85
+ this.reconnectTimeout = null;
86
+ }
87
+
88
+ if (this.ws) {
89
+ this.ws.close();
90
+ this.ws = null;
91
+ }
92
+
93
+ for (const adapter of this.adapters) {
94
+ try {
95
+ await adapter.stop();
96
+ } catch (err) {
97
+ const msg = getErrorMessage(err);
98
+ console.error(`[adapters] Error stopping adapter ${adapter.name}:`, msg);
99
+ }
100
+ }
101
+ }
102
+
103
+ /** Resolve an action by calling resolveAction() directly */
104
+ async resolve(actionId: string, approved: boolean, opts?: ResolveOptions): Promise<ResolveResult> {
105
+ try {
106
+ const result = await resolveAction(actionId, approved, {
107
+ walletAccess: opts?.walletAccess,
108
+ limits: opts?.limits,
109
+ });
110
+ if (!result.success) {
111
+ return { success: false, error: (result.data.error as string) || 'Unknown error' };
112
+ }
113
+ return {
114
+ success: true,
115
+ token: result.data.token as string | undefined,
116
+ agentId: result.data.agentId as string | undefined,
117
+ };
118
+ } catch (err) {
119
+ return { success: false, error: getErrorMessage(err) };
120
+ }
121
+ }
122
+
123
+ /** Route a chat message to an app's AI via the strategy engine directly */
124
+ async sendMessage(appId: string, text: string, onProgress?: (status: string) => void, adapter?: string): Promise<{ reply: string | null; error?: string }> {
125
+ try {
126
+ const adapterName = adapter || 'unknown';
127
+
128
+ // Fast path for direct chat handlers (same routing style as apps.ts).
129
+ if (appId === '__system__' || appId === 'agent-chat') {
130
+ const direct = await handleAppMessage(appId, text, onProgress, adapterName);
131
+ if (direct.error) {
132
+ return { reply: null, error: direct.error };
133
+ }
134
+ return { reply: direct.reply };
135
+ }
136
+
137
+ // Queue path for other apps
138
+ const requestId = await enqueueAppMessage(appId, text, adapterName);
139
+ const timeoutMs = getDefaultSync<number>('strategy.message_timeout_ms', 120_000);
140
+ const result = await waitForQueuedAppMessage(requestId, timeoutMs);
141
+
142
+ if (result.status === 'timeout') {
143
+ return { reply: null, error: result.error || 'Timed out waiting for message processing' };
144
+ }
145
+
146
+ if (result.status === 'error') {
147
+ return { reply: null, error: result.error || 'Message processing failed' };
148
+ }
149
+
150
+ return { reply: result.reply };
151
+ } catch (err) {
152
+ const msg = getErrorMessage(err);
153
+ return { reply: null, error: msg };
154
+ }
155
+ }
156
+
157
+ /** Resolve which app should handle a message */
158
+ async resolveApp(targetApp?: string): Promise<string | null> {
159
+ if (targetApp) return targetApp;
160
+
161
+ // Return cached value if available
162
+ if (this.defaultAppCache !== undefined) return this.defaultAppCache;
163
+
164
+ try {
165
+ const { prisma } = await import('../db');
166
+ const appConfig = await prisma.appConfig.findUnique({
167
+ where: { id: 'global' },
168
+ });
169
+
170
+ if (appConfig?.adapterConfig) {
171
+ const parsed = JSON.parse(appConfig.adapterConfig) as { chat?: { defaultApp?: string } };
172
+ // Fall back to system chat if no specific app is configured
173
+ this.defaultAppCache = parsed.chat?.defaultApp ?? '__system__';
174
+ } else {
175
+ this.defaultAppCache = '__system__';
176
+ }
177
+ } catch (err) {
178
+ console.warn('[adapters] failed to resolve default app:', getErrorMessage(err));
179
+ this.defaultAppCache = '__system__';
180
+ }
181
+
182
+ return this.defaultAppCache;
183
+ }
184
+
185
+ /** Clear the cached default app (call after config changes) */
186
+ clearAppCache(): void {
187
+ this.defaultAppCache = undefined;
188
+ }
189
+
190
+ /** Connect to WebSocket server for live events */
191
+ private connectWebSocket(): void {
192
+ const wsUrl = process.env.WS_URL ?? 'ws://localhost:4748';
193
+ if (!wsUrl) return;
194
+
195
+ try {
196
+ this.ws = new WebSocket(wsUrl);
197
+
198
+ this.ws.on('open', () => {
199
+ console.log('[adapters] WebSocket connected');
200
+ });
201
+
202
+ this.ws.on('message', (data: Buffer) => {
203
+ try {
204
+ const event = JSON.parse(data.toString());
205
+ this.handleEvent(event);
206
+ } catch (err) {
207
+ console.debug('[adapters] malformed websocket message:', getErrorMessage(err));
208
+ }
209
+ });
210
+
211
+ this.ws.on('close', () => {
212
+ if (this.isRunning) {
213
+ this.reconnectTimeout = setTimeout(() => {
214
+ this.connectWebSocket();
215
+ }, 3000);
216
+ }
217
+ });
218
+
219
+ this.ws.on('error', (error) => {
220
+ console.error('[adapters] WebSocket error:', error.message);
221
+ });
222
+ } catch {
223
+ if (this.isRunning) {
224
+ this.reconnectTimeout = setTimeout(() => {
225
+ this.connectWebSocket();
226
+ }, 3000);
227
+ }
228
+ }
229
+ }
230
+
231
+ /** Handle incoming WebSocket event */
232
+ private handleEvent(event: { type: string; data: unknown }): void {
233
+ if (event.type === 'action:created') {
234
+ const notification = event.data as ActionNotification;
235
+ this.fanOutNotify(notification);
236
+ } else if (event.type === 'action:resolved') {
237
+ const resolution = event.data as ActionResolution;
238
+ this.fanOutResolved(resolution);
239
+ }
240
+ }
241
+
242
+ /** Fetch existing pending actions via direct prisma query */
243
+ private async fetchPendingActions(): Promise<void> {
244
+ try {
245
+ const { prisma } = await import('../db');
246
+ const actions = await prisma.humanAction.findMany({
247
+ where: {
248
+ status: 'pending',
249
+ NOT: { type: 'strategy:message' },
250
+ },
251
+ orderBy: { createdAt: 'desc' },
252
+ });
253
+
254
+ for (const action of actions) {
255
+ // Map raw DB row to ActionNotification shape
256
+ let metadata: { source?: string; summary?: string } & Record<string, unknown> = {};
257
+ try { metadata = JSON.parse(action.metadata || '{}'); } catch {}
258
+
259
+ const notification: ActionNotification = {
260
+ id: action.id,
261
+ type: action.type,
262
+ source: metadata.source || (metadata.agentId ? `agent:${metadata.agentId}` : 'unknown'),
263
+ summary: (metadata.summary as string) || action.type,
264
+ expiresAt: null,
265
+ metadata,
266
+ };
267
+ this.fanOutNotify(notification);
268
+ }
269
+
270
+ if (actions.length > 0) {
271
+ console.log(`[adapters] Notified adapters of ${actions.length} pending action(s)`);
272
+ }
273
+ } catch (err) {
274
+ console.debug('[adapters] pending actions fetch failed:', getErrorMessage(err));
275
+ }
276
+ }
277
+
278
+ /** Fan out a notification to all adapters */
279
+ private fanOutNotify(action: ActionNotification): void {
280
+ for (const adapter of this.adapters) {
281
+ adapter.notify(action).catch(err => {
282
+ const msg = getErrorMessage(err);
283
+ console.error(`[adapters] ${adapter.name} notify error:`, msg);
284
+ });
285
+ }
286
+ }
287
+
288
+ /** Fan out a resolution to all adapters */
289
+ private fanOutResolved(resolution: ActionResolution): void {
290
+ for (const adapter of this.adapters) {
291
+ adapter.resolved(resolution).catch(err => {
292
+ const msg = getErrorMessage(err);
293
+ console.error(`[adapters] ${adapter.name} resolved error:`, msg);
294
+ });
295
+ }
296
+ }
297
+ }