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,798 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* auramaxx init — First-time setup
|
|
3
|
+
*
|
|
4
|
+
* 1. Create directories + run migrations + generate Prisma client
|
|
5
|
+
* 2. Start server headless (Express only)
|
|
6
|
+
* 3. If vault exists → start dashboard, print "Already initialized", keep running
|
|
7
|
+
* 4. Prompt: Dashboard or Terminal?
|
|
8
|
+
* a. Dashboard → start dashboard + open browser + poll until vault created
|
|
9
|
+
* b. Terminal → interactive vault creation + optional config
|
|
10
|
+
* 5. Print cold wallet address + funding guidance
|
|
11
|
+
* 6. Keep servers running
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import * as fs from 'fs';
|
|
15
|
+
import * as path from 'path';
|
|
16
|
+
import * as os from 'os';
|
|
17
|
+
import { exec, spawn, ChildProcess } from 'child_process';
|
|
18
|
+
import { fetchSetupStatus, fetchPublicKey, fetchJson, waitForServer, SetupStatus } from '../lib/http';
|
|
19
|
+
import { startServer, stopServer, findProjectRoot } from '../lib/process';
|
|
20
|
+
import { ensureDirectories, runMigrations, generatePrismaClient } from '../lib/init-steps';
|
|
21
|
+
import { promptPassword, promptInput, promptConfirm, promptSelect } from '../lib/prompt';
|
|
22
|
+
import { encryptPassword, generateAgentKeypair } from '../transport-client';
|
|
23
|
+
import { getErrorMessage } from '../../lib/error';
|
|
24
|
+
import { printBanner, printSection, printSeedPhrase } from '../lib/theme';
|
|
25
|
+
import { migrateDotenv } from '../lib/dotenv-migrate';
|
|
26
|
+
import { parseAuraFile } from '../lib/aura-parser';
|
|
27
|
+
import { bootstrapViaSocket, generateEphemeralKeypair } from '../../lib/credential-transport';
|
|
28
|
+
import { createCredentialViaApi, getPrimaryVaultId } from '../lib/credential-create';
|
|
29
|
+
import { resolveLocalAgentModeChoice, persistLocalAgentTrustDefaults } from '../lib/local-agent-trust';
|
|
30
|
+
import { loadServiceIfNeeded, isServiceInstalled } from './service';
|
|
31
|
+
|
|
32
|
+
let serverChildren: ChildProcess[] = [];
|
|
33
|
+
|
|
34
|
+
// SIGINT handler — if launchd is managing the servers, just detach cleanly.
|
|
35
|
+
// Otherwise kill server processes.
|
|
36
|
+
function cleanup() {
|
|
37
|
+
if (serverChildren.length > 0) {
|
|
38
|
+
if (isServiceInstalled()) {
|
|
39
|
+
// Service is registered — load it so servers keep running after we exit.
|
|
40
|
+
loadServiceIfNeeded();
|
|
41
|
+
console.log('\n\nServers will continue running in the background.');
|
|
42
|
+
console.log('Use `auramaxx stop` to stop.');
|
|
43
|
+
} else {
|
|
44
|
+
console.log('\n\nShutting down...');
|
|
45
|
+
stopServer();
|
|
46
|
+
}
|
|
47
|
+
serverChildren = [];
|
|
48
|
+
}
|
|
49
|
+
process.exit(0);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
process.on('SIGINT', cleanup);
|
|
53
|
+
process.on('SIGTERM', cleanup);
|
|
54
|
+
|
|
55
|
+
function openBrowser(url: string) {
|
|
56
|
+
const platform = process.platform;
|
|
57
|
+
const cmd =
|
|
58
|
+
platform === 'darwin' ? `open "${url}"` :
|
|
59
|
+
platform === 'win32' ? `start "${url}"` :
|
|
60
|
+
`xdg-open "${url}"`;
|
|
61
|
+
|
|
62
|
+
exec(cmd, (err) => {
|
|
63
|
+
if (err) {
|
|
64
|
+
// Don't fail — just tell the user to open manually
|
|
65
|
+
console.log(` Could not open browser automatically.`);
|
|
66
|
+
console.log(` Open this URL manually: ${url}\n`);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const DASHBOARD_PORT = process.env.DASHBOARD_PORT || '4747';
|
|
72
|
+
|
|
73
|
+
function startDashboard(): ChildProcess {
|
|
74
|
+
const root = findProjectRoot();
|
|
75
|
+
const dashboard = spawn('npx', ['next', 'dev', '-p', DASHBOARD_PORT], {
|
|
76
|
+
cwd: root,
|
|
77
|
+
env: { ...process.env, BYPASS_RATE_LIMIT: 'true' },
|
|
78
|
+
stdio: 'ignore',
|
|
79
|
+
detached: true,
|
|
80
|
+
});
|
|
81
|
+
dashboard.unref();
|
|
82
|
+
return dashboard;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ─── Mode selection ──────────────────────────────────────────────
|
|
86
|
+
|
|
87
|
+
async function promptSetupMode(): Promise<'dashboard' | 'terminal'> {
|
|
88
|
+
printSection('Setup Mode', 'Choose how you would like to set up your vault.');
|
|
89
|
+
|
|
90
|
+
const mode = await promptSelect(
|
|
91
|
+
' How would you like to set up your vault?',
|
|
92
|
+
[
|
|
93
|
+
{ value: 'dashboard', label: 'dashboard', aliases: ['1', 'browser'] },
|
|
94
|
+
{ value: 'terminal', label: 'terminal', aliases: ['2', 'cli'] },
|
|
95
|
+
],
|
|
96
|
+
'dashboard',
|
|
97
|
+
);
|
|
98
|
+
return mode as 'dashboard' | 'terminal';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ─── Dashboard flow ──────────────────────────────────────────────
|
|
102
|
+
|
|
103
|
+
async function dashboardFlow() {
|
|
104
|
+
printSection('Dashboard Setup', 'Browser-guided vault onboarding.');
|
|
105
|
+
const dashboard = startDashboard();
|
|
106
|
+
serverChildren.push(dashboard);
|
|
107
|
+
|
|
108
|
+
const dashboardUrl = `http://localhost:${DASHBOARD_PORT}`;
|
|
109
|
+
console.log(' Waiting for dashboard to start...');
|
|
110
|
+
|
|
111
|
+
// Wait for Next.js dev server to be ready before opening browser
|
|
112
|
+
const dashboardStart = Date.now();
|
|
113
|
+
while (Date.now() - dashboardStart < 30000) {
|
|
114
|
+
try {
|
|
115
|
+
const res = await fetch(dashboardUrl);
|
|
116
|
+
if (res.ok) break;
|
|
117
|
+
} catch {
|
|
118
|
+
// Not ready yet
|
|
119
|
+
}
|
|
120
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
console.log(' Opening dashboard in browser...');
|
|
124
|
+
openBrowser(dashboardUrl);
|
|
125
|
+
console.log(` Create your vault at ${dashboardUrl}\n`);
|
|
126
|
+
console.log(' Waiting for vault creation...');
|
|
127
|
+
|
|
128
|
+
// Poll until vault is created
|
|
129
|
+
while (true) {
|
|
130
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
131
|
+
try {
|
|
132
|
+
const check = await fetchSetupStatus();
|
|
133
|
+
if (check.hasWallet) {
|
|
134
|
+
console.log('');
|
|
135
|
+
console.log(' Vault created!\n');
|
|
136
|
+
// Vault is ready — activate the launchd service so servers survive Ctrl+C
|
|
137
|
+
loadServiceIfNeeded();
|
|
138
|
+
printBanner('TIME TO AURAMAXX');
|
|
139
|
+
// Password-manager focus for now: hide wallet funding guidance in onboarding output.
|
|
140
|
+
// console.log(` Your cold wallet address: ${check.address}`);
|
|
141
|
+
// console.log(' Send ETH on Base to this address to fund your wallet.\n');
|
|
142
|
+
console.log(` Dashboard ready at ${dashboardUrl}`);
|
|
143
|
+
if (isServiceInstalled()) {
|
|
144
|
+
console.log(' Servers are running in the background. Use `auramaxx stop` to stop.\n');
|
|
145
|
+
} else {
|
|
146
|
+
console.log(' Servers are running. Press Ctrl+C to stop.\n');
|
|
147
|
+
}
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
} catch {
|
|
151
|
+
// Server might be briefly unavailable, keep polling
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ─── Terminal flow ───────────────────────────────────────────────
|
|
157
|
+
|
|
158
|
+
async function terminalFlow(): Promise<string> {
|
|
159
|
+
// Step 1: Password
|
|
160
|
+
printSection('Terminal Setup', 'Local interactive vault onboarding.');
|
|
161
|
+
const password = await promptPasswordWithConfirmation();
|
|
162
|
+
|
|
163
|
+
// Step 2: Create vault
|
|
164
|
+
console.log('\n Creating vault...');
|
|
165
|
+
const publicKey = await fetchPublicKey();
|
|
166
|
+
const encrypted = encryptPassword(password, publicKey);
|
|
167
|
+
const { publicKey: agentPubkey } = generateAgentKeypair();
|
|
168
|
+
|
|
169
|
+
const vault = await fetchJson<{
|
|
170
|
+
success: boolean;
|
|
171
|
+
address: string;
|
|
172
|
+
mnemonic: string;
|
|
173
|
+
token: string;
|
|
174
|
+
}>('/setup', { body: { encrypted, pubkey: agentPubkey } });
|
|
175
|
+
|
|
176
|
+
console.log(' Vault created!\n');
|
|
177
|
+
|
|
178
|
+
// Step 3: Display seed phrase
|
|
179
|
+
printSeedPhrase(vault.mnemonic);
|
|
180
|
+
|
|
181
|
+
let confirmed = await promptConfirm(' Have you saved your seed phrase?');
|
|
182
|
+
while (!confirmed) {
|
|
183
|
+
console.log('\n Please save the phrase above, then confirm to continue.');
|
|
184
|
+
confirmed = await promptConfirm(' Have you saved your seed phrase?');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const token = vault.token;
|
|
188
|
+
|
|
189
|
+
await configureLocalSocketTrust(token);
|
|
190
|
+
|
|
191
|
+
// Optional configuration is intentionally disabled for now.
|
|
192
|
+
/*
|
|
193
|
+
── Optional Configuration ──
|
|
194
|
+
|
|
195
|
+
Press Enter to skip any step.
|
|
196
|
+
|
|
197
|
+
Anthropic API key (sk-ant-...):
|
|
198
|
+
Alchemy API key:
|
|
199
|
+
Telegram bot token:
|
|
200
|
+
*/
|
|
201
|
+
// await configureApiKey(token, 'anthropic', 'Anthropic API key', 'sk-ant-...');
|
|
202
|
+
// await configureApiKey(token, 'alchemy', 'Alchemy API key', '');
|
|
203
|
+
// await configureTelegram(token);
|
|
204
|
+
|
|
205
|
+
// Step 4: Summary
|
|
206
|
+
loadServiceIfNeeded();
|
|
207
|
+
printBanner('TIME TO AURAMAXX');
|
|
208
|
+
// Password-manager focus for now: hide wallet funding/config summary in onboarding.
|
|
209
|
+
// console.log(` Cold wallet address: ${vault.address}`);
|
|
210
|
+
// console.log(' Send ETH on Base to this address to fund your wallet.\n');
|
|
211
|
+
// const status = await fetchSetupStatus();
|
|
212
|
+
// printConfigSummary(status);
|
|
213
|
+
|
|
214
|
+
if (isServiceInstalled()) {
|
|
215
|
+
console.log(' Servers are running in the background. Use `auramaxx stop` to stop.\n');
|
|
216
|
+
} else {
|
|
217
|
+
console.log(' Servers are running. Press Ctrl+C to stop.\n');
|
|
218
|
+
}
|
|
219
|
+
return token;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async function promptPasswordWithConfirmation(): Promise<string> {
|
|
223
|
+
while (true) {
|
|
224
|
+
const password = await promptPassword(' Enter vault password');
|
|
225
|
+
if (password.length < 8) {
|
|
226
|
+
console.log(' Password must be at least 8 characters. Try again.\n');
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const confirm = await promptPassword(' Confirm password');
|
|
231
|
+
if (password !== confirm) {
|
|
232
|
+
console.log(' Passwords do not match. Try again.\n');
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return password;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async function configureLocalSocketTrust(token: string): Promise<void> {
|
|
241
|
+
printSection('Local Agent Trust', 'Choose default local agent mode.');
|
|
242
|
+
|
|
243
|
+
const profile = resolveLocalAgentModeChoice(
|
|
244
|
+
await promptSelect(
|
|
245
|
+
' Local agent mode',
|
|
246
|
+
[
|
|
247
|
+
{ value: 'dev', label: 'dev', aliases: ['1', 'recommended'] },
|
|
248
|
+
{ value: 'strict', label: 'strict', aliases: ['2'] },
|
|
249
|
+
{ value: 'admin', label: 'admin', aliases: ['3', 'dangerous'] },
|
|
250
|
+
],
|
|
251
|
+
'dev',
|
|
252
|
+
),
|
|
253
|
+
);
|
|
254
|
+
await persistLocalAgentTrustDefaults(token, profile);
|
|
255
|
+
|
|
256
|
+
if (profile === 'strict') {
|
|
257
|
+
console.log(' ✓ Strict mode enabled. Local auto-approve is OFF; agent requests require manual approval.\n');
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (profile === 'admin') {
|
|
261
|
+
console.log(' ✓ Admin mode enabled. WARNING: local agents get broad access.\n');
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
console.log(' ✓ Dev mode enabled. Local auto-approve remains ON with scoped profile.\n');
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
async function configureApiKey(
|
|
268
|
+
token: string,
|
|
269
|
+
service: string,
|
|
270
|
+
label: string,
|
|
271
|
+
placeholder: string,
|
|
272
|
+
): Promise<boolean> {
|
|
273
|
+
const prompt = placeholder ? ` ${label} (${placeholder})` : ` ${label}`;
|
|
274
|
+
const key = await promptInput(prompt);
|
|
275
|
+
|
|
276
|
+
if (!key) return false;
|
|
277
|
+
|
|
278
|
+
// Validate
|
|
279
|
+
try {
|
|
280
|
+
const result = await fetchJson<{ valid?: boolean; error?: string }>(
|
|
281
|
+
'/apikeys/validate',
|
|
282
|
+
{ body: { service, key }, token },
|
|
283
|
+
);
|
|
284
|
+
|
|
285
|
+
if (result.valid) {
|
|
286
|
+
console.log(` ✓ Valid\n`);
|
|
287
|
+
} else {
|
|
288
|
+
console.log(` ✗ Invalid: ${result.error || 'unknown error'}`);
|
|
289
|
+
const retry = await promptConfirm(' Try again?');
|
|
290
|
+
if (retry) return configureApiKey(token, service, label, placeholder);
|
|
291
|
+
const saveAnyway = await promptConfirm(' Save anyway?');
|
|
292
|
+
if (!saveAnyway) {
|
|
293
|
+
console.log(' Skipped.\n');
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
} catch (err) {
|
|
298
|
+
const msg = getErrorMessage(err);
|
|
299
|
+
console.log(` ⚠ Could not validate: ${msg}`);
|
|
300
|
+
const saveAnyway = await promptConfirm(' Save anyway?');
|
|
301
|
+
if (!saveAnyway) {
|
|
302
|
+
console.log(' Skipped.\n');
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Save
|
|
308
|
+
await fetchJson('/apikeys', {
|
|
309
|
+
body: { service, name: 'default', key },
|
|
310
|
+
token,
|
|
311
|
+
});
|
|
312
|
+
console.log(` Saved.\n`);
|
|
313
|
+
return true;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
async function configureTelegram(token: string): Promise<boolean> {
|
|
317
|
+
const botToken = await promptInput(' Telegram bot token');
|
|
318
|
+
if (!botToken) return false;
|
|
319
|
+
|
|
320
|
+
// Validate bot token
|
|
321
|
+
try {
|
|
322
|
+
const result = await fetchJson<{ valid?: boolean; error?: string; info?: { botUsername?: string } }>(
|
|
323
|
+
'/apikeys/validate',
|
|
324
|
+
{ body: { service: 'adapter:telegram', key: botToken }, token },
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
if (result.valid) {
|
|
328
|
+
const username = result.info?.botUsername || 'unknown';
|
|
329
|
+
console.log(` ✓ Bot: @${username}\n`);
|
|
330
|
+
} else {
|
|
331
|
+
console.log(` ✗ Invalid bot token: ${result.error || 'unknown error'}`);
|
|
332
|
+
const retry = await promptConfirm(' Try again?');
|
|
333
|
+
if (retry) return configureTelegram(token);
|
|
334
|
+
console.log(' Skipped.\n');
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
} catch (err) {
|
|
338
|
+
const msg = getErrorMessage(err);
|
|
339
|
+
console.log(` ⚠ Could not validate bot token: ${msg}`);
|
|
340
|
+
const skip = await promptConfirm(' Skip Telegram setup?');
|
|
341
|
+
if (skip) {
|
|
342
|
+
console.log(' Skipped.\n');
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Auto-detect chat ID via deep link
|
|
348
|
+
let chatId = '';
|
|
349
|
+
try {
|
|
350
|
+
const linkResult = await fetchJson<{ success?: boolean; link?: string; setupToken?: string; botUsername?: string; error?: string }>(
|
|
351
|
+
'/adapters/telegram/setup-link',
|
|
352
|
+
{ body: { botToken }, token },
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
if (linkResult.success && linkResult.link && linkResult.setupToken) {
|
|
356
|
+
console.log(` Open this link and press Start: ${linkResult.link}\n`);
|
|
357
|
+
process.stdout.write(' Waiting for /start...');
|
|
358
|
+
|
|
359
|
+
// Poll detect-chat (up to 2 attempts ~50s)
|
|
360
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
361
|
+
try {
|
|
362
|
+
const detectResult = await fetchJson<{ chatId?: string | null; firstName?: string; username?: string; verified?: boolean; timeout?: boolean }>(
|
|
363
|
+
'/adapters/telegram/detect-chat',
|
|
364
|
+
{ body: { setupToken: linkResult.setupToken }, token },
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
if (detectResult.chatId) {
|
|
368
|
+
chatId = detectResult.chatId;
|
|
369
|
+
const name = detectResult.username ? `@${detectResult.username}` : detectResult.firstName || '';
|
|
370
|
+
console.log('');
|
|
371
|
+
console.log(` ✓ Detected chat ID: ${chatId}${name ? ` (${name})` : ''}\n`);
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
// timeout — try again
|
|
375
|
+
} catch {
|
|
376
|
+
break;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (!chatId) {
|
|
381
|
+
console.log(' timed out.');
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
} catch {
|
|
385
|
+
// setup-link failed, fall through to manual
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Fall back to manual input if auto-detection didn't work
|
|
389
|
+
if (!chatId) {
|
|
390
|
+
chatId = await promptInput(' Telegram chat ID');
|
|
391
|
+
if (!chatId) {
|
|
392
|
+
console.log(' Skipped (no chat ID).\n');
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Save bot token
|
|
398
|
+
await fetchJson('/apikeys', {
|
|
399
|
+
body: { service: 'adapter:telegram', name: 'botToken', key: botToken },
|
|
400
|
+
token,
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// Save adapter config
|
|
404
|
+
await fetchJson('/adapters', {
|
|
405
|
+
body: { type: 'telegram', enabled: true, config: { chatId } },
|
|
406
|
+
token,
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// Restart adapters
|
|
410
|
+
try {
|
|
411
|
+
await fetchJson('/adapters/restart', { method: 'POST', token });
|
|
412
|
+
} catch {
|
|
413
|
+
// Non-fatal
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Test
|
|
417
|
+
try {
|
|
418
|
+
const testResult = await fetchJson<{ success?: boolean; error?: string }>(
|
|
419
|
+
'/adapters/test',
|
|
420
|
+
{ body: { type: 'telegram' }, token },
|
|
421
|
+
);
|
|
422
|
+
if (testResult.success) {
|
|
423
|
+
console.log(' ✓ Test message sent to Telegram.\n');
|
|
424
|
+
} else {
|
|
425
|
+
console.log(` ⚠ Test failed: ${testResult.error || 'unknown'}. Telegram saved but may need configuration.\n`);
|
|
426
|
+
}
|
|
427
|
+
} catch {
|
|
428
|
+
console.log(' ⚠ Could not send test message. Telegram saved but may need configuration.\n');
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return true;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function printConfigSummary(status: SetupStatus) {
|
|
435
|
+
const check = (val: boolean | undefined) => val ? '✓' : '–';
|
|
436
|
+
console.log(' Configuration:');
|
|
437
|
+
console.log(` Vault: ✓`);
|
|
438
|
+
console.log(` Anthropic: ${check(status.apiKeys?.anthropic)}`);
|
|
439
|
+
console.log(` Alchemy: ${check(status.apiKeys?.alchemy)}`);
|
|
440
|
+
console.log(` Telegram: ${check(status.adapters?.telegram)}`);
|
|
441
|
+
console.log('');
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
function maybeInstallShellHook(): void {
|
|
445
|
+
if (!process.stdout.isTTY || process.env.CI === 'true') {
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
const shell = path.basename(process.env.SHELL || 'bash');
|
|
450
|
+
let rcFile: string;
|
|
451
|
+
let hookCmd: string;
|
|
452
|
+
|
|
453
|
+
switch (shell) {
|
|
454
|
+
case 'zsh':
|
|
455
|
+
rcFile = path.join(os.homedir(), '.zshrc');
|
|
456
|
+
hookCmd = 'eval "$(aura shell-hook zsh)"';
|
|
457
|
+
break;
|
|
458
|
+
case 'bash':
|
|
459
|
+
rcFile = path.join(os.homedir(), '.bashrc');
|
|
460
|
+
hookCmd = 'eval "$(aura shell-hook bash)"';
|
|
461
|
+
break;
|
|
462
|
+
default:
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
try {
|
|
467
|
+
if (fs.existsSync(rcFile)) {
|
|
468
|
+
const content = fs.readFileSync(rcFile, 'utf-8');
|
|
469
|
+
if (content.includes('aura shell-hook')) {
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
fs.appendFileSync(rcFile, `\n# Aura shell hook — auto-load .aura env vars\n${hookCmd}\n`);
|
|
475
|
+
console.log(` ✓ Installed shell hook in ${rcFile}`);
|
|
476
|
+
console.log(` Restart your shell or run: source ${rcFile}\n`);
|
|
477
|
+
} catch {
|
|
478
|
+
// Non-fatal: init should succeed even if shell hook install fails.
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// ─── Post-setup: detect .aura file and offer credential entry ───
|
|
483
|
+
|
|
484
|
+
async function postSetupAuraDetection(): Promise<void> {
|
|
485
|
+
const auraPath = path.join(process.cwd(), '.aura');
|
|
486
|
+
if (!fs.existsSync(auraPath)) return;
|
|
487
|
+
|
|
488
|
+
let mappings;
|
|
489
|
+
try {
|
|
490
|
+
mappings = parseAuraFile(auraPath);
|
|
491
|
+
} catch {
|
|
492
|
+
return; // Invalid .aura file, skip
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (mappings.length === 0) return;
|
|
496
|
+
|
|
497
|
+
console.log(`\n Found .aura file with ${mappings.length} credential(s) needed:\n`);
|
|
498
|
+
for (const m of mappings) {
|
|
499
|
+
const ref = m.vault ? `@${m.vault}/${m.credentialName}/${m.field}` : `${m.credentialName}/${m.field}`;
|
|
500
|
+
console.log(` ${m.envVar} → ${ref}`);
|
|
501
|
+
}
|
|
502
|
+
console.log('');
|
|
503
|
+
|
|
504
|
+
const answer = await promptInput(' Ask your team for access, or enter values manually? (team/manual) [team]');
|
|
505
|
+
const choice = answer?.trim().toLowerCase() || 'team';
|
|
506
|
+
|
|
507
|
+
if (choice === 'manual') {
|
|
508
|
+
// Get auth token via socket
|
|
509
|
+
const kp = generateEphemeralKeypair();
|
|
510
|
+
const token = await bootstrapViaSocket('cli-init', kp);
|
|
511
|
+
const vaultId = await getPrimaryVaultId(token);
|
|
512
|
+
|
|
513
|
+
// Group by credential name
|
|
514
|
+
const byCredential = new Map<string, typeof mappings>();
|
|
515
|
+
for (const m of mappings) {
|
|
516
|
+
const list = byCredential.get(m.credentialName) || [];
|
|
517
|
+
list.push(m);
|
|
518
|
+
byCredential.set(m.credentialName, list);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
for (const [credName, fields] of byCredential) {
|
|
522
|
+
const fieldValues: Array<{ key: string; value: string }> = [];
|
|
523
|
+
|
|
524
|
+
for (const m of fields) {
|
|
525
|
+
const value = await promptInput(` Enter value for ${m.envVar} (→ ${credName}/${m.field})`);
|
|
526
|
+
if (value) {
|
|
527
|
+
fieldValues.push({ key: m.field, value });
|
|
528
|
+
} else {
|
|
529
|
+
console.log(` Skipped ${m.envVar}`);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
if (fieldValues.length > 0) {
|
|
534
|
+
const result = await createCredentialViaApi({
|
|
535
|
+
token,
|
|
536
|
+
vaultId,
|
|
537
|
+
name: credName,
|
|
538
|
+
fields: fieldValues,
|
|
539
|
+
});
|
|
540
|
+
if (result.success) {
|
|
541
|
+
console.log(` ✓ Created credential: ${credName}`);
|
|
542
|
+
} else {
|
|
543
|
+
console.error(` ✗ Failed to create ${credName}: ${result.error}`);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
console.log('');
|
|
548
|
+
} else {
|
|
549
|
+
console.log(' Ask your team admin to share these credentials.');
|
|
550
|
+
console.log(' Once they\'re in your vault, run: aura env -- <your-command>\n');
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// ─── Post-setup: --from-dotenv migration ────────────────────────
|
|
555
|
+
|
|
556
|
+
async function resolveDotenvMigrationToken(existingToken?: string): Promise<string> {
|
|
557
|
+
if (existingToken) return existingToken;
|
|
558
|
+
|
|
559
|
+
const envToken = process.env.AURA_TOKEN?.trim();
|
|
560
|
+
if (envToken) return envToken;
|
|
561
|
+
|
|
562
|
+
const kp = generateEphemeralKeypair();
|
|
563
|
+
try {
|
|
564
|
+
return await bootstrapViaSocket('cli-init', kp);
|
|
565
|
+
} catch (socketErr) {
|
|
566
|
+
if (!process.stdin.isTTY) {
|
|
567
|
+
throw new Error(
|
|
568
|
+
`${getErrorMessage(socketErr)}\n` +
|
|
569
|
+
'Set AURA_TOKEN or run `aura unlock` in another terminal, then retry `aura init --from-dotenv`.',
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
console.log(' Socket auth unavailable. Unlocking vault to continue .env migration...');
|
|
574
|
+
const password = await promptPassword(' Vault password');
|
|
575
|
+
const publicKey = await fetchPublicKey();
|
|
576
|
+
const encrypted = encryptPassword(password, publicKey);
|
|
577
|
+
const { publicKey: agentPubkey } = generateAgentKeypair();
|
|
578
|
+
const unlock = await fetchJson<{ token: string }>('/unlock', {
|
|
579
|
+
body: { encrypted, pubkey: agentPubkey },
|
|
580
|
+
});
|
|
581
|
+
return unlock.token;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
async function postSetupDotenvMigration(existingToken?: string): Promise<void> {
|
|
586
|
+
const args = process.argv.slice(2);
|
|
587
|
+
const fromIdx = args.indexOf('--from');
|
|
588
|
+
const fromPath = fromIdx >= 0 && fromIdx + 1 < args.length ? args[fromIdx + 1] : undefined;
|
|
589
|
+
const dryRun = args.includes('--dry-run');
|
|
590
|
+
const noGroup = args.includes('--no-group');
|
|
591
|
+
|
|
592
|
+
const envPath = fromPath || path.join(process.cwd(), '.env');
|
|
593
|
+
|
|
594
|
+
const token = await resolveDotenvMigrationToken(existingToken);
|
|
595
|
+
|
|
596
|
+
await migrateDotenv({
|
|
597
|
+
token,
|
|
598
|
+
envPath,
|
|
599
|
+
noGroup,
|
|
600
|
+
dryRun,
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// ─── Headless password flow ─────────────────────────────────────
|
|
605
|
+
|
|
606
|
+
async function passwordFlow(password: string): Promise<string> {
|
|
607
|
+
if (password.length < 8) {
|
|
608
|
+
console.log(' Error: Password must be at least 8 characters.');
|
|
609
|
+
process.exit(1);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
console.log(' Creating vault...');
|
|
613
|
+
const publicKey = await fetchPublicKey();
|
|
614
|
+
const encrypted = encryptPassword(password, publicKey);
|
|
615
|
+
const { publicKey: agentPubkey } = generateAgentKeypair();
|
|
616
|
+
|
|
617
|
+
const vault = await fetchJson<{
|
|
618
|
+
success: boolean;
|
|
619
|
+
address: string;
|
|
620
|
+
mnemonic: string;
|
|
621
|
+
token: string;
|
|
622
|
+
}>('/setup', { body: { encrypted, pubkey: agentPubkey } });
|
|
623
|
+
|
|
624
|
+
console.log(' Vault created!\n');
|
|
625
|
+
|
|
626
|
+
printSeedPhrase(vault.mnemonic);
|
|
627
|
+
loadServiceIfNeeded();
|
|
628
|
+
|
|
629
|
+
printBanner('TIME TO AURAMAXX');
|
|
630
|
+
console.log(` Cold wallet address: ${vault.address}`);
|
|
631
|
+
console.log(` Admin token: ${vault.token}\n`);
|
|
632
|
+
console.log(' IMPORTANT: Save the seed phrase above. It cannot be recovered.\n');
|
|
633
|
+
if (isServiceInstalled()) {
|
|
634
|
+
console.log(' Servers are running in the background. Use `auramaxx stop` to stop.\n');
|
|
635
|
+
} else {
|
|
636
|
+
console.log(' Servers are running. Press Ctrl+C to stop.\n');
|
|
637
|
+
}
|
|
638
|
+
return vault.token;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// ─── Main ────────────────────────────────────────────────────────
|
|
642
|
+
|
|
643
|
+
async function main() {
|
|
644
|
+
printBanner('AURAMAXX.SH BOOTING');
|
|
645
|
+
|
|
646
|
+
const root = findProjectRoot();
|
|
647
|
+
const debugMode = process.argv.includes('--debug');
|
|
648
|
+
|
|
649
|
+
// Keep boot output concise before runtime startup.
|
|
650
|
+
ensureDirectories();
|
|
651
|
+
|
|
652
|
+
// Step 1: Migrations
|
|
653
|
+
try {
|
|
654
|
+
runMigrations(root);
|
|
655
|
+
if (debugMode) console.log(' Migrating... complete');
|
|
656
|
+
} catch (error) {
|
|
657
|
+
const msg = getErrorMessage(error);
|
|
658
|
+
console.error(` Migration failed: ${msg}`);
|
|
659
|
+
console.error(' Try running: npx prisma migrate deploy');
|
|
660
|
+
process.exit(1);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// Step 2: Prisma client
|
|
664
|
+
try {
|
|
665
|
+
generatePrismaClient(root);
|
|
666
|
+
if (debugMode) console.log(' Database... complete');
|
|
667
|
+
} catch (error) {
|
|
668
|
+
const msg = getErrorMessage(error);
|
|
669
|
+
console.error(` Prisma generate failed: ${msg}`);
|
|
670
|
+
process.exit(1);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// Step 3: Start server headless (dashboard started later if needed)
|
|
674
|
+
if (debugMode) console.log(' Starting...');
|
|
675
|
+
stopServer();
|
|
676
|
+
serverChildren = startServer({ headless: true, debug: debugMode });
|
|
677
|
+
|
|
678
|
+
try {
|
|
679
|
+
await waitForServer(15000);
|
|
680
|
+
if (debugMode) console.log(' Starting... complete\n');
|
|
681
|
+
} catch {
|
|
682
|
+
console.error(' Server failed to start within 15 seconds.');
|
|
683
|
+
console.error(` Check for port conflicts on :${process.env.WALLET_SERVER_PORT || '4242'}`);
|
|
684
|
+
stopServer();
|
|
685
|
+
process.exit(1);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// Step 5: Check if vault already exists
|
|
689
|
+
const status = await fetchSetupStatus();
|
|
690
|
+
|
|
691
|
+
const args = process.argv.slice(2);
|
|
692
|
+
const fromDotenv = args.includes('--from-dotenv');
|
|
693
|
+
const backgroundAfterSetup = args.includes('--background') || args.includes('--daemon') || args.includes('-d');
|
|
694
|
+
let setupToken: string | undefined;
|
|
695
|
+
|
|
696
|
+
if (status.hasWallet) {
|
|
697
|
+
if (fromDotenv) {
|
|
698
|
+
printSection('Existing Vault', 'Vault already initialized. Running dotenv migration.');
|
|
699
|
+
// Vault exists, just do the dotenv migration
|
|
700
|
+
console.log(' Vault already exists. Running .env migration...\n');
|
|
701
|
+
await postSetupDotenvMigration();
|
|
702
|
+
} else {
|
|
703
|
+
printSection('Already Initialized', 'Vault already exists. Starting dashboard.');
|
|
704
|
+
const dashboard = startDashboard();
|
|
705
|
+
serverChildren.push(dashboard);
|
|
706
|
+
|
|
707
|
+
console.log(' Vault already exists — already initialized.\n');
|
|
708
|
+
console.log(` Cold wallet: ${status.address}`);
|
|
709
|
+
console.log(` Dashboard: http://localhost:${DASHBOARD_PORT}\n`);
|
|
710
|
+
|
|
711
|
+
// TODO(v2): .env-to-vault migration
|
|
712
|
+
// const envPath = path.join(process.cwd(), '.env');
|
|
713
|
+
// if (fs.existsSync(envPath)) {
|
|
714
|
+
// console.log(' 💡 Found .env file. Run `aura init --from-dotenv` to migrate secrets to the vault.\n');
|
|
715
|
+
// }
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
if (fromDotenv) {
|
|
719
|
+
await postSetupAuraDetection();
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
maybeInstallShellHook();
|
|
723
|
+
// Activate launchd service if plist was written during bootstrap
|
|
724
|
+
loadServiceIfNeeded();
|
|
725
|
+
if (backgroundAfterSetup || isServiceInstalled()) {
|
|
726
|
+
console.log(' Servers are running in the background.');
|
|
727
|
+
console.log(' Use `auramaxx stop` to stop.\n');
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
console.log(' Servers are running. Press Ctrl+C to stop.\n');
|
|
731
|
+
// Keep event loop alive (detached children don't keep it running)
|
|
732
|
+
setInterval(() => {}, 60_000);
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
// Step 6: Choose setup mode
|
|
737
|
+
const dashboardFlag = args.includes('--dashboard');
|
|
738
|
+
const passwordIdx = args.indexOf('--password');
|
|
739
|
+
const passwordValue = passwordIdx >= 0 && passwordIdx + 1 < args.length
|
|
740
|
+
? args[passwordIdx + 1]
|
|
741
|
+
: undefined;
|
|
742
|
+
|
|
743
|
+
if (passwordValue) {
|
|
744
|
+
if (fromDotenv) {
|
|
745
|
+
setupToken = await passwordFlow(passwordValue);
|
|
746
|
+
} else {
|
|
747
|
+
await passwordFlow(passwordValue);
|
|
748
|
+
}
|
|
749
|
+
} else if (dashboardFlag) {
|
|
750
|
+
await dashboardFlow();
|
|
751
|
+
} else {
|
|
752
|
+
const mode = await promptSetupMode();
|
|
753
|
+
if (mode === 'dashboard') {
|
|
754
|
+
await dashboardFlow();
|
|
755
|
+
} else {
|
|
756
|
+
if (fromDotenv) {
|
|
757
|
+
setupToken = await terminalFlow();
|
|
758
|
+
} else {
|
|
759
|
+
await terminalFlow();
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// Step 7: Post-setup — handle --from-dotenv or detect .aura
|
|
765
|
+
if (fromDotenv) {
|
|
766
|
+
try {
|
|
767
|
+
await postSetupDotenvMigration(setupToken);
|
|
768
|
+
} finally {
|
|
769
|
+
setupToken = undefined;
|
|
770
|
+
}
|
|
771
|
+
} else {
|
|
772
|
+
// Suggest --from-dotenv if .env exists but no .aura
|
|
773
|
+
// TODO(v2): .env-to-vault migration
|
|
774
|
+
// const envPath = path.join(process.cwd(), '.env');
|
|
775
|
+
// const auraPath = path.join(process.cwd(), '.aura');
|
|
776
|
+
// if (fs.existsSync(envPath) && !fs.existsSync(auraPath)) {
|
|
777
|
+
// console.log(' 💡 Found .env file. Run `aura init --from-dotenv` to migrate secrets to the vault.\n');
|
|
778
|
+
// }
|
|
779
|
+
|
|
780
|
+
// Detect .aura file and offer credential entry
|
|
781
|
+
await postSetupAuraDetection();
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
maybeInstallShellHook();
|
|
785
|
+
if (backgroundAfterSetup) {
|
|
786
|
+
console.log(' Aura services are running in background mode.');
|
|
787
|
+
console.log(' Use `npx auramaxx status` to check health and `npx auramaxx stop` to stop.\n');
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
// Keep event loop alive (detached children don't keep it running)
|
|
791
|
+
setInterval(() => {}, 60_000);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
main().catch((error) => {
|
|
795
|
+
console.error('\nError:', getErrorMessage(error));
|
|
796
|
+
stopServer();
|
|
797
|
+
process.exit(1);
|
|
798
|
+
});
|