arc402-cli 1.7.6 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/chat/harness.d.ts +47 -0
  2. package/dist/chat/harness.d.ts.map +1 -0
  3. package/dist/chat/harness.js +235 -0
  4. package/dist/chat/harness.js.map +1 -0
  5. package/dist/commands/chat.d.ts.map +1 -1
  6. package/dist/commands/chat.js +30 -208
  7. package/dist/commands/chat.js.map +1 -1
  8. package/dist/renderer/index.d.ts +2 -0
  9. package/dist/renderer/index.d.ts.map +1 -1
  10. package/dist/renderer/index.js +2 -0
  11. package/dist/renderer/index.js.map +1 -1
  12. package/dist/renderer/ink.d.ts +29 -13
  13. package/dist/renderer/ink.d.ts.map +1 -1
  14. package/dist/renderer/ink.js +28 -52
  15. package/dist/renderer/ink.js.map +1 -1
  16. package/dist/renderer/reconciler.d.ts.map +1 -1
  17. package/dist/renderer/reconciler.js +12 -1
  18. package/dist/renderer/reconciler.js.map +1 -1
  19. package/dist/renderer/render-frame.d.ts +8 -0
  20. package/dist/renderer/render-frame.d.ts.map +1 -0
  21. package/dist/renderer/render-frame.js +104 -0
  22. package/dist/renderer/render-frame.js.map +1 -0
  23. package/dist/renderer/runtime.d.ts +23 -0
  24. package/dist/renderer/runtime.d.ts.map +1 -0
  25. package/dist/renderer/runtime.js +148 -0
  26. package/dist/renderer/runtime.js.map +1 -0
  27. package/dist/tui/App.d.ts.map +1 -1
  28. package/dist/tui/App.js +43 -14
  29. package/dist/tui/App.js.map +1 -1
  30. package/dist/tui/Footer.js +1 -1
  31. package/dist/tui/Footer.js.map +1 -1
  32. package/dist/tui/InputLine.d.ts +1 -1
  33. package/dist/tui/InputLine.d.ts.map +1 -1
  34. package/dist/tui/InputLine.js +140 -132
  35. package/dist/tui/InputLine.js.map +1 -1
  36. package/dist/tui/components/Button.d.ts.map +1 -1
  37. package/dist/tui/components/Button.js +3 -4
  38. package/dist/tui/components/Button.js.map +1 -1
  39. package/dist/tui/components/ChatHarnessSelector.d.ts +11 -0
  40. package/dist/tui/components/ChatHarnessSelector.d.ts.map +1 -0
  41. package/dist/tui/components/ChatHarnessSelector.js +23 -0
  42. package/dist/tui/components/ChatHarnessSelector.js.map +1 -0
  43. package/dist/tui/components/CustomTextInput.d.ts +1 -1
  44. package/dist/tui/components/CustomTextInput.d.ts.map +1 -1
  45. package/dist/tui/components/CustomTextInput.js +15 -31
  46. package/dist/tui/components/CustomTextInput.js.map +1 -1
  47. package/dist/tui/components/InteractiveTable.d.ts.map +1 -1
  48. package/dist/tui/components/InteractiveTable.js +4 -5
  49. package/dist/tui/components/InteractiveTable.js.map +1 -1
  50. package/dist/tui/components/commerce/AgentPicker.d.ts.map +1 -1
  51. package/dist/tui/components/commerce/AgentPicker.js +5 -6
  52. package/dist/tui/components/commerce/AgentPicker.js.map +1 -1
  53. package/dist/tui/index.js +2 -2
  54. package/dist/tui/index.js.map +1 -1
  55. package/dist/tui/useChat.d.ts +11 -5
  56. package/dist/tui/useChat.d.ts.map +1 -1
  57. package/dist/tui/useChat.js +99 -97
  58. package/dist/tui/useChat.js.map +1 -1
  59. package/dist/tui/useScroll.d.ts.map +1 -1
  60. package/dist/tui/useScroll.js +0 -15
  61. package/dist/tui/useScroll.js.map +1 -1
  62. package/package.json +3 -3
