auramaxx 0.0.1
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 +77 -0
- package/apps/desktop-electron/main.js +428 -0
- package/bin/auramaxx.js +1063 -0
- package/docs/ADAPTERS.md +466 -0
- package/docs/AGENT_SETUP.md +159 -0
- package/docs/API.md +127 -0
- package/docs/APPS.md +199 -0
- package/docs/ARCHITECTURE.md +235 -0
- package/docs/AUTH.md +318 -0
- package/docs/BEST-PRACTICES.md +82 -0
- package/docs/CLI.md +141 -0
- package/docs/DESKTOP_ELECTRON.md +26 -0
- package/docs/DEVELOPING-APPS.md +453 -0
- package/docs/MCP.md +122 -0
- package/docs/PACKAGING_POLICY.md +19 -0
- package/docs/PERMISSION.md +137 -0
- package/docs/PROTOCOL.md +142 -0
- package/docs/README.md +50 -0
- package/docs/SKILLS.md +132 -0
- package/docs/TROUBLESHOOTING.md +376 -0
- package/docs/WORKSPACE.md +673 -0
- package/docs/agent-auth.md +14 -0
- package/docs/api/authentication.md +79 -0
- package/docs/api/secrets/api-keys.md +28 -0
- package/docs/api/secrets/credentials.md +80 -0
- package/docs/api/secrets/sharing.md +48 -0
- package/docs/api/system.md +41 -0
- package/docs/api/wallets/apps-strategies.md +66 -0
- package/docs/api/wallets/core.md +46 -0
- package/docs/api/wallets/data-portfolio.md +42 -0
- package/docs/aura-file.md +48 -0
- package/docs/core-concepts/FEATURES.md +114 -0
- package/docs/credentials.md +120 -0
- package/docs/external/HOW_TO_AURAMAXX/GETTING_SECRETS.md +33 -0
- package/docs/external/HOW_TO_AURAMAXX/README.md +45 -0
- package/docs/external/getting-started.md +10 -0
- package/docs/external/overview.md +19 -0
- package/docs/external/persona-paths.md +7 -0
- package/docs/external/share-secret.md +76 -0
- package/docs/external/why-aura.md +7 -0
- package/docs/security.md +227 -0
- package/docs/templates/RELEASE_NOTES_TEMPLATE.md +22 -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 +28 -0
- package/package.json +167 -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/20260222090000_update_admin_ttl_default/migration.sql +10 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +447 -0
- package/public/logo.webp +0 -0
- package/scripts/add-app.js +245 -0
- package/server/abi/SwapHelper.json +438 -0
- package/server/cli/approval.ts +447 -0
- package/server/cli/commands/actions.ts +474 -0
- package/server/cli/commands/api.ts +220 -0
- package/server/cli/commands/apikey.ts +277 -0
- package/server/cli/commands/app.ts +204 -0
- package/server/cli/commands/auth.ts +464 -0
- package/server/cli/commands/cron.ts +24 -0
- package/server/cli/commands/diary.ts +274 -0
- package/server/cli/commands/doctor.ts +1247 -0
- package/server/cli/commands/env.ts +476 -0
- package/server/cli/commands/experimental.ts +69 -0
- package/server/cli/commands/init.ts +798 -0
- package/server/cli/commands/lock.ts +157 -0
- package/server/cli/commands/mcp.ts +285 -0
- package/server/cli/commands/quickhack.ts +86 -0
- package/server/cli/commands/release-check.ts +231 -0
- package/server/cli/commands/restore.ts +314 -0
- package/server/cli/commands/service.ts +320 -0
- package/server/cli/commands/shell-hook.ts +512 -0
- package/server/cli/commands/skill.ts +216 -0
- package/server/cli/commands/start.ts +139 -0
- package/server/cli/commands/status.ts +59 -0
- package/server/cli/commands/stop.ts +36 -0
- package/server/cli/commands/token.ts +180 -0
- package/server/cli/commands/unlock.ts +50 -0
- package/server/cli/commands/vault.ts +1323 -0
- package/server/cli/commands/wallet.ts +209 -0
- package/server/cli/index.ts +280 -0
- package/server/cli/lib/approval-poll.ts +94 -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 +280 -0
- package/server/cli/lib/dotenv-migrate.ts +116 -0
- package/server/cli/lib/dotenv-parser.ts +146 -0
- package/server/cli/lib/escalation.ts +57 -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/lock-unlock-helper.ts +71 -0
- package/server/cli/lib/process.ts +162 -0
- package/server/cli/lib/prompt.ts +294 -0
- package/server/cli/lib/theme.ts +240 -0
- package/server/cli/socket.ts +579 -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 +420 -0
- package/server/lib/adapters/factory.ts +119 -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 +419 -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 +258 -0
- package/server/lib/app-installer.ts +505 -0
- package/server/lib/app-tokens.ts +247 -0
- package/server/lib/approval-link.ts +27 -0
- package/server/lib/auth.ts +314 -0
- package/server/lib/auto-execute.ts +160 -0
- package/server/lib/batch.ts +242 -0
- package/server/lib/cold.ts +1048 -0
- package/server/lib/config.ts +408 -0
- package/server/lib/credential-access-audit.ts +85 -0
- package/server/lib/credential-access-policy.ts +111 -0
- package/server/lib/credential-health.ts +343 -0
- package/server/lib/credential-import.ts +608 -0
- package/server/lib/credential-scope.ts +102 -0
- package/server/lib/credential-shares.ts +190 -0
- package/server/lib/credential-transport.ts +533 -0
- package/server/lib/credential-vault.ts +77 -0
- package/server/lib/credentials.ts +422 -0
- package/server/lib/crypto.ts +8 -0
- package/server/lib/db.ts +58 -0
- package/server/lib/defaults.ts +386 -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/diary.ts +34 -0
- package/server/lib/dont-ask-again-policy.ts +41 -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 +114 -0
- package/server/lib/error.ts +20 -0
- package/server/lib/events.ts +217 -0
- package/server/lib/feature-flags.ts +93 -0
- package/server/lib/hot.ts +357 -0
- package/server/lib/human-action-summary.ts +80 -0
- package/server/lib/key-fingerprint.ts +28 -0
- package/server/lib/logger.ts +340 -0
- package/server/lib/network.ts +137 -0
- package/server/lib/notifications.ts +230 -0
- package/server/lib/oauth2-refresh.ts +241 -0
- package/server/lib/oursecret.ts +71 -0
- package/server/lib/passkey-credential.ts +360 -0
- package/server/lib/passkey.ts +68 -0
- package/server/lib/permissions.ts +299 -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 +297 -0
- package/server/lib/resolve-action.ts +328 -0
- package/server/lib/resolve.ts +36 -0
- package/server/lib/secret-gist-share.ts +296 -0
- package/server/lib/sessions.ts +634 -0
- package/server/lib/socket-path.ts +56 -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 +159 -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 +237 -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 +84 -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/update-check.ts +35 -0
- package/server/lib/verified-summary.ts +414 -0
- package/server/lib/view-registry.ts +80 -0
- package/server/mcp/profile-policy.ts +30 -0
- package/server/mcp/server.ts +1589 -0
- package/server/mcp/tools.ts +276 -0
- package/server/middleware/auth.ts +119 -0
- package/server/middleware/requestLogger.ts +84 -0
- package/server/routes/actions.ts +539 -0
- package/server/routes/adapters.ts +711 -0
- package/server/routes/addressbook.ts +113 -0
- package/server/routes/ai.ts +34 -0
- package/server/routes/apikeys.ts +343 -0
- package/server/routes/apps.ts +601 -0
- package/server/routes/auth.ts +406 -0
- package/server/routes/backup.ts +404 -0
- package/server/routes/batch.ts +270 -0
- package/server/routes/bookmarks.ts +162 -0
- package/server/routes/credential-shares.ts +380 -0
- package/server/routes/credential-vaults.ts +159 -0
- package/server/routes/credentials.ts +1782 -0
- package/server/routes/dashboard.ts +97 -0
- package/server/routes/defaults.ts +124 -0
- package/server/routes/flags.ts +11 -0
- package/server/routes/fund.ts +225 -0
- package/server/routes/heartbeat.ts +375 -0
- package/server/routes/import.ts +364 -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 +366 -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 +352 -0
- package/server/routes/swap-solana.ts +176 -0
- package/server/routes/swap.ts +356 -0
- package/server/routes/token.ts +247 -0
- package/server/routes/unlock.ts +467 -0
- package/server/routes/views.ts +41 -0
- package/server/routes/wallet-assets.ts +361 -0
- package/server/routes/wallet-transactions.ts +515 -0
- package/server/routes/wallet.ts +709 -0
- package/server/types.ts +146 -0
- package/shared/credential-field-schema.ts +248 -0
- package/skills/auramaxx/HEARTBEAT.md +78 -0
- package/skills/auramaxx/SKILL.md +745 -0
- package/skills/auramaxx/docs/AGENT_SETUP.md +155 -0
- package/skills/auramaxx/docs/API.md +127 -0
- package/skills/auramaxx/docs/AUTH.md +318 -0
- package/skills/auramaxx/docs/CLI.md +130 -0
- package/skills/auramaxx/docs/MCP.md +122 -0
- package/skills/auramaxx/docs/TROUBLESHOOTING.md +357 -0
- package/skills/auramaxx/docs/WORKSPACE.md +673 -0
- package/skills/auramaxx/docs/security.md +227 -0
- package/skills/task-lifecycle/SKILL.md +378 -0
- package/src/app/api/[...doc]/page.tsx +36 -0
- package/src/app/api/agent-requests/route.ts +30 -0
- package/src/app/api/apps/install/route.ts +132 -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/docs/plain/route.ts +74 -0
- package/src/app/api/events/route.ts +92 -0
- package/src/app/api/page.tsx +290 -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 +40 -0
- package/src/app/api/workspace/config/route.ts +121 -0
- package/src/app/api/workspace/import/route.ts +127 -0
- package/src/app/api/workspace/route.ts +116 -0
- package/src/app/app-legacy-do-not-use/page.tsx +2245 -0
- package/src/app/apple-icon.png +0 -0
- package/src/app/approve/[actionId]/page.tsx +409 -0
- package/src/app/docs/DocsPageContent.tsx +269 -0
- package/src/app/docs/[...doc]/page.tsx +41 -0
- package/src/app/docs/page.tsx +38 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +819 -0
- package/src/app/health/page.tsx +5 -0
- package/src/app/hello/page.tsx +102 -0
- package/src/app/icon.png +0 -0
- package/src/app/layout.tsx +39 -0
- package/src/app/page.tsx +1964 -0
- package/src/app/privacy/page.tsx +63 -0
- package/src/app/providers.tsx +87 -0
- package/src/app/share/[token]/page.tsx +295 -0
- package/src/app/terms/page.tsx +80 -0
- package/src/components/ChainSelector.tsx +44 -0
- package/src/components/HumanActionBar.tsx +697 -0
- package/src/components/NotificationDrawer.tsx +387 -0
- package/src/components/PasskeyEnrollmentPrompt.tsx +235 -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 +88 -0
- package/src/components/design-system/ChainIndicator.tsx +65 -0
- package/src/components/design-system/ChainSelector.tsx +147 -0
- package/src/components/design-system/ConfirmationModal.tsx +107 -0
- package/src/components/design-system/ConfirmationPopover.tsx +81 -0
- package/src/components/design-system/DownloadButton.tsx +149 -0
- package/src/components/design-system/Drawer.tsx +133 -0
- package/src/components/design-system/FilterDropdown.tsx +183 -0
- package/src/components/design-system/ItemPicker.tsx +157 -0
- package/src/components/design-system/Modal.tsx +296 -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 +65 -0
- package/src/components/design-system/TyvekCollapsibleSection.tsx +55 -0
- package/src/components/design-system/index.ts +14 -0
- package/src/components/docs/ClientSideMarkdown.tsx +51 -0
- package/src/components/docs/DocsSearchBar.tsx +118 -0
- package/src/components/docs/DocsThemeToggle.tsx +38 -0
- package/src/components/docs/PersistentDocGroup.tsx +91 -0
- package/src/components/docs/ShareUrlButton.tsx +33 -0
- package/src/components/docs/SidebarScrollMemory.tsx +56 -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/CreateViewModal.tsx +88 -0
- package/src/components/layout/LeftRail.tsx +114 -0
- package/src/components/layout/TabBar.tsx +284 -0
- package/src/components/layout/WalletSidebar.tsx +1030 -0
- package/src/components/layout/index.ts +6 -0
- package/src/components/marketing/AuraMaxxSpecOverlay.tsx +653 -0
- package/src/components/marketing/DeviceMorphExperience.tsx +216 -0
- package/src/components/vault/ApiKeysConsole.tsx +1272 -0
- package/src/components/vault/AuditConsole.tsx +600 -0
- package/src/components/vault/CredentialDetail.tsx +625 -0
- package/src/components/vault/CredentialEmpty.tsx +55 -0
- package/src/components/vault/CredentialField.tsx +583 -0
- package/src/components/vault/CredentialForm.tsx +1484 -0
- package/src/components/vault/CredentialList.tsx +265 -0
- package/src/components/vault/CredentialRow.tsx +130 -0
- package/src/components/vault/CredentialShareModal.tsx +273 -0
- package/src/components/vault/CredentialVault.tsx +1662 -0
- package/src/components/vault/CredentialWalletWidget.tsx +103 -0
- package/src/components/vault/DocsConsole.tsx +113 -0
- package/src/components/vault/ImportCredentialsModal.tsx +578 -0
- package/src/components/vault/LargeTypeModal.tsx +88 -0
- package/src/components/vault/PasswordGenerator.tsx +232 -0
- package/src/components/vault/TOTPDisplay.tsx +108 -0
- package/src/components/vault/TotpSetupPanel.tsx +198 -0
- package/src/components/vault/VaultSidebar.tsx +881 -0
- package/src/components/vault/credentialFormName.ts +91 -0
- package/src/components/vault/hooks/useVaultKeyboardShortcuts.ts +69 -0
- package/src/components/vault/types.ts +56 -0
- package/src/context/AuthContext.tsx +365 -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 +4 -0
- package/src/hooks/useAgentActions.ts +552 -0
- package/src/hooks/useBalance.ts +103 -0
- package/src/hooks/useBalances.ts +129 -0
- package/src/hooks/useTheme.ts +156 -0
- package/src/instrumentation.ts +12 -0
- package/src/lib/api-docs.ts +154 -0
- package/src/lib/api.ts +474 -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/credential-field-schema.ts +11 -0
- package/src/lib/crypto.ts +112 -0
- package/src/lib/db.ts +21 -0
- package/src/lib/docs.ts +544 -0
- package/src/lib/events.ts +363 -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/totp-import.ts +57 -0
- package/src/lib/vault-crypto.ts +129 -0
- package/src/lib/view-registry.ts +57 -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 +170 -0
- package/tailwind.config.ts +99 -0
- package/tsconfig.json +42 -0
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
# AI Agent System
|
|
2
|
+
|
|
3
|
+
How AuraMaxx's AI agents work — from app manifests to executed trades.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Apps can embed AI agents via the strategy hook system. A app declares
|
|
8
|
+
hooks (tick, message, execute, result) in its `app.md` frontmatter, and
|
|
9
|
+
the engine orchestrates the AI ↔ API ↔ human-approval loop automatically.
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
|
|
15
|
+
│ App │────▶│ Strategy │────▶│ AI Model │
|
|
16
|
+
│ (app.md) │ │ Engine │ │ (Claude/GPT)│
|
|
17
|
+
└─────────────┘ └──────┬───────┘ └──────┬──────┘
|
|
18
|
+
│ │
|
|
19
|
+
┌──────▼───────┐ ┌──────▼──────┐
|
|
20
|
+
│ Executor │ │ Tool-Use │
|
|
21
|
+
│ (API calls) │ │ (wallet_api)│
|
|
22
|
+
└──────────────┘ └─────────────┘
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Engine Lifecycle
|
|
26
|
+
|
|
27
|
+
### Startup
|
|
28
|
+
|
|
29
|
+
1. `startEngine()` loads all `apps/*/app.md` manifests
|
|
30
|
+
2. Creates `StrategyRuntime` per app (disabled by default)
|
|
31
|
+
3. Groups strategies by tick tier (sniper/active/standard/slow/maintenance)
|
|
32
|
+
4. Creates tick intervals per tier
|
|
33
|
+
5. Auto-enables strategies with `autoStart: true` or `hooks.message`
|
|
34
|
+
|
|
35
|
+
### Enable Strategy
|
|
36
|
+
|
|
37
|
+
1. Gets app token from central registry
|
|
38
|
+
2. Requires `HumanAction` if permissions/limits declared
|
|
39
|
+
3. Restores state from DB
|
|
40
|
+
4. Calls `init` hook if defined
|
|
41
|
+
5. Marks ready for ticking
|
|
42
|
+
|
|
43
|
+
### Disable Strategy
|
|
44
|
+
|
|
45
|
+
1. Calls `shutdown` hook if defined
|
|
46
|
+
2. Persists state to DB
|
|
47
|
+
3. Clears token, CLI session, context hash, message queue
|
|
48
|
+
|
|
49
|
+
## Tick Flow
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
restoreState() ← DB
|
|
53
|
+
│
|
|
54
|
+
fetchAllSources() ← external APIs
|
|
55
|
+
│
|
|
56
|
+
hashContext() ── skip if unchanged
|
|
57
|
+
│
|
|
58
|
+
callHook('tick', context, token)
|
|
59
|
+
│
|
|
60
|
+
processIntents()
|
|
61
|
+
├── Batch approval (if config.approve)
|
|
62
|
+
├── Per-action token approval (if intent has permissions[])
|
|
63
|
+
│
|
|
64
|
+
└── For each approved intent:
|
|
65
|
+
├── Pre-computed action OR execute hook
|
|
66
|
+
├── executeAction() (paper or live)
|
|
67
|
+
├── result hook → state updates + follow-ups
|
|
68
|
+
└── Follow-ups re-enter (depth limit: 3)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Tick Context
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"sources": { "source_id": ["...data"] },
|
|
76
|
+
"positions": [],
|
|
77
|
+
"state": {},
|
|
78
|
+
"config": { "approve": true },
|
|
79
|
+
"permissions": ["swap"],
|
|
80
|
+
"budget": { "limits": {}, "spent": {}, "remaining": {} }
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Context Deduplication
|
|
85
|
+
|
|
86
|
+
SHA-256 hash of tick context. Skips LLM call if unchanged since last tick.
|
|
87
|
+
|
|
88
|
+
## Message Flow
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
Rate limit check (10/60s per app)
|
|
92
|
+
│
|
|
93
|
+
Build MessageContext
|
|
94
|
+
│
|
|
95
|
+
callHook('message', context, token)
|
|
96
|
+
│
|
|
97
|
+
Update state + emit events
|
|
98
|
+
│
|
|
99
|
+
Process intents (if any)
|
|
100
|
+
│
|
|
101
|
+
Return reply
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Serial per-app (prevents state races), parallel across apps.
|
|
105
|
+
|
|
106
|
+
### Entry Points
|
|
107
|
+
|
|
108
|
+
Messages reach the engine via multiple channels, all converging on `handleAppMessage()`:
|
|
109
|
+
|
|
110
|
+
| Channel | Path | Auth |
|
|
111
|
+
|---------|------|------|
|
|
112
|
+
| Dashboard UI | `POST /apps/:id/message` → `handleAppMessage()` | Session token |
|
|
113
|
+
| Adapter (Telegram) | Long-poll → `ctx.sendMessage()` → `handleAppMessage()` | chatId validation |
|
|
114
|
+
| Adapter (Webhook) | `POST /adapters/:type/message` → `router.sendMessage()` → `handleAppMessage()` | HMAC signature |
|
|
115
|
+
|
|
116
|
+
All channels share the same rate limit, tool-use loop, and state. See [ADAPTERS.md](../ADAPTERS.md) for adapter chat configuration.
|
|
117
|
+
|
|
118
|
+
### Message Context
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"message": "user input",
|
|
123
|
+
"appId": "swap-chat",
|
|
124
|
+
"state": {},
|
|
125
|
+
"config": {},
|
|
126
|
+
"permissions": ["wallet:list"],
|
|
127
|
+
"budget": { "limits": {}, "spent": {}, "remaining": {} }
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## AI Provider Selection
|
|
132
|
+
|
|
133
|
+
`getProviderMode()` in `server/lib/ai.ts` reads the `ai.provider` system default. Four provider modes are supported:
|
|
134
|
+
|
|
135
|
+
| Mode | Backend | Auth | Tool Support |
|
|
136
|
+
|------|---------|------|-------------|
|
|
137
|
+
| `claude-cli` (default) | `claude` binary | Subscription/OAuth | MCP server via `--mcp-config` |
|
|
138
|
+
| `claude-api` | Anthropic SDK | `ANTHROPIC_API_KEY` or DB | Native tool-use |
|
|
139
|
+
| `codex-cli` | `codex` binary | Subscription | Prompt-embedded (no native MCP) |
|
|
140
|
+
| `openai-api` | OpenAI SDK | `OPENAI_API_KEY` or DB | Native tool-use (OpenAI format) |
|
|
141
|
+
|
|
142
|
+
### Tiered Model Selection
|
|
143
|
+
|
|
144
|
+
Models are auto-selected using a 3-tier system based on the hook name and the token's permissions at `callHook()` time. No user configuration needed — the right model is chosen automatically:
|
|
145
|
+
|
|
146
|
+
| Tier | Claude | Codex/OpenAI | When |
|
|
147
|
+
|------|--------|-------------|------|
|
|
148
|
+
| `fast` | haiku | codex-mini | `init`/`shutdown` hooks, no token, or read-only permissions |
|
|
149
|
+
| `standard` | sonnet | codex | Write permissions (`wallet:create:hot`, `wallet:create:temp`) |
|
|
150
|
+
| `powerful` | opus | codex-max | Financial permissions (`swap`, `send:hot`, `send:temp`, `fund`, `launch`) or `admin:*` |
|
|
151
|
+
|
|
152
|
+
**How it works:** At each `callHook()` invocation, the engine decodes the token (via `validateToken()` — a synchronous HMAC check, no DB call) to extract permissions, then calls `selectModelTier(hookName, permissions)` to pick the tier. The tier maps to a model short name via `MODEL_TIERS[provider][tier]`, which is then resolved to a full SDK model ID if needed.
|
|
153
|
+
|
|
154
|
+
**Key functions** (`server/lib/ai.ts`):
|
|
155
|
+
- `selectModelTier(hookName, permissions)` — returns `'fast'` | `'standard'` | `'powerful'`
|
|
156
|
+
- `MODEL_TIERS` — maps `AiProviderMode × ModelTier → model short name`
|
|
157
|
+
- `getDefaultModel()` — returns the `standard` tier model for the active provider (backward compat)
|
|
158
|
+
|
|
159
|
+
| Provider | Fast | Standard | Powerful |
|
|
160
|
+
|----------|------|----------|----------|
|
|
161
|
+
| `claude-cli` | `haiku` | `sonnet` | `opus` |
|
|
162
|
+
| `claude-api` | `haiku` → `claude-haiku-4-5-20251001` | `sonnet` → `claude-sonnet-4-5-20250929` | `opus` → `claude-opus-4-6` |
|
|
163
|
+
| `codex-cli` | `codex-mini` | `codex` | `codex-max` |
|
|
164
|
+
| `openai-api` | `codex-mini` → `gpt-5.1-codex-mini` | `codex` → `gpt-5.3-codex` | `codex-max` → `gpt-5.1-codex-max` |
|
|
165
|
+
|
|
166
|
+
All four paths use the same hook system, same tools, same context injection.
|
|
167
|
+
|
|
168
|
+
### Configuring Providers
|
|
169
|
+
|
|
170
|
+
Via SystemDefaultsApp (AI ENGINE section) or API:
|
|
171
|
+
```bash
|
|
172
|
+
# Change provider (model auto-selected: claude→sonnet, codex/openai→codex)
|
|
173
|
+
curl -X PATCH http://localhost:4242/defaults/ai.provider \
|
|
174
|
+
-H "Authorization: Bearer <admin-token>" \
|
|
175
|
+
-H "Content-Type: application/json" \
|
|
176
|
+
-d '{"value": "openai-api"}'
|
|
177
|
+
|
|
178
|
+
# Check provider availability
|
|
179
|
+
curl http://localhost:4242/ai/status \
|
|
180
|
+
-H "Authorization: Bearer <admin-token>"
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Hook Dispatch
|
|
184
|
+
|
|
185
|
+
`callHook(manifest, hookName, context, token?)` in `hooks.ts` dispatches to the correct provider:
|
|
186
|
+
|
|
187
|
+
### Claude SDK Path (`callHookViaSdk`)
|
|
188
|
+
|
|
189
|
+
- `client.messages.create()` with system prompt + tools array
|
|
190
|
+
- System context: `cache_control: { type: 'ephemeral' }` (sent once, cached)
|
|
191
|
+
- Tool-use loop: if `stop_reason === 'tool_use'` → execute → append result → retry
|
|
192
|
+
- Max 10 tool calls per invocation
|
|
193
|
+
|
|
194
|
+
### Claude CLI Path (`callHookViaCli`)
|
|
195
|
+
|
|
196
|
+
- `execFile('claude', ['-p', '--model', model, ...])` with MCP config
|
|
197
|
+
- Per-strategy session memory (conversation persists across ticks)
|
|
198
|
+
- Separate sessions for tick vs message: `{id}` vs `{id}:message`
|
|
199
|
+
- MCP server provides `wallet_api` tool via `--mcp-config`
|
|
200
|
+
|
|
201
|
+
### OpenAI SDK Path (`callHookViaOpenAiSdk`)
|
|
202
|
+
|
|
203
|
+
- `client.chat.completions.create()` with messages + tools (OpenAI format)
|
|
204
|
+
- Uses existing `toOpenAITools()` from `server/mcp/tools.ts`
|
|
205
|
+
- Tool-use loop: if `finish_reason === 'tool_calls'` → execute via `executeTool()` → feed results back
|
|
206
|
+
- Same max tool calls limit
|
|
207
|
+
|
|
208
|
+
### Codex CLI Path (`callHookViaCodexCli`)
|
|
209
|
+
|
|
210
|
+
- `execFile('codex', ['exec', '--json', '--model', model, '--ephemeral', '-'])` with stdin prompt
|
|
211
|
+
- Ephemeral sessions (no persistence across ticks)
|
|
212
|
+
- No native MCP support — tool instructions embedded in prompt text
|
|
213
|
+
- JSONL output parsed for final assistant message
|
|
214
|
+
|
|
215
|
+
## Tool-Use (API Access)
|
|
216
|
+
|
|
217
|
+
Hook AIs call the wallet API mid-conversation using the `wallet_api` tool.
|
|
218
|
+
Instead of pre-injecting wallet data, the agent fetches what it needs.
|
|
219
|
+
|
|
220
|
+
### Flow
|
|
221
|
+
|
|
222
|
+
1. Agent receives API docs + permissions in system context (auto-injected)
|
|
223
|
+
2. Agent decides it needs data (e.g., wallet addresses for a swap)
|
|
224
|
+
3. Agent calls `wallet_api` with `{ method: "GET", endpoint: "/wallets" }`
|
|
225
|
+
4. Engine executes HTTP call using app's token
|
|
226
|
+
5. Agent receives response and continues (constructs swap intent)
|
|
227
|
+
|
|
228
|
+
### Tool Definition
|
|
229
|
+
|
|
230
|
+
| Param | Type | Description |
|
|
231
|
+
|-------|------|-------------|
|
|
232
|
+
| method | `"GET"` or `"POST"` | HTTP method |
|
|
233
|
+
| endpoint | string | API path (e.g., `/wallets`) |
|
|
234
|
+
| body | object | POST request body (optional) |
|
|
235
|
+
|
|
236
|
+
### request_human_action
|
|
237
|
+
|
|
238
|
+
Request human approval for a privileged wallet action. Available in message hooks (tool-call mode).
|
|
239
|
+
|
|
240
|
+
| Param | Type | Required | Description |
|
|
241
|
+
|-------|------|----------|-------------|
|
|
242
|
+
| summary | string | yes | Human-readable description (shown in approval card) |
|
|
243
|
+
| permissions | string[] | yes | Permission strings needed (e.g. `["swap"]`) |
|
|
244
|
+
| action | object | yes | Pre-computed API call `{ endpoint, method, body }` |
|
|
245
|
+
| limits | object | no | Spending caps per permission (e.g. `{ swap: 0.01 }`) |
|
|
246
|
+
| walletAccess | string[] | no | Wallet addresses the temp token needs access to (include all addresses involved in the action) |
|
|
247
|
+
| ttl | number | no | Seconds the temporary token lives (default 120) |
|
|
248
|
+
|
|
249
|
+
**Flow:**
|
|
250
|
+
1. AI tries `wallet_api` POST to execute action directly
|
|
251
|
+
2. Gets 403 (insufficient permissions)
|
|
252
|
+
3. AI calls `request_human_action` with the action details
|
|
253
|
+
4. Human sees approval card with summary + action details
|
|
254
|
+
5. On approval: action auto-executes with a scoped temporary token
|
|
255
|
+
6. Result emitted back to app via `action:executed` channel
|
|
256
|
+
7. Execution result is fed back to the app's AI, which generates a contextual follow-up reply sent to the app via `agent:message` channel (e.g. "Wallet created at 0x123, want to fund it?")
|
|
257
|
+
|
|
258
|
+
**App event channels for `request_human_action`:**
|
|
259
|
+
|
|
260
|
+
| Channel | When | Data |
|
|
261
|
+
|---------|------|------|
|
|
262
|
+
| `action:resolved` | Always on approve/reject | `{ requestId, approved }` |
|
|
263
|
+
| `action:executed` | After auto-execute attempt | `{ requestId, approved, status, result }` |
|
|
264
|
+
| `agent:message` | After AI processes result | `{ message: "contextual reply" }` |
|
|
265
|
+
|
|
266
|
+
On rejection, only `action:resolved` fires (with `approved: false`). On approval with auto-execute, all three fire in sequence.
|
|
267
|
+
|
|
268
|
+
**Permission → Endpoint mapping:**
|
|
269
|
+
|
|
270
|
+
Use exactly these permission strings when calling `request_human_action`:
|
|
271
|
+
|
|
272
|
+
| Permission | Endpoint |
|
|
273
|
+
|------------|----------|
|
|
274
|
+
| `swap` | `/swap` |
|
|
275
|
+
| `send:hot` | `/send` |
|
|
276
|
+
| `send:temp` | `/send` |
|
|
277
|
+
| `fund` | `/fund` |
|
|
278
|
+
| `launch` | `/launch` |
|
|
279
|
+
| `wallet:create:hot` | `/wallet/create` |
|
|
280
|
+
| `wallet:create:temp` | `/wallet/create` |
|
|
281
|
+
|
|
282
|
+
**Callback depth limit:** Auto-execute callbacks (where the result is fed back to the app AI) are capped at **3 per app per 2-minute window**. This prevents infinite loops where the AI creates approval requests in a cycle (e.g., approve → callback → new approval → approve → callback...). When the limit is hit, the `action:executed` event still fires to the app UI, but the AI callback is skipped. The counter resets after 2 minutes of inactivity.
|
|
283
|
+
|
|
284
|
+
**Security:** The tool validates that requested permissions match the action endpoint both forward (permission → endpoint) and reverse (endpoint → required permissions). Using an unknown or incorrect permission string for a known endpoint returns an immediate error.
|
|
285
|
+
|
|
286
|
+
### Safety Limits
|
|
287
|
+
|
|
288
|
+
- Max 10 tool calls per hook invocation
|
|
289
|
+
- 10s timeout per call
|
|
290
|
+
- Responses truncated to 4KB
|
|
291
|
+
- Uses app's own token — server enforces permissions
|
|
292
|
+
|
|
293
|
+
### Provider Comparison
|
|
294
|
+
|
|
295
|
+
| Feature | Claude CLI | Claude API | Codex CLI | OpenAI API |
|
|
296
|
+
|---------|-----------|-----------|----------|-----------|
|
|
297
|
+
| Tool-use | MCP server (`--mcp-config`) | Native (`tools` param) | Prompt-embedded | Native (`tools` param) |
|
|
298
|
+
| Sessions | Persistent per-strategy | None (stateless) | Ephemeral | None (stateless) |
|
|
299
|
+
| Tool format | `server/mcp/server.ts` | `toAnthropicTools()` | N/A | `toOpenAITools()` |
|
|
300
|
+
|
|
301
|
+
All providers use the same tool definitions from `server/mcp/tools.ts` and the same `executeTool()` handler.
|
|
302
|
+
|
|
303
|
+
## Auto-Injected System Context
|
|
304
|
+
|
|
305
|
+
The system context that guides hook AI calls lives in `skills/auramaxx/SKILL.md` — a single source of truth shared by both the MCP server (as `docs://guide` resource) and the SDK injection path.
|
|
306
|
+
|
|
307
|
+
### Provider-Aware Injection
|
|
308
|
+
|
|
309
|
+
`hook-context.ts` is a thin loader that adapts based on the AI provider:
|
|
310
|
+
|
|
311
|
+
| Provider | What Gets Injected | How Agent Gets Full Docs |
|
|
312
|
+
|----------|-------------------|--------------------------|
|
|
313
|
+
| `claude-cli` | Minimal response-format reminder | Reads `docs://guide` and `docs://api` MCP resources |
|
|
314
|
+
| `claude-api` | Full guide section + API reference from doc files | Injected in system prompt |
|
|
315
|
+
| `codex-cli` | Full guide section + API reference from doc files | Injected in stdin (no MCP support) |
|
|
316
|
+
| `openai-api` | Full guide section + API reference from doc files | Injected in system prompt |
|
|
317
|
+
|
|
318
|
+
**CLI providers** get a minimal system context (just response format + "read docs://guide/docs://api") because the MCP server provides the full documentation as resources. This avoids triple-injecting the same content.
|
|
319
|
+
|
|
320
|
+
**SDK providers** get the full content loaded from `skills/auramaxx/SKILL.md` + the agent endpoints section of `docs/API.md`, since they have no MCP resource access.
|
|
321
|
+
|
|
322
|
+
### Dual Framing Modes
|
|
323
|
+
|
|
324
|
+
The agent guide contains two sections, one per hook type:
|
|
325
|
+
|
|
326
|
+
| Mode | Used By | Behavior |
|
|
327
|
+
|------|---------|----------|
|
|
328
|
+
| `intent` | Tick hooks (`tick`, `execute`, `result`, `init`, `shutdown`) | AI returns structured intents with permissions arrays. Engine handles approval + execution. |
|
|
329
|
+
| `tool-call` | Message hooks (`message`) | AI uses `wallet_api` and `request_human_action` tools directly. Try action → 403 → request approval → auto-execute. No intents needed. |
|
|
330
|
+
|
|
331
|
+
**Tool-call mode** (chat apps like swap-chat, launch-chat):
|
|
332
|
+
- AI calls `wallet_api` for reads and writes
|
|
333
|
+
- Token mint requests (`POST /auth`, `POST /actions/token`, approval-derived token issuance) must include caller `pubkey`
|
|
334
|
+
- On 403, AI calls `request_human_action` to request human approval
|
|
335
|
+
- On approval, the action auto-executes with a scoped temporary token
|
|
336
|
+
- Response format: `{ reply, state, emit }` — no intents field needed
|
|
337
|
+
|
|
338
|
+
**Intent mode** (tick-based strategies):
|
|
339
|
+
- AI returns intents with optional `permissions` arrays
|
|
340
|
+
- Engine handles batch approval, per-action tokens, and execution
|
|
341
|
+
- Response format: `{ reply, state, intents, emit }`
|
|
342
|
+
|
|
343
|
+
Both modes share the same API reference and wallet tier documentation. See `skills/auramaxx/SKILL.md` for the full guide content.
|
|
344
|
+
|
|
345
|
+
## Intent & Approval System
|
|
346
|
+
|
|
347
|
+
### Intent Types
|
|
348
|
+
|
|
349
|
+
1. **Batch intents** (no `permissions` array) — approved together if `config.approve`
|
|
350
|
+
2. **Per-action intents** (has `permissions` array) — each gets own approval + scoped temp token
|
|
351
|
+
|
|
352
|
+
### Approval Flow
|
|
353
|
+
|
|
354
|
+
- Engine creates `HumanAction` → emits `action:created` event
|
|
355
|
+
- Dashboard/adapters show approval card with intent summary
|
|
356
|
+
- Human approves → engine creates scoped token → executes action
|
|
357
|
+
- Human rejects or timeout → intent skipped
|
|
358
|
+
|
|
359
|
+
### Pre-Computed Actions
|
|
360
|
+
|
|
361
|
+
Hooks can return intents with `action: { endpoint, method, body }` to skip
|
|
362
|
+
the execute hook entirely. The engine calls the API directly.
|
|
363
|
+
|
|
364
|
+
## State Management
|
|
365
|
+
|
|
366
|
+
- **In-memory**: `Map<string, Record<string, unknown>>` per app
|
|
367
|
+
- **Persistence**: REST calls to app storage (`PUT /apps/{id}/storage/_strategy_state`)
|
|
368
|
+
- **Restore**: Read from DB at tick start (picks up UI changes)
|
|
369
|
+
- **Auto-persist**: Every 5 minutes + on disable + on error
|
|
370
|
+
|
|
371
|
+
## Action Execution
|
|
372
|
+
|
|
373
|
+
`executeAction()` in `executor.ts`:
|
|
374
|
+
|
|
375
|
+
- HTTP request to `http://127.0.0.1:4242{endpoint}` with Bearer token
|
|
376
|
+
- 30-second timeout per action
|
|
377
|
+
- External endpoints are validated before fetch:
|
|
378
|
+
- Only `http:` and `https:` protocols are allowed
|
|
379
|
+
- Private/internal destinations are blocked after DNS resolution (SSRF protection)
|
|
380
|
+
- External hosts must be explicitly allowed (`allowedHosts` + source-derived hosts)
|
|
381
|
+
- Redirects are blocked (`redirect: 'error'`)
|
|
382
|
+
|
|
383
|
+
## Emit System
|
|
384
|
+
|
|
385
|
+
Hooks can return `emit: { channel, data }` or `emit: [...]`.
|
|
386
|
+
Engine broadcasts as `app:emit` WebSocket events.
|
|
387
|
+
Dashboard forwards to app iframe via `postMessage()`.
|
|
388
|
+
|
|
389
|
+
## Error Handling
|
|
390
|
+
|
|
391
|
+
Configurable per strategy via `config.errors`:
|
|
392
|
+
|
|
393
|
+
- `sourceFail`: `'skip'` | `'pause'` | `'retry'` — what to do when sources fail
|
|
394
|
+
- `executeFail`: `'skip'` | `'pause'` — what to do when actions fail
|
|
395
|
+
- Error counting with cooldown (strategy pauses after N consecutive errors)
|
|
396
|
+
- Skip-on-busy: if previous tick still running, next tick is skipped
|
|
397
|
+
|
|
398
|
+
## Integration Testing
|
|
399
|
+
|
|
400
|
+
The AI agent pipeline has its own integration test suite, separate from the main unit tests.
|
|
401
|
+
|
|
402
|
+
### Running
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
# AI integration tests only
|
|
406
|
+
npm run test:ai
|
|
407
|
+
|
|
408
|
+
# Main unit tests (does NOT include AI integration tests)
|
|
409
|
+
npm test
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Architecture
|
|
413
|
+
|
|
414
|
+
```
|
|
415
|
+
User prompt
|
|
416
|
+
→ processMessage() [message.ts — REAL]
|
|
417
|
+
→ callHook() [hooks.ts — REAL]
|
|
418
|
+
→ callHookViaSdk() [hooks.ts — REAL, Anthropic SDK MOCKED]
|
|
419
|
+
→ client.messages.create() ← SCRIPTED RESPONSES
|
|
420
|
+
→ executeTool() [mcp/tools.ts — REAL]
|
|
421
|
+
→ fetch(127.0.0.1:4242) ← INTERCEPTED → test Express app
|
|
422
|
+
→ Express routes [REAL — auth, permissions, wallet ops]
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
**Mock boundary**: Only the AI model is mocked (scripted tool_use / text responses). Everything from `executeTool` through Express routes is real code — real auth, real permission checks, real wallet state, real test database.
|
|
426
|
+
|
|
427
|
+
**Fetch interception**: `executeTool` hardcodes `http://127.0.0.1:4242`. Tests start Express on port 0 (random), then intercept `globalThis.fetch` to rewrite the URL. This preserves all of executeTool's real validation, timeouts, and truncation logic.
|
|
428
|
+
|
|
429
|
+
### Key Files
|
|
430
|
+
|
|
431
|
+
| File | Purpose |
|
|
432
|
+
|------|---------|
|
|
433
|
+
| `server/tests/ai-integration/vitest.config.ts` | Separate vitest config (60s timeout, sequential) |
|
|
434
|
+
| `server/tests/ai-integration/harness.ts` | Server setup, fetch interception, `runPrompt()` helper |
|
|
435
|
+
| `server/tests/ai-integration/scenarios.test.ts` | Prompt scenarios (simple queries, multi-step, errors) |
|
|
436
|
+
|
|
437
|
+
### Adding Scenarios
|
|
438
|
+
|
|
439
|
+
Use `runPrompt()` to script an AI conversation:
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
const result = await runPrompt(
|
|
443
|
+
mockCreate,
|
|
444
|
+
'What are my wallets?',
|
|
445
|
+
[
|
|
446
|
+
// Turn 1: AI calls wallet_api tool (real HTTP to test server)
|
|
447
|
+
{ toolCalls: [{ name: 'wallet_api', input: { method: 'GET', endpoint: '/wallets' } }] },
|
|
448
|
+
// Turn 2: AI returns final text (parsed as HookResult)
|
|
449
|
+
{ text: '{"reply": "You have 1 wallet.", "state": {}}' },
|
|
450
|
+
],
|
|
451
|
+
{ token: agentToken },
|
|
452
|
+
);
|
|
453
|
+
expect(result.reply).toBe('You have 1 wallet.');
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
Each `ScriptedTurn` is either a tool_use turn (tool calls executed against real server) or a text turn (final AI response). Add new scenarios by defining the expected AI conversation turns.
|
|
457
|
+
|
|
458
|
+
### Live Model Testing
|
|
459
|
+
|
|
460
|
+
A separate test suite sends real prompts to real Claude and validates that the model makes sensible tool calls against the real wallet server. This tests **system prompt quality** — does `hook-context.ts` + tool descriptions guide the model correctly?
|
|
461
|
+
|
|
462
|
+
```bash
|
|
463
|
+
# Uses claude CLI (subscription) or ANTHROPIC_API_KEY — whichever is available
|
|
464
|
+
npm run test:ai:live
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
**Architecture (two provider paths):**
|
|
468
|
+
|
|
469
|
+
```
|
|
470
|
+
SDK path (API key in env or DB):
|
|
471
|
+
User prompt → processMessage() → callHookViaSdk()
|
|
472
|
+
→ client.messages.create() ← REAL CLAUDE (haiku)
|
|
473
|
+
→ executeTool() [mcp/tools.ts — REAL]
|
|
474
|
+
→ fetch(WALLET_SERVER_URL) → test Express app
|
|
475
|
+
|
|
476
|
+
CLI path (claude subscription):
|
|
477
|
+
User prompt → processMessage() → callHookViaCli()
|
|
478
|
+
→ execFile('claude', ...) ← REAL CLAUDE (haiku) via CLI
|
|
479
|
+
→ MCP server subprocess [mcp/server.ts — REAL]
|
|
480
|
+
→ executeTool() → fetch(WALLET_SERVER_URL) → test Express app
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
**Nothing is mocked.** Real Claude, real system prompt, real tools, real server. The test Express app runs on a random port, reached via `WALLET_SERVER_URL` env var (propagated to MCP subprocesses) and fetch interception (for in-process calls).
|
|
484
|
+
|
|
485
|
+
**Key differences from scripted tests:**
|
|
486
|
+
|
|
487
|
+
| | Scripted (`test:ai`) | Live (`test:ai:live`) |
|
|
488
|
+
|---|---|---|
|
|
489
|
+
| AI model | Mocked (scripted responses) | Real Claude (haiku) |
|
|
490
|
+
| What it tests | Plumbing (tool execution, auth, permissions) | System prompt quality (does Claude pick the right tools?) |
|
|
491
|
+
| Assertions | Exact replies, tool call sequences | Keywords in reply, DB side effects |
|
|
492
|
+
| Cost | Free | ~$0.01-0.05 per run |
|
|
493
|
+
| AI provider | Not needed (test placeholder) | Claude CLI or API key |
|
|
494
|
+
| Timeout | 60s | 120s |
|
|
495
|
+
|
|
496
|
+
**Skip behavior:** Auto-skips if neither `claude` CLI nor a real `ANTHROPIC_API_KEY` is available. Safe to run in CI without secrets or CLI configured.
|
|
497
|
+
|
|
498
|
+
**Key files:**
|
|
499
|
+
|
|
500
|
+
| File | Purpose |
|
|
501
|
+
|------|---------|
|
|
502
|
+
| `server/tests/ai-integration/vitest.live.config.ts` | Vitest config (120s timeout, sequential) |
|
|
503
|
+
| `server/tests/ai-integration/live-harness.ts` | Server setup, `runLivePrompt()` (no mocking) |
|
|
504
|
+
| `server/tests/ai-integration/live.test.ts` | Live model scenarios |
|
|
505
|
+
|
|
506
|
+
## MCP Server (Standalone)
|
|
507
|
+
|
|
508
|
+
See [MCP.md](../MCP.md) for standalone MCP server usage.
|