auramaxx 1.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +26 -0
- package/README.md +112 -0
- package/bin/aurawallet.js +121 -0
- package/docs/ADAPTERS.md +467 -0
- package/docs/API.md +2679 -0
- package/docs/APPS.md +198 -0
- package/docs/ARCHITECTURE.md +350 -0
- package/docs/AUTH.md +698 -0
- package/docs/BEST-PRACTICES.md +121 -0
- package/docs/CLI.md +61 -0
- package/docs/DEVELOPING-APPS.md +452 -0
- package/docs/EXTENSION.md +97 -0
- package/docs/JOBS.md +33 -0
- package/docs/MCP.md +76 -0
- package/docs/PROTOCOL.md +142 -0
- package/docs/SETUP.md +219 -0
- package/docs/WORKSPACE.md +672 -0
- package/docs/agent-auth.md +63 -0
- package/docs/aura-file.md +48 -0
- package/docs/credentials.md +53 -0
- package/docs/external/getting-started.md +65 -0
- package/docs/external/overview.md +45 -0
- package/docs/external/use-cases.md +48 -0
- package/docs/external/why-aura.md +35 -0
- package/docs/jobs/connect-agent.md +77 -0
- package/docs/jobs/migrate-from-dotenv.md +79 -0
- package/docs/jobs/recover-from-lockout.md +72 -0
- package/docs/jobs/secure-ci.md +63 -0
- package/docs/oauth2.md +42 -0
- package/docs/passkeys.md +60 -0
- package/docs/security.md +540 -0
- package/docs/specs/aura-open-protocol.md +61 -0
- package/docs/specs/aura-provider-plugin.md +24 -0
- package/docs/specs/aura-registry-model.md +31 -0
- package/docs/specs/fixtures/invalid-bad-key.aura +1 -0
- package/docs/specs/fixtures/invalid-bad-unicode-escape.aura +1 -0
- package/docs/specs/fixtures/invalid-duplicate-key.aura +2 -0
- package/docs/specs/fixtures/valid-basic.aura +4 -0
- package/docs/specs/fixtures/valid-provider-ref.aura +1 -0
- package/docs/specs/fixtures/valid-quoted-escapes.aura +2 -0
- package/docs/templates/RELEASE_NOTES_TEMPLATE.md +22 -0
- package/docs/totp.md +40 -0
- package/docs/wallet/AI.md +508 -0
- package/docs/wallet/DEVELOPING-STRATEGIES.md +713 -0
- package/docs/wallet/README.md +47 -0
- package/docs/wallet/STRATEGY.md +89 -0
- package/next.config.ts +21 -0
- package/package.json +151 -0
- package/postcss.config.mjs +8 -0
- package/prisma/migrations/20260214170000_baseline/migration.sql +511 -0
- package/prisma/migrations/20260216214537_add_passkey_model/migration.sql +18 -0
- package/prisma/migrations/20260217150500_add_credential_access_audit/migration.sql +31 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +447 -0
- package/public/logo-chevron.svg +31 -0
- package/public/logo-concentric.svg +31 -0
- package/public/logo-crosshatch.svg +39 -0
- package/public/logo-dashed.svg +39 -0
- package/public/logo-horizontal.svg +31 -0
- package/public/logo-m56.svg +64 -0
- package/public/logo.webp +0 -0
- package/scripts/add-app.js +245 -0
- package/scripts/init.sh +57 -0
- package/scripts/migrate-apikeys-to-credentials.ts +35 -0
- package/scripts/sandbox-agent-flow.sh +235 -0
- package/scripts/sandbox.sh +175 -0
- package/scripts/validate-job-docs.mjs +125 -0
- package/server/abi/SwapHelper.json +438 -0
- package/server/cli/approval.ts +447 -0
- package/server/cli/commands/app.ts +204 -0
- package/server/cli/commands/cron.ts +24 -0
- package/server/cli/commands/doctor.ts +1007 -0
- package/server/cli/commands/env.ts +456 -0
- package/server/cli/commands/init.ts +752 -0
- package/server/cli/commands/mcp.ts +125 -0
- package/server/cli/commands/restore.ts +314 -0
- package/server/cli/commands/shell-hook.ts +468 -0
- package/server/cli/commands/start.ts +62 -0
- package/server/cli/commands/status.ts +59 -0
- package/server/cli/commands/stop.ts +14 -0
- package/server/cli/commands/token.ts +180 -0
- package/server/cli/commands/unlock.ts +49 -0
- package/server/cli/commands/vault.ts +417 -0
- package/server/cli/index.ts +328 -0
- package/server/cli/lib/aura-parser.ts +64 -0
- package/server/cli/lib/credential-create.ts +74 -0
- package/server/cli/lib/credential-resolve.ts +254 -0
- package/server/cli/lib/dotenv-migrate.ts +116 -0
- package/server/cli/lib/dotenv-parser.ts +146 -0
- package/server/cli/lib/http.ts +91 -0
- package/server/cli/lib/init-steps.ts +76 -0
- package/server/cli/lib/local-agent-trust.ts +45 -0
- package/server/cli/lib/process.ts +136 -0
- package/server/cli/lib/prompt.ts +85 -0
- package/server/cli/lib/theme.ts +240 -0
- package/server/cli/socket.ts +570 -0
- package/server/cli/transport-client.ts +50 -0
- package/server/cron/index.ts +137 -0
- package/server/cron/job.ts +31 -0
- package/server/cron/jobs/balance-sync.ts +436 -0
- package/server/cron/jobs/incoming-scan.ts +506 -0
- package/server/cron/jobs/native-price.ts +70 -0
- package/server/cron/jobs/orphan-cleanup.ts +40 -0
- package/server/cron/jobs/strategy-runner.ts +175 -0
- package/server/cron/scheduler.ts +125 -0
- package/server/index.ts +406 -0
- package/server/lib/adapters/factory.ts +110 -0
- package/server/lib/adapters/index.ts +19 -0
- package/server/lib/adapters/router.ts +297 -0
- package/server/lib/adapters/telegram.ts +645 -0
- package/server/lib/adapters/types.ts +89 -0
- package/server/lib/adapters/webhook.ts +95 -0
- package/server/lib/address.ts +49 -0
- package/server/lib/agent-auth/contracts.ts +1194 -0
- package/server/lib/agent-profiles.ts +328 -0
- package/server/lib/ai.ts +285 -0
- package/server/lib/api-registry/contracts.ts +86 -0
- package/server/lib/api-registry/validation.ts +172 -0
- package/server/lib/apikey-migration.ts +189 -0
- package/server/lib/app-installer.ts +505 -0
- package/server/lib/app-tokens.ts +247 -0
- package/server/lib/auth.ts +314 -0
- package/server/lib/batch.ts +242 -0
- package/server/lib/cold.ts +874 -0
- package/server/lib/config.ts +381 -0
- package/server/lib/credential-access-audit.ts +85 -0
- package/server/lib/credential-access-policy.ts +110 -0
- package/server/lib/credential-health.ts +343 -0
- package/server/lib/credential-import.ts +487 -0
- package/server/lib/credential-scope.ts +87 -0
- package/server/lib/credential-shares.ts +190 -0
- package/server/lib/credential-transport.ts +342 -0
- package/server/lib/credential-vault.ts +77 -0
- package/server/lib/credentials.ts +333 -0
- package/server/lib/crypto.ts +8 -0
- package/server/lib/db.ts +15 -0
- package/server/lib/defaults.ts +366 -0
- package/server/lib/dex/index.ts +80 -0
- package/server/lib/dex/relay.ts +235 -0
- package/server/lib/dex/types.ts +59 -0
- package/server/lib/dex/uniswap.ts +370 -0
- package/server/lib/e2e-agent/artifacts.ts +36 -0
- package/server/lib/e2e-agent/contracts.ts +112 -0
- package/server/lib/e2e-agent/validation.ts +135 -0
- package/server/lib/encrypt.ts +128 -0
- package/server/lib/error.ts +20 -0
- package/server/lib/events.ts +205 -0
- package/server/lib/hot.ts +357 -0
- package/server/lib/key-fingerprint.ts +28 -0
- package/server/lib/logger.ts +331 -0
- package/server/lib/network.ts +137 -0
- package/server/lib/notifications.ts +219 -0
- package/server/lib/oauth2-refresh.ts +241 -0
- package/server/lib/oursecret.ts +54 -0
- package/server/lib/passkey-credential.ts +360 -0
- package/server/lib/passkey.ts +68 -0
- package/server/lib/permissions.ts +248 -0
- package/server/lib/pino.ts +24 -0
- package/server/lib/policy-preview.ts +138 -0
- package/server/lib/price.ts +338 -0
- package/server/lib/prices.ts +34 -0
- package/server/lib/project-scope.ts +239 -0
- package/server/lib/resolve-action.ts +427 -0
- package/server/lib/resolve.ts +36 -0
- package/server/lib/sessions.ts +632 -0
- package/server/lib/solana/connection.ts +26 -0
- package/server/lib/solana/jupiter.ts +128 -0
- package/server/lib/solana/transfer.ts +108 -0
- package/server/lib/solana/wallet.ts +136 -0
- package/server/lib/strategy/emits.ts +21 -0
- package/server/lib/strategy/engine.ts +1305 -0
- package/server/lib/strategy/executor.ts +115 -0
- package/server/lib/strategy/hook-context.ts +158 -0
- package/server/lib/strategy/hooks.ts +990 -0
- package/server/lib/strategy/index.ts +28 -0
- package/server/lib/strategy/installer.ts +305 -0
- package/server/lib/strategy/loader.ts +256 -0
- package/server/lib/strategy/message.ts +235 -0
- package/server/lib/strategy/repository.ts +218 -0
- package/server/lib/strategy/session-logger.ts +693 -0
- package/server/lib/strategy/sources.ts +288 -0
- package/server/lib/strategy/state.ts +189 -0
- package/server/lib/strategy/templates.ts +403 -0
- package/server/lib/strategy/tick.ts +404 -0
- package/server/lib/strategy/types.ts +230 -0
- package/server/lib/swap.ts +3 -0
- package/server/lib/temp.ts +86 -0
- package/server/lib/token-metadata.ts +86 -0
- package/server/lib/token-safety.ts +200 -0
- package/server/lib/token-search.ts +444 -0
- package/server/lib/totp.ts +194 -0
- package/server/lib/transactions.ts +123 -0
- package/server/lib/transport.ts +75 -0
- package/server/lib/txhistory/decoder.ts +262 -0
- package/server/lib/txhistory/enricher.ts +652 -0
- package/server/lib/txhistory/index.ts +391 -0
- package/server/lib/txhistory/signatures.ts +59 -0
- package/server/lib/verified-summary.ts +421 -0
- package/server/mcp/profile-policy.ts +30 -0
- package/server/mcp/server.ts +619 -0
- package/server/mcp/tools.ts +523 -0
- package/server/middleware/auth.ts +119 -0
- package/server/middleware/requestLogger.ts +84 -0
- package/server/routes/actions.ts +459 -0
- package/server/routes/adapters.ts +703 -0
- package/server/routes/addressbook.ts +113 -0
- package/server/routes/ai.ts +34 -0
- package/server/routes/apikeys.ts +295 -0
- package/server/routes/apps.ts +601 -0
- package/server/routes/auth.ts +457 -0
- package/server/routes/backup.ts +340 -0
- package/server/routes/batch.ts +270 -0
- package/server/routes/bookmarks.ts +162 -0
- package/server/routes/credential-shares.ts +198 -0
- package/server/routes/credential-vaults.ts +154 -0
- package/server/routes/credentials.ts +1290 -0
- package/server/routes/dashboard.ts +71 -0
- package/server/routes/defaults.ts +124 -0
- package/server/routes/fund.ts +229 -0
- package/server/routes/import.ts +352 -0
- package/server/routes/launch.ts +665 -0
- package/server/routes/lock.ts +54 -0
- package/server/routes/logs.ts +68 -0
- package/server/routes/nuke.ts +111 -0
- package/server/routes/passkey-credentials.ts +99 -0
- package/server/routes/passkey.ts +346 -0
- package/server/routes/portfolio.ts +217 -0
- package/server/routes/price.ts +63 -0
- package/server/routes/resolve.ts +31 -0
- package/server/routes/security.ts +45 -0
- package/server/routes/send-evm.ts +241 -0
- package/server/routes/send-solana.ts +281 -0
- package/server/routes/send.ts +178 -0
- package/server/routes/setup.ts +210 -0
- package/server/routes/strategy.ts +894 -0
- package/server/routes/swap-evm.ts +353 -0
- package/server/routes/swap-solana.ts +177 -0
- package/server/routes/swap.ts +356 -0
- package/server/routes/token.ts +247 -0
- package/server/routes/unlock.ts +403 -0
- package/server/routes/wallet-assets.ts +361 -0
- package/server/routes/wallet-transactions.ts +515 -0
- package/server/routes/wallet.ts +710 -0
- package/server/types.ts +146 -0
- package/skills/aurawallet/SKILL.md +739 -0
- package/skills/aurawallet-setup/SKILL.md +74 -0
- package/skills/security-review/SKILL.md +148 -0
- package/src/app/api/agent-requests/route.ts +30 -0
- package/src/app/api/apps/install/route.ts +126 -0
- package/src/app/api/apps/manifests/route.ts +16 -0
- package/src/app/api/apps/static/[...path]/route.ts +57 -0
- package/src/app/api/events/route.ts +92 -0
- package/src/app/api/page.tsx +212 -0
- package/src/app/api/workspace/[id]/apps/[wid]/route.ts +119 -0
- package/src/app/api/workspace/[id]/apps/route.ts +81 -0
- package/src/app/api/workspace/[id]/export/route.ts +67 -0
- package/src/app/api/workspace/[id]/route.ts +168 -0
- package/src/app/api/workspace/auth.ts +34 -0
- package/src/app/api/workspace/config/route.ts +106 -0
- package/src/app/api/workspace/import/route.ts +127 -0
- package/src/app/api/workspace/route.ts +116 -0
- package/src/app/app/page.tsx +2122 -0
- package/src/app/apple-icon.png +0 -0
- package/src/app/docs/page.tsx +178 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +572 -0
- package/src/app/health/page.tsx +5 -0
- package/src/app/hello/page.tsx +15 -0
- package/src/app/icon.png +0 -0
- package/src/app/layout.tsx +34 -0
- package/src/app/page.tsx +986 -0
- package/src/app/providers.tsx +90 -0
- package/src/app/share/[token]/page.tsx +295 -0
- package/src/components/ChainSelector.tsx +144 -0
- package/src/components/HumanActionBar.tsx +695 -0
- package/src/components/NotificationDrawer.tsx +129 -0
- package/src/components/apps/AgentKeysApp.tsx +490 -0
- package/src/components/apps/App.tsx +153 -0
- package/src/components/apps/AppGrid.tsx +15 -0
- package/src/components/apps/DetailedAddressDrawer.tsx +325 -0
- package/src/components/apps/DraggableApp.tsx +562 -0
- package/src/components/apps/IFrameApp.tsx +73 -0
- package/src/components/apps/LogsApp.tsx +360 -0
- package/src/components/apps/SendApp.tsx +394 -0
- package/src/components/apps/SetupWizardApp.tsx +1004 -0
- package/src/components/apps/SystemDefaultsApp.tsx +845 -0
- package/src/components/apps/ThirdPartyApp.tsx +428 -0
- package/src/components/apps/TokenApp.tsx +319 -0
- package/src/components/apps/TransactionsApp.tsx +438 -0
- package/src/components/apps/WalletDetailApp.tsx +1505 -0
- package/src/components/apps/index.ts +13 -0
- package/src/components/design-system/Button.tsx +53 -0
- package/src/components/design-system/ChainIndicator.tsx +65 -0
- package/src/components/design-system/ChainSelector.tsx +137 -0
- package/src/components/design-system/ConfirmationModal.tsx +106 -0
- package/src/components/design-system/ConfirmationPopover.tsx +81 -0
- package/src/components/design-system/Drawer.tsx +123 -0
- package/src/components/design-system/FilterDropdown.tsx +72 -0
- package/src/components/design-system/Modal.tsx +206 -0
- package/src/components/design-system/Popover.tsx +142 -0
- package/src/components/design-system/TextInput.tsx +85 -0
- package/src/components/design-system/Toggle.tsx +58 -0
- package/src/components/design-system/index.ts +11 -0
- package/src/components/docs/DocsThemeToggle.tsx +49 -0
- package/src/components/health/CredentialHealthDashboard.tsx +214 -0
- package/src/components/icons/ChainIcons.tsx +72 -0
- package/src/components/layout/AppStoreDrawer.tsx +369 -0
- package/src/components/layout/ContentArea.tsx +21 -0
- package/src/components/layout/TabBar.tsx +278 -0
- package/src/components/layout/WalletSidebar.tsx +1033 -0
- package/src/components/layout/index.ts +4 -0
- package/src/components/marketing/AuraWalletSpecOverlay.tsx +635 -0
- package/src/components/marketing/DeviceMorphExperience.tsx +216 -0
- package/src/components/vault/ApiKeysConsole.tsx +1080 -0
- package/src/components/vault/AuditConsole.tsx +584 -0
- package/src/components/vault/CredentialDetail.tsx +455 -0
- package/src/components/vault/CredentialEmpty.tsx +55 -0
- package/src/components/vault/CredentialField.tsx +361 -0
- package/src/components/vault/CredentialForm.tsx +1212 -0
- package/src/components/vault/CredentialList.tsx +165 -0
- package/src/components/vault/CredentialRow.tsx +97 -0
- package/src/components/vault/CredentialShareModal.tsx +178 -0
- package/src/components/vault/CredentialVault.tsx +754 -0
- package/src/components/vault/CredentialWalletWidget.tsx +103 -0
- package/src/components/vault/ImportCredentialsModal.tsx +515 -0
- package/src/components/vault/LargeTypeModal.tsx +64 -0
- package/src/components/vault/PasswordGenerator.tsx +224 -0
- package/src/components/vault/TOTPDisplay.tsx +123 -0
- package/src/components/vault/VaultSidebar.tsx +413 -0
- package/src/components/vault/types.ts +54 -0
- package/src/context/AuthContext.tsx +337 -0
- package/src/context/PriceContext.tsx +113 -0
- package/src/context/ThemeContext.tsx +164 -0
- package/src/context/WebSocketContext.tsx +269 -0
- package/src/context/WorkspaceContext.tsx +668 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useAgentActions.ts +368 -0
- package/src/hooks/useBalance.ts +103 -0
- package/src/hooks/useBalances.ts +129 -0
- package/src/instrumentation.ts +12 -0
- package/src/lib/api.ts +449 -0
- package/src/lib/app-loader.ts +148 -0
- package/src/lib/app-registry.ts +178 -0
- package/src/lib/app-sdk.ts +157 -0
- package/src/lib/audit-console-adapter.ts +151 -0
- package/src/lib/auth-client.ts +75 -0
- package/src/lib/config.ts +74 -0
- package/src/lib/crypto.ts +112 -0
- package/src/lib/db.ts +21 -0
- package/src/lib/docs.ts +390 -0
- package/src/lib/events.ts +361 -0
- package/src/lib/pino.ts +24 -0
- package/src/lib/theme-handlers.ts +168 -0
- package/src/lib/theme.ts +351 -0
- package/src/lib/tokenData.ts +378 -0
- package/src/lib/vault-crypto.ts +129 -0
- package/src/lib/websocket-server.ts +302 -0
- package/src/lib/websocket-setup.ts +79 -0
- package/src/lib/wordlist.ts +2050 -0
- package/src/lib/workspace-handlers.ts +285 -0
- package/start.sh +80 -0
- package/tailwind.config.ts +99 -0
- package/tsconfig.json +42 -0
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal Approval Interface
|
|
3
|
+
*
|
|
4
|
+
* Connects to the WebSocket server to receive ACTION_CREATED events
|
|
5
|
+
* and presents an interactive terminal UI for approve/reject decisions.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as readline from 'readline';
|
|
9
|
+
import { WebSocket } from 'ws';
|
|
10
|
+
import { getErrorMessage } from '../lib/error';
|
|
11
|
+
|
|
12
|
+
interface HumanAction {
|
|
13
|
+
id: string;
|
|
14
|
+
type: string;
|
|
15
|
+
agentId: string;
|
|
16
|
+
limit: number;
|
|
17
|
+
permissions: string[];
|
|
18
|
+
ttl: number;
|
|
19
|
+
createdAt: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface ApprovalManagerOptions {
|
|
23
|
+
serverUrl: string;
|
|
24
|
+
getToken: () => string | null;
|
|
25
|
+
autoApprove?: boolean;
|
|
26
|
+
headless?: boolean; // Skip terminal interface (for --password-stdin mode)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class ApprovalManager {
|
|
30
|
+
private ws: WebSocket | null = null;
|
|
31
|
+
private pendingRequests: Map<string, HumanAction> = new Map();
|
|
32
|
+
private rl: readline.Interface | null = null;
|
|
33
|
+
private options: ApprovalManagerOptions;
|
|
34
|
+
private reconnectTimeout: NodeJS.Timeout | null = null;
|
|
35
|
+
private isRunning = false;
|
|
36
|
+
|
|
37
|
+
constructor(options: ApprovalManagerOptions) {
|
|
38
|
+
this.options = options;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Start the approval manager
|
|
43
|
+
*/
|
|
44
|
+
async start(): Promise<void> {
|
|
45
|
+
this.isRunning = true;
|
|
46
|
+
|
|
47
|
+
// Fetch any existing pending requests
|
|
48
|
+
await this.fetchPendingRequests();
|
|
49
|
+
|
|
50
|
+
// Connect to WebSocket
|
|
51
|
+
this.connectWebSocket();
|
|
52
|
+
|
|
53
|
+
// Set up terminal interface (skip in headless mode)
|
|
54
|
+
if (!this.options.headless) {
|
|
55
|
+
this.setupTerminalInterface();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Stop the approval manager
|
|
61
|
+
*/
|
|
62
|
+
stop(): void {
|
|
63
|
+
this.isRunning = false;
|
|
64
|
+
|
|
65
|
+
if (this.reconnectTimeout) {
|
|
66
|
+
clearTimeout(this.reconnectTimeout);
|
|
67
|
+
this.reconnectTimeout = null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (this.ws) {
|
|
71
|
+
this.ws.close();
|
|
72
|
+
this.ws = null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (this.rl) {
|
|
76
|
+
this.rl.close();
|
|
77
|
+
this.rl = null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Fetch existing pending requests from the server
|
|
83
|
+
*/
|
|
84
|
+
private async fetchPendingRequests(): Promise<void> {
|
|
85
|
+
try {
|
|
86
|
+
const token = this.options.getToken();
|
|
87
|
+
if (!token) return;
|
|
88
|
+
|
|
89
|
+
const response = await fetch(`${this.options.serverUrl}/actions/pending`, {
|
|
90
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (response.ok) {
|
|
94
|
+
const data = await response.json() as { success?: boolean; actions?: HumanAction[] };
|
|
95
|
+
const requests = data.actions || [];
|
|
96
|
+
for (const req of requests) {
|
|
97
|
+
this.addRequest(req);
|
|
98
|
+
}
|
|
99
|
+
if (requests.length > 0) {
|
|
100
|
+
console.log(`\nFound ${requests.length} pending request(s).`);
|
|
101
|
+
this.displayQueue();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
// Silently ignore - will get requests via WebSocket
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Connect to the WebSocket server
|
|
111
|
+
*/
|
|
112
|
+
private connectWebSocket(): void {
|
|
113
|
+
const wsUrl = process.env.WS_URL || 'ws://localhost:4748';
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
this.ws = new WebSocket(wsUrl);
|
|
117
|
+
|
|
118
|
+
this.ws.on('open', () => {
|
|
119
|
+
console.log('WebSocket connected - listening for events');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
this.ws.on('message', (data: Buffer) => {
|
|
123
|
+
try {
|
|
124
|
+
const event = JSON.parse(data.toString());
|
|
125
|
+
this.handleEvent(event);
|
|
126
|
+
} catch {
|
|
127
|
+
// Ignore malformed messages
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
this.ws.on('close', () => {
|
|
132
|
+
if (this.isRunning) {
|
|
133
|
+
console.log('WebSocket disconnected, reconnecting in 3s...');
|
|
134
|
+
this.reconnectTimeout = setTimeout(() => {
|
|
135
|
+
this.connectWebSocket();
|
|
136
|
+
}, 3000);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
this.ws.on('error', (error) => {
|
|
141
|
+
console.error('WebSocket error:', error.message);
|
|
142
|
+
});
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.error('Failed to connect WebSocket:', error);
|
|
145
|
+
if (this.isRunning) {
|
|
146
|
+
this.reconnectTimeout = setTimeout(() => {
|
|
147
|
+
this.connectWebSocket();
|
|
148
|
+
}, 3000);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Handle incoming WebSocket event
|
|
155
|
+
*/
|
|
156
|
+
private handleEvent(event: { type: string; data: unknown }): void {
|
|
157
|
+
switch (event.type) {
|
|
158
|
+
case 'action:created':
|
|
159
|
+
this.handleRequestCreated(event.data as HumanAction);
|
|
160
|
+
break;
|
|
161
|
+
case 'action:resolved':
|
|
162
|
+
this.handleRequestResolved((event.data as { id: string }).id);
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Handle new request created
|
|
169
|
+
*/
|
|
170
|
+
private handleRequestCreated(request: HumanAction): void {
|
|
171
|
+
this.addRequest(request);
|
|
172
|
+
|
|
173
|
+
console.log('\n┌─────────────────────────────────────────────────────────────┐');
|
|
174
|
+
console.log('│ NEW AGENT REQUEST │');
|
|
175
|
+
console.log('├─────────────────────────────────────────────────────────────┤');
|
|
176
|
+
console.log(`│ ID: ${request.id.substring(0, 40).padEnd(45)}│`);
|
|
177
|
+
console.log(`│ Agent: ${request.agentId.substring(0, 40).padEnd(45)}│`);
|
|
178
|
+
console.log(`│ Type: ${request.type.padEnd(45)}│`);
|
|
179
|
+
console.log(`│ Limit: ${(request.limit + ' ETH').padEnd(45)}│`);
|
|
180
|
+
console.log(`│ Permissions: ${request.permissions.slice(0, 3).join(', ').substring(0, 40).padEnd(45)}│`);
|
|
181
|
+
console.log(`│ TTL: ${(request.ttl + 's').padEnd(45)}│`);
|
|
182
|
+
console.log('└─────────────────────────────────────────────────────────────┘');
|
|
183
|
+
|
|
184
|
+
if (this.options.autoApprove) {
|
|
185
|
+
console.log('Auto-approving (--auto-approve enabled)...');
|
|
186
|
+
this.resolveAction(request.id, true);
|
|
187
|
+
} else {
|
|
188
|
+
console.log('\nEnter request number to review, or:');
|
|
189
|
+
console.log(' a <id> - approve r <id> - reject l - list pending\n');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Handle request resolved (approved or rejected)
|
|
195
|
+
*/
|
|
196
|
+
private handleRequestResolved(requestId: string): void {
|
|
197
|
+
this.pendingRequests.delete(requestId);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Add request to pending queue
|
|
202
|
+
*/
|
|
203
|
+
private addRequest(request: HumanAction): void {
|
|
204
|
+
this.pendingRequests.set(request.id, {
|
|
205
|
+
...request,
|
|
206
|
+
createdAt: Date.now()
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Display the pending request queue
|
|
212
|
+
*/
|
|
213
|
+
private displayQueue(): void {
|
|
214
|
+
const requests = Array.from(this.pendingRequests.values());
|
|
215
|
+
|
|
216
|
+
if (requests.length === 0) {
|
|
217
|
+
console.log('\nNo pending requests.\n');
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
console.log('\n┌─────────────────────────────────────────────────────────────┐');
|
|
222
|
+
console.log('│ PENDING REQUESTS │');
|
|
223
|
+
console.log('├─────────────────────────────────────────────────────────────┤');
|
|
224
|
+
|
|
225
|
+
requests.forEach((req, index) => {
|
|
226
|
+
const shortId = req.id.substring(0, 8);
|
|
227
|
+
const agent = req.agentId.substring(0, 20).padEnd(20);
|
|
228
|
+
const type = req.type.substring(0, 15).padEnd(15);
|
|
229
|
+
console.log(`│ ${(index + 1).toString().padStart(2)}. [${shortId}] ${agent} ${type} ${req.limit} ETH │`);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
console.log('└─────────────────────────────────────────────────────────────┘');
|
|
233
|
+
console.log('\nCommands: a <id> approve, r <id> reject, <num> review, l list\n');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Set up terminal interface for user input
|
|
238
|
+
*/
|
|
239
|
+
private setupTerminalInterface(): void {
|
|
240
|
+
this.rl = readline.createInterface({
|
|
241
|
+
input: process.stdin,
|
|
242
|
+
output: process.stdout,
|
|
243
|
+
prompt: 'aura> '
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
this.rl.on('line', (line) => {
|
|
247
|
+
this.handleCommand(line.trim());
|
|
248
|
+
this.rl?.prompt();
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
this.rl.on('close', () => {
|
|
252
|
+
// Interface closed
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Initial prompt
|
|
256
|
+
this.rl.prompt();
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Handle user command
|
|
261
|
+
*/
|
|
262
|
+
private handleCommand(input: string): void {
|
|
263
|
+
if (!input) return;
|
|
264
|
+
|
|
265
|
+
const parts = input.split(/\s+/);
|
|
266
|
+
const cmd = parts[0].toLowerCase();
|
|
267
|
+
const arg = parts[1];
|
|
268
|
+
|
|
269
|
+
switch (cmd) {
|
|
270
|
+
case 'l':
|
|
271
|
+
case 'list':
|
|
272
|
+
this.displayQueue();
|
|
273
|
+
break;
|
|
274
|
+
|
|
275
|
+
case 'a':
|
|
276
|
+
case 'approve':
|
|
277
|
+
if (arg) {
|
|
278
|
+
this.approveByIdOrNumber(arg);
|
|
279
|
+
} else {
|
|
280
|
+
console.log('Usage: a <id or number>');
|
|
281
|
+
}
|
|
282
|
+
break;
|
|
283
|
+
|
|
284
|
+
case 'r':
|
|
285
|
+
case 'reject':
|
|
286
|
+
if (arg) {
|
|
287
|
+
this.rejectByIdOrNumber(arg);
|
|
288
|
+
} else {
|
|
289
|
+
console.log('Usage: r <id or number>');
|
|
290
|
+
}
|
|
291
|
+
break;
|
|
292
|
+
|
|
293
|
+
case 'h':
|
|
294
|
+
case 'help':
|
|
295
|
+
this.showHelp();
|
|
296
|
+
break;
|
|
297
|
+
|
|
298
|
+
case 'q':
|
|
299
|
+
case 'quit':
|
|
300
|
+
console.log('Use Ctrl+C to exit.');
|
|
301
|
+
break;
|
|
302
|
+
|
|
303
|
+
default:
|
|
304
|
+
// Check if it's a number (review by index)
|
|
305
|
+
const num = parseInt(cmd, 10);
|
|
306
|
+
if (!isNaN(num)) {
|
|
307
|
+
this.reviewByNumber(num);
|
|
308
|
+
} else {
|
|
309
|
+
console.log(`Unknown command: ${cmd}. Type 'h' for help.`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Show help
|
|
316
|
+
*/
|
|
317
|
+
private showHelp(): void {
|
|
318
|
+
console.log(`
|
|
319
|
+
Commands:
|
|
320
|
+
l, list List all pending requests
|
|
321
|
+
a, approve <id> Approve request by ID or number
|
|
322
|
+
r, reject <id> Reject request by ID or number
|
|
323
|
+
<number> Review request details by queue number
|
|
324
|
+
h, help Show this help
|
|
325
|
+
Ctrl+C Exit CLI
|
|
326
|
+
`);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Review request by queue number
|
|
331
|
+
*/
|
|
332
|
+
private reviewByNumber(num: number): void {
|
|
333
|
+
const requests = Array.from(this.pendingRequests.values());
|
|
334
|
+
const index = num - 1;
|
|
335
|
+
|
|
336
|
+
if (index < 0 || index >= requests.length) {
|
|
337
|
+
console.log(`Invalid number. Use 1-${requests.length}`);
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const req = requests[index];
|
|
342
|
+
console.log(`
|
|
343
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
344
|
+
│ REQUEST DETAILS │
|
|
345
|
+
├─────────────────────────────────────────────────────────────┤
|
|
346
|
+
│ ID: ${req.id}
|
|
347
|
+
│ Agent: ${req.agentId}
|
|
348
|
+
│ Type: ${req.type}
|
|
349
|
+
│ Limit: ${req.limit} ETH
|
|
350
|
+
│ Permissions: ${req.permissions.join(', ')}
|
|
351
|
+
│ TTL: ${req.ttl}s (${Math.round(req.ttl / 60)} minutes)
|
|
352
|
+
└─────────────────────────────────────────────────────────────┘
|
|
353
|
+
|
|
354
|
+
a ${num} - approve r ${num} - reject
|
|
355
|
+
`);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Approve by ID or queue number
|
|
360
|
+
*/
|
|
361
|
+
private approveByIdOrNumber(arg: string): void {
|
|
362
|
+
const id = this.resolveRequestId(arg);
|
|
363
|
+
if (id) {
|
|
364
|
+
this.resolveAction(id, true);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Reject by ID or queue number
|
|
370
|
+
*/
|
|
371
|
+
private rejectByIdOrNumber(arg: string): void {
|
|
372
|
+
const id = this.resolveRequestId(arg);
|
|
373
|
+
if (id) {
|
|
374
|
+
this.resolveAction(id, false);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Resolve argument to request ID
|
|
380
|
+
*/
|
|
381
|
+
private resolveRequestId(arg: string): string | null {
|
|
382
|
+
// Try as number first
|
|
383
|
+
const num = parseInt(arg, 10);
|
|
384
|
+
if (!isNaN(num)) {
|
|
385
|
+
const requests = Array.from(this.pendingRequests.values());
|
|
386
|
+
const index = num - 1;
|
|
387
|
+
if (index >= 0 && index < requests.length) {
|
|
388
|
+
return requests[index].id;
|
|
389
|
+
}
|
|
390
|
+
console.log(`Invalid number. Use 1-${requests.length}`);
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Try as ID (partial match)
|
|
395
|
+
const matching = Array.from(this.pendingRequests.keys()).filter(
|
|
396
|
+
id => id.startsWith(arg) || id.includes(arg)
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
if (matching.length === 1) {
|
|
400
|
+
return matching[0];
|
|
401
|
+
} else if (matching.length > 1) {
|
|
402
|
+
console.log('Ambiguous ID, matches:', matching.map(id => id.substring(0, 12)).join(', '));
|
|
403
|
+
return null;
|
|
404
|
+
} else {
|
|
405
|
+
console.log('Request not found:', arg);
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Resolve an action (approve or reject)
|
|
412
|
+
*/
|
|
413
|
+
private async resolveAction(requestId: string, approved: boolean): Promise<void> {
|
|
414
|
+
const token = this.options.getToken();
|
|
415
|
+
if (!token) {
|
|
416
|
+
console.log('Error: No admin token available');
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
try {
|
|
421
|
+
const response = await fetch(`${this.options.serverUrl}/actions/${requestId}/resolve`, {
|
|
422
|
+
method: 'POST',
|
|
423
|
+
headers: {
|
|
424
|
+
'Content-Type': 'application/json',
|
|
425
|
+
Authorization: `Bearer ${token}`
|
|
426
|
+
},
|
|
427
|
+
body: JSON.stringify({ approved })
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
const data = await response.json() as { success?: boolean; error?: string; agentId?: string; token?: string };
|
|
431
|
+
|
|
432
|
+
if (response.ok && data.success) {
|
|
433
|
+
if (approved) {
|
|
434
|
+
console.log(`✓ Request approved. Token created for ${data.agentId}`);
|
|
435
|
+
} else {
|
|
436
|
+
console.log(`✓ Request rejected`);
|
|
437
|
+
}
|
|
438
|
+
this.pendingRequests.delete(requestId);
|
|
439
|
+
} else {
|
|
440
|
+
console.log(`✗ Failed to ${approved ? 'approve' : 'reject'}: ${data.error || 'Unknown error'}`);
|
|
441
|
+
}
|
|
442
|
+
} catch (error) {
|
|
443
|
+
const message = getErrorMessage(error);
|
|
444
|
+
console.log(`✗ Error ${approved ? 'approving' : 'rejecting'} request: ${message}`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* aurawallet app — Manage installed apps
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* npx aurawallet app install <source> [--name <id>] [--force]
|
|
6
|
+
* npx aurawallet app remove <id> [--yes]
|
|
7
|
+
* npx aurawallet app list
|
|
8
|
+
* npx aurawallet app update <id>
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
installApp,
|
|
13
|
+
removeApp,
|
|
14
|
+
listApps,
|
|
15
|
+
updateApp,
|
|
16
|
+
} from '../../lib/app-installer';
|
|
17
|
+
import { promptConfirm } from '../lib/prompt';
|
|
18
|
+
import { getErrorMessage } from '../../lib/error';
|
|
19
|
+
|
|
20
|
+
const args = process.argv.slice(2);
|
|
21
|
+
|
|
22
|
+
function getFlag(name: string): boolean {
|
|
23
|
+
return args.includes(`--${name}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getFlagValue(name: string): string | undefined {
|
|
27
|
+
const idx = args.indexOf(`--${name}`);
|
|
28
|
+
if (idx === -1 || idx + 1 >= args.length) return undefined;
|
|
29
|
+
return args[idx + 1];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function showHelp() {
|
|
33
|
+
console.log(`
|
|
34
|
+
aurawallet app — Manage installed apps
|
|
35
|
+
|
|
36
|
+
Usage:
|
|
37
|
+
npx aurawallet app install <source> [--name <id>] [--force]
|
|
38
|
+
npx aurawallet app remove <id> [--yes]
|
|
39
|
+
npx aurawallet app list
|
|
40
|
+
npx aurawallet app update <id>
|
|
41
|
+
|
|
42
|
+
Sources:
|
|
43
|
+
Local path ./path/to/app or /absolute/path
|
|
44
|
+
Git repo github.com/user/repo
|
|
45
|
+
Tarball https://example.com/app.tar.gz
|
|
46
|
+
Zip https://example.com/app.zip
|
|
47
|
+
Subdirectory github.com/user/repo#path=apps/my-app
|
|
48
|
+
|
|
49
|
+
Options:
|
|
50
|
+
--name <id> Override the app folder name
|
|
51
|
+
--force Overwrite existing app with same ID
|
|
52
|
+
--yes Skip removal confirmation
|
|
53
|
+
|
|
54
|
+
Examples:
|
|
55
|
+
npx aurawallet app install github.com/user/my-app
|
|
56
|
+
npx aurawallet app install ./my-local-app --name custom-id
|
|
57
|
+
npx aurawallet app list
|
|
58
|
+
npx aurawallet app remove my-app
|
|
59
|
+
npx aurawallet app update my-app
|
|
60
|
+
`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function main() {
|
|
64
|
+
const subcommand = args[0];
|
|
65
|
+
|
|
66
|
+
if (!subcommand || subcommand === '--help' || subcommand === '-h') {
|
|
67
|
+
showHelp();
|
|
68
|
+
process.exit(0);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
switch (subcommand) {
|
|
72
|
+
case 'install': {
|
|
73
|
+
const source = args[1];
|
|
74
|
+
if (!source || source.startsWith('--')) {
|
|
75
|
+
console.error(' Error: Missing source argument\n');
|
|
76
|
+
console.error(' Usage: npx aurawallet app install <source> [--name <id>] [--force]');
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const name = getFlagValue('name');
|
|
81
|
+
const force = getFlag('force');
|
|
82
|
+
|
|
83
|
+
console.log(`\n Installing app from: ${source}`);
|
|
84
|
+
if (name) console.log(` App ID: ${name}`);
|
|
85
|
+
if (force) console.log(` Force: overwrite existing`);
|
|
86
|
+
console.log('');
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
const result = installApp(source, { name, force });
|
|
90
|
+
console.log(` ┌─────────────────────────────────────────┐`);
|
|
91
|
+
console.log(` │ App installed successfully │`);
|
|
92
|
+
console.log(` ├─────────────────────────────────────────┤`);
|
|
93
|
+
console.log(` │ ID: ${result.id.padEnd(32)}│`);
|
|
94
|
+
console.log(` │ Name: ${result.name.padEnd(32)}│`);
|
|
95
|
+
console.log(` │ Source: ${result.source.type.padEnd(32)}│`);
|
|
96
|
+
console.log(` │ Path: apps/${result.id.padEnd(23)}│`);
|
|
97
|
+
console.log(` └─────────────────────────────────────────┘`);
|
|
98
|
+
console.log('');
|
|
99
|
+
console.log(' App will appear in the App Store under INSTALLED.');
|
|
100
|
+
console.log(' Restart the server or use the dashboard to load it.\n');
|
|
101
|
+
} catch (err) {
|
|
102
|
+
const msg = getErrorMessage(err);
|
|
103
|
+
console.error(` Error: ${msg}\n`);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
case 'remove': {
|
|
110
|
+
const id = args[1];
|
|
111
|
+
if (!id || id.startsWith('--')) {
|
|
112
|
+
console.error(' Error: Missing app ID\n');
|
|
113
|
+
console.error(' Usage: npx aurawallet app remove <id> [--yes]');
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const skipConfirm = getFlag('yes');
|
|
118
|
+
|
|
119
|
+
if (!skipConfirm) {
|
|
120
|
+
const confirmed = await promptConfirm(` Remove app "${id}"?`);
|
|
121
|
+
if (!confirmed) {
|
|
122
|
+
console.log(' Cancelled.\n');
|
|
123
|
+
process.exit(0);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
removeApp(id);
|
|
129
|
+
console.log(`\n App "${id}" removed.\n`);
|
|
130
|
+
console.log(' Note: App token will be revoked on next server restart.\n');
|
|
131
|
+
} catch (err) {
|
|
132
|
+
const msg = getErrorMessage(err);
|
|
133
|
+
console.error(` Error: ${msg}\n`);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
case 'list': {
|
|
140
|
+
const apps = listApps();
|
|
141
|
+
|
|
142
|
+
if (apps.length === 0) {
|
|
143
|
+
console.log('\n No apps installed.\n');
|
|
144
|
+
console.log(' Install a app:');
|
|
145
|
+
console.log(' npx aurawallet app install <source>\n');
|
|
146
|
+
process.exit(0);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
console.log(`\n Installed Apps (${apps.length})\n`);
|
|
150
|
+
|
|
151
|
+
for (const w of apps) {
|
|
152
|
+
const sourceLabel = w.source
|
|
153
|
+
? `${w.source.type} — ${w.source.url}`
|
|
154
|
+
: 'local (no .source.json)';
|
|
155
|
+
const perms = w.permissions.length > 0
|
|
156
|
+
? w.permissions.join(', ')
|
|
157
|
+
: 'none';
|
|
158
|
+
|
|
159
|
+
console.log(` ┌ ${w.name} (${w.id})`);
|
|
160
|
+
console.log(` │ ${w.description || '(no description)'}`);
|
|
161
|
+
console.log(` │ Permissions: ${perms}`);
|
|
162
|
+
console.log(` │ Source: ${sourceLabel}`);
|
|
163
|
+
if (w.source?.installedAt) {
|
|
164
|
+
console.log(` │ Installed: ${w.source.installedAt}`);
|
|
165
|
+
}
|
|
166
|
+
console.log(` └──`);
|
|
167
|
+
console.log('');
|
|
168
|
+
}
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
case 'update': {
|
|
173
|
+
const id = args[1];
|
|
174
|
+
if (!id || id.startsWith('--')) {
|
|
175
|
+
console.error(' Error: Missing app ID\n');
|
|
176
|
+
console.error(' Usage: npx aurawallet app update <id>');
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
console.log(`\n Updating app "${id}"...\n`);
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
const result = updateApp(id);
|
|
184
|
+
console.log(` App "${result.id}" updated from ${result.source.type} source.`);
|
|
185
|
+
console.log(` Restart the server to load changes.\n`);
|
|
186
|
+
} catch (err) {
|
|
187
|
+
const msg = getErrorMessage(err);
|
|
188
|
+
console.error(` Error: ${msg}\n`);
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
default:
|
|
195
|
+
console.error(` Unknown subcommand: ${subcommand}\n`);
|
|
196
|
+
showHelp();
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
main().catch((error) => {
|
|
202
|
+
console.error('Error:', getErrorMessage(error));
|
|
203
|
+
process.exit(1);
|
|
204
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* aurawallet cron — Run the cron server standalone
|
|
3
|
+
* Useful for development or running cron separately from the main server.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { findProjectRoot } from '../lib/process';
|
|
7
|
+
import { execFileSync } from 'child_process';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
|
|
10
|
+
const root = findProjectRoot();
|
|
11
|
+
const cronEntry = path.join(root, 'server', 'cron', 'index.ts');
|
|
12
|
+
|
|
13
|
+
console.log('Starting AuraWallet Cron Server...\n');
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
execFileSync('npx', ['tsx', cronEntry], {
|
|
17
|
+
cwd: root,
|
|
18
|
+
stdio: 'inherit',
|
|
19
|
+
env: process.env,
|
|
20
|
+
});
|
|
21
|
+
} catch (error: unknown) {
|
|
22
|
+
const exitCode = (error as { status?: number }).status || 1;
|
|
23
|
+
process.exit(exitCode);
|
|
24
|
+
}
|