@@ -0,0 +1,47 @@
1
+ import { type DaemonNodeMode } from "../commerce-client";
2
+ export type SupportedHarness = "openclaw" | "claude-code" | "codex" | "hermes";
3
+ export type ChatRuntimeConfig = {
4
+ daemonUrl: string;
5
+ nodeMode: DaemonNodeMode;
6
+ harness?: SupportedHarness;
7
+ model?: string;
8
+ };
9
+ export type HarnessReadiness = {
10
+ ready: boolean;
11
+ summary: string;
12
+ nextStep?: string;
13
+ };
14
+ export type HarnessChoice = {
15
+ harness: SupportedHarness;
16
+ label: string;
17
+ readiness: HarnessReadiness;
18
+ };
19
+ export declare const SUPPORTED_HARNESSES: SupportedHarness[];
20
+ export declare function normalizeHarness(value?: string): SupportedHarness | undefined;
21
+ export declare function getHarnessLabel(harness: SupportedHarness): string;
22
+ export declare function getHarnessReadiness(harness: SupportedHarness): HarnessReadiness;
23
+ export declare function getHarnessChoices(): HarnessChoice[];
24
+ export declare function loadDaemonHarnessDefault(): SupportedHarness | undefined;
25
+ export declare function resolveInitialChatRuntime(options?: {
26
+ daemonUrl?: string;
27
+ harness?: string;
28
+ model?: string;
29
+ local?: boolean;
30
+ remote?: boolean;
31
+ }): {
32
+ config: ChatRuntimeConfig;
33
+ missingHarness: boolean;
34
+ };
35
+ export declare function persistChatHarnessSelection(runtime: ChatRuntimeConfig): void;
36
+ export declare function resolveOpenClawEndpoint(): {
37
+ url: string;
38
+ token?: string;
39
+ };
40
+ export declare function dispatchHarnessChat(params: {
41
+ harness: SupportedHarness;
42
+ message: string;
43
+ model?: string;
44
+ systemPrompt?: string;
45
+ daemonUrl?: string;
46
+ }): Promise<string>;
47
+ //# sourceMappingURL=harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/chat/harness.ts"],"names":[],"mappings":"AAMA,OAAO,EAAgD,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEvG,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,aAAa,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,gBAAgB,CAAC;CAC7B,CAAC;AAGF,eAAO,MAAM,mBAAmB,EAAE,gBAAgB,EAAmD,CAAC;AAEtG,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAQ7E;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAOjE;AAOD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB,CAwB/E;AAED,wBAAgB,iBAAiB,IAAI,aAAa,EAAE,CAMnD;AAOD,wBAAgB,wBAAwB,IAAI,gBAAgB,GAAG,SAAS,CAOvE;AAED,wBAAgB,yBAAyB,CAAC,OAAO,GAAE;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CACb,GAAG;IAAE,MAAM,EAAE,iBAAiB,CAAC;IAAC,cAAc,EAAE,OAAO,CAAA;CAAE,CAkB9D;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAY5E;AAED,wBAAgB,uBAAuB,IAAI;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAezE;AAED,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,OAAO,EAAE,gBAAgB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyDlB"}
@@ -0,0 +1,235 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SUPPORTED_HARNESSES = void 0;
37
+ exports.normalizeHarness = normalizeHarness;
38
+ exports.getHarnessLabel = getHarnessLabel;
39
+ exports.getHarnessReadiness = getHarnessReadiness;
40
+ exports.getHarnessChoices = getHarnessChoices;
41
+ exports.loadDaemonHarnessDefault = loadDaemonHarnessDefault;
42
+ exports.resolveInitialChatRuntime = resolveInitialChatRuntime;
43
+ exports.persistChatHarnessSelection = persistChatHarnessSelection;
44
+ exports.resolveOpenClawEndpoint = resolveOpenClawEndpoint;
45
+ exports.dispatchHarnessChat = dispatchHarnessChat;
46
+ const fs = __importStar(require("fs"));
47
+ const os = __importStar(require("os"));
48
+ const path = __importStar(require("path"));
49
+ const child_process_1 = require("child_process");
50
+ const config_1 = require("../config");
51
+ const config_2 = require("../daemon/config");
52
+ const commerce_client_1 = require("../commerce-client");
53
+ const OPENCLAW_CONFIG_PATH = process.env.OPENCLAW_CONFIG || path.join(os.homedir(), ".openclaw", "openclaw.json");
54
+ exports.SUPPORTED_HARNESSES = ["openclaw", "claude-code", "codex", "hermes"];
55
+ function normalizeHarness(value) {
56
+ const normalized = value?.trim().toLowerCase();
57
+ if (!normalized)
58
+ return undefined;
59
+ if (normalized === "openclaw")
60
+ return "openclaw";
61
+ if (normalized === "claude" || normalized === "claude-code")
62
+ return "claude-code";
63
+ if (normalized === "codex")
64
+ return "codex";
65
+ if (normalized === "hermes")
66
+ return "hermes";
67
+ return undefined;
68
+ }
69
+ function getHarnessLabel(harness) {
70
+ switch (harness) {
71
+ case "openclaw": return "OpenClaw";
72
+ case "claude-code": return "Claude Code";
73
+ case "codex": return "Codex";
74
+ case "hermes": return "Hermes";
75
+ }
76
+ }
77
+ function commandExists(command) {
78
+ const result = (0, child_process_1.spawnSync)("sh", ["-lc", `command -v ${command}`], { stdio: "ignore" });
79
+ return result.status === 0;
80
+ }
81
+ function getHarnessReadiness(harness) {
82
+ switch (harness) {
83
+ case "openclaw":
84
+ if (fs.existsSync(OPENCLAW_CONFIG_PATH)) {
85
+ return { ready: true, summary: `gateway config found at ${OPENCLAW_CONFIG_PATH}` };
86
+ }
87
+ return {
88
+ ready: false,
89
+ summary: `missing ${OPENCLAW_CONFIG_PATH}`,
90
+ nextStep: "Run OpenClaw locally or create ~/.openclaw/openclaw.json before relying on OpenClaw-backed execution.",
91
+ };
92
+ case "claude-code":
93
+ return commandExists("claude")
94
+ ? { ready: true, summary: "claude CLI found on PATH" }
95
+ : { ready: false, summary: "claude CLI not found on PATH", nextStep: "Install Claude Code or pick a different harness." };
96
+ case "codex":
97
+ return commandExists("codex")
98
+ ? { ready: true, summary: "codex CLI found on PATH" }
99
+ : { ready: false, summary: "codex CLI not found on PATH", nextStep: "Install Codex CLI or pick a different harness." };
100
+ case "hermes":
101
+ return commandExists("hermes")
102
+ ? { ready: true, summary: "hermes CLI found on PATH" }
103
+ : { ready: false, summary: "hermes CLI not found on PATH", nextStep: "Run `arc402 hermes init` or install Hermes before using this harness." };
104
+ }
105
+ }
106
+ function getHarnessChoices() {
107
+ return exports.SUPPORTED_HARNESSES.map((harness) => ({
108
+ harness,
109
+ label: getHarnessLabel(harness),
110
+ readiness: getHarnessReadiness(harness),
111
+ }));
112
+ }
113
+ function loadSavedChatConfig() {
114
+ if (!(0, config_1.configExists)())
115
+ return undefined;
116
+ return (0, config_1.loadConfig)().chat;
117
+ }
118
+ function loadDaemonHarnessDefault() {
119
+ if (!fs.existsSync(config_2.DAEMON_TOML))
120
+ return undefined;
121
+ try {
122
+ return normalizeHarness((0, config_2.loadDaemonConfig)().worker?.agent_type);
123
+ }
124
+ catch {
125
+ return undefined;
126
+ }
127
+ }
128
+ function resolveInitialChatRuntime(options = {}) {
129
+ const saved = loadSavedChatConfig();
130
+ const daemonHarness = loadDaemonHarnessDefault();
131
+ const explicitNodeMode = options.local ? "local" : options.remote ? "remote" : undefined;
132
+ const target = (0, commerce_client_1.resolveChatDaemonTarget)({ explicitBaseUrl: options.daemonUrl, explicitNodeMode });
133
+ const harness = normalizeHarness(options.harness) ?? normalizeHarness(saved?.harness) ?? daemonHarness;
134
+ const model = options.model?.trim() || saved?.model?.trim() || undefined;
135
+ const nodeMode = explicitNodeMode ?? saved?.nodeMode ?? target.mode ?? (0, commerce_client_1.inferDaemonNodeMode)(target.baseUrl);
136
+ return {
137
+ missingHarness: !harness,
138
+ config: {
139
+ daemonUrl: target.baseUrl,
140
+ nodeMode,
141
+ harness,
142
+ model,
143
+ },
144
+ };
145
+ }
146
+ function persistChatHarnessSelection(runtime) {
147
+ const existing = (0, config_1.configExists)() ? (0, config_1.loadConfig)() : undefined;
148
+ const nextConfig = {
149
+ ...(existing ?? (0, config_1.loadConfig)()),
150
+ chat: {
151
+ daemonUrl: runtime.daemonUrl,
152
+ nodeMode: runtime.nodeMode,
153
+ harness: runtime.harness,
154
+ model: runtime.model,
155
+ },
156
+ };
157
+ (0, config_1.saveConfig)(nextConfig);
158
+ }
159
+ function resolveOpenClawEndpoint() {
160
+ try {
161
+ const raw = fs.readFileSync(OPENCLAW_CONFIG_PATH, "utf-8");
162
+ const config = JSON.parse(raw);
163
+ const gateway = config.gateway;
164
+ let gatewayUrl = gateway?.url;
165
+ if (!gatewayUrl || gatewayUrl === "lan" || gatewayUrl === "local") {
166
+ const port = gateway?.port ?? 18789;
167
+ gatewayUrl = `http://127.0.0.1:${port}`;
168
+ }
169
+ const token = gateway?.auth?.token;
170
+ return { url: `${String(gatewayUrl).replace(/\/$/, "")}/v1/chat/completions`, token };
171
+ }
172
+ catch {
173
+ return { url: "http://127.0.0.1:18789/v1/chat/completions" };
174
+ }
175
+ }
176
+ async function dispatchHarnessChat(params) {
177
+ const { harness, message, model, systemPrompt, daemonUrl } = params;
178
+ if (harness === "openclaw" || harness === "hermes") {
179
+ const endpoint = harness === "openclaw"
180
+ ? resolveOpenClawEndpoint().url
181
+ : `${(daemonUrl ?? "http://127.0.0.1:4403").replace(/\/$/, "")}/v1/chat/completions`;
182
+ const token = harness === "openclaw" ? resolveOpenClawEndpoint().token : undefined;
183
+ const headers = { "Content-Type": "application/json" };
184
+ if (token)
185
+ headers.Authorization = `Bearer ${token}`;
186
+ const messages = [];
187
+ if (systemPrompt?.trim())
188
+ messages.push({ role: "system", content: systemPrompt });
189
+ messages.push({ role: "user", content: message });
190
+ const res = await fetch(endpoint, {
191
+ method: "POST",
192
+ headers,
193
+ body: JSON.stringify({ model: model ?? "claude-sonnet-4-6", stream: false, messages }),
194
+ signal: AbortSignal.timeout(120000),
195
+ });
196
+ if (!res.ok) {
197
+ const text = await res.text().catch(() => "");
198
+ throw new Error(`${getHarnessLabel(harness)} responded with HTTP ${res.status}${text ? `: ${text}` : ""}`);
199
+ }
200
+ const json = await res.json();
201
+ const choice = json.choices?.[0];
202
+ const content = choice?.message?.content;
203
+ if (typeof content === "string")
204
+ return content;
205
+ if (typeof json.content === "string")
206
+ return json.content;
207
+ return JSON.stringify(json, null, 2);
208
+ }
209
+ if (harness === "claude-code") {
210
+ const env = { ...process.env };
211
+ delete env.ANTHROPIC_API_KEY;
212
+ const prompt = systemPrompt?.trim() ? `${systemPrompt}\n\nUser request: ${message}` : message;
213
+ const result = (0, child_process_1.spawnSync)("claude", ["--print", "--permission-mode", "bypassPermissions"], {
214
+ input: prompt,
215
+ encoding: "utf8",
216
+ env,
217
+ timeout: 120000,
218
+ });
219
+ if (result.error)
220
+ throw result.error;
221
+ if (result.status !== 0 && !result.stdout?.trim()) {
222
+ throw new Error((result.stderr || `Claude Code exited with status ${result.status ?? "unknown"}`).trim());
223
+ }
224
+ return (result.stdout || result.stderr || "").trim();
225
+ }
226
+ const prompt = systemPrompt?.trim() ? `${systemPrompt}\n\nUser request: ${message}` : message;
227
+ const result = (0, child_process_1.spawnSync)("codex", ["exec", prompt], { encoding: "utf8", timeout: 120000 });
228
+ if (result.error)
229
+ throw result.error;
230
+ if (result.status !== 0 && !result.stdout?.trim()) {
231
+ throw new Error((result.stderr || `Codex exited with status ${result.status ?? "unknown"}`).trim());
232
+ }
233
+ return (result.stdout || result.stderr || "").trim();
234
+ }
235
+ //# sourceMappingURL=harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/chat/harness.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/commands/chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8qBpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+I1D"}
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/commands/chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+epC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+I1D"}
@@ -39,16 +39,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.registerChatCommand = registerChatCommand;
40
40
  const chalk_1 = __importDefault(require("chalk"));
