@heyditto/cli 3.4.0 → 3.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -0
- package/dist/agents/claude.js +13 -4
- package/dist/agents/claude.js.map +1 -1
- package/dist/agents/cliproxy.d.ts +13 -0
- package/dist/agents/cliproxy.js +115 -0
- package/dist/agents/cliproxy.js.map +1 -0
- package/dist/agents/codex.js +1 -1
- package/dist/agents/codex.js.map +1 -1
- package/dist/agents/launch.d.ts +2 -0
- package/dist/agents/launch.js +53 -17
- package/dist/agents/launch.js.map +1 -1
- package/dist/agents/sessions.d.ts +2 -0
- package/dist/agents/sessions.js.map +1 -1
- package/dist/agents/types.d.ts +4 -0
- package/dist/agents/types.js.map +1 -1
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands.js +4 -0
- package/dist/commands.js.map +1 -1
- package/dist/relay/client.d.ts +28 -0
- package/dist/relay/client.js +166 -0
- package/dist/relay/client.js.map +1 -0
- package/dist/relay/commands.d.ts +2 -0
- package/dist/relay/commands.js +71 -0
- package/dist/relay/commands.js.map +1 -0
- package/dist/remote/channel-server.js +22 -16
- package/dist/remote/channel-server.js.map +1 -1
- package/dist/update-lock.json +1 -1
- package/docs/t3-code.md +110 -0
- package/package.json +3 -1
- package/scripts/claude-router-launcher.sh +113 -0
package/README.md
CHANGED
|
@@ -1281,6 +1281,71 @@ says so. Tracked artifact directories are flagged rather than claimed excluded.
|
|
|
1281
1281
|
`heyditto offload` refuses to delete a folder when unrelated files, unknown projects or
|
|
1282
1282
|
escaping symlinks beneath it would be lost.
|
|
1283
1283
|
|
|
1284
|
+
### Cloud-assisted CLIProxy inference
|
|
1285
|
+
|
|
1286
|
+
To use subscription inference with Router optimizations, cloud session recording
|
|
1287
|
+
and remote control, connect a local CLIProxy through an outbound relay. Use a
|
|
1288
|
+
dedicated **personal** endpoint and a model exposed by your local proxy:
|
|
1289
|
+
|
|
1290
|
+
```sh
|
|
1291
|
+
heyditto endpoints create my-local-models
|
|
1292
|
+
heyditto cliproxy relay --endpoint my-local-models --enable --model gpt-6.1-sol
|
|
1293
|
+
# In another terminal, while the relay stays running:
|
|
1294
|
+
heyditto claude --endpoint my-local-models
|
|
1295
|
+
```
|
|
1296
|
+
|
|
1297
|
+
The first `--enable` changes that endpoint to relay-only BYOK inference, enables
|
|
1298
|
+
cloud trace recording and selects Router inference instead of a native-account
|
|
1299
|
+
default. Later relay starts omit `--enable`. The CLI keeps an outbound
|
|
1300
|
+
authenticated connection; your local proxy access key and provider credentials
|
|
1301
|
+
stay on your computer. Stopping the relay makes requests fail without switching
|
|
1302
|
+
to paid inference. Existing Router optimization/tool resource costs still apply.
|
|
1303
|
+
|
|
1304
|
+
The first release supports one relay per personal endpoint and requires the API
|
|
1305
|
+
and inference request to reach the same backend process. Organization endpoints
|
|
1306
|
+
and routing across multiple backend processes are not supported yet. The local
|
|
1307
|
+
model IDs must match the endpoint's routes/aliases; the cloud model list does not
|
|
1308
|
+
discover laptop providers. Deploy the matching backend before enabling an endpoint.
|
|
1309
|
+
|
|
1310
|
+
For the official T3 Code app, see [the Router setup guide](docs/t3-code.md).
|
|
1311
|
+
|
|
1312
|
+
### Direct local CLIProxy inference
|
|
1313
|
+
|
|
1314
|
+
Use a locally installed CLIProxy with Claude Code or Codex instead of Ditto Router
|
|
1315
|
+
inference:
|
|
1316
|
+
|
|
1317
|
+
```sh
|
|
1318
|
+
heyditto claude --cliproxy --endpoint my-tools
|
|
1319
|
+
heyditto codex --cliproxy --endpoint my-tools --model gpt-6-luna
|
|
1320
|
+
heyditto claude --cliproxy http://127.0.0.1:8317/v1 --dry-run --endpoint my-tools
|
|
1321
|
+
```
|
|
1322
|
+
|
|
1323
|
+
`--cliproxy` detects EasyCLIProxyAPI's saved host, port and API access key. It
|
|
1324
|
+
reads the GUI configuration from the platform's `com.cpa.gui` application-data
|
|
1325
|
+
directory. Set `CLIPROXY_CONFIG` for another EasyCLIProxyAPI TOML file, or use
|
|
1326
|
+
`CLIPROXY_BASE_URL` and `CLIPROXY_API_KEY` for a standalone CLIProxy installation.
|
|
1327
|
+
The URL must be loopback (`127.0.0.1`, `localhost` or `::1`); discovery does not
|
|
1328
|
+
accept LAN/public hosts, URL credentials or redirects. An API key is never
|
|
1329
|
+
copied between two different proxy addresses automatically.
|
|
1330
|
+
|
|
1331
|
+
Before launching, the CLI authenticates `/v1/models` and selects a Claude/GPT
|
|
1332
|
+
model exposed by the proxy, or checks your explicit `--model`. Local failure
|
|
1333
|
+
stops the launch without switching to paid Router inference. `--dry-run` checks
|
|
1334
|
+
the proxy and prints a plan with credentials masked; it mints no Ditto key.
|
|
1335
|
+
Resume remembers the proxy URL and reads its credential again, so `--resume`
|
|
1336
|
+
keeps local inference. Use `--no-cliproxy` to return to the normal inference mode.
|
|
1337
|
+
|
|
1338
|
+
This mode still uses a Ditto login and endpoint for selected Claude MCP tools
|
|
1339
|
+
and remote control. The local API access key stays local; Ditto MCP uses a
|
|
1340
|
+
separate temporary endpoint key, which is revoked on exit. `--no-mcp` omits the
|
|
1341
|
+
selected Claude MCP tools; `--no-remote-control` omits cloud session registration.
|
|
1342
|
+
Those flags do not remove the current launcher's Ditto login/endpoint dependency.
|
|
1343
|
+
Local inference bypasses Router compression, routing and inference recording;
|
|
1344
|
+
cloud-assisted relay is a separate mode. Cloud MCP calls and remote-control
|
|
1345
|
+
activity still reach Ditto when enabled. `--mcp-only` keeps using the native
|
|
1346
|
+
Claude account instead; it cannot be combined with `--cliproxy`. `--budget`
|
|
1347
|
+
cannot cap subscription inference and is rejected in direct CLIProxy mode.
|
|
1348
|
+
|
|
1284
1349
|
### Native Claude inference and remote delivery
|
|
1285
1350
|
|
|
1286
1351
|
`heyditto claude` keeps using Ditto Router for inference. `--mcp` changes
|
package/dist/agents/claude.js
CHANGED
|
@@ -53,7 +53,7 @@ export function planClaude(input) {
|
|
|
53
53
|
if (input.model)
|
|
54
54
|
envSet.ANTHROPIC_MODEL = input.model;
|
|
55
55
|
if (input.mcp)
|
|
56
|
-
envSet[MCP_KEY_ENV] = input.apiKey;
|
|
56
|
+
envSet[MCP_KEY_ENV] = input.mcpApiKey ?? input.apiKey;
|
|
57
57
|
if (input.mcpOnly) {
|
|
58
58
|
// Endpoint keys are only MCP credentials in this mode. Never forward one
|
|
59
59
|
// to Anthropic or inherit a parent launch's inference gateway settings.
|
|
@@ -64,11 +64,20 @@ export function planClaude(input) {
|
|
|
64
64
|
installHint: "install Claude Code and sign in with `claude auth login`",
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
|
-
// Claude Code's
|
|
68
|
-
//
|
|
69
|
-
// denies every auto-mode tool use. Decide locally unless the caller chose.
|
|
67
|
+
// Intermediaries do not forward Claude Code's auto-mode classifier fields.
|
|
68
|
+
// Decide locally for Router and CLIProxy inference unless the caller chose.
|
|
70
69
|
if (input.env.CLAUDE_CODE_AUTO_MODE_SERVER === undefined)
|
|
71
70
|
envSet.CLAUDE_CODE_AUTO_MODE_SERVER = "0";
|
|
71
|
+
if (input.localInference) {
|
|
72
|
+
// Cloud MCP auth never becomes the local inference credential, and a
|
|
73
|
+
// parent Router launch's custom headers/other provider modes stay out.
|
|
74
|
+
delete envSet.ANTHROPIC_CUSTOM_HEADERS;
|
|
75
|
+
return {
|
|
76
|
+
command: "claude", args: finalArgs, envSet,
|
|
77
|
+
envUnset: ["ANTHROPIC_API_KEY", "ANTHROPIC_CUSTOM_HEADERS", "CLAUDE_CODE_OAUTH_TOKEN", "CLAUDE_CODE_USE_BEDROCK", "CLAUDE_CODE_USE_VERTEX", "CLAUDE_CODE_USE_FOUNDRY", ...(!input.model ? ["ANTHROPIC_MODEL"] : []), ...(!input.mcp ? [MCP_KEY_ENV] : [])],
|
|
78
|
+
installHint: "install Claude Code: npm i -g @anthropic-ai/claude-code",
|
|
79
|
+
};
|
|
80
|
+
}
|
|
72
81
|
// Claude Code only labels requests (x-claude-code-request-class: main,
|
|
73
82
|
// subagent, auxiliary) for gateways when asked. The router uses the label to
|
|
74
83
|
// skip memory recall on housekeeping calls such as the auto-mode classifier.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface CliProxy {
|
|
2
|
+
/** Canonical loopback OpenAI/Responses root. */
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
/** Local credential, never a Ditto endpoint key. */
|
|
5
|
+
apiKey: string;
|
|
6
|
+
models: string[];
|
|
7
|
+
}
|
|
8
|
+
/** Deliberately no public/LAN destinations, embedded credentials or redirects. */
|
|
9
|
+
export declare function cliProxyBaseUrl(value: string): string;
|
|
10
|
+
export declare function cliProxyConfigPaths(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform, home?: string): string[];
|
|
11
|
+
/** Reads only the API access key; OAuth/provider/management credentials stay untouched. */
|
|
12
|
+
export declare function resolveCliProxy(requested: string | true, env?: NodeJS.ProcessEnv): Promise<CliProxy>;
|
|
13
|
+
export declare function cliProxyModel(proxy: Pick<CliProxy, "models">, harness: "claude" | "codex", requested?: string): string;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { parse } from "smol-toml";
|
|
5
|
+
/** Deliberately no public/LAN destinations, embedded credentials or redirects. */
|
|
6
|
+
export function cliProxyBaseUrl(value) {
|
|
7
|
+
let url;
|
|
8
|
+
try {
|
|
9
|
+
url = new URL(value);
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
throw new Error("CLIProxy URL must be an http(s) loopback URL, such as http://127.0.0.1:8317/v1");
|
|
13
|
+
}
|
|
14
|
+
if (!["http:", "https:"].includes(url.protocol) || !["127.0.0.1", "[::1]", "localhost"].includes(url.hostname) ||
|
|
15
|
+
url.username || url.password || url.search || url.hash || !["", "/", "/v1", "/v1/"].includes(url.pathname)) {
|
|
16
|
+
throw new Error("CLIProxy requires a loopback URL with no credentials, query or fragment, ending in /v1 or /");
|
|
17
|
+
}
|
|
18
|
+
// Pin localhost rather than resolving it through potentially modified DNS.
|
|
19
|
+
if (url.hostname === "localhost")
|
|
20
|
+
url.hostname = "127.0.0.1";
|
|
21
|
+
url.pathname = "/v1";
|
|
22
|
+
return url.toString().replace(/\/$/, "");
|
|
23
|
+
}
|
|
24
|
+
export function cliProxyConfigPaths(env = process.env, platform = process.platform, home = os.homedir()) {
|
|
25
|
+
if (env.CLIPROXY_CONFIG)
|
|
26
|
+
return [env.CLIPROXY_CONFIG];
|
|
27
|
+
if (platform === "darwin")
|
|
28
|
+
return [path.join(home, "Library", "Application Support", "com.cpa.gui", "config.toml")];
|
|
29
|
+
if (platform === "win32")
|
|
30
|
+
return [path.join(env.APPDATA || path.join(home, "AppData", "Roaming"), "com.cpa.gui", "config.toml")];
|
|
31
|
+
return [
|
|
32
|
+
path.join(env.XDG_DATA_HOME || path.join(home, ".local", "share"), "com.cpa.gui", "config.toml"),
|
|
33
|
+
path.join(env.XDG_CONFIG_HOME || path.join(home, ".config"), "com.cpa.gui", "config.toml"),
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
/** Reads only the API access key; OAuth/provider/management credentials stay untouched. */
|
|
37
|
+
export async function resolveCliProxy(requested, env = process.env) {
|
|
38
|
+
let config;
|
|
39
|
+
const explicitUrl = typeof requested === "string" ? requested : env.CLIPROXY_BASE_URL;
|
|
40
|
+
for (const file of explicitUrl && env.CLIPROXY_API_KEY ? [] : cliProxyConfigPaths(env)) {
|
|
41
|
+
try {
|
|
42
|
+
config = parse(await readFile(file, "utf8"));
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
if (err.code === "ENOENT" && !env.CLIPROXY_CONFIG)
|
|
47
|
+
continue;
|
|
48
|
+
throw new Error("Could not read CLIProxy configuration; check CLIPROXY_CONFIG or set CLIPROXY_BASE_URL and CLIPROXY_API_KEY");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
let detectedUrl;
|
|
52
|
+
if (config) {
|
|
53
|
+
const port = config.port;
|
|
54
|
+
const host = config.host === "::1" ? "[::1]" : (config.host || "127.0.0.1");
|
|
55
|
+
if (typeof host === "string" && typeof port === "number" && Number.isInteger(port) && port > 0 && port <= 65535) {
|
|
56
|
+
try {
|
|
57
|
+
detectedUrl = cliProxyBaseUrl(`http://${host}:${port}`);
|
|
58
|
+
}
|
|
59
|
+
catch { /* A LAN-configured application is not eligible for auto-discovery. */ }
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const baseUrl = cliProxyBaseUrl(typeof requested === "string" ? requested : env.CLIPROXY_BASE_URL || detectedUrl || "http://127.0.0.1:8317/v1");
|
|
63
|
+
const keys = config?.["api-keys"];
|
|
64
|
+
// EasyCLIProxyAPI also writes annotated entries as [[api-keys]] tables.
|
|
65
|
+
// Only their access-key field is relevant; remarks are display metadata.
|
|
66
|
+
const detectedKey = detectedUrl === baseUrl && Array.isArray(keys)
|
|
67
|
+
? keys.map((entry) => typeof entry === "string" ? entry : entry && typeof entry === "object" && "key" in entry ? entry.key : undefined)
|
|
68
|
+
.find((key) => typeof key === "string" && Boolean(key.trim()))
|
|
69
|
+
: undefined;
|
|
70
|
+
const apiKey = env.CLIPROXY_API_KEY || detectedKey || "";
|
|
71
|
+
if (!apiKey || /[\r\n]/.test(apiKey)) {
|
|
72
|
+
throw new Error("No CLIProxy API access key found; set CLIPROXY_API_KEY or configure an API key in EasyCLIProxyAPI");
|
|
73
|
+
}
|
|
74
|
+
let response;
|
|
75
|
+
try {
|
|
76
|
+
response = await fetch(`${baseUrl}/models`, {
|
|
77
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
78
|
+
redirect: "error",
|
|
79
|
+
signal: AbortSignal.timeout(5_000),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
throw new Error("CLIProxy is not reachable at the configured loopback address; start the proxy and check its port. Ditto Router inference was not used");
|
|
84
|
+
}
|
|
85
|
+
if (!response.ok) {
|
|
86
|
+
await response.body?.cancel();
|
|
87
|
+
throw new Error(`CLIProxy model check failed (HTTP ${response.status}); check its API access key and provider setup. Ditto Router inference was not used`);
|
|
88
|
+
}
|
|
89
|
+
let data;
|
|
90
|
+
try {
|
|
91
|
+
data = await response.json();
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
throw new Error("CLIProxy returned an invalid model catalog; Ditto Router inference was not used");
|
|
95
|
+
}
|
|
96
|
+
if (data?.object !== "list" || !Array.isArray(data.data))
|
|
97
|
+
throw new Error("CLIProxy returned an invalid model catalog; Ditto Router inference was not used");
|
|
98
|
+
const models = data.data.flatMap((model) => typeof model?.id === "string" && model.id.trim() ? [model.id] : []);
|
|
99
|
+
if (!models.length)
|
|
100
|
+
throw new Error("CLIProxy has no models; connect a provider in the proxy before launching");
|
|
101
|
+
return { baseUrl, apiKey, models };
|
|
102
|
+
}
|
|
103
|
+
export function cliProxyModel(proxy, harness, requested) {
|
|
104
|
+
if (requested) {
|
|
105
|
+
if (!proxy.models.includes(requested))
|
|
106
|
+
throw new Error("The requested model is not in CLIProxy's model catalog; select a model exposed by your local proxy");
|
|
107
|
+
return requested;
|
|
108
|
+
}
|
|
109
|
+
const pattern = harness === "claude" ? /^claude-/ : /^(gpt-|o[1-9])/;
|
|
110
|
+
const model = proxy.models.find((id) => pattern.test(id));
|
|
111
|
+
if (!model)
|
|
112
|
+
throw new Error(`CLIProxy has no default ${harness} model; pass --model with an ID exposed by your local proxy`);
|
|
113
|
+
return model;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=cliproxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliproxy.js","sourceRoot":"","sources":["../../src/agents/cliproxy.ts"],"names":[],"mappings":"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"}
|
package/dist/agents/codex.js
CHANGED
|
@@ -33,7 +33,7 @@ export function planCodex(input) {
|
|
|
33
33
|
else if (resuming) {
|
|
34
34
|
args.push("resume");
|
|
35
35
|
}
|
|
36
|
-
args.push("-c", `model_provider=${tomlString("ditto")}`, "-c", `model_providers.ditto.name=${tomlString("Ditto")}`, "-c", `model_providers.ditto.base_url=${tomlString(input.baseUrl)}`, "-c", `model_providers.ditto.env_key=${tomlString(CODEX_KEY_ENV)}`, "-c", `model_providers.ditto.wire_api=${tomlString("responses")}`, "-c", `model_providers.ditto.http_headers=${tomlInlineTable([[SESSION_HEADER, input.sessionId], ...harnessHeaders("codex", input.harnessVersion)])}`);
|
|
36
|
+
args.push("-c", `model_provider=${tomlString("ditto")}`, "-c", `model_providers.ditto.name=${tomlString(input.localInference ? "CLIProxy" : "Ditto")}`, "-c", `model_providers.ditto.base_url=${tomlString(input.baseUrl)}`, "-c", `model_providers.ditto.env_key=${tomlString(CODEX_KEY_ENV)}`, "-c", `model_providers.ditto.wire_api=${tomlString("responses")}`, "-c", `model_providers.ditto.http_headers=${tomlInlineTable(input.localInference ? [] : [[SESSION_HEADER, input.sessionId], ...harnessHeaders("codex", input.harnessVersion)])}`);
|
|
37
37
|
if (input.model)
|
|
38
38
|
args.push("-m", input.model);
|
|
39
39
|
if (input.yolo)
|
package/dist/agents/codex.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/agents/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAoC,cAAc,EAAE,MAAM,YAAY,CAAC;AAE7F,uEAAuE;AACvE,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,eAAe,CAAC,OAAgC;IAC9D,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AACvF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS,CAAC,KAAgB;IACxC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,2EAA2E;IAC3E,0EAA0E;IAC1E,sEAAsE;IACtE,2EAA2E;IAC3E,qBAAqB;IACrB,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;IAC7D,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClB,IAAI,QAAQ;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;SAAM,IAAI,QAAQ,EAAE,CAAC;QACpB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtB,CAAC;IAED,IAAI,CAAC,IAAI,CACP,IAAI,EACJ,kBAAkB,UAAU,CAAC,OAAO,CAAC,EAAE,EACvC,IAAI,EACJ,8BAA8B,UAAU,CAAC,OAAO,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/agents/codex.ts"],"names":[],"mappings":"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"}
|
package/dist/agents/launch.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export interface LaunchOptions {
|
|
|
40
40
|
*/
|
|
41
41
|
mcp?: boolean;
|
|
42
42
|
mcpOnly?: boolean;
|
|
43
|
+
/** Direct inference through a loopback CLIProxy; URL is persisted, keys are not. */
|
|
44
|
+
cliproxy?: string | boolean;
|
|
43
45
|
remoteTransport?: "cli" | "channels";
|
|
44
46
|
}
|
|
45
47
|
/** Explicit flags (or resumed choices) win over repo/cloud launch defaults. */
|
package/dist/agents/launch.js
CHANGED
|
@@ -20,6 +20,7 @@ import { resolveClaudeResume, transcriptCwd } from "./claude-resume.js";
|
|
|
20
20
|
import { findTranscriptById, isUuid, listTranscriptsIn } from "./claude-transcripts.js";
|
|
21
21
|
import { watchClaudeSessionTitle } from "./claude-title-sync.js";
|
|
22
22
|
import { planCodex } from "./codex.js";
|
|
23
|
+
import { cliProxyModel, resolveCliProxy } from "./cliproxy.js";
|
|
23
24
|
import { readHarnessVersion } from "./harness-headers.js";
|
|
24
25
|
import { ensureGrokHome, planGrok } from "./grok.js";
|
|
25
26
|
import { latestSession, readSession, sessionForHarnessId, writeSession } from "./sessions.js";
|
|
@@ -33,7 +34,7 @@ import { loadPty, spawnInPty } from "../remote/pty.js";
|
|
|
33
34
|
import { checkpointPush } from "../teleport/commands.js";
|
|
34
35
|
/** Explicit flags (or resumed choices) win over repo/cloud launch defaults. */
|
|
35
36
|
export function resolveClaudeLaunchDefaults(options, defaults = {}) {
|
|
36
|
-
const mcpOnly = options.mcpOnly ?? (defaults.claude_inference === "native");
|
|
37
|
+
const mcpOnly = options.cliproxy ? false : options.mcpOnly ?? (defaults.claude_inference === "native");
|
|
37
38
|
const channelsUsable = !options.headless && remoteMode(options) === "tui";
|
|
38
39
|
const remoteTransport = options.remoteTransport ?? (mcpOnly && channelsUsable && defaults.claude_remote_transport === "channels" ? "channels" : "cli");
|
|
39
40
|
return { ...options, mcpOnly, remoteTransport };
|
|
@@ -297,6 +298,12 @@ function waitForExit(child, command, cwd) {
|
|
|
297
298
|
}
|
|
298
299
|
/** Launches a coding harness against a Ditto inference endpoint with a temporary key. */
|
|
299
300
|
export async function launchHarness(harness, rawArgs, options) {
|
|
301
|
+
// An explicit empty value (often an unset shell variable) still requests
|
|
302
|
+
// CLIProxy. Reject it before any launch/setup work rather than treating it
|
|
303
|
+
// as a false boolean and silently using Router inference.
|
|
304
|
+
if (typeof options.cliproxy === "string" && !options.cliproxy.trim()) {
|
|
305
|
+
throw new Error("--cliproxy requires a loopback URL; pass --cliproxy alone to auto-detect");
|
|
306
|
+
}
|
|
300
307
|
let passthrough = stripSeparator(rawArgs);
|
|
301
308
|
if (harness === "claude") {
|
|
302
309
|
const lifted = liftResumeFlags(passthrough);
|
|
@@ -377,7 +384,26 @@ export async function launchHarness(harness, rawArgs, options) {
|
|
|
377
384
|
if (!record.harnessSessionId)
|
|
378
385
|
resumeLast = true;
|
|
379
386
|
}
|
|
380
|
-
options = {
|
|
387
|
+
options = {
|
|
388
|
+
...options,
|
|
389
|
+
cliproxy: options.cliproxy ?? (options.mcpOnly !== undefined ? false : record?.cliproxy),
|
|
390
|
+
mcpOnly: options.cliproxy ? options.mcpOnly : options.mcpOnly ?? record?.mcpOnly,
|
|
391
|
+
remoteTransport: options.remoteTransport ?? (remoteMode(options) === "tui" ? record?.remoteTransport : undefined),
|
|
392
|
+
};
|
|
393
|
+
if (typeof options.cliproxy === "string" && !options.cliproxy.trim()) {
|
|
394
|
+
throw new Error("The saved CLIProxy URL is empty; pass --cliproxy to auto-detect or --no-cliproxy to change inference mode");
|
|
395
|
+
}
|
|
396
|
+
if (options.cliproxy && options.mcpOnly)
|
|
397
|
+
throw new Error("choose either --cliproxy or --mcp-only");
|
|
398
|
+
if (options.cliproxy && harness === "grok")
|
|
399
|
+
throw new Error("--cliproxy is supported for claude and codex");
|
|
400
|
+
if (options.cliproxy && options.budget !== undefined)
|
|
401
|
+
throw new Error("--budget cannot cap CLIProxy subscription inference; configure limits in your local proxy instead");
|
|
402
|
+
// Check the local proxy before sign-in or minting any cloud key. A failure
|
|
403
|
+
// must never silently switch inference back to the paid Router.
|
|
404
|
+
const proxy = options.cliproxy ? await resolveCliProxy(options.cliproxy) : undefined;
|
|
405
|
+
if (proxy)
|
|
406
|
+
options = { ...options, cliproxy: proxy.baseUrl, mcpOnly: false };
|
|
381
407
|
const requestedEndpoint = options.endpoint ?? record?.endpointSlug;
|
|
382
408
|
let selected = options.dryRun ? undefined : await ensureLoggedIn(harness, requestedEndpoint);
|
|
383
409
|
let catalog;
|
|
@@ -462,7 +488,7 @@ export async function launchHarness(harness, rawArgs, options) {
|
|
|
462
488
|
endpoint = { ...endpoint, providerOptions: { ...endpoint.providerOptions, ...repoLaunchDefaults } };
|
|
463
489
|
options = resolveClaudeLaunchDefaults(options, endpoint.providerOptions);
|
|
464
490
|
}
|
|
465
|
-
if (!options.mcpOnly)
|
|
491
|
+
if (!options.mcpOnly && !proxy)
|
|
466
492
|
await assertEndpointActive(endpoint);
|
|
467
493
|
if (options.mcpOnly && (harness !== "claude" || options.mcp === false))
|
|
468
494
|
throw new Error("--mcp-only requires Claude Code with MCP tools enabled");
|
|
@@ -484,7 +510,7 @@ export async function launchHarness(harness, rawArgs, options) {
|
|
|
484
510
|
// claude-* ids). Earlier releases pinned Codex sessions to the endpoint
|
|
485
511
|
// slug; that pin is dropped on resume so they pass through too.
|
|
486
512
|
const recordedModel = record?.model === endpoint.slug ? undefined : record?.model;
|
|
487
|
-
const model = options.model ?? recordedModel;
|
|
513
|
+
const model = proxy ? cliProxyModel(proxy, harness, options.model ?? recordedModel) : options.model ?? recordedModel;
|
|
488
514
|
const now = new Date().toISOString();
|
|
489
515
|
if (!(await isDirectory(cwd)))
|
|
490
516
|
throw new Error(`launch directory ${cwd} does not exist`);
|
|
@@ -538,7 +564,7 @@ export async function launchHarness(harness, rawArgs, options) {
|
|
|
538
564
|
log(c("yellow", line));
|
|
539
565
|
}
|
|
540
566
|
catch (err) {
|
|
541
|
-
if (options.mcpOnly) {
|
|
567
|
+
if (options.mcpOnly || proxy) {
|
|
542
568
|
if (!options.keepKey) {
|
|
543
569
|
try {
|
|
544
570
|
await revokeKey(endpoint.id, key.id);
|
|
@@ -547,7 +573,7 @@ export async function launchHarness(harness, rawArgs, options) {
|
|
|
547
573
|
log(`could not revoke session key …${key.keyHint}; it expires in ${expiresIn}`);
|
|
548
574
|
}
|
|
549
575
|
}
|
|
550
|
-
throw new Error(
|
|
576
|
+
throw new Error(`${proxy ? "CLIProxy MCP" : "MCP-only"} setup failed; no inference Router fallback: ${err.message}`);
|
|
551
577
|
}
|
|
552
578
|
const note = c(chosen ? "yellow" : "dim", "native MCP unavailable");
|
|
553
579
|
log(`${note} (${err.message}); the router keeps this endpoint's tools`);
|
|
@@ -556,8 +582,10 @@ export async function launchHarness(harness, rawArgs, options) {
|
|
|
556
582
|
// Read once per launch and reused by every turn.
|
|
557
583
|
const harnessVersion = await harnessVersionProbe;
|
|
558
584
|
const plan = planFor(harness, {
|
|
559
|
-
baseUrl: catalog.baseUrl,
|
|
560
|
-
apiKey: key?.key ?? DRY_RUN_KEY,
|
|
585
|
+
baseUrl: proxy?.baseUrl ?? catalog.baseUrl,
|
|
586
|
+
apiKey: proxy?.apiKey ?? key?.key ?? DRY_RUN_KEY,
|
|
587
|
+
mcpApiKey: key?.key ?? DRY_RUN_KEY,
|
|
588
|
+
localInference: Boolean(proxy),
|
|
561
589
|
sessionId,
|
|
562
590
|
harnessVersion,
|
|
563
591
|
model,
|
|
@@ -578,7 +606,7 @@ export async function launchHarness(harness, rawArgs, options) {
|
|
|
578
606
|
const field = (name, value) => `${c("dim", `${name}=`)}${value}`;
|
|
579
607
|
const banner = [
|
|
580
608
|
field("endpoint", c(["bold", "cyan"], endpoint.slug)),
|
|
581
|
-
field("inference", options.mcpOnly ? "native Claude Code account (MCP only)" : "Ditto Router"),
|
|
609
|
+
field("inference", proxy ? `CLIProxy (${proxy.baseUrl})` : options.mcpOnly ? "native Claude Code account (MCP only)" : "Ditto Router"),
|
|
582
610
|
field("model", model ?? c("dim", options.mcpOnly ? "(native Claude Code default)" : "(harness default → endpoint routes)")),
|
|
583
611
|
field("key", key ? `…${key.keyHint || maskKey(key.key ?? "")}` : "(dry run)"),
|
|
584
612
|
field("expires", `${expiresIn}${options.keepKey ? "" : c("dim", " (revoked on exit)")}`),
|
|
@@ -589,9 +617,12 @@ export async function launchHarness(harness, rawArgs, options) {
|
|
|
589
617
|
.filter(Boolean)
|
|
590
618
|
.join(" ");
|
|
591
619
|
log(banner);
|
|
592
|
-
|
|
620
|
+
if (proxy)
|
|
621
|
+
log("inference stays on CLIProxy; Ditto provides MCP tools/remote control, without Router inference optimizations or inference traces");
|
|
622
|
+
else
|
|
623
|
+
log(`traces: ${c(["underline", "cyan"], endpointURL(endpoint.id))}`);
|
|
593
624
|
if (options.dryRun) {
|
|
594
|
-
const env = Object.fromEntries(Object.entries(plan.envSet).map(([k, v]) => [k, v === DRY_RUN_KEY ? "<key>" : v]));
|
|
625
|
+
const env = Object.fromEntries(Object.entries(plan.envSet).map(([k, v]) => [k, v === DRY_RUN_KEY || v === proxy?.apiKey ? "<key>" : v]));
|
|
595
626
|
process.stdout.write(`${JSON.stringify({
|
|
596
627
|
harness,
|
|
597
628
|
command: plan.command,
|
|
@@ -603,9 +634,9 @@ export async function launchHarness(harness, rawArgs, options) {
|
|
|
603
634
|
sessionId,
|
|
604
635
|
// A dry run reads no catalog, so the plan above is the router's; say
|
|
605
636
|
// which surface a real launch would ask for, separately.
|
|
606
|
-
toolSurface: mcp ? "mcp" : "router",
|
|
607
|
-
toolSurfaceRequested: wantMcp ? "mcp" : "router",
|
|
608
|
-
inference: options.mcpOnly ? "native" : "router",
|
|
637
|
+
toolSurface: mcp ? "mcp" : proxy ? "none" : "router",
|
|
638
|
+
toolSurfaceRequested: wantMcp ? "mcp" : proxy ? "none" : "router",
|
|
639
|
+
inference: proxy ? "cliproxy" : options.mcpOnly ? "native" : "router",
|
|
609
640
|
remoteTransport: options.remoteTransport ?? "cli",
|
|
610
641
|
key: { name: keyName, expiresIn, spendLimitTokens: budget ?? null },
|
|
611
642
|
}, null, 2)}\n`);
|
|
@@ -629,6 +660,7 @@ export async function launchHarness(harness, rawArgs, options) {
|
|
|
629
660
|
lastLaunchedAt: now,
|
|
630
661
|
launches: (record?.launches ?? 0) + 1,
|
|
631
662
|
mcpOnly: options.mcpOnly,
|
|
663
|
+
cliproxy: proxy?.baseUrl,
|
|
632
664
|
remoteTransport: options.remoteTransport,
|
|
633
665
|
...(explicitLaunchTitle ? { explicitLaunchTitle } : {}),
|
|
634
666
|
};
|
|
@@ -636,7 +668,7 @@ export async function launchHarness(harness, rawArgs, options) {
|
|
|
636
668
|
const remote = remoteMode(options);
|
|
637
669
|
const launchRegistration = {
|
|
638
670
|
sessionId, endpointId: endpoint.id, harness: harness === "claude" ? "claude-code" : harness,
|
|
639
|
-
inference: options.mcpOnly ? "native" : "router", transport: options.remoteTransport ?? "cli",
|
|
671
|
+
inference: proxy || options.mcpOnly ? "native" : "router", transport: options.remoteTransport ?? "cli",
|
|
640
672
|
title: explicitLaunchTitle || `${path.basename(cwd)} · ${sessionId.slice(0, 8)}`,
|
|
641
673
|
...(harness === "claude" && harnessSessionId && isUuid(harnessSessionId) ? { nativeSessionId: harnessSessionId } : {}),
|
|
642
674
|
};
|
|
@@ -671,8 +703,10 @@ export async function launchHarness(harness, rawArgs, options) {
|
|
|
671
703
|
cwd,
|
|
672
704
|
sessionId,
|
|
673
705
|
harnessSessionId,
|
|
674
|
-
baseUrl: catalog.baseUrl,
|
|
675
|
-
apiKey: key.key ?? "",
|
|
706
|
+
baseUrl: proxy?.baseUrl ?? catalog.baseUrl,
|
|
707
|
+
apiKey: proxy?.apiKey ?? key.key ?? "",
|
|
708
|
+
mcpApiKey: key.key ?? "",
|
|
709
|
+
localInference: Boolean(proxy),
|
|
676
710
|
harnessVersion,
|
|
677
711
|
model,
|
|
678
712
|
options,
|
|
@@ -896,6 +930,8 @@ async function runHeadless(harness, ctx) {
|
|
|
896
930
|
base: {
|
|
897
931
|
baseUrl: ctx.baseUrl,
|
|
898
932
|
apiKey: ctx.apiKey,
|
|
933
|
+
mcpApiKey: ctx.mcpApiKey,
|
|
934
|
+
localInference: ctx.localInference,
|
|
899
935
|
sessionId: ctx.sessionId,
|
|
900
936
|
harnessVersion: ctx.harnessVersion,
|
|
901
937
|
model: ctx.model,
|