arc402-cli 0.9.18 → 0.10.0
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/README.md +41 -2
- package/dist/abis.d.ts +1 -0
- package/dist/abis.d.ts.map +1 -1
- package/dist/abis.js +45 -14
- package/dist/abis.js.map +1 -1
- package/dist/bundler.d.ts +1 -1
- package/dist/bundler.d.ts.map +1 -1
- package/dist/bundler.js +61 -27
- package/dist/bundler.js.map +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +9 -5
- package/dist/client.js.map +1 -1
- package/dist/coinbase-smart-wallet.js +4 -1
- package/dist/coinbase-smart-wallet.js.map +1 -1
- package/dist/commands/accept.js +28 -25
- package/dist/commands/accept.js.map +1 -1
- package/dist/commands/agent-handshake.js +18 -15
- package/dist/commands/agent-handshake.js.map +1 -1
- package/dist/commands/agent.js +104 -98
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/agreements.js +98 -62
- package/dist/commands/agreements.js.map +1 -1
- package/dist/commands/arbitrator.js +81 -45
- package/dist/commands/arbitrator.js.map +1 -1
- package/dist/commands/arena-handshake.d.ts.map +1 -1
- package/dist/commands/arena-handshake.js +35 -53
- package/dist/commands/arena-handshake.js.map +1 -1
- package/dist/commands/arena.js +18 -12
- package/dist/commands/arena.js.map +1 -1
- package/dist/commands/backup.js +36 -30
- package/dist/commands/backup.js.map +1 -1
- package/dist/commands/cancel.js +18 -15
- package/dist/commands/cancel.js.map +1 -1
- package/dist/commands/channel.js +81 -45
- package/dist/commands/channel.js.map +1 -1
- package/dist/commands/coldstart.js +34 -31
- package/dist/commands/coldstart.js.map +1 -1
- package/dist/commands/compute.d.ts +14 -0
- package/dist/commands/compute.d.ts.map +1 -0
- package/dist/commands/compute.js +466 -0
- package/dist/commands/compute.js.map +1 -0
- package/dist/commands/config.js +30 -24
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/contract-interaction.js +15 -12
- package/dist/commands/contract-interaction.js.map +1 -1
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/daemon.js +135 -98
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/deliver.js +76 -37
- package/dist/commands/deliver.js.map +1 -1
- package/dist/commands/discover.js +27 -24
- package/dist/commands/discover.js.map +1 -1
- package/dist/commands/dispute.js +110 -104
- package/dist/commands/dispute.js.map +1 -1
- package/dist/commands/doctor.js +55 -16
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/endpoint.js +95 -56
- package/dist/commands/endpoint.js.map +1 -1
- package/dist/commands/feed.js +18 -11
- package/dist/commands/feed.js.map +1 -1
- package/dist/commands/hire.js +40 -37
- package/dist/commands/hire.js.map +1 -1
- package/dist/commands/migrate.js +33 -30
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/negotiate.d.ts.map +1 -1
- package/dist/commands/negotiate.js +36 -34
- package/dist/commands/negotiate.js.map +1 -1
- package/dist/commands/openshell.js +104 -68
- package/dist/commands/openshell.js.map +1 -1
- package/dist/commands/owner.js +20 -17
- package/dist/commands/owner.js.map +1 -1
- package/dist/commands/policy.js +43 -41
- package/dist/commands/policy.js.map +1 -1
- package/dist/commands/relay.d.ts.map +1 -1
- package/dist/commands/relay.js +51 -18
- package/dist/commands/relay.js.map +1 -1
- package/dist/commands/remediate.js +23 -20
- package/dist/commands/remediate.js.map +1 -1
- package/dist/commands/reputation.js +27 -25
- package/dist/commands/reputation.js.map +1 -1
- package/dist/commands/setup.js +104 -65
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/trust.js +20 -17
- package/dist/commands/trust.js.map +1 -1
- package/dist/commands/verify.js +21 -18
- package/dist/commands/verify.js.map +1 -1
- package/dist/commands/wallet.d.ts.map +1 -1
- package/dist/commands/wallet.js +645 -679
- package/dist/commands/wallet.js.map +1 -1
- package/dist/commands/watch.js +36 -33
- package/dist/commands/watch.js.map +1 -1
- package/dist/commands/watchtower.js +73 -37
- package/dist/commands/watchtower.js.map +1 -1
- package/dist/commands/workroom.d.ts.map +1 -1
- package/dist/commands/workroom.js +282 -143
- package/dist/commands/workroom.js.map +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +71 -22
- package/dist/config.js.map +1 -1
- package/dist/daemon/compute-metering.d.ts +61 -0
- package/dist/daemon/compute-metering.d.ts.map +1 -0
- package/dist/daemon/compute-metering.js +299 -0
- package/dist/daemon/compute-metering.js.map +1 -0
- package/dist/daemon/compute-session.d.ts +100 -0
- package/dist/daemon/compute-session.d.ts.map +1 -0
- package/dist/daemon/compute-session.js +231 -0
- package/dist/daemon/compute-session.js.map +1 -0
- package/dist/daemon/config.d.ts +19 -1
- package/dist/daemon/config.d.ts.map +1 -1
- package/dist/daemon/config.js +90 -16
- package/dist/daemon/config.js.map +1 -1
- package/dist/daemon/credentials.d.ts +24 -0
- package/dist/daemon/credentials.d.ts.map +1 -0
- package/dist/daemon/credentials.js +80 -0
- package/dist/daemon/credentials.js.map +1 -0
- package/dist/daemon/delivery-client.d.ts +35 -0
- package/dist/daemon/delivery-client.d.ts.map +1 -0
- package/dist/daemon/delivery-client.js +231 -0
- package/dist/daemon/delivery-client.js.map +1 -0
- package/dist/daemon/file-delivery.d.ts +98 -0
- package/dist/daemon/file-delivery.d.ts.map +1 -0
- package/dist/daemon/file-delivery.js +461 -0
- package/dist/daemon/file-delivery.js.map +1 -0
- package/dist/daemon/hire-listener.d.ts +3 -3
- package/dist/daemon/hire-listener.d.ts.map +1 -1
- package/dist/daemon/hire-listener.js +47 -13
- package/dist/daemon/hire-listener.js.map +1 -1
- package/dist/daemon/index.d.ts +2 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +526 -53
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/job-lifecycle.d.ts +1 -1
- package/dist/daemon/job-lifecycle.d.ts.map +1 -1
- package/dist/daemon/job-lifecycle.js +51 -11
- package/dist/daemon/job-lifecycle.js.map +1 -1
- package/dist/daemon/notify.d.ts +1 -1
- package/dist/daemon/notify.d.ts.map +1 -1
- package/dist/daemon/notify.js +53 -19
- package/dist/daemon/notify.js.map +1 -1
- package/dist/daemon/token-metering.js +47 -8
- package/dist/daemon/token-metering.js.map +1 -1
- package/dist/daemon/userops.d.ts +2 -2
- package/dist/daemon/userops.d.ts.map +1 -1
- package/dist/daemon/userops.js +27 -23
- package/dist/daemon/userops.js.map +1 -1
- package/dist/daemon/wallet-monitor.d.ts +1 -1
- package/dist/daemon/wallet-monitor.d.ts.map +1 -1
- package/dist/daemon/wallet-monitor.js +12 -8
- package/dist/daemon/wallet-monitor.js.map +1 -1
- package/dist/daemon/worker-executor.d.ts +71 -0
- package/dist/daemon/worker-executor.d.ts.map +1 -0
- package/dist/daemon/worker-executor.js +382 -0
- package/dist/daemon/worker-executor.js.map +1 -0
- package/dist/drain-v4.js +64 -26
- package/dist/drain-v4.js.map +1 -1
- package/dist/endpoint-config.js +63 -20
- package/dist/endpoint-config.js.map +1 -1
- package/dist/endpoint-notify.js +48 -9
- package/dist/endpoint-notify.js.map +1 -1
- package/dist/index.js +50 -18
- package/dist/index.js.map +1 -1
- package/dist/openshell-runtime.d.ts.map +1 -1
- package/dist/openshell-runtime.js +82 -38
- package/dist/openshell-runtime.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +85 -78
- package/dist/program.js.map +1 -1
- package/dist/repl.js +31 -25
- package/dist/repl.js.map +1 -1
- package/dist/signing.js +6 -3
- package/dist/signing.js.map +1 -1
- package/dist/telegram-notify.js +40 -3
- package/dist/telegram-notify.js.map +1 -1
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +56 -89
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/Footer.js +7 -4
- package/dist/tui/Footer.js.map +1 -1
- package/dist/tui/Header.d.ts +1 -1
- package/dist/tui/Header.d.ts.map +1 -1
- package/dist/tui/Header.js +14 -9
- package/dist/tui/Header.js.map +1 -1
- package/dist/tui/InputLine.d.ts +2 -1
- package/dist/tui/InputLine.d.ts.map +1 -1
- package/dist/tui/InputLine.js +47 -97
- package/dist/tui/InputLine.js.map +1 -1
- package/dist/tui/Viewport.d.ts +1 -2
- package/dist/tui/Viewport.d.ts.map +1 -1
- package/dist/tui/Viewport.js +26 -6
- package/dist/tui/Viewport.js.map +1 -1
- package/dist/tui/WalletConnectPairing.js +19 -16
- package/dist/tui/WalletConnectPairing.js.map +1 -1
- package/dist/tui/components/Button.js +9 -6
- package/dist/tui/components/Button.js.map +1 -1
- package/dist/tui/components/CeremonyView.js +8 -5
- package/dist/tui/components/CeremonyView.js.map +1 -1
- package/dist/tui/components/CompletionDropdown.js +9 -6
- package/dist/tui/components/CompletionDropdown.js.map +1 -1
- package/dist/tui/components/ConfirmPrompt.js +8 -5
- package/dist/tui/components/ConfirmPrompt.js.map +1 -1
- package/dist/tui/components/CustomTextInput.js +14 -11
- package/dist/tui/components/CustomTextInput.js.map +1 -1
- package/dist/tui/components/InteractiveTable.js +12 -9
- package/dist/tui/components/InteractiveTable.js.map +1 -1
- package/dist/tui/components/StepSpinner.js +13 -10
- package/dist/tui/components/StepSpinner.js.map +1 -1
- package/dist/tui/components/Toast.js +12 -8
- package/dist/tui/components/Toast.js.map +1 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +21 -28
- package/dist/tui/index.js.map +1 -1
- package/dist/tui/useChat.js +19 -13
- package/dist/tui/useChat.js.map +1 -1
- package/dist/tui/useCommand.d.ts +2 -3
- package/dist/tui/useCommand.d.ts.map +1 -1
- package/dist/tui/useCommand.js +24 -100
- package/dist/tui/useCommand.js.map +1 -1
- package/dist/tui/useNotifications.js +8 -5
- package/dist/tui/useNotifications.js.map +1 -1
- package/dist/tui/useScroll.d.ts.map +1 -1
- package/dist/tui/useScroll.js +12 -15
- package/dist/tui/useScroll.js.map +1 -1
- package/dist/ui/banner.d.ts +0 -12
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +19 -35
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/colors.js +19 -13
- package/dist/ui/colors.js.map +1 -1
- package/dist/ui/format.js +14 -6
- package/dist/ui/format.js.map +1 -1
- package/dist/ui/qr-render.js +11 -4
- package/dist/ui/qr-render.js.map +1 -1
- package/dist/ui/rpc-fallback.js +11 -6
- package/dist/ui/rpc-fallback.js.map +1 -1
- package/dist/ui/spinner.js +12 -6
- package/dist/ui/spinner.js.map +1 -1
- package/dist/ui/tree.js +6 -3
- package/dist/ui/tree.js.map +1 -1
- package/dist/utils/format.js +41 -27
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/hash.js +42 -4
- package/dist/utils/hash.js.map +1 -1
- package/dist/utils/time.js +6 -2
- package/dist/utils/time.js.map +1 -1
- package/dist/wallet-router.d.ts +1 -1
- package/dist/wallet-router.d.ts.map +1 -1
- package/dist/wallet-router.js +19 -12
- package/dist/wallet-router.js.map +1 -1
- package/dist/walletconnect-session.d.ts +1 -1
- package/dist/walletconnect-session.d.ts.map +1 -1
- package/dist/walletconnect-session.js +11 -6
- package/dist/walletconnect-session.js.map +1 -1
- package/dist/walletconnect.d.ts +5 -6
- package/dist/walletconnect.d.ts.map +1 -1
- package/dist/walletconnect.js +35 -32
- package/dist/walletconnect.js.map +1 -1
- package/package.json +11 -10
- package/INK6-UX-SPEC.md +0 -446
- package/MIGRATION-SPEC.md +0 -108
- package/TUI-SPEC.md +0 -214
- package/scripts/authorize-machine-key.ts +0 -43
- package/scripts/drain-wallet.ts +0 -149
- package/scripts/execute-spend-only.ts +0 -81
- package/scripts/register-agent-userop.ts +0 -186
- package/src/abis.ts +0 -187
- package/src/bundler.ts +0 -235
- package/src/client.ts +0 -36
- package/src/coinbase-smart-wallet.ts +0 -51
- package/src/commands/accept.ts +0 -64
- package/src/commands/agent-handshake.ts +0 -72
- package/src/commands/agent.ts +0 -691
- package/src/commands/agreements.ts +0 -350
- package/src/commands/arbitrator.ts +0 -180
- package/src/commands/arena-handshake.ts +0 -274
- package/src/commands/arena.ts +0 -122
- package/src/commands/backup.ts +0 -117
- package/src/commands/cancel.ts +0 -35
- package/src/commands/channel.ts +0 -218
- package/src/commands/coldstart.ts +0 -165
- package/src/commands/config.ts +0 -68
- package/src/commands/contract-interaction.ts +0 -166
- package/src/commands/daemon.ts +0 -1054
- package/src/commands/deliver.ts +0 -148
- package/src/commands/discover.ts +0 -350
- package/src/commands/dispute.ts +0 -375
- package/src/commands/doctor.ts +0 -172
- package/src/commands/endpoint.ts +0 -620
- package/src/commands/feed.ts +0 -229
- package/src/commands/hire.ts +0 -245
- package/src/commands/migrate.ts +0 -177
- package/src/commands/negotiate.ts +0 -272
- package/src/commands/openshell.ts +0 -1055
- package/src/commands/owner.ts +0 -35
- package/src/commands/policy.ts +0 -263
- package/src/commands/relay.ts +0 -277
- package/src/commands/remediate.ts +0 -24
- package/src/commands/reputation.ts +0 -79
- package/src/commands/setup.ts +0 -343
- package/src/commands/trust.ts +0 -27
- package/src/commands/verify.ts +0 -91
- package/src/commands/wallet.ts +0 -3548
- package/src/commands/watch.ts +0 -220
- package/src/commands/watchtower.ts +0 -248
- package/src/commands/workroom.ts +0 -963
- package/src/config.ts +0 -220
- package/src/daemon/config.ts +0 -344
- package/src/daemon/hire-listener.ts +0 -226
- package/src/daemon/index.ts +0 -1089
- package/src/daemon/job-lifecycle.ts +0 -215
- package/src/daemon/notify.ts +0 -297
- package/src/daemon/token-metering.ts +0 -183
- package/src/daemon/userops.ts +0 -119
- package/src/daemon/wallet-monitor.ts +0 -90
- package/src/drain-v4.ts +0 -159
- package/src/endpoint-config.ts +0 -83
- package/src/endpoint-notify.ts +0 -129
- package/src/index.ts +0 -74
- package/src/openshell-runtime.ts +0 -281
- package/src/program.ts +0 -88
- package/src/repl.ts +0 -178
- package/src/signing.ts +0 -28
- package/src/telegram-notify.ts +0 -88
- package/src/tui/App.tsx +0 -263
- package/src/tui/Footer.tsx +0 -18
- package/src/tui/Header.tsx +0 -45
- package/src/tui/InputLine.tsx +0 -243
- package/src/tui/Viewport.tsx +0 -51
- package/src/tui/WalletConnectPairing.tsx +0 -114
- package/src/tui/components/Button.tsx +0 -38
- package/src/tui/components/CeremonyView.tsx +0 -39
- package/src/tui/components/CompletionDropdown.tsx +0 -56
- package/src/tui/components/ConfirmPrompt.tsx +0 -36
- package/src/tui/components/CustomTextInput.tsx +0 -132
- package/src/tui/components/InteractiveTable.tsx +0 -106
- package/src/tui/components/StepSpinner.tsx +0 -84
- package/src/tui/components/Toast.tsx +0 -59
- package/src/tui/index.tsx +0 -90
- package/src/tui/useChat.ts +0 -103
- package/src/tui/useCommand.ts +0 -238
- package/src/tui/useNotifications.ts +0 -28
- package/src/tui/useScroll.ts +0 -69
- package/src/ui/banner.ts +0 -78
- package/src/ui/colors.ts +0 -30
- package/src/ui/format.ts +0 -78
- package/src/ui/qr-render.ts +0 -92
- package/src/ui/rpc-fallback.ts +0 -59
- package/src/ui/spinner.ts +0 -56
- package/src/ui/tree.ts +0 -16
- package/src/utils/format.ts +0 -48
- package/src/utils/hash.ts +0 -5
- package/src/utils/time.ts +0 -15
- package/src/wallet-router.ts +0 -178
- package/src/walletconnect-session.ts +0 -27
- package/src/walletconnect.ts +0 -309
- package/test/time.test.js +0 -11
- package/tsconfig.json +0 -33
package/src/commands/endpoint.ts
DELETED
|
@@ -1,620 +0,0 @@
|
|
|
1
|
-
import { Command } from "commander";
|
|
2
|
-
import { ethers } from "ethers";
|
|
3
|
-
import { AgentRegistryClient } from "@arc402/sdk";
|
|
4
|
-
import {
|
|
5
|
-
buildEndpointConfig,
|
|
6
|
-
DEFAULT_LOCAL_INGRESS_TARGET,
|
|
7
|
-
ENDPOINT_CONFIG_PATH,
|
|
8
|
-
loadEndpointConfig,
|
|
9
|
-
normalizeAgentName,
|
|
10
|
-
saveEndpointConfig,
|
|
11
|
-
} from "../endpoint-config.js";
|
|
12
|
-
import { configExists, getSubdomainApi, loadConfig, NETWORK_DEFAULTS } from "../config.js";
|
|
13
|
-
import { DAEMON_PID } from "../daemon/config.js";
|
|
14
|
-
import { detectDockerAccess, readOpenShellConfig, runCmd } from "../openshell-runtime.js";
|
|
15
|
-
import { getClient } from "../client.js";
|
|
16
|
-
import * as dns from "dns/promises";
|
|
17
|
-
import * as fs from "fs";
|
|
18
|
-
import * as net from "net";
|
|
19
|
-
import chalk from "chalk";
|
|
20
|
-
import { c } from '../ui/colors.js';
|
|
21
|
-
|
|
22
|
-
interface DoctorCheck {
|
|
23
|
-
layer: string;
|
|
24
|
-
label: string;
|
|
25
|
-
ok: boolean;
|
|
26
|
-
detail: string;
|
|
27
|
-
fix?: string;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function readWalletAddress(): string | undefined {
|
|
31
|
-
if (!configExists()) return undefined;
|
|
32
|
-
try {
|
|
33
|
-
const config = loadConfig();
|
|
34
|
-
if (config.walletContractAddress) return config.walletContractAddress;
|
|
35
|
-
if (config.privateKey) return new ethers.Wallet(config.privateKey).address;
|
|
36
|
-
} catch {
|
|
37
|
-
return undefined;
|
|
38
|
-
}
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function readSubdomainApi(): string {
|
|
43
|
-
if (!configExists()) return "https://api.arc402.xyz";
|
|
44
|
-
try {
|
|
45
|
-
return getSubdomainApi(loadConfig());
|
|
46
|
-
} catch {
|
|
47
|
-
return "https://api.arc402.xyz";
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function readAgentRegistryAddress(): string | undefined {
|
|
52
|
-
if (!configExists()) return undefined;
|
|
53
|
-
try {
|
|
54
|
-
const config = loadConfig();
|
|
55
|
-
return config.agentRegistryV2Address ?? NETWORK_DEFAULTS[config.network]?.agentRegistryV2Address;
|
|
56
|
-
} catch {
|
|
57
|
-
return undefined;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function isProcessAlive(pid: number): boolean {
|
|
62
|
-
try {
|
|
63
|
-
process.kill(pid, 0);
|
|
64
|
-
return true;
|
|
65
|
-
} catch {
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async function checkLocalTarget(target: string): Promise<{ ok: boolean; detail: string }> {
|
|
71
|
-
try {
|
|
72
|
-
const url = new URL(target);
|
|
73
|
-
const host = url.hostname;
|
|
74
|
-
const port = Number(url.port || (url.protocol === "https:" ? 443 : 80));
|
|
75
|
-
const socket = new net.Socket();
|
|
76
|
-
socket.setTimeout(1500);
|
|
77
|
-
return await new Promise<{ ok: boolean; detail: string }>((resolve) => {
|
|
78
|
-
socket.once("connect", () => {
|
|
79
|
-
socket.destroy();
|
|
80
|
-
resolve({ ok: true, detail: `${host}:${port} accepted TCP connection` });
|
|
81
|
-
});
|
|
82
|
-
socket.once("timeout", () => {
|
|
83
|
-
socket.destroy();
|
|
84
|
-
resolve({ ok: false, detail: `${host}:${port} timed out` });
|
|
85
|
-
});
|
|
86
|
-
socket.once("error", (err) => {
|
|
87
|
-
socket.destroy();
|
|
88
|
-
resolve({ ok: false, detail: `${host}:${port} unreachable (${err.message})` });
|
|
89
|
-
});
|
|
90
|
-
socket.connect(port, host);
|
|
91
|
-
});
|
|
92
|
-
} catch (err) {
|
|
93
|
-
return { ok: false, detail: `invalid URL: ${err instanceof Error ? err.message : String(err)}` };
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function checkDaemon(): DoctorCheck {
|
|
98
|
-
if (!fs.existsSync(DAEMON_PID)) {
|
|
99
|
-
return {
|
|
100
|
-
layer: "runtime",
|
|
101
|
-
label: "Daemon",
|
|
102
|
-
ok: false,
|
|
103
|
-
detail: "no PID file found",
|
|
104
|
-
fix: "Run `arc402 openshell init` if needed, then `arc402 daemon start`.",
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const rawPid = fs.readFileSync(DAEMON_PID, "utf-8").trim();
|
|
109
|
-
const pid = Number(rawPid);
|
|
110
|
-
if (!Number.isFinite(pid) || pid <= 0) {
|
|
111
|
-
return {
|
|
112
|
-
layer: "runtime",
|
|
113
|
-
label: "Daemon",
|
|
114
|
-
ok: false,
|
|
115
|
-
detail: `invalid PID file contents: ${JSON.stringify(rawPid)}`,
|
|
116
|
-
fix: "Remove the stale PID file and restart the daemon.",
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (!isProcessAlive(pid)) {
|
|
121
|
-
return {
|
|
122
|
-
layer: "runtime",
|
|
123
|
-
label: "Daemon",
|
|
124
|
-
ok: false,
|
|
125
|
-
detail: `stale PID file (${pid})`,
|
|
126
|
-
fix: "Remove the stale PID file and restart with `arc402 daemon start`.",
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return {
|
|
131
|
-
layer: "runtime",
|
|
132
|
-
label: "Daemon",
|
|
133
|
-
ok: true,
|
|
134
|
-
detail: `running (PID ${pid})`,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function checkOpenShell(): DoctorCheck {
|
|
139
|
-
const config = readOpenShellConfig();
|
|
140
|
-
const docker = detectDockerAccess();
|
|
141
|
-
if (!config?.sandbox?.name) {
|
|
142
|
-
return {
|
|
143
|
-
layer: "runtime",
|
|
144
|
-
label: "OpenShell runtime",
|
|
145
|
-
ok: false,
|
|
146
|
-
detail: "not configured for launch",
|
|
147
|
-
fix: "Run `arc402 openshell init` so ARC-402 runtime stays sandboxed.",
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
if (!docker.ok) {
|
|
151
|
-
return {
|
|
152
|
-
layer: "runtime",
|
|
153
|
-
label: "OpenShell runtime",
|
|
154
|
-
ok: false,
|
|
155
|
-
detail: `configured, but Docker/OpenShell substrate is unhealthy: ${docker.detail}`,
|
|
156
|
-
fix: "Restore Docker/OpenShell health, then re-run `arc402 openshell status`.",
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
return {
|
|
160
|
-
layer: "runtime",
|
|
161
|
-
label: "OpenShell runtime",
|
|
162
|
-
ok: true,
|
|
163
|
-
detail: `${config.sandbox.name} configured; Docker ${docker.detail}`,
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function checkCloudflared(endpointTunnelTarget?: string): DoctorCheck {
|
|
168
|
-
const which = runCmd("which", ["cloudflared"]);
|
|
169
|
-
if (!which.ok || !which.stdout) {
|
|
170
|
-
return {
|
|
171
|
-
layer: "ingress",
|
|
172
|
-
label: "Tunnel binary",
|
|
173
|
-
ok: false,
|
|
174
|
-
detail: "cloudflared not found in PATH",
|
|
175
|
-
fix: "Install cloudflared on the host machine for the launch-default ingress path.",
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const ps = runCmd("bash", ["-lc", "ps -ef | grep '[c]loudflared tunnel' | head -1"]);
|
|
180
|
-
if (!ps.ok || !ps.stdout) {
|
|
181
|
-
return {
|
|
182
|
-
layer: "ingress",
|
|
183
|
-
label: "Tunnel process",
|
|
184
|
-
ok: false,
|
|
185
|
-
detail: endpointTunnelTarget
|
|
186
|
-
? `cloudflared is installed, but no tunnel process was detected for ${endpointTunnelTarget}`
|
|
187
|
-
: "cloudflared is installed, but no tunnel process was detected",
|
|
188
|
-
fix: "Start your host-managed tunnel (for example `cloudflared tunnel run ...`).",
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return {
|
|
193
|
-
layer: "ingress",
|
|
194
|
-
label: "Tunnel process",
|
|
195
|
-
ok: true,
|
|
196
|
-
detail: `detected: ${ps.stdout}`,
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
async function checkPublicHostname(endpoint: ReturnType<typeof loadEndpointConfig>): Promise<DoctorCheck> {
|
|
201
|
-
if (!endpoint) {
|
|
202
|
-
return {
|
|
203
|
-
layer: "public",
|
|
204
|
-
label: "Public hostname",
|
|
205
|
-
ok: false,
|
|
206
|
-
detail: "cannot resolve because endpoint config is missing",
|
|
207
|
-
fix: "Run `arc402 endpoint init <agentname>` first.",
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
try {
|
|
212
|
-
const results = await dns.lookup(endpoint.hostname, { all: true });
|
|
213
|
-
if (!results.length) {
|
|
214
|
-
return {
|
|
215
|
-
layer: "public",
|
|
216
|
-
label: "Public hostname",
|
|
217
|
-
ok: false,
|
|
218
|
-
detail: `${endpoint.hostname} did not resolve`,
|
|
219
|
-
fix: endpoint.claimedAt
|
|
220
|
-
? "Verify the claimed hostname is live in DNS / Cloudflare and that propagation is complete."
|
|
221
|
-
: "Claim the hostname first, then wait for DNS to propagate.",
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const addresses = results.map((entry) => entry.address).join(", ");
|
|
226
|
-
return {
|
|
227
|
-
layer: "public",
|
|
228
|
-
label: "Public hostname",
|
|
229
|
-
ok: true,
|
|
230
|
-
detail: `${endpoint.hostname} resolves (${addresses})`,
|
|
231
|
-
};
|
|
232
|
-
} catch (err) {
|
|
233
|
-
return {
|
|
234
|
-
layer: "public",
|
|
235
|
-
label: "Public hostname",
|
|
236
|
-
ok: false,
|
|
237
|
-
detail: `${endpoint.hostname} not resolvable yet (${err instanceof Error ? err.message : String(err)})`,
|
|
238
|
-
fix: endpoint.claimedAt
|
|
239
|
-
? "If the claim succeeded, verify DNS propagation / Cloudflare routing rather than the local runtime."
|
|
240
|
-
: "Claim the hostname first, then re-run status/doctor.",
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
async function checkAgentRegistryParity(endpoint: ReturnType<typeof loadEndpointConfig>): Promise<DoctorCheck> {
|
|
246
|
-
if (!endpoint) {
|
|
247
|
-
return {
|
|
248
|
-
layer: "registry",
|
|
249
|
-
label: "AgentRegistry parity",
|
|
250
|
-
ok: false,
|
|
251
|
-
detail: "endpoint config missing, so local ↔ registry parity cannot be checked",
|
|
252
|
-
fix: "Run `arc402 endpoint init <agentname>` first.",
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const walletAddress = endpoint.walletAddress ?? readWalletAddress();
|
|
257
|
-
if (!walletAddress) {
|
|
258
|
-
return {
|
|
259
|
-
layer: "registry",
|
|
260
|
-
label: "AgentRegistry parity",
|
|
261
|
-
ok: false,
|
|
262
|
-
detail: "no wallet address resolved from local config, so registry parity proof is partial",
|
|
263
|
-
fix: "Run `arc402 config init` (or set walletContractAddress/privateKey) so ARC-402 can compare local endpoint identity against AgentRegistry.",
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
const registryAddress = readAgentRegistryAddress();
|
|
268
|
-
if (!registryAddress) {
|
|
269
|
-
return {
|
|
270
|
-
layer: "registry",
|
|
271
|
-
label: "AgentRegistry parity",
|
|
272
|
-
ok: false,
|
|
273
|
-
detail: "AgentRegistry address missing from config, so on-chain endpoint parity cannot be checked",
|
|
274
|
-
fix: "Set `agentRegistryV2Address` in ARC-402 config or select a known network config.",
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
try {
|
|
279
|
-
const config = loadConfig();
|
|
280
|
-
const { provider } = await getClient(config);
|
|
281
|
-
const registry = new AgentRegistryClient(registryAddress, provider);
|
|
282
|
-
const agent = await registry.getAgent(walletAddress);
|
|
283
|
-
|
|
284
|
-
if (!agent.active && !agent.endpoint) {
|
|
285
|
-
return {
|
|
286
|
-
layer: "registry",
|
|
287
|
-
label: "AgentRegistry parity",
|
|
288
|
-
ok: false,
|
|
289
|
-
detail: `${walletAddress} is not actively registered with an endpoint in AgentRegistry`,
|
|
290
|
-
fix: `Register or update AgentRegistry with \`${endpoint.publicUrl}\` once local ingress is ready.`,
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
if (agent.endpoint === endpoint.publicUrl) {
|
|
295
|
-
return {
|
|
296
|
-
layer: "registry",
|
|
297
|
-
label: "AgentRegistry parity",
|
|
298
|
-
ok: true,
|
|
299
|
-
detail: `on-chain endpoint matches local canonical URL (${agent.endpoint || endpoint.publicUrl})`,
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
if (!agent.endpoint) {
|
|
304
|
-
return {
|
|
305
|
-
layer: "registry",
|
|
306
|
-
label: "AgentRegistry parity",
|
|
307
|
-
ok: false,
|
|
308
|
-
detail: `wallet is registered, but no public endpoint is stored on-chain yet (local expects ${endpoint.publicUrl})`,
|
|
309
|
-
fix: `Run \`arc402 agent update --name <name> --service-type <type> --endpoint ${endpoint.publicUrl}\` when you want AgentRegistry parity.`,
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
return {
|
|
314
|
-
layer: "registry",
|
|
315
|
-
label: "AgentRegistry parity",
|
|
316
|
-
ok: false,
|
|
317
|
-
detail: `mismatch: local canonical URL is ${endpoint.publicUrl}, but AgentRegistry has ${agent.endpoint}`,
|
|
318
|
-
fix: `Update AgentRegistry or re-init local endpoint config so the public identity matches one source of truth.`,
|
|
319
|
-
};
|
|
320
|
-
} catch (err) {
|
|
321
|
-
return {
|
|
322
|
-
layer: "registry",
|
|
323
|
-
label: "AgentRegistry parity",
|
|
324
|
-
ok: false,
|
|
325
|
-
detail: `could not prove on-chain parity (${err instanceof Error ? err.message : String(err)})`,
|
|
326
|
-
fix: "Check RPC / wallet / registry config. If local runtime is healthy, this is a registry-proof gap rather than an ingress failure.",
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
async function buildDoctorChecks(endpoint = loadEndpointConfig()): Promise<DoctorCheck[]> {
|
|
332
|
-
const checks: DoctorCheck[] = [];
|
|
333
|
-
|
|
334
|
-
if (!endpoint) {
|
|
335
|
-
checks.push({
|
|
336
|
-
layer: "config",
|
|
337
|
-
label: "Endpoint config",
|
|
338
|
-
ok: false,
|
|
339
|
-
detail: `missing (${ENDPOINT_CONFIG_PATH})`,
|
|
340
|
-
fix: "Run `arc402 endpoint init <agentname>` first.",
|
|
341
|
-
});
|
|
342
|
-
checks.push(await checkAgentRegistryParity(endpoint));
|
|
343
|
-
checks.push(await checkPublicHostname(endpoint));
|
|
344
|
-
return checks;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
checks.push({
|
|
348
|
-
layer: "config",
|
|
349
|
-
label: "Endpoint config",
|
|
350
|
-
ok: true,
|
|
351
|
-
detail: `${endpoint.publicUrl} → ${endpoint.localIngressTarget}`,
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
if (endpoint.walletAddress) {
|
|
355
|
-
checks.push({
|
|
356
|
-
layer: "config",
|
|
357
|
-
label: "Wallet binding",
|
|
358
|
-
ok: true,
|
|
359
|
-
detail: `endpoint config bound to ${endpoint.walletAddress}`,
|
|
360
|
-
});
|
|
361
|
-
} else {
|
|
362
|
-
checks.push({
|
|
363
|
-
layer: "config",
|
|
364
|
-
label: "Wallet binding",
|
|
365
|
-
ok: false,
|
|
366
|
-
detail: "endpoint config exists, but no wallet address is recorded for parity checks",
|
|
367
|
-
fix: "Set walletContractAddress/privateKey in ARC-402 config and re-run `arc402 endpoint init --force <agentname>` or claim again.",
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
checks.push(checkOpenShell());
|
|
372
|
-
checks.push(checkDaemon());
|
|
373
|
-
|
|
374
|
-
const localTarget = await checkLocalTarget(endpoint.localIngressTarget);
|
|
375
|
-
checks.push({
|
|
376
|
-
layer: "ingress",
|
|
377
|
-
label: "Local ingress target",
|
|
378
|
-
ok: localTarget.ok,
|
|
379
|
-
detail: localTarget.detail,
|
|
380
|
-
fix: localTarget.ok ? undefined : "Ensure your host ingress target is listening and forwards to the ARC-402 surface you intend to expose.",
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
checks.push(checkCloudflared(endpoint.tunnelTarget));
|
|
384
|
-
|
|
385
|
-
if (endpoint.claimedAt) {
|
|
386
|
-
checks.push({
|
|
387
|
-
layer: "public",
|
|
388
|
-
label: "Subdomain claim",
|
|
389
|
-
ok: true,
|
|
390
|
-
detail: `claimed at ${endpoint.claimedAt}`,
|
|
391
|
-
});
|
|
392
|
-
} else {
|
|
393
|
-
checks.push({
|
|
394
|
-
layer: "public",
|
|
395
|
-
label: "Subdomain claim",
|
|
396
|
-
ok: false,
|
|
397
|
-
detail: "not claimed yet",
|
|
398
|
-
fix: `Run \`arc402 endpoint claim ${endpoint.agentName}${endpoint.tunnelTarget ? "" : " --tunnel-target <https://...>"}\`.`,
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
checks.push(await checkPublicHostname(endpoint));
|
|
403
|
-
checks.push(await checkAgentRegistryParity(endpoint));
|
|
404
|
-
|
|
405
|
-
return checks;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
async function claimSubdomain(subdomain: string, walletAddress: string, tunnelTarget: string, apiBase: string): Promise<void> {
|
|
409
|
-
const normalized = normalizeAgentName(subdomain);
|
|
410
|
-
console.log(`\nClaiming canonical endpoint: https://${normalized}.arc402.xyz`);
|
|
411
|
-
console.log(` Wallet: ${walletAddress}`);
|
|
412
|
-
console.log(` Tunnel target: ${tunnelTarget}`);
|
|
413
|
-
console.log(` API: ${apiBase}`);
|
|
414
|
-
|
|
415
|
-
const tryPaths = [
|
|
416
|
-
{ path: "/register-subdomain", body: { subdomain: normalized, walletAddress, tunnelTarget } },
|
|
417
|
-
{ path: "/register", body: { subdomain: normalized, walletAddress, tunnelTarget } },
|
|
418
|
-
];
|
|
419
|
-
|
|
420
|
-
let lastError = "unknown error";
|
|
421
|
-
for (const candidate of tryPaths) {
|
|
422
|
-
try {
|
|
423
|
-
const res = await fetch(`${apiBase}${candidate.path}`, {
|
|
424
|
-
method: "POST",
|
|
425
|
-
headers: { "Content-Type": "application/json" },
|
|
426
|
-
body: JSON.stringify(candidate.body),
|
|
427
|
-
});
|
|
428
|
-
const body = await res.json() as Record<string, unknown>;
|
|
429
|
-
if (res.ok) {
|
|
430
|
-
console.log(chalk.green(`✓ Subdomain claimed: ${body["subdomain"] ?? `${normalized}.arc402.xyz`}`));
|
|
431
|
-
return;
|
|
432
|
-
}
|
|
433
|
-
lastError = `${candidate.path}: ${String(body["error"] ?? res.statusText)}`;
|
|
434
|
-
} catch (err) {
|
|
435
|
-
lastError = `${candidate.path}: ${err instanceof Error ? err.message : String(err)}`;
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
throw new Error(lastError);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
export function registerEndpointCommands(program: Command): void {
|
|
443
|
-
const endpoint = program
|
|
444
|
-
.command("endpoint")
|
|
445
|
-
.description("Canonical public endpoint scaffold for ARC-402 launch: public ingress identity outside the sandbox, runtime still sandboxed inside OpenShell.");
|
|
446
|
-
|
|
447
|
-
endpoint
|
|
448
|
-
.command("init [agentName]")
|
|
449
|
-
.description("Scaffold the canonical endpoint config for <agentname>.arc402.xyz and the host-managed ingress target. This does not claim DNS or open outbound sandbox policy.")
|
|
450
|
-
.option("--local-ingress-target <url>", "Host ingress target the tunnel/proxy should forward into", DEFAULT_LOCAL_INGRESS_TARGET)
|
|
451
|
-
.option("--tunnel-target <url>", "Public tunnel target / route metadata if already known (must be https://... for claim flows)")
|
|
452
|
-
.option("--force", "Overwrite the existing endpoint scaffold")
|
|
453
|
-
.action((agentName: string | undefined, opts) => {
|
|
454
|
-
const existing = loadEndpointConfig();
|
|
455
|
-
if (existing && !opts.force && !agentName) {
|
|
456
|
-
console.log(`Endpoint config already exists at ${ENDPOINT_CONFIG_PATH}`);
|
|
457
|
-
console.log(` Public URL: ${existing.publicUrl}`);
|
|
458
|
-
console.log(` Local target: ${existing.localIngressTarget}`);
|
|
459
|
-
console.log("Use --force to replace it, or pass a new agent name explicitly.");
|
|
460
|
-
return;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
const chosenName = agentName ?? existing?.agentName;
|
|
464
|
-
if (!chosenName) {
|
|
465
|
-
console.error("Agent name is required the first time. Example: arc402 endpoint init gigabrain");
|
|
466
|
-
process.exit(1);
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
const walletAddress = readWalletAddress();
|
|
470
|
-
const cfg = buildEndpointConfig({
|
|
471
|
-
agentName: chosenName,
|
|
472
|
-
localIngressTarget: opts.localIngressTarget,
|
|
473
|
-
tunnelTarget: opts.tunnelTarget,
|
|
474
|
-
walletAddress,
|
|
475
|
-
subdomainApi: readSubdomainApi(),
|
|
476
|
-
existing,
|
|
477
|
-
notes: "Launch default: host-managed Cloudflare Tunnel outside the sandbox. Public ingress identity is separate from OpenShell outbound policy.",
|
|
478
|
-
});
|
|
479
|
-
saveEndpointConfig(cfg);
|
|
480
|
-
|
|
481
|
-
console.log(c.success + c.white(' Endpoint scaffold written: ' + ENDPOINT_CONFIG_PATH));
|
|
482
|
-
console.log(` Agent name: ${cfg.agentName}`);
|
|
483
|
-
console.log(` Hostname: ${cfg.hostname}`);
|
|
484
|
-
console.log(` Public URL: ${cfg.publicUrl}`);
|
|
485
|
-
console.log(` Tunnel mode: ${cfg.tunnelMode}`);
|
|
486
|
-
console.log(` Local target: ${cfg.localIngressTarget}`);
|
|
487
|
-
if (cfg.tunnelTarget) console.log(` Tunnel target: ${cfg.tunnelTarget}`);
|
|
488
|
-
console.log(` Wallet: ${cfg.walletAddress ?? "not yet resolved"}`);
|
|
489
|
-
console.log("\nArchitecture truth:");
|
|
490
|
-
console.log(" • ARC-402 runtime stays inside the OpenShell sandbox.");
|
|
491
|
-
console.log(" • This command only locks the public-ingress identity + host target.");
|
|
492
|
-
console.log(" • Sandbox outbound policy remains separate: use `arc402 openshell policy ...` for peer/API allowlists.");
|
|
493
|
-
console.log("\nNext:");
|
|
494
|
-
console.log(` 1. Start your host-managed tunnel toward ${cfg.localIngressTarget}`);
|
|
495
|
-
console.log(` 2. Claim the canonical hostname: arc402 endpoint claim ${cfg.agentName}${cfg.tunnelTarget ? "" : " --tunnel-target <https://your-tunnel.example.com>"}`);
|
|
496
|
-
console.log(" 3. Verify the whole chain: arc402 endpoint status");
|
|
497
|
-
});
|
|
498
|
-
|
|
499
|
-
endpoint
|
|
500
|
-
.command("status")
|
|
501
|
-
.description("Show the current endpoint scaffold and whether local runtime/ingress pieces line up. Useful now even before DNS automation is complete.")
|
|
502
|
-
.action(async () => {
|
|
503
|
-
const cfg = loadEndpointConfig();
|
|
504
|
-
if (!cfg) {
|
|
505
|
-
console.error(`No endpoint config found at ${ENDPOINT_CONFIG_PATH}`);
|
|
506
|
-
console.error("Run: arc402 endpoint init <agentname>");
|
|
507
|
-
process.exit(1);
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
const checks = await buildDoctorChecks(cfg);
|
|
511
|
-
const allGood = checks.every((check) => check.ok);
|
|
512
|
-
const brokenLayers = Array.from(new Set(checks.filter((check) => !check.ok).map((check) => check.layer)));
|
|
513
|
-
|
|
514
|
-
console.log('\n ' + c.mark + c.white(' ARC-402 Endpoint Status'));
|
|
515
|
-
console.log("─────────────────────");
|
|
516
|
-
console.log(`Agent name: ${cfg.agentName}`);
|
|
517
|
-
console.log(`Hostname: ${cfg.hostname}`);
|
|
518
|
-
console.log(`Public URL: ${cfg.publicUrl}`);
|
|
519
|
-
console.log(`Tunnel mode: ${cfg.tunnelMode}`);
|
|
520
|
-
console.log(`Local target: ${cfg.localIngressTarget}`);
|
|
521
|
-
console.log(`Tunnel target: ${cfg.tunnelTarget ?? "not set"}`);
|
|
522
|
-
console.log(`Claimed at: ${cfg.claimedAt ?? "not yet claimed"}`);
|
|
523
|
-
console.log(`Config file: ${ENDPOINT_CONFIG_PATH}`);
|
|
524
|
-
console.log(`\nReadiness: ${allGood ? chalk.green("fully proven for current launch scope") : chalk.yellow("partial proof / needs attention")}`);
|
|
525
|
-
if (brokenLayers.length) {
|
|
526
|
-
console.log(`Broken layers: ${brokenLayers.join(", ")}`);
|
|
527
|
-
}
|
|
528
|
-
console.log();
|
|
529
|
-
|
|
530
|
-
for (const check of checks) {
|
|
531
|
-
console.log(`${check.ok ? chalk.green("✓") : chalk.yellow("!")} [${check.layer}] ${check.label.padEnd(20)} ${check.detail}`);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
console.log("\nWhat this proves now:");
|
|
535
|
-
console.log(" • canonical endpoint identity is locked locally");
|
|
536
|
-
console.log(" • runtime sandboxing is checked separately from ingress");
|
|
537
|
-
console.log(" • local ingress target + daemon/tunnel wiring can be diagnosed without pretending every external layer is automated");
|
|
538
|
-
console.log(" • AgentRegistry/public-hostname parity is checked when config + RPC + wallet context make proof possible");
|
|
539
|
-
});
|
|
540
|
-
|
|
541
|
-
endpoint
|
|
542
|
-
.command("claim <agentName>")
|
|
543
|
-
.description("Claim the canonical <agentname>.arc402.xyz hostname and lock the local endpoint config to it. Uses the launch-default host-managed ingress model.")
|
|
544
|
-
.requiredOption("--tunnel-target <url>", "Public tunnel target registered behind the canonical hostname (must start with https://)")
|
|
545
|
-
.action(async (agentName: string, opts) => {
|
|
546
|
-
if (!opts.tunnelTarget.startsWith("https://")) {
|
|
547
|
-
console.error("--tunnel-target must start with https://");
|
|
548
|
-
process.exit(1);
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
const walletAddress = readWalletAddress();
|
|
552
|
-
if (!walletAddress) {
|
|
553
|
-
console.error("No wallet address could be resolved from ARC-402 config.");
|
|
554
|
-
console.error("Run `arc402 config init` (or set walletContractAddress/privateKey) first.");
|
|
555
|
-
process.exit(1);
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
const existing = loadEndpointConfig();
|
|
559
|
-
const normalized = normalizeAgentName(agentName);
|
|
560
|
-
const apiBase = readSubdomainApi();
|
|
561
|
-
await claimSubdomain(normalized, walletAddress, opts.tunnelTarget, apiBase);
|
|
562
|
-
|
|
563
|
-
const cfg = buildEndpointConfig({
|
|
564
|
-
agentName: normalized,
|
|
565
|
-
localIngressTarget: existing?.localIngressTarget ?? DEFAULT_LOCAL_INGRESS_TARGET,
|
|
566
|
-
tunnelTarget: opts.tunnelTarget,
|
|
567
|
-
walletAddress,
|
|
568
|
-
subdomainApi: apiBase,
|
|
569
|
-
existing,
|
|
570
|
-
claimedAt: new Date().toISOString(),
|
|
571
|
-
notes: existing?.notes,
|
|
572
|
-
});
|
|
573
|
-
saveEndpointConfig(cfg);
|
|
574
|
-
|
|
575
|
-
console.log(c.success + c.white(' Endpoint config locked to ' + cfg.publicUrl));
|
|
576
|
-
console.log(` Hostname: ${cfg.hostname}`);
|
|
577
|
-
console.log(` Tunnel target: ${cfg.tunnelTarget}`);
|
|
578
|
-
console.log(` Wallet: ${cfg.walletAddress}`);
|
|
579
|
-
console.log("\nOptional next step if you have not updated AgentRegistry yet:");
|
|
580
|
-
console.log(` arc402 agent update --name <name> --service-type <type> --endpoint ${cfg.publicUrl}`);
|
|
581
|
-
});
|
|
582
|
-
|
|
583
|
-
endpoint
|
|
584
|
-
.command("doctor")
|
|
585
|
-
.description("Diagnose the broken layer without blurring ingress, runtime sandbox, or public identity.")
|
|
586
|
-
.action(async () => {
|
|
587
|
-
const checks = await buildDoctorChecks();
|
|
588
|
-
console.log("ARC-402 Endpoint Doctor");
|
|
589
|
-
console.log("─────────────────────");
|
|
590
|
-
|
|
591
|
-
const failuresByLayer = new Map<string, number>();
|
|
592
|
-
let failures = 0;
|
|
593
|
-
for (const check of checks) {
|
|
594
|
-
if (check.ok) {
|
|
595
|
-
console.log(`${chalk.green("✓")} [${check.layer}] ${check.label}: ${check.detail}`);
|
|
596
|
-
continue;
|
|
597
|
-
}
|
|
598
|
-
failures += 1;
|
|
599
|
-
failuresByLayer.set(check.layer, (failuresByLayer.get(check.layer) ?? 0) + 1);
|
|
600
|
-
console.log(`${chalk.red("✗")} [${check.layer}] ${check.label}: ${check.detail}`);
|
|
601
|
-
if (check.fix) console.log(` Fix: ${check.fix}`);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
if (failures === 0) {
|
|
605
|
-
console.log(chalk.green("\nNo obvious scaffold-layer breakage detected."));
|
|
606
|
-
} else {
|
|
607
|
-
console.log(chalk.yellow(`\n${failures} check(s) failed across ${failuresByLayer.size} layer(s): ${Array.from(failuresByLayer.keys()).join(", ")}.`));
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
console.log("\nLayer model:");
|
|
611
|
-
console.log(" 1. config / local source of truth");
|
|
612
|
-
console.log(" 2. public identity (`agentname.arc402.xyz`)");
|
|
613
|
-
console.log(" 3. host-managed ingress / tunnel");
|
|
614
|
-
console.log(" 4. local ingress target");
|
|
615
|
-
console.log(" 5. ARC-402 runtime inside OpenShell");
|
|
616
|
-
console.log(" 6. AgentRegistry/public-endpoint parity");
|
|
617
|
-
console.log(" 7. sandbox outbound policy (separate; not implied by public ingress)");
|
|
618
|
-
console.log("\nIf only the registry/public checks fail while local runtime is healthy, the proof is partial rather than the stack being fully down.");
|
|
619
|
-
});
|
|
620
|
-
}
|