arc402-cli 1.4.50 → 1.6.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/dist/commands/agreements.d.ts.map +1 -1
- package/dist/commands/agreements.js +19 -0
- package/dist/commands/agreements.js.map +1 -1
- package/dist/commands/arena-v2.d.ts.map +1 -1
- package/dist/commands/arena-v2.js +129 -4
- package/dist/commands/arena-v2.js.map +1 -1
- package/dist/commands/auth.d.ts +11 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +188 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/chat.d.ts +3 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +752 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/compute.d.ts.map +1 -1
- package/dist/commands/compute.js +84 -10
- package/dist/commands/compute.js.map +1 -1
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/daemon.js +44 -5
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/discover.d.ts.map +1 -1
- package/dist/commands/discover.js +20 -0
- package/dist/commands/discover.js.map +1 -1
- package/dist/commands/hermes-init.d.ts +1 -1
- package/dist/commands/hermes-init.js +9 -9
- package/dist/commands/hermes-init.js.map +1 -1
- package/dist/commands/hire.d.ts.map +1 -1
- package/dist/commands/hire.js +20 -0
- package/dist/commands/hire.js.map +1 -1
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +74 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/lifecycle.d.ts +3 -0
- package/dist/commands/lifecycle.d.ts.map +1 -0
- package/dist/commands/lifecycle.js +58 -0
- package/dist/commands/lifecycle.js.map +1 -0
- package/dist/commands/security.d.ts +3 -0
- package/dist/commands/security.d.ts.map +1 -0
- package/dist/commands/security.js +44 -0
- package/dist/commands/security.js.map +1 -0
- package/dist/commands/status.d.ts +18 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +179 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/subscription.d.ts +3 -0
- package/dist/commands/subscription.d.ts.map +1 -0
- package/dist/commands/subscription.js +465 -0
- package/dist/commands/subscription.js.map +1 -0
- package/dist/commands/workroom.d.ts.map +1 -1
- package/dist/commands/workroom.js +13 -0
- package/dist/commands/workroom.js.map +1 -1
- package/dist/commerce-client.d.ts +77 -0
- package/dist/commerce-client.d.ts.map +1 -0
- package/dist/commerce-client.js +224 -0
- package/dist/commerce-client.js.map +1 -0
- package/dist/commerce-index.d.ts +39 -0
- package/dist/commerce-index.d.ts.map +1 -0
- package/dist/commerce-index.js +294 -0
- package/dist/commerce-index.js.map +1 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/daemon/config.d.ts +1 -0
- package/dist/daemon/config.d.ts.map +1 -1
- package/dist/daemon/config.js +7 -3
- package/dist/daemon/config.js.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +18 -4
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon-client.d.ts +46 -0
- package/dist/daemon-client.d.ts.map +1 -0
- package/dist/daemon-client.js +80 -0
- package/dist/daemon-client.js.map +1 -0
- package/dist/index.js +40 -34
- package/dist/index.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +14 -0
- package/dist/program.js.map +1 -1
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +61 -58
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/InputLine.d.ts +4 -2
- package/dist/tui/InputLine.d.ts.map +1 -1
- package/dist/tui/InputLine.js +79 -60
- package/dist/tui/InputLine.js.map +1 -1
- package/dist/tui/KernelPayloadRenderer.d.ts +12 -0
- package/dist/tui/KernelPayloadRenderer.d.ts.map +1 -0
- package/dist/tui/KernelPayloadRenderer.js +41 -0
- package/dist/tui/KernelPayloadRenderer.js.map +1 -0
- package/dist/tui/Viewport.d.ts +15 -5
- package/dist/tui/Viewport.d.ts.map +1 -1
- package/dist/tui/Viewport.js +18 -24
- package/dist/tui/Viewport.js.map +1 -1
- package/dist/tui/command-catalog.d.ts +11 -0
- package/dist/tui/command-catalog.d.ts.map +1 -0
- package/dist/tui/command-catalog.js +119 -0
- package/dist/tui/command-catalog.js.map +1 -0
- package/dist/tui/command-renderers.d.ts +33 -0
- package/dist/tui/command-renderers.d.ts.map +1 -0
- package/dist/tui/command-renderers.js +215 -0
- package/dist/tui/command-renderers.js.map +1 -0
- package/dist/tui/commerce-format.d.ts +3 -0
- package/dist/tui/commerce-format.d.ts.map +1 -0
- package/dist/tui/commerce-format.js +19 -0
- package/dist/tui/commerce-format.js.map +1 -0
- package/dist/tui/components/commerce/AgentPicker.d.ts +7 -0
- package/dist/tui/components/commerce/AgentPicker.d.ts.map +1 -0
- package/dist/tui/components/commerce/AgentPicker.js +33 -0
- package/dist/tui/components/commerce/AgentPicker.js.map +1 -0
- package/dist/tui/components/commerce/AgreementList.d.ts +18 -0
- package/dist/tui/components/commerce/AgreementList.d.ts.map +1 -0
- package/dist/tui/components/commerce/AgreementList.js +25 -0
- package/dist/tui/components/commerce/AgreementList.js.map +1 -0
- package/dist/tui/components/commerce/ComputeCard.d.ts +14 -0
- package/dist/tui/components/commerce/ComputeCard.d.ts.map +1 -0
- package/dist/tui/components/commerce/ComputeCard.js +9 -0
- package/dist/tui/components/commerce/ComputeCard.js.map +1 -0
- package/dist/tui/components/commerce/DiscoverList.d.ts +20 -0
- package/dist/tui/components/commerce/DiscoverList.d.ts.map +1 -0
- package/dist/tui/components/commerce/DiscoverList.js +22 -0
- package/dist/tui/components/commerce/DiscoverList.js.map +1 -0
- package/dist/tui/components/commerce/HireCard.d.ts +14 -0
- package/dist/tui/components/commerce/HireCard.d.ts.map +1 -0
- package/dist/tui/components/commerce/HireCard.js +11 -0
- package/dist/tui/components/commerce/HireCard.js.map +1 -0
- package/dist/tui/components/commerce/ProfileCard.d.ts +19 -0
- package/dist/tui/components/commerce/ProfileCard.d.ts.map +1 -0
- package/dist/tui/components/commerce/ProfileCard.js +10 -0
- package/dist/tui/components/commerce/ProfileCard.js.map +1 -0
- package/dist/tui/components/commerce/RoundsList.d.ts +18 -0
- package/dist/tui/components/commerce/RoundsList.d.ts.map +1 -0
- package/dist/tui/components/commerce/RoundsList.js +9 -0
- package/dist/tui/components/commerce/RoundsList.js.map +1 -0
- package/dist/tui/components/commerce/SquadCard.d.ts +25 -0
- package/dist/tui/components/commerce/SquadCard.d.ts.map +1 -0
- package/dist/tui/components/commerce/SquadCard.js +10 -0
- package/dist/tui/components/commerce/SquadCard.js.map +1 -0
- package/dist/tui/components/commerce/StatusCard.d.ts +21 -0
- package/dist/tui/components/commerce/StatusCard.d.ts.map +1 -0
- package/dist/tui/components/commerce/StatusCard.js +10 -0
- package/dist/tui/components/commerce/StatusCard.js.map +1 -0
- package/dist/tui/components/commerce/SubscribeCard.d.ts +13 -0
- package/dist/tui/components/commerce/SubscribeCard.d.ts.map +1 -0
- package/dist/tui/components/commerce/SubscribeCard.js +10 -0
- package/dist/tui/components/commerce/SubscribeCard.js.map +1 -0
- package/dist/tui/components/commerce/WorkroomCard.d.ts +18 -0
- package/dist/tui/components/commerce/WorkroomCard.d.ts.map +1 -0
- package/dist/tui/components/commerce/WorkroomCard.js +10 -0
- package/dist/tui/components/commerce/WorkroomCard.js.map +1 -0
- package/dist/tui/components/commerce/common.d.ts +53 -0
- package/dist/tui/components/commerce/common.d.ts.map +1 -0
- package/dist/tui/components/commerce/common.js +71 -0
- package/dist/tui/components/commerce/common.js.map +1 -0
- package/dist/tui/components/commerce/index.d.ts +11 -0
- package/dist/tui/components/commerce/index.d.ts.map +1 -0
- package/dist/tui/components/commerce/index.js +27 -0
- package/dist/tui/components/commerce/index.js.map +1 -0
- package/dist/tui/hire-interactive.d.ts +13 -0
- package/dist/tui/hire-interactive.d.ts.map +1 -0
- package/dist/tui/hire-interactive.js +157 -0
- package/dist/tui/hire-interactive.js.map +1 -0
- package/dist/tui/kernel-payload.d.ts +45 -0
- package/dist/tui/kernel-payload.d.ts.map +1 -0
- package/dist/tui/kernel-payload.js +8 -0
- package/dist/tui/kernel-payload.js.map +1 -0
- package/dist/tui/kernel.d.ts +6 -0
- package/dist/tui/kernel.d.ts.map +1 -0
- package/dist/tui/kernel.js +791 -0
- package/dist/tui/kernel.js.map +1 -0
- package/dist/tui/render-inline.d.ts +9 -0
- package/dist/tui/render-inline.d.ts.map +1 -0
- package/dist/tui/render-inline.js +32 -0
- package/dist/tui/render-inline.js.map +1 -0
- package/dist/tui/useChat.d.ts.map +1 -1
- package/dist/tui/useChat.js +2 -2
- package/dist/tui/useChat.js.map +1 -1
- package/dist/tui/useCommand.d.ts +2 -2
- package/dist/tui/useCommand.d.ts.map +1 -1
- package/dist/tui/useCommand.js +57 -19
- package/dist/tui/useCommand.js.map +1 -1
- package/dist/tui/useDaemonEvents.d.ts +4 -0
- package/dist/tui/useDaemonEvents.d.ts.map +1 -0
- package/dist/tui/useDaemonEvents.js +69 -0
- package/dist/tui/useDaemonEvents.js.map +1 -0
- package/dist/tui/useTerminalSize.d.ts +11 -0
- package/dist/tui/useTerminalSize.d.ts.map +1 -0
- package/dist/tui/useTerminalSize.js +32 -0
- package/dist/tui/useTerminalSize.js.map +1 -0
- package/dist/tui-esm/App.js +136 -0
- package/dist/tui-esm/App.js.map +1 -0
- package/dist/tui-esm/Footer.js +13 -0
- package/dist/tui-esm/Footer.js.map +1 -0
- package/dist/tui-esm/Header.js +19 -0
- package/dist/tui-esm/Header.js.map +1 -0
- package/dist/tui-esm/InputLine.js +121 -0
- package/dist/tui-esm/InputLine.js.map +1 -0
- package/dist/tui-esm/Viewport.js +39 -0
- package/dist/tui-esm/Viewport.js.map +1 -0
- package/dist/tui-esm/WalletConnectPairing.js +61 -0
- package/dist/tui-esm/WalletConnectPairing.js.map +1 -0
- package/dist/tui-esm/command-catalog.js +20 -0
- package/dist/tui-esm/command-catalog.js.map +1 -0
- package/dist/tui-esm/command-renderers.js +180 -0
- package/dist/tui-esm/command-renderers.js.map +1 -0
- package/dist/tui-esm/commerce-format.js +19 -0
- package/dist/tui-esm/commerce-format.js.map +1 -0
- package/dist/tui-esm/components/Button.js +21 -0
- package/dist/tui-esm/components/Button.js.map +1 -0
- package/dist/tui-esm/components/CeremonyView.js +10 -0
- package/dist/tui-esm/components/CeremonyView.js.map +1 -0
- package/dist/tui-esm/components/CompletionDropdown.js +23 -0
- package/dist/tui-esm/components/CompletionDropdown.js.map +1 -0
- package/dist/tui-esm/components/ConfirmPrompt.js +10 -0
- package/dist/tui-esm/components/ConfirmPrompt.js.map +1 -0
- package/dist/tui-esm/components/CustomTextInput.js +99 -0
- package/dist/tui-esm/components/CustomTextInput.js.map +1 -0
- package/dist/tui-esm/components/InteractiveTable.js +61 -0
- package/dist/tui-esm/components/InteractiveTable.js.map +1 -0
- package/dist/tui-esm/components/StepSpinner.js +32 -0
- package/dist/tui-esm/components/StepSpinner.js.map +1 -0
- package/dist/tui-esm/components/Toast.js +29 -0
- package/dist/tui-esm/components/Toast.js.map +1 -0
- package/dist/tui-esm/components/commerce/AgreementList.js +25 -0
- package/dist/tui-esm/components/commerce/AgreementList.js.map +1 -0
- package/dist/tui-esm/components/commerce/ComputeCard.js +9 -0
- package/dist/tui-esm/components/commerce/ComputeCard.js.map +1 -0
- package/dist/tui-esm/components/commerce/DiscoverList.js +14 -0
- package/dist/tui-esm/components/commerce/DiscoverList.js.map +1 -0
- package/dist/tui-esm/components/commerce/HireCard.js +11 -0
- package/dist/tui-esm/components/commerce/HireCard.js.map +1 -0
- package/dist/tui-esm/components/commerce/RoundsList.js +9 -0
- package/dist/tui-esm/components/commerce/RoundsList.js.map +1 -0
- package/dist/tui-esm/components/commerce/SquadCard.js +10 -0
- package/dist/tui-esm/components/commerce/SquadCard.js.map +1 -0
- package/dist/tui-esm/components/commerce/StatusCard.js +10 -0
- package/dist/tui-esm/components/commerce/StatusCard.js.map +1 -0
- package/dist/tui-esm/components/commerce/SubscribeCard.js +10 -0
- package/dist/tui-esm/components/commerce/SubscribeCard.js.map +1 -0
- package/dist/tui-esm/components/commerce/WorkroomCard.js +10 -0
- package/dist/tui-esm/components/commerce/WorkroomCard.js.map +1 -0
- package/dist/tui-esm/components/commerce/common.js +71 -0
- package/dist/tui-esm/components/commerce/common.js.map +1 -0
- package/dist/tui-esm/components/commerce/index.js +27 -0
- package/dist/tui-esm/components/commerce/index.js.map +1 -0
- package/dist/tui-esm/index.js +55 -0
- package/dist/tui-esm/index.js.map +1 -0
- package/dist/tui-esm/kernel.js +734 -0
- package/dist/tui-esm/kernel.js.map +1 -0
- package/dist/tui-esm/render-inline.js +32 -0
- package/dist/tui-esm/render-inline.js.map +1 -0
- package/dist/tui-esm/useChat.js +91 -0
- package/dist/tui-esm/useChat.js.map +1 -0
- package/dist/tui-esm/useCommand.js +142 -0
- package/dist/tui-esm/useCommand.js.map +1 -0
- package/dist/tui-esm/useNotifications.js +17 -0
- package/dist/tui-esm/useNotifications.js.map +1 -0
- package/dist/tui-esm/useScroll.js +46 -0
- package/dist/tui-esm/useScroll.js.map +1 -0
- package/dist/tui-esm/useTerminalSize.js +32 -0
- package/dist/tui-esm/useTerminalSize.js.map +1 -0
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +46 -2
- package/dist/ui/banner.js.map +1 -1
- package/hermes/DELIVERY-SPEC.md +219 -0
- package/hermes/HERMES-INTEGRATION-SPEC.md +338 -0
- package/hermes/plugins/arc402_hermes/__init__.py +5 -0
- package/hermes/plugins/arc402_hermes/plugin.py +489 -0
- package/hermes/plugins/arc402_hermes/py.typed +0 -0
- package/hermes/plugins/arc402_hermes.egg-info/PKG-INFO +24 -0
- package/hermes/plugins/arc402_hermes.egg-info/SOURCES.txt +10 -0
- package/hermes/plugins/arc402_hermes.egg-info/dependency_links.txt +1 -0
- package/hermes/plugins/arc402_hermes.egg-info/entry_points.txt +2 -0
- package/hermes/plugins/arc402_hermes.egg-info/requires.txt +5 -0
- package/hermes/plugins/arc402_hermes.egg-info/top_level.txt +1 -0
- package/hermes/plugins/arc402_plugin.py +489 -0
- package/hermes/plugins/dist/arc402_hermes-1.0.0-py3-none-any.whl +0 -0
- package/hermes/plugins/dist/arc402_hermes-1.0.0.tar.gz +0 -0
- package/hermes/plugins/pyproject.toml +47 -0
- package/hermes/skills/arc402-agent/SKILL.md +559 -0
- package/hermes/workroom/README.md +174 -0
- package/hermes/workroom/hermes-daemon.toml +21 -0
- package/hermes/workroom/hermes-worker/IDENTITY.md +44 -0
- package/hermes/workroom/hermes-worker/SOUL.md +45 -0
- package/hermes/workroom/hermes-worker/config.json +32 -0
- package/hermes/workroom/hermes-worker/datasets/.gitkeep +0 -0
- package/hermes/workroom/hermes-worker/knowledge/.gitkeep +0 -0
- package/hermes/workroom/hermes-worker/memory/learnings.md +9 -0
- package/hermes/workroom/hermes-worker/skills/.gitkeep +0 -0
- package/package.json +9 -3
- package/README.md +0 -288
|
@@ -0,0 +1,752 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.registerChatCommand = registerChatCommand;
|
|
40
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const os = __importStar(require("os"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const prompts_1 = __importDefault(require("prompts"));
|
|
45
|
+
const readline_1 = __importDefault(require("readline"));
|
|
46
|
+
const child_process_1 = require("child_process");
|
|
47
|
+
const commerce_client_1 = require("../commerce-client");
|
|
48
|
+
const config_1 = require("../config");
|
|
49
|
+
const config_2 = require("../daemon/config");
|
|
50
|
+
const OPENCLAW_CONFIG_PATH = process.env.OPENCLAW_CONFIG || path.join(os.homedir(), ".openclaw", "openclaw.json");
|
|
51
|
+
const SUPPORTED_HARNESSES = ["openclaw", "claude-code", "codex", "hermes"];
|
|
52
|
+
function parseTokens(input) {
|
|
53
|
+
const tokens = [];
|
|
54
|
+
let current = "";
|
|
55
|
+
let inQuote = false;
|
|
56
|
+
let quoteChar = "";
|
|
57
|
+
let escape = false;
|
|
58
|
+
for (const ch of input) {
|
|
59
|
+
if (escape) {
|
|
60
|
+
current += ch;
|
|
61
|
+
escape = false;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (inQuote) {
|
|
65
|
+
if (quoteChar === '"' && ch === "\\") {
|
|
66
|
+
escape = true;
|
|
67
|
+
}
|
|
68
|
+
else if (ch === quoteChar) {
|
|
69
|
+
inQuote = false;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
current += ch;
|
|
73
|
+
}
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (ch === '"' || ch === "'") {
|
|
77
|
+
inQuote = true;
|
|
78
|
+
quoteChar = ch;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (/\s/.test(ch)) {
|
|
82
|
+
if (current) {
|
|
83
|
+
tokens.push(current);
|
|
84
|
+
current = "";
|
|
85
|
+
}
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
current += ch;
|
|
89
|
+
}
|
|
90
|
+
if (current) {
|
|
91
|
+
tokens.push(current);
|
|
92
|
+
}
|
|
93
|
+
return tokens;
|
|
94
|
+
}
|
|
95
|
+
function truncateAddress(address) {
|
|
96
|
+
return address.length > 12 ? `${address.slice(0, 6)}…${address.slice(-4)}` : address;
|
|
97
|
+
}
|
|
98
|
+
function formatAgreementStatus(value) {
|
|
99
|
+
const raw = typeof value === "string" ? value : typeof value === "number" ? String(value) : "unknown";
|
|
100
|
+
return raw.toUpperCase();
|
|
101
|
+
}
|
|
102
|
+
function normalizeHarness(value) {
|
|
103
|
+
const normalized = value?.trim().toLowerCase();
|
|
104
|
+
if (!normalized)
|
|
105
|
+
return undefined;
|
|
106
|
+
if (normalized === "openclaw")
|
|
107
|
+
return "openclaw";
|
|
108
|
+
if (normalized === "claude" || normalized === "claude-code")
|
|
109
|
+
return "claude-code";
|
|
110
|
+
if (normalized === "codex")
|
|
111
|
+
return "codex";
|
|
112
|
+
if (normalized === "hermes")
|
|
113
|
+
return "hermes";
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
function getHarnessLabel(harness) {
|
|
117
|
+
switch (harness) {
|
|
118
|
+
case "openclaw":
|
|
119
|
+
return "OpenClaw";
|
|
120
|
+
case "claude-code":
|
|
121
|
+
return "Claude Code";
|
|
122
|
+
case "codex":
|
|
123
|
+
return "Codex";
|
|
124
|
+
case "hermes":
|
|
125
|
+
return "Hermes";
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function commandExists(command) {
|
|
129
|
+
const result = (0, child_process_1.spawnSync)("sh", ["-lc", `command -v ${command}`], { stdio: "ignore" });
|
|
130
|
+
return result.status === 0;
|
|
131
|
+
}
|
|
132
|
+
function getHarnessReadiness(harness) {
|
|
133
|
+
switch (harness) {
|
|
134
|
+
case "openclaw":
|
|
135
|
+
if (fs.existsSync(OPENCLAW_CONFIG_PATH)) {
|
|
136
|
+
return {
|
|
137
|
+
ready: true,
|
|
138
|
+
summary: `gateway config found at ${OPENCLAW_CONFIG_PATH}`,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
ready: false,
|
|
143
|
+
summary: `missing ${OPENCLAW_CONFIG_PATH}`,
|
|
144
|
+
nextStep: "Run OpenClaw locally or create ~/.openclaw/openclaw.json before relying on OpenClaw-backed execution.",
|
|
145
|
+
};
|
|
146
|
+
case "claude-code":
|
|
147
|
+
return commandExists("claude")
|
|
148
|
+
? { ready: true, summary: "claude CLI found on PATH" }
|
|
149
|
+
: { ready: false, summary: "claude CLI not found on PATH", nextStep: "Install Claude Code or pick a different harness." };
|
|
150
|
+
case "codex":
|
|
151
|
+
return commandExists("codex")
|
|
152
|
+
? { ready: true, summary: "codex CLI found on PATH" }
|
|
153
|
+
: { ready: false, summary: "codex CLI not found on PATH", nextStep: "Install Codex CLI or pick a different harness." };
|
|
154
|
+
case "hermes":
|
|
155
|
+
return commandExists("hermes")
|
|
156
|
+
? { ready: true, summary: "hermes CLI found on PATH" }
|
|
157
|
+
: { ready: false, summary: "hermes CLI not found on PATH", nextStep: "Run `arc402 hermes init` or install Hermes before using this harness." };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async function testDaemonConnection(options) {
|
|
161
|
+
try {
|
|
162
|
+
await (0, commerce_client_1.fetchDaemonHealth)(options);
|
|
163
|
+
return { ok: true };
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
return {
|
|
167
|
+
ok: false,
|
|
168
|
+
error: error instanceof Error ? error.message : String(error),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function loadSavedChatConfig() {
|
|
173
|
+
if (!(0, config_1.configExists)())
|
|
174
|
+
return undefined;
|
|
175
|
+
return (0, config_1.loadConfig)().chat;
|
|
176
|
+
}
|
|
177
|
+
function loadDaemonHarnessDefault() {
|
|
178
|
+
if (!fs.existsSync(config_2.DAEMON_TOML))
|
|
179
|
+
return undefined;
|
|
180
|
+
try {
|
|
181
|
+
return normalizeHarness((0, config_2.loadDaemonConfig)().worker?.agent_type);
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function resolveInitialRuntimeConfig(opts) {
|
|
188
|
+
const saved = loadSavedChatConfig();
|
|
189
|
+
const daemonHarness = loadDaemonHarnessDefault();
|
|
190
|
+
const explicitNodeMode = opts.local ? "local" : opts.remote ? "remote" : undefined;
|
|
191
|
+
const target = (0, commerce_client_1.resolveChatDaemonTarget)({
|
|
192
|
+
explicitBaseUrl: opts.daemonUrl,
|
|
193
|
+
explicitNodeMode,
|
|
194
|
+
});
|
|
195
|
+
const harness = normalizeHarness(opts.harness) ?? normalizeHarness(saved?.harness) ?? daemonHarness;
|
|
196
|
+
const model = opts.model?.trim() || saved?.model?.trim() || undefined;
|
|
197
|
+
const nodeMode = explicitNodeMode ?? saved?.nodeMode ?? target.mode ?? (0, commerce_client_1.inferDaemonNodeMode)(target.baseUrl);
|
|
198
|
+
if (!harness) {
|
|
199
|
+
return { missingHarness: true };
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
missingHarness: false,
|
|
203
|
+
config: {
|
|
204
|
+
daemonUrl: target.baseUrl,
|
|
205
|
+
nodeMode,
|
|
206
|
+
harness,
|
|
207
|
+
model,
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
async function runGuidedSetup(seed) {
|
|
212
|
+
const saved = loadSavedChatConfig();
|
|
213
|
+
const daemonHarness = loadDaemonHarnessDefault();
|
|
214
|
+
const recommendedLocalUrl = (0, commerce_client_1.resolveDaemonApiBaseUrl)();
|
|
215
|
+
const initialNodeMode = seed?.nodeMode ?? saved?.nodeMode ?? "local";
|
|
216
|
+
const initialDaemonUrl = seed?.daemonUrl ??
|
|
217
|
+
saved?.daemonUrl ??
|
|
218
|
+
(initialNodeMode === "local" ? recommendedLocalUrl : "https://your-node.example.com");
|
|
219
|
+
const initialHarness = seed?.harness ?? normalizeHarness(saved?.harness) ?? daemonHarness ?? "openclaw";
|
|
220
|
+
const initialModel = seed?.model ?? saved?.model ?? "";
|
|
221
|
+
console.log(chalk_1.default.bold("◈ Commerce chat setup"));
|
|
222
|
+
console.log(" ARC-402 chat reads daemon state from either a local node on this machine or a remote node over HTTP.");
|
|
223
|
+
console.log(" It also needs a harness choice so chat can explain how hired work should be executed.");
|
|
224
|
+
console.log("");
|
|
225
|
+
const setup = await (0, prompts_1.default)([
|
|
226
|
+
{
|
|
227
|
+
type: "select",
|
|
228
|
+
name: "nodeMode",
|
|
229
|
+
message: "Which node should chat talk to?",
|
|
230
|
+
initial: initialNodeMode === "remote" ? 1 : 0,
|
|
231
|
+
choices: [
|
|
232
|
+
{ title: `Local node on this machine (${recommendedLocalUrl})`, value: "local" },
|
|
233
|
+
{ title: "Remote ARC-402 node", value: "remote" },
|
|
234
|
+
],
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
type: "text",
|
|
238
|
+
name: "daemonUrl",
|
|
239
|
+
message: "Daemon API base URL",
|
|
240
|
+
initial: (_prev, values) => values.nodeMode === "local" ? recommendedLocalUrl : initialDaemonUrl,
|
|
241
|
+
validate: (value) => {
|
|
242
|
+
try {
|
|
243
|
+
const parsed = new URL(value.trim());
|
|
244
|
+
return parsed.protocol === "http:" || parsed.protocol === "https:"
|
|
245
|
+
? true
|
|
246
|
+
: "Use an http:// or https:// URL";
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
return "Enter a valid URL";
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
type: "select",
|
|
255
|
+
name: "harness",
|
|
256
|
+
message: "Which harness should arc402 chat describe and expect?",
|
|
257
|
+
initial: Math.max(SUPPORTED_HARNESSES.indexOf(initialHarness), 0),
|
|
258
|
+
choices: [
|
|
259
|
+
{ title: "OpenClaw", value: "openclaw" },
|
|
260
|
+
{ title: "Claude Code", value: "claude-code" },
|
|
261
|
+
{ title: "Codex", value: "codex" },
|
|
262
|
+
{ title: "Hermes", value: "hermes" },
|
|
263
|
+
],
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
type: "text",
|
|
267
|
+
name: "model",
|
|
268
|
+
message: "Default model hint for chat (optional)",
|
|
269
|
+
initial: initialModel,
|
|
270
|
+
},
|
|
271
|
+
], {
|
|
272
|
+
onCancel: () => true,
|
|
273
|
+
});
|
|
274
|
+
const harness = normalizeHarness(setup.harness);
|
|
275
|
+
if (!setup.nodeMode || !setup.daemonUrl || !harness) {
|
|
276
|
+
console.log(chalk_1.default.yellow("Setup cancelled."));
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
const runtime = {
|
|
280
|
+
nodeMode: setup.nodeMode,
|
|
281
|
+
daemonUrl: String(setup.daemonUrl).trim().replace(/\/$/, ""),
|
|
282
|
+
harness,
|
|
283
|
+
model: String(setup.model ?? "").trim() || undefined,
|
|
284
|
+
};
|
|
285
|
+
console.log("");
|
|
286
|
+
console.log("Testing daemon endpoint...");
|
|
287
|
+
const daemonTest = await testDaemonConnection({ baseUrl: runtime.daemonUrl });
|
|
288
|
+
console.log(daemonTest.ok
|
|
289
|
+
? chalk_1.default.green(` OK: daemon responded at ${runtime.daemonUrl}`)
|
|
290
|
+
: chalk_1.default.yellow(` Daemon check failed: ${daemonTest.error}`));
|
|
291
|
+
if (!daemonTest.ok) {
|
|
292
|
+
if (runtime.nodeMode === "local") {
|
|
293
|
+
console.log(chalk_1.default.dim(" Local node hint: run `arc402 setup` or `arc402 daemon init`, then start the daemon before using local chat."));
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
console.log(chalk_1.default.dim(" Remote node hint: confirm the URL is reachable and the remote ARC-402 node is online."));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
const readiness = getHarnessReadiness(runtime.harness);
|
|
300
|
+
console.log(readiness.ready
|
|
301
|
+
? chalk_1.default.green(` Harness check: ${getHarnessLabel(runtime.harness)} ready (${readiness.summary})`)
|
|
302
|
+
: chalk_1.default.yellow(` Harness check: ${getHarnessLabel(runtime.harness)} not ready (${readiness.summary})`));
|
|
303
|
+
if (readiness.nextStep) {
|
|
304
|
+
console.log(chalk_1.default.dim(` ${readiness.nextStep}`));
|
|
305
|
+
}
|
|
306
|
+
const existing = (0, config_1.configExists)() ? (0, config_1.loadConfig)() : undefined;
|
|
307
|
+
const nextConfig = {
|
|
308
|
+
...(existing ?? (0, config_1.loadConfig)()),
|
|
309
|
+
chat: {
|
|
310
|
+
daemonUrl: runtime.daemonUrl,
|
|
311
|
+
nodeMode: runtime.nodeMode,
|
|
312
|
+
harness: runtime.harness,
|
|
313
|
+
model: runtime.model,
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
(0, config_1.saveConfig)(nextConfig);
|
|
317
|
+
console.log("");
|
|
318
|
+
console.log(chalk_1.default.green("Saved chat setup to ~/.arc402/config.json"));
|
|
319
|
+
return runtime;
|
|
320
|
+
}
|
|
321
|
+
function describeNodeMode(config) {
|
|
322
|
+
if (config.nodeMode === "local") {
|
|
323
|
+
return `Local node: chat will read daemon state from ${config.daemonUrl} on this machine.`;
|
|
324
|
+
}
|
|
325
|
+
return `Remote node: chat will read daemon state from ${config.daemonUrl} over HTTP instead of assuming a local daemon.`;
|
|
326
|
+
}
|
|
327
|
+
function printBanner(config) {
|
|
328
|
+
console.log(chalk_1.default.cyanBright("◈"), chalk_1.default.bold("ARC-402 Commerce Shell"));
|
|
329
|
+
console.log(chalk_1.default.dim(`Node: ${config.nodeMode} Endpoint: ${config.daemonUrl}`));
|
|
330
|
+
console.log(chalk_1.default.dim(`Harness: ${getHarnessLabel(config.harness)}${config.model ? ` Model: ${config.model}` : ""} Use /<command> for direct CLI commands`));
|
|
331
|
+
console.log(chalk_1.default.dim(describeNodeMode(config)));
|
|
332
|
+
const readiness = getHarnessReadiness(config.harness);
|
|
333
|
+
console.log(readiness.ready
|
|
334
|
+
? chalk_1.default.dim(`Harness check: ${readiness.summary}`)
|
|
335
|
+
: chalk_1.default.yellow(`Harness check: ${readiness.summary}`));
|
|
336
|
+
if (!readiness.ready && readiness.nextStep) {
|
|
337
|
+
console.log(chalk_1.default.dim(`Next: ${readiness.nextStep}`));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
async function renderStatus(options) {
|
|
341
|
+
const [health, wallet, workroom, agreements] = await Promise.all([
|
|
342
|
+
(0, commerce_client_1.fetchDaemonHealth)(options),
|
|
343
|
+
(0, commerce_client_1.fetchDaemonWalletStatus)(options),
|
|
344
|
+
(0, commerce_client_1.fetchDaemonWorkroomStatus)(options),
|
|
345
|
+
(0, commerce_client_1.fetchDaemonAgreements)(options),
|
|
346
|
+
]);
|
|
347
|
+
console.log(chalk_1.default.bold("◈ ARC-402 Commerce Shell"));
|
|
348
|
+
console.log(` Wallet: ${truncateAddress(wallet.wallet)} Chain: ${wallet.chainId} Workroom: ${workroom.status} Agreements: ${agreements.agreements.length}`);
|
|
349
|
+
console.log(` Daemon: ${truncateAddress(wallet.daemonId)} RPC: ${wallet.rpcUrl}`);
|
|
350
|
+
console.log(` Health: ${health.ok ? chalk_1.default.green("ok") : chalk_1.default.red("down")}`);
|
|
351
|
+
}
|
|
352
|
+
async function renderAgreements(options) {
|
|
353
|
+
const result = await (0, commerce_client_1.fetchDaemonAgreements)(options);
|
|
354
|
+
console.log(chalk_1.default.bold("◈ Agreements"));
|
|
355
|
+
if (result.agreements.length === 0) {
|
|
356
|
+
console.log(" No agreements found.");
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
for (const agreement of result.agreements.slice(0, 10)) {
|
|
360
|
+
const id = agreement["agreement_id"] ?? agreement["id"] ?? "n/a";
|
|
361
|
+
const counterparty = agreement["provider_address"] ??
|
|
362
|
+
agreement["hirer_address"] ??
|
|
363
|
+
agreement["counterparty"] ??
|
|
364
|
+
"unknown";
|
|
365
|
+
const status = formatAgreementStatus(agreement["status"]);
|
|
366
|
+
console.log(` #${String(id).padEnd(6)} ${status.padEnd(22)} ${truncateAddress(String(counterparty))}`);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
async function renderWorkroom(options) {
|
|
370
|
+
const result = await (0, commerce_client_1.fetchDaemonWorkroomStatus)(options);
|
|
371
|
+
console.log(chalk_1.default.bold("◈ Workroom"));
|
|
372
|
+
console.log(` Status: ${result.status}`);
|
|
373
|
+
}
|
|
374
|
+
function printHelp() {
|
|
375
|
+
console.log(chalk_1.default.bold("◈ Commerce REPL"));
|
|
376
|
+
console.log(" status Refresh wallet/workroom/agreement context from the configured node");
|
|
377
|
+
console.log(" agreements List recent agreements from the configured node");
|
|
378
|
+
console.log(" workroom Show current workroom status");
|
|
379
|
+
console.log(" setup Re-run the guided node/harness setup");
|
|
380
|
+
console.log(" /<command> Run any existing arc402 CLI command inside the shell");
|
|
381
|
+
console.log(" help Show this help");
|
|
382
|
+
console.log(" exit Leave the shell");
|
|
383
|
+
}
|
|
384
|
+
function printLocalDaemonSetupGuidance(config, detail) {
|
|
385
|
+
const configured = fs.existsSync(config_2.DAEMON_TOML);
|
|
386
|
+
console.log(chalk_1.default.yellow(configured
|
|
387
|
+
? `Local daemon context is unavailable at ${config.daemonUrl}.`
|
|
388
|
+
: "Local daemon mode was selected, but this machine is not configured as an ARC-402 node yet."));
|
|
389
|
+
if (detail) {
|
|
390
|
+
console.log(chalk_1.default.dim(` ${detail}`));
|
|
391
|
+
}
|
|
392
|
+
console.log("");
|
|
393
|
+
console.log("Next steps:");
|
|
394
|
+
if (!configured) {
|
|
395
|
+
console.log(" 1. Run `arc402 daemon init` or `arc402 setup` to create ~/.arc402/daemon.toml.");
|
|
396
|
+
console.log(" 2. Fill in wallet, node, and harness settings, then start the node with `arc402 daemon start`.");
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
console.log(" 1. Start the local node with `arc402 daemon start`.");
|
|
400
|
+
console.log(" 2. If startup fails, inspect `arc402 daemon logs` for the exact guidance.");
|
|
401
|
+
}
|
|
402
|
+
console.log(" 3. Re-run `arc402 chat --setup` and choose Remote if you meant to use another machine's node.");
|
|
403
|
+
}
|
|
404
|
+
async function dispatchCliCommand(line) {
|
|
405
|
+
const tokens = parseTokens(line);
|
|
406
|
+
if (tokens.length === 0)
|
|
407
|
+
return;
|
|
408
|
+
const { createProgram } = await Promise.resolve().then(() => __importStar(require("../program")));
|
|
409
|
+
const program = createProgram();
|
|
410
|
+
program.exitOverride();
|
|
411
|
+
program.configureOutput({
|
|
412
|
+
writeOut: (str) => process.stdout.write(str),
|
|
413
|
+
writeErr: (str) => process.stderr.write(str),
|
|
414
|
+
});
|
|
415
|
+
try {
|
|
416
|
+
await program.parseAsync(["node", "arc402", ...tokens]);
|
|
417
|
+
}
|
|
418
|
+
catch (err) {
|
|
419
|
+
const error = err;
|
|
420
|
+
if (error.code === "commander.helpDisplayed" ||
|
|
421
|
+
error.code === "commander.version" ||
|
|
422
|
+
error.code === "commander.executeSubCommandAsync") {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
throw err;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
async function buildSystemContext(options) {
|
|
429
|
+
let walletAddress = "unknown";
|
|
430
|
+
let trustScore = "unknown";
|
|
431
|
+
let agreementCount = 0;
|
|
432
|
+
let workroomStatus = "unknown";
|
|
433
|
+
try {
|
|
434
|
+
const wallet = await (0, commerce_client_1.fetchDaemonWalletStatus)(options);
|
|
435
|
+
walletAddress = wallet.wallet ?? "unknown";
|
|
436
|
+
const walletAny = wallet;
|
|
437
|
+
trustScore = String(walletAny["trustScore"] ?? walletAny["trust_score"] ?? "unknown");
|
|
438
|
+
}
|
|
439
|
+
catch {
|
|
440
|
+
// ignore
|
|
441
|
+
}
|
|
442
|
+
try {
|
|
443
|
+
const workroom = await (0, commerce_client_1.fetchDaemonWorkroomStatus)(options);
|
|
444
|
+
workroomStatus = workroom.status ?? "unknown";
|
|
445
|
+
}
|
|
446
|
+
catch {
|
|
447
|
+
// ignore
|
|
448
|
+
}
|
|
449
|
+
try {
|
|
450
|
+
const agr = await (0, commerce_client_1.fetchDaemonAgreements)(options);
|
|
451
|
+
agreementCount = agr.agreements.length;
|
|
452
|
+
}
|
|
453
|
+
catch {
|
|
454
|
+
// ignore
|
|
455
|
+
}
|
|
456
|
+
return [
|
|
457
|
+
"You are operating as the ARC-402 Commerce Shell agent.",
|
|
458
|
+
`Wallet: ${walletAddress}`,
|
|
459
|
+
"Network: Base Mainnet",
|
|
460
|
+
`Active agreements: ${agreementCount}`,
|
|
461
|
+
`Workroom: ${workroomStatus}`,
|
|
462
|
+
`Trust score: ${trustScore}`,
|
|
463
|
+
"",
|
|
464
|
+
"You have access to these ARC-402 CLI tools via shell commands:",
|
|
465
|
+
"- arc402 hire <endpoint> --task \"<desc>\" --service-type <type> --max <price> --deadline <duration>",
|
|
466
|
+
"- arc402 accept <id>",
|
|
467
|
+
"- arc402 deliver <id>",
|
|
468
|
+
"- arc402 verify <id>",
|
|
469
|
+
"- arc402 discover [--capability <cap>] [--limit N]",
|
|
470
|
+
"- arc402 agreements [--as client|provider]",
|
|
471
|
+
"- arc402 workroom status",
|
|
472
|
+
"- arc402 compute hire <provider> --hours <n> --rate <wei>",
|
|
473
|
+
"- arc402 arena rounds --limit N",
|
|
474
|
+
"- arc402 arena squad list",
|
|
475
|
+
"",
|
|
476
|
+
"When asked to hire, discover, or check status — use these tools directly by outputting shell commands in a code block, then explaining what you did.",
|
|
477
|
+
].join("\n");
|
|
478
|
+
}
|
|
479
|
+
async function executeDetectedToolCalls(output) {
|
|
480
|
+
// Find fenced code blocks containing arc402 commands
|
|
481
|
+
const fencePattern = /```(?:sh|bash|shell)?\n([\s\S]*?)```/g;
|
|
482
|
+
let match;
|
|
483
|
+
while ((match = fencePattern.exec(output)) !== null) {
|
|
484
|
+
const block = match[1];
|
|
485
|
+
const lines = block.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("arc402 "));
|
|
486
|
+
for (const cmdLine of lines) {
|
|
487
|
+
// strip leading "arc402 " and dispatch
|
|
488
|
+
const sub = cmdLine.replace(/^arc402\s+/, "");
|
|
489
|
+
console.log(chalk_1.default.dim(` > arc402 ${sub}`));
|
|
490
|
+
try {
|
|
491
|
+
await dispatchCliCommand(sub);
|
|
492
|
+
}
|
|
493
|
+
catch (err) {
|
|
494
|
+
console.log(chalk_1.default.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
async function dispatchToHarness(input, context, config, _clientOptions) {
|
|
500
|
+
const harness = config.harness;
|
|
501
|
+
if (harness === "openclaw" || harness === "hermes") {
|
|
502
|
+
// Determine endpoint
|
|
503
|
+
let endpoint;
|
|
504
|
+
if (harness === "openclaw") {
|
|
505
|
+
// Try reading gateway URL from openclaw config
|
|
506
|
+
try {
|
|
507
|
+
const raw = fs.readFileSync(OPENCLAW_CONFIG_PATH, "utf8");
|
|
508
|
+
const ocConfig = JSON.parse(raw);
|
|
509
|
+
const gatewayUrl = ocConfig["gateway"]?.["url"] ??
|
|
510
|
+
ocConfig["gatewayUrl"] ??
|
|
511
|
+
ocConfig["baseUrl"];
|
|
512
|
+
endpoint = gatewayUrl ? String(gatewayUrl).replace(/\/$/, "") + "/v1/chat/completions" : `${config.daemonUrl}/v1/chat/completions`;
|
|
513
|
+
}
|
|
514
|
+
catch {
|
|
515
|
+
endpoint = `${config.daemonUrl}/v1/chat/completions`;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
else {
|
|
519
|
+
endpoint = `${config.daemonUrl}/v1/chat/completions`;
|
|
520
|
+
}
|
|
521
|
+
const body = {
|
|
522
|
+
model: config.model ?? "claude-3-5-sonnet-latest",
|
|
523
|
+
stream: false,
|
|
524
|
+
messages: [
|
|
525
|
+
{ role: "system", content: context },
|
|
526
|
+
{ role: "user", content: input },
|
|
527
|
+
],
|
|
528
|
+
};
|
|
529
|
+
try {
|
|
530
|
+
const res = await fetch(endpoint, {
|
|
531
|
+
method: "POST",
|
|
532
|
+
headers: { "Content-Type": "application/json" },
|
|
533
|
+
body: JSON.stringify(body),
|
|
534
|
+
});
|
|
535
|
+
if (!res.ok) {
|
|
536
|
+
const text = await res.text().catch(() => "");
|
|
537
|
+
console.log(chalk_1.default.yellow(` Harness responded with HTTP ${res.status}: ${text || "(no body)"}`));
|
|
538
|
+
console.log(chalk_1.default.dim(` Endpoint: ${endpoint}`));
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
const json = await res.json();
|
|
542
|
+
const content = json["choices"]?.[0]?.["message"]?.["content"] ??
|
|
543
|
+
json["content"] ??
|
|
544
|
+
JSON.stringify(json);
|
|
545
|
+
console.log("\n" + String(content));
|
|
546
|
+
await executeDetectedToolCalls(String(content));
|
|
547
|
+
}
|
|
548
|
+
catch (err) {
|
|
549
|
+
console.log(chalk_1.default.yellow(` Could not reach ${harness} endpoint (${endpoint}).`));
|
|
550
|
+
console.log(chalk_1.default.dim(` ${err instanceof Error ? err.message : String(err)}`));
|
|
551
|
+
if (harness === "openclaw") {
|
|
552
|
+
console.log(chalk_1.default.dim(" Hint: make sure OpenClaw gateway is running (openclaw gateway start)."));
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
if (harness === "claude-code") {
|
|
558
|
+
if (!commandExists("claude")) {
|
|
559
|
+
console.log(chalk_1.default.yellow(" claude CLI not found. Install Claude Code to use this harness."));
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
const prompt = `${context}\n\nUser request: ${input}`;
|
|
563
|
+
const tmpFile = path.join(os.tmpdir(), `arc402-chat-${Date.now()}.txt`);
|
|
564
|
+
try {
|
|
565
|
+
fs.writeFileSync(tmpFile, prompt, "utf8");
|
|
566
|
+
// Unset ANTHROPIC_API_KEY so OAuth (Max subscription) is used
|
|
567
|
+
const env = { ...process.env };
|
|
568
|
+
delete env["ANTHROPIC_API_KEY"];
|
|
569
|
+
const result = (0, child_process_1.spawnSync)("claude", ["--print", "--permission-mode", "bypassPermissions"], { input: prompt, encoding: "utf8", env, timeout: 120000 });
|
|
570
|
+
const output = result.stdout ?? "";
|
|
571
|
+
const errOut = result.stderr ?? "";
|
|
572
|
+
if (output) {
|
|
573
|
+
console.log("\n" + output);
|
|
574
|
+
await executeDetectedToolCalls(output);
|
|
575
|
+
}
|
|
576
|
+
if (!output && errOut) {
|
|
577
|
+
console.log(chalk_1.default.yellow(` claude stderr: ${errOut}`));
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
finally {
|
|
581
|
+
try {
|
|
582
|
+
fs.unlinkSync(tmpFile);
|
|
583
|
+
}
|
|
584
|
+
catch { /* ignore */ }
|
|
585
|
+
}
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
if (harness === "codex") {
|
|
589
|
+
if (!commandExists("codex")) {
|
|
590
|
+
console.log(chalk_1.default.yellow(" codex CLI not found. Install Codex CLI to use this harness."));
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
const prompt = `${context}\n\nUser request: ${input}`;
|
|
594
|
+
const result = (0, child_process_1.spawnSync)("codex", ["exec", prompt], { encoding: "utf8", timeout: 120000 });
|
|
595
|
+
const output = result.stdout ?? "";
|
|
596
|
+
const errOut = result.stderr ?? "";
|
|
597
|
+
if (output) {
|
|
598
|
+
console.log("\n" + output);
|
|
599
|
+
await executeDetectedToolCalls(output);
|
|
600
|
+
}
|
|
601
|
+
if (!output && errOut) {
|
|
602
|
+
console.log(chalk_1.default.yellow(` codex stderr: ${errOut}`));
|
|
603
|
+
}
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
console.log(chalk_1.default.yellow(` Unknown harness: ${harness}. Run \`arc402 chat --setup\` to reconfigure.`));
|
|
607
|
+
}
|
|
608
|
+
function inferIntent(input) {
|
|
609
|
+
const normalized = input.trim().toLowerCase();
|
|
610
|
+
if (normalized === "help")
|
|
611
|
+
return "help";
|
|
612
|
+
if (normalized === "setup")
|
|
613
|
+
return "setup";
|
|
614
|
+
if (normalized.includes("agreement"))
|
|
615
|
+
return "agreements";
|
|
616
|
+
if (normalized.includes("workroom"))
|
|
617
|
+
return "workroom";
|
|
618
|
+
if (normalized.includes("status") || normalized.includes("wallet") || normalized.includes("balance"))
|
|
619
|
+
return "status";
|
|
620
|
+
return "unknown";
|
|
621
|
+
}
|
|
622
|
+
function registerChatCommand(program) {
|
|
623
|
+
program
|
|
624
|
+
.command("chat")
|
|
625
|
+
.description("Launch the ARC-402 Commerce REPL with guided node and harness setup")
|
|
626
|
+
.option("--daemon-url <url>", "Override the daemon API base URL")
|
|
627
|
+
.option("--harness <name>", "Harness to describe and expect: openclaw | claude-code | codex | hermes")
|
|
628
|
+
.option("--model <name>", "Default model hint shown in the shell")
|
|
629
|
+
.option("--setup", "Run guided chat setup before entering the shell")
|
|
630
|
+
.option("--local", "Force local node mode")
|
|
631
|
+
.option("--remote", "Force remote node mode")
|
|
632
|
+
.action(async (opts) => {
|
|
633
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
634
|
+
throw new Error("arc402 chat requires an interactive TTY");
|
|
635
|
+
}
|
|
636
|
+
if (opts.local && opts.remote) {
|
|
637
|
+
throw new Error("Choose either --local or --remote, not both.");
|
|
638
|
+
}
|
|
639
|
+
let state = resolveInitialRuntimeConfig(opts);
|
|
640
|
+
let runtimeConfig = state.config;
|
|
641
|
+
if (opts.setup || state.missingHarness) {
|
|
642
|
+
if (state.missingHarness) {
|
|
643
|
+
console.log(chalk_1.default.yellow("No chat harness is configured yet. Running guided setup."));
|
|
644
|
+
console.log("");
|
|
645
|
+
}
|
|
646
|
+
runtimeConfig = await runGuidedSetup(runtimeConfig);
|
|
647
|
+
if (!runtimeConfig) {
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
state = { missingHarness: false, config: runtimeConfig };
|
|
651
|
+
}
|
|
652
|
+
if (!runtimeConfig) {
|
|
653
|
+
throw new Error("Chat setup is incomplete. Run `arc402 chat --setup`.");
|
|
654
|
+
}
|
|
655
|
+
let activeConfig = runtimeConfig;
|
|
656
|
+
const clientOptions = { baseUrl: activeConfig.daemonUrl };
|
|
657
|
+
if (activeConfig.nodeMode === "local" && !fs.existsSync(config_2.DAEMON_TOML)) {
|
|
658
|
+
printLocalDaemonSetupGuidance(activeConfig);
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
printBanner(activeConfig);
|
|
662
|
+
try {
|
|
663
|
+
await renderStatus(clientOptions);
|
|
664
|
+
}
|
|
665
|
+
catch (err) {
|
|
666
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
667
|
+
if (activeConfig.nodeMode === "local") {
|
|
668
|
+
printLocalDaemonSetupGuidance(activeConfig, detail);
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
console.log(chalk_1.default.yellow(` Remote daemon context unavailable from ${activeConfig.daemonUrl}: ${detail}`));
|
|
672
|
+
}
|
|
673
|
+
printHelp();
|
|
674
|
+
const rl = readline_1.default.createInterface({
|
|
675
|
+
input: process.stdin,
|
|
676
|
+
output: process.stdout,
|
|
677
|
+
prompt: `${chalk_1.default.cyanBright(">")} `,
|
|
678
|
+
terminal: true,
|
|
679
|
+
});
|
|
680
|
+
rl.prompt();
|
|
681
|
+
rl.on("line", async (line) => {
|
|
682
|
+
const trimmed = line.trim();
|
|
683
|
+
if (!trimmed) {
|
|
684
|
+
rl.prompt();
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
try {
|
|
688
|
+
if (trimmed === "exit" || trimmed === "quit") {
|
|
689
|
+
rl.close();
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
if (trimmed.startsWith("/")) {
|
|
693
|
+
await dispatchCliCommand(trimmed.slice(1));
|
|
694
|
+
console.log("");
|
|
695
|
+
rl.prompt();
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
switch (inferIntent(trimmed)) {
|
|
699
|
+
case "help":
|
|
700
|
+
printHelp();
|
|
701
|
+
break;
|
|
702
|
+
case "setup": {
|
|
703
|
+
const updated = await runGuidedSetup(activeConfig);
|
|
704
|
+
if (updated) {
|
|
705
|
+
activeConfig = updated;
|
|
706
|
+
clientOptions.baseUrl = updated.daemonUrl;
|
|
707
|
+
printBanner(activeConfig);
|
|
708
|
+
}
|
|
709
|
+
break;
|
|
710
|
+
}
|
|
711
|
+
case "status":
|
|
712
|
+
await renderStatus(clientOptions);
|
|
713
|
+
break;
|
|
714
|
+
case "agreements":
|
|
715
|
+
await renderAgreements(clientOptions);
|
|
716
|
+
break;
|
|
717
|
+
case "workroom":
|
|
718
|
+
await renderWorkroom(clientOptions);
|
|
719
|
+
break;
|
|
720
|
+
default: {
|
|
721
|
+
// Natural language — dispatch to configured harness
|
|
722
|
+
const readiness = getHarnessReadiness(activeConfig.harness);
|
|
723
|
+
if (!readiness.ready) {
|
|
724
|
+
console.log(chalk_1.default.yellow(` ${getHarnessLabel(activeConfig.harness)} harness is not ready: ${readiness.summary}`));
|
|
725
|
+
if (readiness.nextStep)
|
|
726
|
+
console.log(chalk_1.default.dim(` ${readiness.nextStep}`));
|
|
727
|
+
console.log(chalk_1.default.dim(" Use `setup` to reconfigure the harness, or `/...` for direct CLI commands."));
|
|
728
|
+
}
|
|
729
|
+
else {
|
|
730
|
+
const context = await buildSystemContext(clientOptions);
|
|
731
|
+
await dispatchToHarness(trimmed, context, activeConfig, clientOptions);
|
|
732
|
+
}
|
|
733
|
+
break;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
catch (err) {
|
|
738
|
+
console.log(` ${chalk_1.default.red(err instanceof Error ? err.message : String(err))}`);
|
|
739
|
+
}
|
|
740
|
+
console.log("");
|
|
741
|
+
rl.prompt();
|
|
742
|
+
});
|
|
743
|
+
rl.on("close", () => {
|
|
744
|
+
console.log(chalk_1.default.dim("Commerce shell closed."));
|
|
745
|
+
process.exit(0);
|
|
746
|
+
});
|
|
747
|
+
await new Promise(() => {
|
|
748
|
+
// readline keeps the process alive until close()
|
|
749
|
+
});
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
//# sourceMappingURL=chat.js.map
|