41
41
  const fs = __importStar(require("fs"));
42
- const os = __importStar(require("os"));
43
- const path = __importStar(require("path"));
44
42
  const prompts_1 = __importDefault(require("prompts"));
45
43
  const readline_1 = __importDefault(require("readline"));
46
44
  const child_process_1 = require("child_process");
47
45
  const commerce_client_1 = require("../commerce-client");
48
46
  const config_1 = require("../config");
49
47
  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"];
48
+ const harness_1 = require("../chat/harness");
52
49
  function parseTokens(input) {
53
50
  const tokens = [];
54
51
  let current = "";
@@ -99,64 +96,10 @@ function formatAgreementStatus(value) {
99
96
  const raw = typeof value === "string" ? value : typeof value === "number" ? String(value) : "unknown";
100
97
  return raw.toUpperCase();
101
98
  }
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
99
  function commandExists(command) {
129
100
  const result = (0, child_process_1.spawnSync)("sh", ["-lc", `command -v ${command}`], { stdio: "ignore" });
130
101
  return result.status === 0;
131
102
  }
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
103
  async function testDaemonConnection(options) {
161
104
  try {
162
105
  await (0, commerce_client_1.fetchDaemonHealth)(options);
@@ -174,49 +117,22 @@ function loadSavedChatConfig() {
174
117
  return undefined;
175
118
  return (0, config_1.loadConfig)().chat;
176
119
  }
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
120
  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
- }
121
+ const resolved = (0, harness_1.resolveInitialChatRuntime)(opts);
201
122
  return {
202
- missingHarness: false,
203
- config: {
204
- daemonUrl: target.baseUrl,
205
- nodeMode,
206
- harness,
207
- model,
208
- },
123
+ missingHarness: resolved.missingHarness,
124
+ config: resolved.config.harness ? resolved.config : undefined,
209
125
  };
210
126
  }
211
127
  async function runGuidedSetup(seed) {
212
128
  const saved = loadSavedChatConfig();
213
- const daemonHarness = loadDaemonHarnessDefault();
129
+ const daemonHarness = (0, harness_1.loadDaemonHarnessDefault)();
214
130
  const recommendedLocalUrl = (0, commerce_client_1.resolveDaemonApiBaseUrl)();
215
131
  const initialNodeMode = seed?.nodeMode ?? saved?.nodeMode ?? "local";
216
132
  const initialDaemonUrl = seed?.daemonUrl ??
217
133
  saved?.daemonUrl ??
218
134
  (initialNodeMode === "local" ? recommendedLocalUrl : "https://your-node.example.com");
219
- const initialHarness = seed?.harness ?? normalizeHarness(saved?.harness) ?? daemonHarness ?? "openclaw";
135
+ const initialHarness = seed?.harness ?? (0, harness_1.normalizeHarness)(saved?.harness) ?? daemonHarness ?? "openclaw";
220
136
  const initialModel = seed?.model ?? saved?.model ?? "";
221
137
  console.log(chalk_1.default.bold("◈ Commerce chat setup"));
222
138
  console.log(" ARC-402 chat reads daemon state from either a local node on this machine or a remote node over HTTP.");
@@ -254,7 +170,7 @@ async function runGuidedSetup(seed) {
254
170
  type: "select",
255
171
  name: "harness",
256
172
  message: "Which harness should arc402 chat describe and expect?",
257
- initial: Math.max(SUPPORTED_HARNESSES.indexOf(initialHarness), 0),
173
+ initial: Math.max(harness_1.SUPPORTED_HARNESSES.indexOf(initialHarness), 0),
258
174
  choices: [
259
175
  { title: "OpenClaw", value: "openclaw" },
260
176
  { title: "Claude Code", value: "claude-code" },
@@ -271,7 +187,7 @@ async function runGuidedSetup(seed) {
271
187
  ], {
272
188
  onCancel: () => true,
273
189
  });
274
- const harness = normalizeHarness(setup.harness);
190
+ const harness = (0, harness_1.normalizeHarness)(setup.harness);
275
191
  if (!setup.nodeMode || !setup.daemonUrl || !harness) {
276
192
  console.log(chalk_1.default.yellow("Setup cancelled."));
277
193
  return null;
@@ -296,10 +212,10 @@ async function runGuidedSetup(seed) {
296
212
  console.log(chalk_1.default.dim(" Remote node hint: confirm the URL is reachable and the remote ARC-402 node is online."));
297
213
  }
298
214
  }
299
- const readiness = getHarnessReadiness(runtime.harness);
215
+ const readiness = (0, harness_1.getHarnessReadiness)(runtime.harness);
300
216
  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})`));
217
+ ? chalk_1.default.green(` Harness check: ${(0, harness_1.getHarnessLabel)(runtime.harness)} ready (${readiness.summary})`)
218
+ : chalk_1.default.yellow(` Harness check: ${(0, harness_1.getHarnessLabel)(runtime.harness)} not ready (${readiness.summary})`));
303
219
  if (readiness.nextStep) {
304
220
  console.log(chalk_1.default.dim(` ${readiness.nextStep}`));
305
221
  }
@@ -327,9 +243,9 @@ function describeNodeMode(config) {
327
243
  function printBanner(config) {
328
244
  console.log(chalk_1.default.cyanBright("◈"), chalk_1.default.bold("ARC-402 Commerce Shell"));
329
245
  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`));
