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.
- package/LICENSE +26 -0
- package/README.md +112 -0
- package/bin/aurawallet.js +121 -0
- package/docs/ADAPTERS.md +467 -0
- package/docs/API.md +2679 -0
- package/docs/APPS.md +198 -0
- package/docs/ARCHITECTURE.md +350 -0
- package/docs/AUTH.md +698 -0
- package/docs/BEST-PRACTICES.md +121 -0
- package/docs/CLI.md +61 -0
- package/docs/DEVELOPING-APPS.md +452 -0
- package/docs/EXTENSION.md +97 -0
- package/docs/JOBS.md +33 -0
- package/docs/MCP.md +76 -0
- package/docs/PROTOCOL.md +142 -0
- package/docs/SETUP.md +219 -0
- package/docs/WORKSPACE.md +672 -0
- package/docs/agent-auth.md +63 -0
- package/docs/aura-file.md +48 -0
- package/docs/credentials.md +53 -0
- package/docs/external/getting-started.md +65 -0
- package/docs/external/overview.md +45 -0
- package/docs/external/use-cases.md +48 -0
- package/docs/external/why-aura.md +35 -0
- package/docs/jobs/connect-agent.md +77 -0
- package/docs/jobs/migrate-from-dotenv.md +79 -0
- package/docs/jobs/recover-from-lockout.md +72 -0
- package/docs/jobs/secure-ci.md +63 -0
- package/docs/oauth2.md +42 -0
- package/docs/passkeys.md +60 -0
- package/docs/security.md +540 -0
- package/docs/specs/aura-open-protocol.md +61 -0
- package/docs/specs/aura-provider-plugin.md +24 -0
- package/docs/specs/aura-registry-model.md +31 -0
- package/docs/specs/fixtures/invalid-bad-key.aura +1 -0
- package/docs/specs/fixtures/invalid-bad-unicode-escape.aura +1 -0
- package/docs/specs/fixtures/invalid-duplicate-key.aura +2 -0
- package/docs/specs/fixtures/valid-basic.aura +4 -0
- package/docs/specs/fixtures/valid-provider-ref.aura +1 -0
- package/docs/specs/fixtures/valid-quoted-escapes.aura +2 -0
- package/docs/templates/RELEASE_NOTES_TEMPLATE.md +22 -0
- package/docs/totp.md +40 -0
- package/docs/wallet/AI.md +508 -0
- package/docs/wallet/DEVELOPING-STRATEGIES.md +713 -0
- package/docs/wallet/README.md +47 -0
- package/docs/wallet/STRATEGY.md +89 -0
- package/next.config.ts +21 -0
- package/package.json +151 -0
- package/postcss.config.mjs +8 -0
- package/prisma/migrations/20260214170000_baseline/migration.sql +511 -0
- package/prisma/migrations/20260216214537_add_passkey_model/migration.sql +18 -0
- package/prisma/migrations/20260217150500_add_credential_access_audit/migration.sql +31 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +447 -0
- package/public/logo-chevron.svg +31 -0
- package/public/logo-concentric.svg +31 -0
- package/public/logo-crosshatch.svg +39 -0
- package/public/logo-dashed.svg +39 -0
- package/public/logo-horizontal.svg +31 -0
- package/public/logo-m56.svg +64 -0
- package/public/logo.webp +0 -0
- package/scripts/add-app.js +245 -0
- package/scripts/init.sh +57 -0
- package/scripts/migrate-apikeys-to-credentials.ts +35 -0
- package/scripts/sandbox-agent-flow.sh +235 -0
- package/scripts/sandbox.sh +175 -0
- package/scripts/validate-job-docs.mjs +125 -0
- package/server/abi/SwapHelper.json +438 -0
- package/server/cli/approval.ts +447 -0
- package/server/cli/commands/app.ts +204 -0
- package/server/cli/commands/cron.ts +24 -0
- package/server/cli/commands/doctor.ts +1007 -0
- package/server/cli/commands/env.ts +456 -0
- package/server/cli/commands/init.ts +752 -0
- package/server/cli/commands/mcp.ts +125 -0
- package/server/cli/commands/restore.ts +314 -0
- package/server/cli/commands/shell-hook.ts +468 -0
- package/server/cli/commands/start.ts +62 -0
- package/server/cli/commands/status.ts +59 -0
- package/server/cli/commands/stop.ts +14 -0
- package/server/cli/commands/token.ts +180 -0
- package/server/cli/commands/unlock.ts +49 -0
- package/server/cli/commands/vault.ts +417 -0
- package/server/cli/index.ts +328 -0
- package/server/cli/lib/aura-parser.ts +64 -0
- package/server/cli/lib/credential-create.ts +74 -0
- package/server/cli/lib/credential-resolve.ts +254 -0
- package/server/cli/lib/dotenv-migrate.ts +116 -0
- package/server/cli/lib/dotenv-parser.ts +146 -0
- package/server/cli/lib/http.ts +91 -0
- package/server/cli/lib/init-steps.ts +76 -0
- package/server/cli/lib/local-agent-trust.ts +45 -0
- package/server/cli/lib/process.ts +136 -0
- package/server/cli/lib/prompt.ts +85 -0
- package/server/cli/lib/theme.ts +240 -0
- package/server/cli/socket.ts +570 -0
- package/server/cli/transport-client.ts +50 -0
- package/server/cron/index.ts +137 -0
- package/server/cron/job.ts +31 -0
- package/server/cron/jobs/balance-sync.ts +436 -0
- package/server/cron/jobs/incoming-scan.ts +506 -0
- package/server/cron/jobs/native-price.ts +70 -0
- package/server/cron/jobs/orphan-cleanup.ts +40 -0
- package/server/cron/jobs/strategy-runner.ts +175 -0
- package/server/cron/scheduler.ts +125 -0
- package/server/index.ts +406 -0
- package/server/lib/adapters/factory.ts +110 -0
- package/server/lib/adapters/index.ts +19 -0
- package/server/lib/adapters/router.ts +297 -0
- package/server/lib/adapters/telegram.ts +645 -0
- package/server/lib/adapters/types.ts +89 -0
- package/server/lib/adapters/webhook.ts +95 -0
- package/server/lib/address.ts +49 -0
- package/server/lib/agent-auth/contracts.ts +1194 -0
- package/server/lib/agent-profiles.ts +328 -0
- package/server/lib/ai.ts +285 -0
- package/server/lib/api-registry/contracts.ts +86 -0
- package/server/lib/api-registry/validation.ts +172 -0
- package/server/lib/apikey-migration.ts +189 -0
- package/server/lib/app-installer.ts +505 -0
- package/server/lib/app-tokens.ts +247 -0
- package/server/lib/auth.ts +314 -0
- package/server/lib/batch.ts +242 -0
- package/server/lib/cold.ts +874 -0
- package/server/lib/config.ts +381 -0
- package/server/lib/credential-access-audit.ts +85 -0
- package/server/lib/credential-access-policy.ts +110 -0
- package/server/lib/credential-health.ts +343 -0
- package/server/lib/credential-import.ts +487 -0
- package/server/lib/credential-scope.ts +87 -0
- package/server/lib/credential-shares.ts +190 -0
- package/server/lib/credential-transport.ts +342 -0
- package/server/lib/credential-vault.ts +77 -0
- package/server/lib/credentials.ts +333 -0
- package/server/lib/crypto.ts +8 -0
- package/server/lib/db.ts +15 -0
- package/server/lib/defaults.ts +366 -0
- package/server/lib/dex/index.ts +80 -0
- package/server/lib/dex/relay.ts +235 -0
- package/server/lib/dex/types.ts +59 -0
- package/server/lib/dex/uniswap.ts +370 -0
- package/server/lib/e2e-agent/artifacts.ts +36 -0
- package/server/lib/e2e-agent/contracts.ts +112 -0
- package/server/lib/e2e-agent/validation.ts +135 -0
- package/server/lib/encrypt.ts +128 -0
- package/server/lib/error.ts +20 -0
- package/server/lib/events.ts +205 -0
- package/server/lib/hot.ts +357 -0
- package/server/lib/key-fingerprint.ts +28 -0
- package/server/lib/logger.ts +331 -0
- package/server/lib/network.ts +137 -0
- package/server/lib/notifications.ts +219 -0
- package/server/lib/oauth2-refresh.ts +241 -0
- package/server/lib/oursecret.ts +54 -0
- package/server/lib/passkey-credential.ts +360 -0
- package/server/lib/passkey.ts +68 -0
- package/server/lib/permissions.ts +248 -0
- package/server/lib/pino.ts +24 -0
- package/server/lib/policy-preview.ts +138 -0
- package/server/lib/price.ts +338 -0
- package/server/lib/prices.ts +34 -0
- package/server/lib/project-scope.ts +239 -0
- package/server/lib/resolve-action.ts +427 -0
- package/server/lib/resolve.ts +36 -0
- package/server/lib/sessions.ts +632 -0
- package/server/lib/solana/connection.ts +26 -0
- package/server/lib/solana/jupiter.ts +128 -0
- package/server/lib/solana/transfer.ts +108 -0
- package/server/lib/solana/wallet.ts +136 -0
- package/server/lib/strategy/emits.ts +21 -0
- package/server/lib/strategy/engine.ts +1305 -0
- package/server/lib/strategy/executor.ts +115 -0
- package/server/lib/strategy/hook-context.ts +158 -0
- package/server/lib/strategy/hooks.ts +990 -0
- package/server/lib/strategy/index.ts +28 -0
- package/server/lib/strategy/installer.ts +305 -0
- package/server/lib/strategy/loader.ts +256 -0
- package/server/lib/strategy/message.ts +235 -0
- package/server/lib/strategy/repository.ts +218 -0
- package/server/lib/strategy/session-logger.ts +693 -0
- package/server/lib/strategy/sources.ts +288 -0
- package/server/lib/strategy/state.ts +189 -0
- package/server/lib/strategy/templates.ts +403 -0
- package/server/lib/strategy/tick.ts +404 -0
- package/server/lib/strategy/types.ts +230 -0
- package/server/lib/swap.ts +3 -0
- package/server/lib/temp.ts +86 -0
- package/server/lib/token-metadata.ts +86 -0
- package/server/lib/token-safety.ts +200 -0
- package/server/lib/token-search.ts +444 -0
- package/server/lib/totp.ts +194 -0
- package/server/lib/transactions.ts +123 -0
- package/server/lib/transport.ts +75 -0
- package/server/lib/txhistory/decoder.ts +262 -0
- package/server/lib/txhistory/enricher.ts +652 -0
- package/server/lib/txhistory/index.ts +391 -0
- package/server/lib/txhistory/signatures.ts +59 -0
- package/server/lib/verified-summary.ts +421 -0
- package/server/mcp/profile-policy.ts +30 -0
- package/server/mcp/server.ts +619 -0
- package/server/mcp/tools.ts +523 -0
- package/server/middleware/auth.ts +119 -0
- package/server/middleware/requestLogger.ts +84 -0
- package/server/routes/actions.ts +459 -0
- package/server/routes/adapters.ts +703 -0
- package/server/routes/addressbook.ts +113 -0
- package/server/routes/ai.ts +34 -0
- package/server/routes/apikeys.ts +295 -0
- package/server/routes/apps.ts +601 -0
- package/server/routes/auth.ts +457 -0
- package/server/routes/backup.ts +340 -0
- package/server/routes/batch.ts +270 -0
- package/server/routes/bookmarks.ts +162 -0
- package/server/routes/credential-shares.ts +198 -0
- package/server/routes/credential-vaults.ts +154 -0
- package/server/routes/credentials.ts +1290 -0
- package/server/routes/dashboard.ts +71 -0
- package/server/routes/defaults.ts +124 -0
- package/server/routes/fund.ts +229 -0
- package/server/routes/import.ts +352 -0
- package/server/routes/launch.ts +665 -0
- package/server/routes/lock.ts +54 -0
- package/server/routes/logs.ts +68 -0
- package/server/routes/nuke.ts +111 -0
- package/server/routes/passkey-credentials.ts +99 -0
- package/server/routes/passkey.ts +346 -0
- package/server/routes/portfolio.ts +217 -0
- package/server/routes/price.ts +63 -0
- package/server/routes/resolve.ts +31 -0
- package/server/routes/security.ts +45 -0
- package/server/routes/send-evm.ts +241 -0
- package/server/routes/send-solana.ts +281 -0
- package/server/routes/send.ts +178 -0
- package/server/routes/setup.ts +210 -0
- package/server/routes/strategy.ts +894 -0
- package/server/routes/swap-evm.ts +353 -0
- package/server/routes/swap-solana.ts +177 -0
- package/server/routes/swap.ts +356 -0
- package/server/routes/token.ts +247 -0
- package/server/routes/unlock.ts +403 -0
- package/server/routes/wallet-assets.ts +361 -0
- package/server/routes/wallet-transactions.ts +515 -0
- package/server/routes/wallet.ts +710 -0
- package/server/types.ts +146 -0
- package/skills/aurawallet/SKILL.md +739 -0
- package/skills/aurawallet-setup/SKILL.md +74 -0
- package/skills/security-review/SKILL.md +148 -0
- package/src/app/api/agent-requests/route.ts +30 -0
- package/src/app/api/apps/install/route.ts +126 -0
- package/src/app/api/apps/manifests/route.ts +16 -0
- package/src/app/api/apps/static/[...path]/route.ts +57 -0
- package/src/app/api/events/route.ts +92 -0
- package/src/app/api/page.tsx +212 -0
- package/src/app/api/workspace/[id]/apps/[wid]/route.ts +119 -0
- package/src/app/api/workspace/[id]/apps/route.ts +81 -0
- package/src/app/api/workspace/[id]/export/route.ts +67 -0
- package/src/app/api/workspace/[id]/route.ts +168 -0
- package/src/app/api/workspace/auth.ts +34 -0
- package/src/app/api/workspace/config/route.ts +106 -0
- package/src/app/api/workspace/import/route.ts +127 -0
- package/src/app/api/workspace/route.ts +116 -0
- package/src/app/app/page.tsx +2122 -0
- package/src/app/apple-icon.png +0 -0
- package/src/app/docs/page.tsx +178 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +572 -0
- package/src/app/health/page.tsx +5 -0
- package/src/app/hello/page.tsx +15 -0
- package/src/app/icon.png +0 -0
- package/src/app/layout.tsx +34 -0
- package/src/app/page.tsx +986 -0
- package/src/app/providers.tsx +90 -0
- package/src/app/share/[token]/page.tsx +295 -0
- package/src/components/ChainSelector.tsx +144 -0
- package/src/components/HumanActionBar.tsx +695 -0
- package/src/components/NotificationDrawer.tsx +129 -0
- package/src/components/apps/AgentKeysApp.tsx +490 -0
- package/src/components/apps/App.tsx +153 -0
- package/src/components/apps/AppGrid.tsx +15 -0
- package/src/components/apps/DetailedAddressDrawer.tsx +325 -0
- package/src/components/apps/DraggableApp.tsx +562 -0
- package/src/components/apps/IFrameApp.tsx +73 -0
- package/src/components/apps/LogsApp.tsx +360 -0
- package/src/components/apps/SendApp.tsx +394 -0
- package/src/components/apps/SetupWizardApp.tsx +1004 -0
- package/src/components/apps/SystemDefaultsApp.tsx +845 -0
- package/src/components/apps/ThirdPartyApp.tsx +428 -0
- package/src/components/apps/TokenApp.tsx +319 -0
- package/src/components/apps/TransactionsApp.tsx +438 -0
- package/src/components/apps/WalletDetailApp.tsx +1505 -0
- package/src/components/apps/index.ts +13 -0
- package/src/components/design-system/Button.tsx +53 -0
- package/src/components/design-system/ChainIndicator.tsx +65 -0
- package/src/components/design-system/ChainSelector.tsx +137 -0
- package/src/components/design-system/ConfirmationModal.tsx +106 -0
- package/src/components/design-system/ConfirmationPopover.tsx +81 -0
- package/src/components/design-system/Drawer.tsx +123 -0
- package/src/components/design-system/FilterDropdown.tsx +72 -0
- package/src/components/design-system/Modal.tsx +206 -0
- package/src/components/design-system/Popover.tsx +142 -0
- package/src/components/design-system/TextInput.tsx +85 -0
- package/src/components/design-system/Toggle.tsx +58 -0
- package/src/components/design-system/index.ts +11 -0
- package/src/components/docs/DocsThemeToggle.tsx +49 -0
- package/src/components/health/CredentialHealthDashboard.tsx +214 -0
- package/src/components/icons/ChainIcons.tsx +72 -0
- package/src/components/layout/AppStoreDrawer.tsx +369 -0
- package/src/components/layout/ContentArea.tsx +21 -0
- package/src/components/layout/TabBar.tsx +278 -0
- package/src/components/layout/WalletSidebar.tsx +1033 -0
- package/src/components/layout/index.ts +4 -0
- package/src/components/marketing/AuraWalletSpecOverlay.tsx +635 -0
- package/src/components/marketing/DeviceMorphExperience.tsx +216 -0
- package/src/components/vault/ApiKeysConsole.tsx +1080 -0
- package/src/components/vault/AuditConsole.tsx +584 -0
- package/src/components/vault/CredentialDetail.tsx +455 -0
- package/src/components/vault/CredentialEmpty.tsx +55 -0
- package/src/components/vault/CredentialField.tsx +361 -0
- package/src/components/vault/CredentialForm.tsx +1212 -0
- package/src/components/vault/CredentialList.tsx +165 -0
- package/src/components/vault/CredentialRow.tsx +97 -0
- package/src/components/vault/CredentialShareModal.tsx +178 -0
- package/src/components/vault/CredentialVault.tsx +754 -0
- package/src/components/vault/CredentialWalletWidget.tsx +103 -0
- package/src/components/vault/ImportCredentialsModal.tsx +515 -0
- package/src/components/vault/LargeTypeModal.tsx +64 -0
- package/src/components/vault/PasswordGenerator.tsx +224 -0
- package/src/components/vault/TOTPDisplay.tsx +123 -0
- package/src/components/vault/VaultSidebar.tsx +413 -0
- package/src/components/vault/types.ts +54 -0
- package/src/context/AuthContext.tsx +337 -0
- package/src/context/PriceContext.tsx +113 -0
- package/src/context/ThemeContext.tsx +164 -0
- package/src/context/WebSocketContext.tsx +269 -0
- package/src/context/WorkspaceContext.tsx +668 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useAgentActions.ts +368 -0
- package/src/hooks/useBalance.ts +103 -0
- package/src/hooks/useBalances.ts +129 -0
- package/src/instrumentation.ts +12 -0
- package/src/lib/api.ts +449 -0
- package/src/lib/app-loader.ts +148 -0
- package/src/lib/app-registry.ts +178 -0
- package/src/lib/app-sdk.ts +157 -0
- package/src/lib/audit-console-adapter.ts +151 -0
- package/src/lib/auth-client.ts +75 -0
- package/src/lib/config.ts +74 -0
- package/src/lib/crypto.ts +112 -0
- package/src/lib/db.ts +21 -0
- package/src/lib/docs.ts +390 -0
- package/src/lib/events.ts +361 -0
- package/src/lib/pino.ts +24 -0
- package/src/lib/theme-handlers.ts +168 -0
- package/src/lib/theme.ts +351 -0
- package/src/lib/tokenData.ts +378 -0
- package/src/lib/vault-crypto.ts +129 -0
- package/src/lib/websocket-server.ts +302 -0
- package/src/lib/websocket-setup.ts +79 -0
- package/src/lib/wordlist.ts +2050 -0
- package/src/lib/workspace-handlers.ts +285 -0
- package/start.sh +80 -0
- package/tailwind.config.ts +99 -0
- package/tsconfig.json +42 -0
package/docs/ADAPTERS.md
ADDED
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
# Approval Adapters
|
|
2
|
+
|
|
3
|
+
External approval channels for agent actions. Adapters forward `action:created` events to external services (Telegram, Discord, webhooks, etc.) and relay human decisions back to `POST /actions/:id/resolve`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## How It Works
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Agent requests token
|
|
11
|
+
│
|
|
12
|
+
▼
|
|
13
|
+
POST /actions/:id/resolve ◄─── Dashboard UI
|
|
14
|
+
▲ ◄─── CLI terminal
|
|
15
|
+
│ ◄─── Adapter (Telegram, webhook, etc.)
|
|
16
|
+
│
|
|
17
|
+
All channels converge on the same endpoint
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Adapters don't change the resolve endpoint or any existing code paths. They simply:
|
|
21
|
+
1. Receive the `action:created` WebSocket event
|
|
22
|
+
2. Present it to a human in some external medium
|
|
23
|
+
3. POST back to resolve when the human responds
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Configuration
|
|
28
|
+
|
|
29
|
+
Adapter config is stored in the database, not in config files. This keeps secrets out of plain-text JSON and aligns with how API keys (Alchemy, etc.) are already managed.
|
|
30
|
+
|
|
31
|
+
**Two pieces:**
|
|
32
|
+
- **Secrets** (bot tokens, HMAC keys) → `POST /apikeys` with `service: "adapter:<type>"`
|
|
33
|
+
- **Settings** (enabled flags, non-secret config) → `POST /adapters`
|
|
34
|
+
|
|
35
|
+
### 1. Store secrets via `/apikeys`
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Telegram bot token
|
|
39
|
+
curl -X POST http://localhost:4242/apikeys \
|
|
40
|
+
-H "Authorization: Bearer <admin-token>" \
|
|
41
|
+
-H "Content-Type: application/json" \
|
|
42
|
+
-d '{"service": "adapter:telegram", "name": "botToken", "key": "123456:ABC-DEF..."}'
|
|
43
|
+
|
|
44
|
+
# Webhook HMAC secret
|
|
45
|
+
curl -X POST http://localhost:4242/apikeys \
|
|
46
|
+
-H "Authorization: Bearer <admin-token>" \
|
|
47
|
+
-H "Content-Type: application/json" \
|
|
48
|
+
-d '{"service": "adapter:webhook", "name": "secret", "key": "my-hmac-secret"}'
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 2. Configure adapter settings via `/adapters`
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Enable Telegram adapter (chatId is non-secret, stored in AppConfig)
|
|
55
|
+
curl -X POST http://localhost:4242/adapters \
|
|
56
|
+
-H "Authorization: Bearer <admin-token>" \
|
|
57
|
+
-H "Content-Type: application/json" \
|
|
58
|
+
-d '{"type": "telegram", "enabled": true, "config": {"chatId": "987654321"}}'
|
|
59
|
+
|
|
60
|
+
# Enable webhook adapter
|
|
61
|
+
curl -X POST http://localhost:4242/adapters \
|
|
62
|
+
-H "Authorization: Bearer <admin-token>" \
|
|
63
|
+
-H "Content-Type: application/json" \
|
|
64
|
+
-d '{"type": "webhook", "enabled": true, "config": {"url": "https://hooks.slack.com/services/T.../B.../xxx"}}'
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 3. Restart the adapter router
|
|
68
|
+
|
|
69
|
+
After changing config, restart to pick up changes:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
curl -X POST http://localhost:4242/adapters/restart \
|
|
73
|
+
-H "Authorization: Bearer <admin-token>"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Adapter Management Endpoints
|
|
77
|
+
|
|
78
|
+
| Method | Route | Description |
|
|
79
|
+
|--------|-------|-------------|
|
|
80
|
+
| `GET` | `/adapters` | List configured adapters (with secret status) |
|
|
81
|
+
| `POST` | `/adapters` | Add/update adapter config `{ type, enabled, config, chat? }` |
|
|
82
|
+
| `POST` | `/adapters/chat` | Set top-level chat config (defaultApp) |
|
|
83
|
+
| `POST` | `/adapters/:type/message` | Inbound chat from adapter webhook (HMAC auth) |
|
|
84
|
+
| `DELETE` | `/adapters/:type` | Remove adapter config |
|
|
85
|
+
| `POST` | `/adapters/restart` | Restart approval router with current DB config |
|
|
86
|
+
|
|
87
|
+
All adapter endpoints require `adapter:manage` permission (or `admin:*` which includes it).
|
|
88
|
+
|
|
89
|
+
Adapters are opt-in. If no adapters are configured, the approval router doesn't start.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Built-in Adapters
|
|
94
|
+
|
|
95
|
+
### Webhook (notification-only)
|
|
96
|
+
|
|
97
|
+
POSTs action events to a URL. Useful for Slack/Discord incoming webhooks, ntfy, or any HTTP endpoint.
|
|
98
|
+
|
|
99
|
+
**Config (`POST /adapters`):**
|
|
100
|
+
|
|
101
|
+
| Field | Type | Storage | Description |
|
|
102
|
+
|-------|------|---------|-------------|
|
|
103
|
+
| `url` | string | `POST /adapters` config | URL to POST to |
|
|
104
|
+
| `secret` | string | `POST /apikeys` | HMAC-SHA256 secret for `X-Signature-256` header |
|
|
105
|
+
| `headers` | object | `POST /adapters` config | Custom headers to include |
|
|
106
|
+
|
|
107
|
+
**Setup:**
|
|
108
|
+
```bash
|
|
109
|
+
# 1. Store HMAC secret (optional)
|
|
110
|
+
curl -X POST http://localhost:4242/apikeys \
|
|
111
|
+
-H "Authorization: Bearer <admin-token>" \
|
|
112
|
+
-H "Content-Type: application/json" \
|
|
113
|
+
-d '{"service": "adapter:webhook", "name": "secret", "key": "my-hmac-secret"}'
|
|
114
|
+
|
|
115
|
+
# 2. Configure webhook URL and custom headers
|
|
116
|
+
curl -X POST http://localhost:4242/adapters \
|
|
117
|
+
-H "Authorization: Bearer <admin-token>" \
|
|
118
|
+
-H "Content-Type: application/json" \
|
|
119
|
+
-d '{"type": "webhook", "enabled": true, "config": {"url": "https://hooks.slack.com/services/...", "headers": {"X-Custom": "value"}}}'
|
|
120
|
+
|
|
121
|
+
# 3. Restart
|
|
122
|
+
curl -X POST http://localhost:4242/adapters/restart \
|
|
123
|
+
-H "Authorization: Bearer <admin-token>"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Payload format:**
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"type": "action:created",
|
|
131
|
+
"data": {
|
|
132
|
+
"id": "abc-123",
|
|
133
|
+
"type": "action",
|
|
134
|
+
"source": "agent:my-agent",
|
|
135
|
+
"summary": "Swap 0.01 ETH for USDC",
|
|
136
|
+
"expiresAt": null,
|
|
137
|
+
"metadata": {
|
|
138
|
+
"agentId": "my-agent",
|
|
139
|
+
"permissions": ["swap"],
|
|
140
|
+
"verifiedSummary": {
|
|
141
|
+
"action": "/swap",
|
|
142
|
+
"oneLiner": "Buy 0xABC...DEF with 0.01 ETH on base",
|
|
143
|
+
"facts": [{ "label": "Amount", "value": "0.01 ETH" }],
|
|
144
|
+
"discrepancies": [],
|
|
145
|
+
"verified": true,
|
|
146
|
+
"generatedAt": "2026-02-11T..."
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"timestamp": 1738599000000
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**HMAC verification (if secret configured):**
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
const crypto = require('crypto');
|
|
158
|
+
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
|
|
159
|
+
const valid = req.headers['x-signature-256'] === `sha256=${expected}`;
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The webhook adapter is notification-only — it doesn't handle responses. To approve/reject from a webhook target, have your service POST directly to `/actions/:id/resolve` with an admin token, or build a bidirectional adapter.
|
|
163
|
+
|
|
164
|
+
### Telegram (bidirectional)
|
|
165
|
+
|
|
166
|
+
Full approval flow via Telegram Bot API. Sends inline keyboard buttons, handles callbacks.
|
|
167
|
+
|
|
168
|
+
**Config:**
|
|
169
|
+
|
|
170
|
+
| Field | Type | Storage | Description |
|
|
171
|
+
|-------|------|---------|-------------|
|
|
172
|
+
| `botToken` | string | `POST /apikeys` | Bot API token from @BotFather |
|
|
173
|
+
| `chatId` | string/number | `POST /adapters` config | Chat ID for notifications and callbacks |
|
|
174
|
+
|
|
175
|
+
**Setup:**
|
|
176
|
+
1. Create a bot via [@BotFather](https://t.me/BotFather)
|
|
177
|
+
2. Get your chat ID (message the bot, check `getUpdates`)
|
|
178
|
+
3. Store the bot token as an API key and configure the adapter:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Store bot token
|
|
182
|
+
curl -X POST http://localhost:4242/apikeys \
|
|
183
|
+
-H "Authorization: Bearer <admin-token>" \
|
|
184
|
+
-H "Content-Type: application/json" \
|
|
185
|
+
-d '{"service": "adapter:telegram", "name": "botToken", "key": "123456:ABC-DEF..."}'
|
|
186
|
+
|
|
187
|
+
# Configure adapter
|
|
188
|
+
curl -X POST http://localhost:4242/adapters \
|
|
189
|
+
-H "Authorization: Bearer <admin-token>" \
|
|
190
|
+
-H "Content-Type: application/json" \
|
|
191
|
+
-d '{"type": "telegram", "enabled": true, "config": {"chatId": "987654321"}}'
|
|
192
|
+
|
|
193
|
+
# Restart to apply
|
|
194
|
+
curl -X POST http://localhost:4242/adapters/restart \
|
|
195
|
+
-H "Authorization: Bearer <admin-token>"
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**How it works:**
|
|
199
|
+
- `action:created` → sends message with Approve/Reject inline keyboard
|
|
200
|
+
- `action:created` with `type: 'notify'` → sends plain info message (no buttons, no resolution)
|
|
201
|
+
- Human taps Approve/Reject → adapter calls `POST /actions/:id/resolve`
|
|
202
|
+
- `action:resolved` → edits original message to show result, removes keyboard
|
|
203
|
+
- Only responds to callbacks from the configured `chatId` (security)
|
|
204
|
+
- When a `verifiedSummary` is present, the Telegram message shows the server-generated one-liner as primary action text and displays discrepancy warnings with severity icons
|
|
205
|
+
|
|
206
|
+
**Notification metadata:** When `type: 'notify'`, the Telegram adapter renders known metadata fields if present: `contractAddress` (DexScreener link), `symbol`, `marketCap`, `risk`, `socialLinks` (clickable links), and `evaluation` (full AI analysis text).
|
|
207
|
+
|
|
208
|
+
**No npm dependencies** — uses raw `fetch` calls to `api.telegram.org` and long-polling via `getUpdates`.
|
|
209
|
+
|
|
210
|
+
#### Agent Chat
|
|
211
|
+
|
|
212
|
+
The Telegram adapter supports opt-in agent chat — send text messages in Telegram and your AI agent replies.
|
|
213
|
+
|
|
214
|
+
**Enable chat:**
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
curl -X POST http://localhost:4242/adapters \
|
|
218
|
+
-H "Authorization: Bearer <admin-token>" \
|
|
219
|
+
-H "Content-Type: application/json" \
|
|
220
|
+
-d '{"type": "telegram", "enabled": true, "config": {"chatId": "987654321"}, "chat": {"enabled": true}}'
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Set default app** (which app's AI handles messages):
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
curl -X POST http://localhost:4242/adapters/chat \
|
|
227
|
+
-H "Authorization: Bearer <admin-token>" \
|
|
228
|
+
-H "Content-Type: application/json" \
|
|
229
|
+
-d '{"defaultApp": "swap-chat"}'
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**How it works:**
|
|
233
|
+
- Human sends text in Telegram → adapter routes to app's `message` hook
|
|
234
|
+
- AI processes with full tool-use (wallet_api, request_human_action)
|
|
235
|
+
- Reply sent back as Telegram message
|
|
236
|
+
- Long replies (>4096 chars) are split into multiple messages
|
|
237
|
+
- Same rate limiting as dashboard chat (10 messages / 60 seconds per app)
|
|
238
|
+
- Chat is **off by default** — must be explicitly enabled with `chat: { enabled: true }`
|
|
239
|
+
- Approval callbacks (Approve/Reject buttons) continue to work alongside chat
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Agent Chat
|
|
244
|
+
|
|
245
|
+
Adapters can route text messages to app AI agents via the strategy engine's `handleAppMessage()`. This reuses existing message hooks, tool-use, rate limiting, and conversation memory — no new AI infrastructure.
|
|
246
|
+
|
|
247
|
+
### How It Works
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
Human sends text via adapter
|
|
251
|
+
│
|
|
252
|
+
▼
|
|
253
|
+
AdapterContext.resolveApp() → find target app
|
|
254
|
+
│
|
|
255
|
+
▼
|
|
256
|
+
AdapterContext.sendMessage() → handleAppMessage()
|
|
257
|
+
│ │
|
|
258
|
+
│ processMessage()
|
|
259
|
+
│ │
|
|
260
|
+
│ AI hook + tool-use
|
|
261
|
+
│ │
|
|
262
|
+
▼ ▼
|
|
263
|
+
Adapter sends reply { reply, error }
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Configuration
|
|
267
|
+
|
|
268
|
+
Chat config is stored in `AppConfig.adapterConfig`:
|
|
269
|
+
|
|
270
|
+
```json
|
|
271
|
+
{
|
|
272
|
+
"enabled": true,
|
|
273
|
+
"chat": {
|
|
274
|
+
"defaultApp": "swap-chat"
|
|
275
|
+
},
|
|
276
|
+
"adapters": [
|
|
277
|
+
{
|
|
278
|
+
"type": "telegram",
|
|
279
|
+
"enabled": true,
|
|
280
|
+
"config": { "chatId": "123456789" },
|
|
281
|
+
"chat": { "enabled": true }
|
|
282
|
+
}
|
|
283
|
+
]
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**Two levels of config:**
|
|
288
|
+
- **Top-level `chat.defaultApp`**: Which app receives messages (system-wide)
|
|
289
|
+
- **Per-adapter `chat.enabled`**: Whether that adapter accepts chat messages (default: false)
|
|
290
|
+
|
|
291
|
+
### Webhook Chat Endpoint
|
|
292
|
+
|
|
293
|
+
For adapters that use HTTP callbacks (webhooks, Slack, Discord):
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
POST /adapters/:type/message
|
|
297
|
+
Content-Type: application/json
|
|
298
|
+
X-Signature-256: sha256=<hmac>
|
|
299
|
+
|
|
300
|
+
{
|
|
301
|
+
"text": "What is my balance?",
|
|
302
|
+
"senderId": "user-123",
|
|
303
|
+
"targetApp": "swap-chat"
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Response:**
|
|
308
|
+
```json
|
|
309
|
+
{
|
|
310
|
+
"success": true,
|
|
311
|
+
"reply": "You have 1.5 ETH in your hot wallet.",
|
|
312
|
+
"error": null
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**Authentication:** HMAC-SHA256 signature required if the adapter has a secret configured (same `X-Signature-256` header pattern as webhook notifications).
|
|
317
|
+
|
|
318
|
+
### Security
|
|
319
|
+
|
|
320
|
+
- **Same auth model**: Chat messages use the app's existing token + permissions
|
|
321
|
+
- **Rate limiting**: Existing 10 msg/60s per app applies to adapter messages
|
|
322
|
+
- **Sender validation**: Telegram validates chatId; webhooks validate HMAC
|
|
323
|
+
- **App scoping**: The app's token determines what the AI can do
|
|
324
|
+
- **No new attack surface**: Messages flow through the same `handleAppMessage()` as dashboard chat
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Security Model
|
|
329
|
+
|
|
330
|
+
### Secrets in Database, Not Config Files
|
|
331
|
+
|
|
332
|
+
Adapter secrets (bot tokens, HMAC keys) are stored in the `ApiKey` database table with `service: "adapter:<type>"`. This is the same pattern used for Alchemy API keys and other service credentials. Non-secret settings (enabled flags, chat IDs, URLs) are stored in the `AppConfig.adapterConfig` JSON field.
|
|
333
|
+
|
|
334
|
+
### Direct In-Process Calls
|
|
335
|
+
|
|
336
|
+
The adapter router is an in-process trusted component that calls `resolveAction()` and `handleAppMessage()` directly — no admin tokens, no HTTP round-trips. This eliminates token management overhead and retry logic.
|
|
337
|
+
|
|
338
|
+
**Key properties:**
|
|
339
|
+
- `resolve()` calls `resolveAction()` from `server/lib/resolve-action.ts` directly
|
|
340
|
+
- `sendMessage()` calls `handleAppMessage()` / `enqueueAppMessage()` from the strategy engine directly
|
|
341
|
+
- `fetchPendingActions()` queries prisma directly (same query as `GET /actions/pending`)
|
|
342
|
+
- If the wallet is locked when resolving an `auth`/`agent_access` action, `resolveAction()` returns a 401-equivalent error
|
|
343
|
+
|
|
344
|
+
### Adapter Isolation
|
|
345
|
+
|
|
346
|
+
- Each adapter runs independently — one failing adapter doesn't affect others
|
|
347
|
+
- Adapter errors are caught and logged per-adapter
|
|
348
|
+
- The router catches all adapter exceptions in `notify()` and `resolved()` calls
|
|
349
|
+
|
|
350
|
+
### Webhook Security
|
|
351
|
+
|
|
352
|
+
- HMAC-SHA256 signatures (optional but recommended) verify payload authenticity
|
|
353
|
+
- Custom headers can be used for additional authentication
|
|
354
|
+
- Webhook URLs should use HTTPS
|
|
355
|
+
|
|
356
|
+
### Telegram Security
|
|
357
|
+
|
|
358
|
+
- Only callbacks from the configured `chatId` are processed
|
|
359
|
+
- The bot token should be kept secret (treat it like a password)
|
|
360
|
+
- Long-polling means no publicly accessible webhook endpoint is needed
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## Building Custom Adapters
|
|
365
|
+
|
|
366
|
+
Implement the `ApprovalAdapter` interface:
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
import type { ApprovalAdapter, AdapterContext, ActionNotification, ActionResolution } from './types';
|
|
370
|
+
|
|
371
|
+
class MyAdapter implements ApprovalAdapter {
|
|
372
|
+
readonly name = 'my-adapter';
|
|
373
|
+
|
|
374
|
+
async start(ctx: AdapterContext): Promise<void> {
|
|
375
|
+
// ctx.resolve(actionId, approved, opts?) — call this to resolve actions
|
|
376
|
+
// ctx.serverUrl — base URL of the wallet server
|
|
377
|
+
// ctx.sendMessage(appId, text) — route chat messages to app AI
|
|
378
|
+
// ctx.resolveApp(target?) — resolve which app handles chat
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
async notify(action: ActionNotification): Promise<void> {
|
|
382
|
+
// Present action to human: action.id, action.type, action.summary, etc.
|
|
383
|
+
// action.verifiedSummary contains server-generated facts and discrepancy warnings
|
|
384
|
+
// action.metadata?.verifiedSummary is also available (from WebSocket events)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
async resolved(resolution: ActionResolution): Promise<void> {
|
|
388
|
+
// Clean up UI: resolution.id, resolution.approved, resolution.resolvedBy
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
async stop(): Promise<void> {
|
|
392
|
+
// Clean up resources
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Register it before server start:
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
import { registerAdapterType } from './server/lib/adapters';
|
|
401
|
+
|
|
402
|
+
registerAdapterType('my-adapter', (config) => new MyAdapter(config));
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
Then configure via API:
|
|
406
|
+
|
|
407
|
+
```bash
|
|
408
|
+
# Store any secrets
|
|
409
|
+
curl -X POST http://localhost:4242/apikeys \
|
|
410
|
+
-H "Authorization: Bearer <admin-token>" \
|
|
411
|
+
-H "Content-Type: application/json" \
|
|
412
|
+
-d '{"service": "adapter:my-adapter", "name": "apiKey", "key": "secret-value"}'
|
|
413
|
+
|
|
414
|
+
# Configure adapter
|
|
415
|
+
curl -X POST http://localhost:4242/adapters \
|
|
416
|
+
-H "Authorization: Bearer <admin-token>" \
|
|
417
|
+
-H "Content-Type: application/json" \
|
|
418
|
+
-d '{"type": "my-adapter", "enabled": true, "config": {"myOption": "value"}}'
|
|
419
|
+
|
|
420
|
+
# Restart
|
|
421
|
+
curl -X POST http://localhost:4242/adapters/restart \
|
|
422
|
+
-H "Authorization: Bearer <admin-token>"
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
## Architecture
|
|
428
|
+
|
|
429
|
+
```
|
|
430
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
431
|
+
│ ApprovalRouter │
|
|
432
|
+
│ ┌─────────┐ ┌─────────────┐ ┌──────────────────────────┐ │
|
|
433
|
+
│ │WebSocket │ │ Admin Token │ │ Adapters │ │
|
|
434
|
+
│ │Listener │──│ (lazy-init) │ │ ├── WebhookAdapter │ │
|
|
435
|
+
│ │ │ │ │ │ ├── TelegramAdapter │ │
|
|
436
|
+
│ └────┬─────┘ └──────┬──────┘ │ └── CustomAdapter... │ │
|
|
437
|
+
│ │ │ └──────────────────────────┘ │
|
|
438
|
+
│ │ │ │
|
|
439
|
+
│ action:created ──────┼──► adapter.notify() │
|
|
440
|
+
│ action:resolved ─────┼──► adapter.resolved() │
|
|
441
|
+
│ action:executed ─────┼──► (app-scoped, not adapter) │
|
|
442
|
+
│ │ │
|
|
443
|
+
│ adapter calls ───────┤──► POST /actions/:id/resolve │
|
|
444
|
+
│ │ │
|
|
445
|
+
│ chat message ────────┼──► sendMessage() → engine │
|
|
446
|
+
│ resolveApp() ─────┼──► DB lookup (cached) │
|
|
447
|
+
└──────────────────────────────────────────────────────────────┘
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
**Storage:**
|
|
451
|
+
|
|
452
|
+
| Data | Storage | Key |
|
|
453
|
+
|------|---------|-----|
|
|
454
|
+
| Secrets (bot tokens, HMAC keys) | `ApiKey` table | `service: "adapter:<type>"` |
|
|
455
|
+
| Settings (enabled, chatId, URL) | `AppConfig.adapterConfig` | JSON field |
|
|
456
|
+
|
|
457
|
+
**Files:**
|
|
458
|
+
|
|
459
|
+
| File | Description |
|
|
460
|
+
|------|-------------|
|
|
461
|
+
| `server/lib/adapters/types.ts` | Core interfaces |
|
|
462
|
+
| `server/lib/adapters/router.ts` | WebSocket listener + resolve proxy |
|
|
463
|
+
| `server/lib/adapters/webhook.ts` | Webhook adapter |
|
|
464
|
+
| `server/lib/adapters/telegram.ts` | Telegram adapter |
|
|
465
|
+
| `server/lib/adapters/factory.ts` | Registry + factory + `loadAdaptersFromDb` |
|
|
466
|
+
| `server/lib/adapters/index.ts` | Public exports |
|
|
467
|
+
| `server/routes/adapters.ts` | Admin REST endpoints |
|