246
+ console.log(chalk_1.default.dim(`Harness: ${(0, harness_1.getHarnessLabel)(config.harness)}${config.model ? ` Model: ${config.model}` : ""} Use /<command> for direct CLI commands`));
331
247
  console.log(chalk_1.default.dim(describeNodeMode(config)));
332
- const readiness = getHarnessReadiness(config.harness);
248
+ const readiness = (0, harness_1.getHarnessReadiness)(config.harness);
333
249
  console.log(readiness.ready
334
250
  ? chalk_1.default.dim(`Harness check: ${readiness.summary}`)
335
251
  : chalk_1.default.yellow(`Harness check: ${readiness.summary}`));
@@ -497,119 +413,25 @@ async function executeDetectedToolCalls(output) {
497
413
  }
498
414
  }
499
415
  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
- // Resolve openclaw gateway endpoint
506
- try {
507
- const raw = fs.readFileSync(OPENCLAW_CONFIG_PATH, "utf8");
508
- const ocConfig = JSON.parse(raw);
509
- const gatewayConfig = ocConfig["gateway"];
510
- // Resolve gateway URL: prioritize explicit url, fall back to localhost + port
511
- let gatewayUrl = gatewayConfig?.["url"];
512
- if (!gatewayUrl || gatewayUrl === "lan" || gatewayUrl === "local") {
513
- // Use localhost + port from config
514
- const port = gatewayConfig?.["port"] ?? 18789;
515
- gatewayUrl = `http://127.0.0.1:${port}`;
516
- }
517
- endpoint = gatewayUrl.replace(/\/$/, "") + "/v1/chat/completions";
518
- }
519
- catch {
520
- // Fallback: try default localhost:18789
521
- endpoint = "http://127.0.0.1:18789/v1/chat/completions";
522
- }
523
- }
524
- else {
525
- endpoint = `${config.daemonUrl}/v1/chat/completions`;
526
- }
527
- const body = {
528
- model: config.model ?? "claude-3-5-sonnet-latest",
529
- stream: false,
530
- messages: [
531
- { role: "system", content: context },
532
- { role: "user", content: input },
533
- ],
534
- };
535
- try {
536
- const res = await fetch(endpoint, {
537
- method: "POST",
538
- headers: { "Content-Type": "application/json" },
539
- body: JSON.stringify(body),
540
- });
541
- if (!res.ok) {
542
- const text = await res.text().catch(() => "");
543
- console.log(chalk_1.default.yellow(` Harness responded with HTTP ${res.status}: ${text || "(no body)"}`));
544
- console.log(chalk_1.default.dim(` Endpoint: ${endpoint}`));
545
- return;
546
- }
547
- const json = await res.json();
548
- const content = json["choices"]?.[0]?.["message"]?.["content"] ??
549
- json["content"] ??
550
- JSON.stringify(json);
551
- console.log("\n" + String(content));
552
- await executeDetectedToolCalls(String(content));
553
- }
554
- catch (err) {
555
- console.log(chalk_1.default.yellow(` Could not reach ${harness} endpoint (${endpoint}).`));
556
- console.log(chalk_1.default.dim(` ${err instanceof Error ? err.message : String(err)}`));
557
- if (harness === "openclaw") {
558
- console.log(chalk_1.default.dim(" Hint: make sure OpenClaw gateway is running (openclaw gateway start)."));
559
- }
560
- }
561
- return;
562
- }
563
- if (harness === "claude-code") {
564
- if (!commandExists("claude")) {
565
- console.log(chalk_1.default.yellow(" claude CLI not found. Install Claude Code to use this harness."));
416
+ try {
417
+ const output = await (0, harness_1.dispatchHarnessChat)({
418
+ harness: config.harness,
419
+ message: input,
420
+ model: config.model,
421
+ systemPrompt: context,
422
+ daemonUrl: config.daemonUrl,
423
+ });
424
+ if (!output.trim())
566
425
  return;
567
- }
568
- const prompt = `${context}\n\nUser request: ${input}`;
569
- const tmpFile = path.join(os.tmpdir(), `arc402-chat-${Date.now()}.txt`);
570
- try {
571
- fs.writeFileSync(tmpFile, prompt, "utf8");
572
- // Unset ANTHROPIC_API_KEY so OAuth (Max subscription) is used
573
- const env = { ...process.env };
574
- delete env["ANTHROPIC_API_KEY"];
575
- const result = (0, child_process_1.spawnSync)("claude", ["--print", "--permission-mode", "bypassPermissions"], { input: prompt, encoding: "utf8", env, timeout: 120000 });
576
- const output = result.stdout ?? "";
577
- const errOut = result.stderr ?? "";
578
- if (output) {
579
- console.log("\n" + output);
580
- await executeDetectedToolCalls(output);
581
- }
582
- if (!output && errOut) {
583
- console.log(chalk_1.default.yellow(` claude stderr: ${errOut}`));
584
- }
585
- }
586
- finally {
587
- try {
588
- fs.unlinkSync(tmpFile);
589
- }
590
- catch { /* ignore */ }
591
- }
592
- return;
426
+ console.log("\n" + output);
427
+ await executeDetectedToolCalls(output);
593
428
  }
594
- if (harness === "codex") {
595
- if (!commandExists("codex")) {
596
- console.log(chalk_1.default.yellow(" codex CLI not found. Install Codex CLI to use this harness."));
597
- return;
598
- }
599
- const prompt = `${context}\n\nUser request: ${input}`;
600
- const result = (0, child_process_1.spawnSync)("codex", ["exec", prompt], { encoding: "utf8", timeout: 120000 });
601
- const output = result.stdout ?? "";
602
- const errOut = result.stderr ?? "";
603
- if (output) {
604
- console.log("\n" + output);
605
- await executeDetectedToolCalls(output);
606
- }
607
- if (!output && errOut) {
608
- console.log(chalk_1.default.yellow(` codex stderr: ${errOut}`));
429
+ catch (err) {
430
+ console.log(chalk_1.default.yellow(` ${err instanceof Error ? err.message : String(err)}`));
431
+ if (config.harness === "openclaw") {
432
+ console.log(chalk_1.default.dim(" Hint: make sure OpenClaw gateway is running (openclaw gateway start)."));
609
433
  }
610
- return;
611
434
  }
612
- console.log(chalk_1.default.yellow(` Unknown harness: ${harness}. Run \`arc402 chat --setup\` to reconfigure.`));
613
435
  }
614
436
  function inferIntent(input) {
615
437
  const normalized = input.trim().toLowerCase();
@@ -725,9 +547,9 @@ function registerChatCommand(program) {
725
547
  break;
726
548
  default: {
727
549
  // Natural language — dispatch to configured harness
728
- const readiness = getHarnessReadiness(activeConfig.harness);
550
+ const readiness = (0, harness_1.getHarnessReadiness)(activeConfig.harness);
729
551
  if (!readiness.ready) {
730
- console.log(chalk_1.default.yellow(` ${getHarnessLabel(activeConfig.harness)} harness is not ready: ${readiness.summary}`));
552
+ console.log(chalk_1.default.yellow(` ${(0, harness_1.getHarnessLabel)(activeConfig.harness)} harness is not ready: ${readiness.summary}`));
731
553
  if (readiness.nextStep)
732
554
  console.log(chalk_1.default.dim(` ${readiness.nextStep}`));
733
555
  console.log(chalk_1.default.dim(" Use `setup` to reconfigure the harness, or `/...` for direct CLI commands."));