@heyditto/cli 2.0.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +167 -1
- package/dist/agents/claude.d.ts +11 -0
- package/dist/agents/claude.js +48 -0
- package/dist/agents/claude.js.map +1 -0
- package/dist/agents/codex.d.ts +13 -0
- package/dist/agents/codex.js +48 -0
- package/dist/agents/codex.js.map +1 -0
- package/dist/agents/launch.d.ts +25 -0
- package/dist/agents/launch.js +376 -0
- package/dist/agents/launch.js.map +1 -0
- package/dist/agents/sessions.d.ts +28 -0
- package/dist/agents/sessions.js +63 -0
- package/dist/agents/sessions.js.map +1 -0
- package/dist/agents/types.d.ts +50 -0
- package/dist/agents/types.js +44 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/agents/worktree.d.ts +19 -0
- package/dist/agents/worktree.js +72 -0
- package/dist/agents/worktree.js.map +1 -0
- package/dist/api.d.ts +178 -0
- package/dist/api.js +163 -0
- package/dist/api.js.map +1 -0
- package/dist/browser.d.ts +2 -0
- package/dist/browser.js +17 -0
- package/dist/browser.js.map +1 -0
- package/dist/cli.js +107 -24
- package/dist/cli.js.map +1 -1
- package/dist/commands.d.ts +77 -0
- package/dist/commands.js +638 -0
- package/dist/commands.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +18 -1
- package/dist/config.js.map +1 -1
- package/dist/device-login.d.ts +28 -0
- package/dist/device-login.js +43 -0
- package/dist/device-login.js.map +1 -0
- package/dist/endpoint-format.d.ts +9 -0
- package/dist/endpoint-format.js +21 -0
- package/dist/endpoint-format.js.map +1 -0
- package/dist/mcp-session.d.ts +40 -0
- package/dist/mcp-session.js +133 -0
- package/dist/mcp-session.js.map +1 -0
- package/dist/store.d.ts +26 -0
- package/dist/store.js +61 -0
- package/dist/store.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,6 +42,17 @@ You can also reorder your `PATH` so the npm global bin comes before `/usr/bin`,
|
|
|
42
42
|
|
|
43
43
|
## Auth
|
|
44
44
|
|
|
45
|
+
Humans sign in through the browser:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
heyditto login
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This prints a short code, opens `https://heyditto.ai/device` (pre-filled with the
|
|
52
|
+
code), and saves the resulting key to your CLI config directory once you approve
|
|
53
|
+
it. Pass a key as an argument (`heyditto login ditto_mcp_…`), pipe it with
|
|
54
|
+
`--stdin`, or use `--paste` for the older copy-a-key page.
|
|
55
|
+
|
|
45
56
|
Agents can self-provision without a browser, email, or OTP:
|
|
46
57
|
|
|
47
58
|
```bash
|
|
@@ -74,7 +85,25 @@ requires backend support — see
|
|
|
74
85
|
[ditto-assistant/backend#1199](https://github.com/ditto-assistant/backend/issues/1199)),
|
|
75
86
|
so picking the right name at init avoids a stuck label.
|
|
76
87
|
|
|
77
|
-
|
|
88
|
+
### Humans: sign in through the browser
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
heyditto login
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
opens the Ditto web app with a one-time device code (sign in with Google, X, Apple
|
|
95
|
+
or GitHub, or create an account), approves it, and hands the key back to the CLI —
|
|
96
|
+
nothing to copy. `heyditto claude` / `heyditto codex` run the same flow
|
|
97
|
+
automatically on first use, and the web page lets you pick or create the
|
|
98
|
+
inference endpoint to launch through, so a fresh machine needs exactly one
|
|
99
|
+
command:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npx @heyditto/cli@latest claude --yolo --worktree
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
You can still paste a key from **https://app.heyditto.ai/mcp/newkey**
|
|
106
|
+
(`heyditto login <key>`, `--paste`, or `--stdin`), or set it in the environment:
|
|
78
107
|
|
|
79
108
|
```bash
|
|
80
109
|
export DITTO_API_KEY=ditto_mcp_…
|
|
@@ -111,6 +140,17 @@ heyditto graphs subscribers
|
|
|
111
140
|
heyditto graphs sharing (--enable|--disable) [--title <t>] [--description <d>]
|
|
112
141
|
heyditto init [--name <name>] [--subscribe <@graph>]... [<@graph>...] [--json]
|
|
113
142
|
heyditto login [<key>] [--paste] [--stdin]
|
|
143
|
+
heyditto endpoints [--set-default <slug>] [--clear-default]
|
|
144
|
+
heyditto claude [options] [-- <claude args>]
|
|
145
|
+
heyditto codex [options] [-- <codex args>]
|
|
146
|
+
heyditto sessions [--json] [--all]
|
|
147
|
+
heyditto sessions rm <id>
|
|
148
|
+
heyditto session new [<name>...] [--id <id>]
|
|
149
|
+
heyditto session list [--all]
|
|
150
|
+
heyditto session use <id>
|
|
151
|
+
heyditto session current
|
|
152
|
+
heyditto session end
|
|
153
|
+
heyditto agents [--output <format>]
|
|
114
154
|
heyditto logout
|
|
115
155
|
heyditto status [--output <format>]
|
|
116
156
|
heyditto config
|
|
@@ -289,10 +329,136 @@ graph. Choose it up front — renaming after init isn't yet supported. See
|
|
|
289
329
|
|
|
290
330
|
Print a Claude Desktop / Cursor / generic-MCP-client config snippet for the Ditto memory server.
|
|
291
331
|
|
|
332
|
+
## Coding agents
|
|
333
|
+
|
|
334
|
+
`heyditto claude` and `heyditto codex` launch Claude Code or Codex through one of
|
|
335
|
+
your Ditto **inference endpoints** (managed at https://developer.heyditto.ai/endpoints;
|
|
336
|
+
the Ditto app's Settings → Developer page still works too). Each launch:
|
|
337
|
+
|
|
338
|
+
1. signs you in through the browser if this machine has no key yet, then uses
|
|
339
|
+
the endpoint you picked there, `--endpoint`, the saved default, or a picker,
|
|
340
|
+
2. mints a temporary endpoint key (optionally capped with `--budget <tokens>`),
|
|
341
|
+
3. starts the agent with that key and a fresh `X-Ditto-Session-Id`, so the
|
|
342
|
+
session becomes its own thread with full traces under the endpoint,
|
|
343
|
+
4. **revokes the key when the agent exits** (Ctrl+C included). The thread and
|
|
344
|
+
traces are kept; `--keep-key` opts out, `--expires` sets a server-side
|
|
345
|
+
safety expiry (default `1d`).
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
npx -y @heyditto/cli login
|
|
349
|
+
npx -y @heyditto/cli claude --endpoint my-endpoint
|
|
350
|
+
|
|
351
|
+
heyditto endpoints --set-default my-endpoint # skip the picker next time
|
|
352
|
+
heyditto claude # interactive Claude Code
|
|
353
|
+
heyditto codex --yellow # Codex, auto-accept edits
|
|
354
|
+
heyditto claude --yolo --worktree fix-login # bypass prompts in <repo>/.worktrees/fix-login
|
|
355
|
+
heyditto codex -p "summarize this repo" --json # headless (codex exec)
|
|
356
|
+
heyditto claude -p "list TODOs" --output-format json --max-turns 3
|
|
357
|
+
heyditto claude --resume # reopen the last session in the same thread
|
|
358
|
+
heyditto claude -- --verbose # anything after -- goes to the agent
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Options shared by both commands:
|
|
362
|
+
|
|
363
|
+
| Flag | Meaning |
|
|
364
|
+
| --- | --- |
|
|
365
|
+
| `-e, --endpoint <slug>` | endpoint to route through (default: saved default, else a picker) |
|
|
366
|
+
| `--budget <tokens>` | spend cap for this session's key, in Ditto tokens |
|
|
367
|
+
| `--expires <1h…never>` | server-side key expiry; the key is still revoked on exit unless `--keep-key` |
|
|
368
|
+
| `--session <id>` | reuse a Ditto session id so traces land in an existing thread |
|
|
369
|
+
| `--resume [id]` / `-c, --continue` | resume a local session (`heyditto sessions`) / the agent's most recent conversation |
|
|
370
|
+
| `--yolo` / `--yellow` / `--plan` | bypass permissions / auto-accept edits / plan mode (Claude only) |
|
|
371
|
+
| `-p, --prompt <text>` | headless run: `claude -p` or `codex exec` |
|
|
372
|
+
| `-m, --model <id>` | model to request (Codex defaults to the endpoint slug; Claude's ids follow the endpoint's routes) |
|
|
373
|
+
| `-w, --worktree [name]` | run inside `<repo>/.worktrees/<name>` on a branch of that name; `.worktrees/` is added to `.gitignore` |
|
|
374
|
+
| `--name <label>` | key name shown in the app (default `cli:<agent>:<hostname>`) |
|
|
375
|
+
| `--dry-run` | print the command, args and env with the key masked; mints nothing |
|
|
376
|
+
|
|
377
|
+
Unknown flags and everything after `--` are forwarded to the agent, so Claude's
|
|
378
|
+
and Codex's own options keep working.
|
|
379
|
+
|
|
380
|
+
How the wiring works:
|
|
381
|
+
|
|
382
|
+
- **Claude Code** gets `ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN` (a bearer
|
|
383
|
+
token, which skips Claude's "use this API key?" prompt) and
|
|
384
|
+
`ANTHROPIC_CUSTOM_HEADERS` with the session id. Any inherited
|
|
385
|
+
`ANTHROPIC_API_KEY` is removed from the child environment.
|
|
386
|
+
- **Codex** speaks the Responses API only, so the endpoint is injected as a
|
|
387
|
+
`ditto` model provider via `-c` overrides (nothing is written to
|
|
388
|
+
`~/.codex/config.toml`) with the key in `DITTO_INFERENCE_API_KEY`.
|
|
389
|
+
|
|
390
|
+
### `endpoints`
|
|
391
|
+
|
|
392
|
+
Manage the inference endpoints the launchers route through — a CLI mirror of
|
|
393
|
+
the developer console at https://developer.heyditto.ai/endpoints (`open` takes
|
|
394
|
+
you to an endpoint's page there; set `DITTO_DEVELOPER_BASE` to point elsewhere):
|
|
395
|
+
|
|
396
|
+
```
|
|
397
|
+
heyditto endpoints [--set-default <slug>] [--clear-default] list (* = default)
|
|
398
|
+
heyditto endpoints create [--name <n>] [--slug <s>] [--model <id>] [--default]
|
|
399
|
+
heyditto endpoints show <endpoint>
|
|
400
|
+
heyditto endpoints use <endpoint> make it the default
|
|
401
|
+
heyditto endpoints pick choose the default interactively
|
|
402
|
+
heyditto endpoints open [endpoint] open the editor in the Ditto app
|
|
403
|
+
heyditto endpoints set <endpoint> --model … --system-prompt … --spend-limit <tokens|none>
|
|
404
|
+
--spend-period … --record-trace on|off --recall on|off
|
|
405
|
+
--record on|off --memory-depth <n>
|
|
406
|
+
heyditto endpoints delete <endpoint> [--yes]
|
|
407
|
+
heyditto endpoints keys <endpoint> list keys
|
|
408
|
+
heyditto endpoints keys revoke <endpoint> <keyId> [--yes]
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
Endpoints spend your Ditto credits, so deleting one, revoking a key or raising a
|
|
412
|
+
spend limit asks you to type the slug back; pass `--yes` in scripts. `--output
|
|
413
|
+
json` is available everywhere and includes the gateway base URL.
|
|
414
|
+
|
|
415
|
+
**Agent accounts.** An agent set up with `heyditto init` can create and manage
|
|
416
|
+
endpoints too, but an endpoint created by an unclaimed agent starts **inactive**:
|
|
417
|
+
it serves requests once the person the agent works for claims the agent and
|
|
418
|
+
subscribes to Ditto Hero. The CLI prints the server's explanation together with
|
|
419
|
+
an activation link (the agent's claim link plus the endpoint) — hand that link
|
|
420
|
+
to the user.
|
|
421
|
+
|
|
422
|
+
### `sessions`
|
|
423
|
+
|
|
424
|
+
List the coding-agent sessions launched from this machine (stored under
|
|
425
|
+
`~/.config/heyditto/cli/sessions/`). `heyditto sessions rm <id>` forgets a local
|
|
426
|
+
record; the Ditto thread and traces are unaffected.
|
|
427
|
+
|
|
428
|
+
### `session`
|
|
429
|
+
|
|
430
|
+
Explicit MCP sessions. Without one, the server groups your saves and searches
|
|
431
|
+
into a time-based *implicit* session (activity within a cooldown, auto-named
|
|
432
|
+
when it goes quiet). `heyditto session new [name]` pins an explicit session:
|
|
433
|
+
every MCP request from then on carries `X-Ditto-Session-Id`, and the name goes
|
|
434
|
+
out once as `X-Ditto-Session-Name` so the thread gets that title. Saves and
|
|
435
|
+
searches land in one thread inside the agent your key is attached to.
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
heyditto session new "refactor auth module" # prints the id and makes it active
|
|
439
|
+
heyditto save "Decided to keep JWT refresh in the gateway"
|
|
440
|
+
heyditto session current # the active id (exit 1 when none)
|
|
441
|
+
heyditto session list # local history, * marks the active one
|
|
442
|
+
heyditto session end # back to implicit sessions
|
|
443
|
+
heyditto session use 9e9a93c3 # reactivate by id or unique prefix
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
`DITTO_SESSION_ID=<id>` pins a session for one shell or script (it overrides the
|
|
447
|
+
saved one and never sends a name). Sessions are tracked locally in
|
|
448
|
+
`~/.config/heyditto/cli/mcp-sessions.json`; the server keeps the threads.
|
|
449
|
+
|
|
450
|
+
### `agents`
|
|
451
|
+
|
|
452
|
+
List your Ditto agents (`GET /api/v5/chat-agents`): id, kind (`main`, `chat`,
|
|
453
|
+
`inference_endpoint`, `mcp`, `connector`), name, thread count, last activity and
|
|
454
|
+
the live connections (API keys, OAuth grants, endpoints) writing into each.
|
|
455
|
+
|
|
292
456
|
## Environment
|
|
293
457
|
|
|
294
458
|
- `DITTO_API_KEY` (optional) — MCP API key override. Agents can instead run `heyditto init --json` for no-human setup.
|
|
295
459
|
- `DITTO_API_BASE` (optional) — API base URL. Defaults to `https://api.heyditto.ai`. Useful for local dev (`http://localhost:3400`).
|
|
460
|
+
- `DITTO_SESSION_ID` (optional) — pin an explicit MCP session id for this shell (see `session`).
|
|
461
|
+
- `DITTO_CONFIG_DIR` (optional) — config directory for the saved key, default endpoint and session records. Defaults to `$XDG_CONFIG_HOME/heyditto/cli` or `~/.config/heyditto/cli`.
|
|
296
462
|
|
|
297
463
|
## Output
|
|
298
464
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type HarnessPlan, type PlanInput } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Builds the `claude` invocation.
|
|
4
|
+
*
|
|
5
|
+
* Auth goes through ANTHROPIC_AUTH_TOKEN (sent as `Authorization: Bearer`):
|
|
6
|
+
* unlike ANTHROPIC_API_KEY it never triggers the interactive "use this API
|
|
7
|
+
* key? No (recommended)" approval prompt, so the same plan works headless.
|
|
8
|
+
* Any inherited ANTHROPIC_API_KEY is removed so it cannot re-trigger that
|
|
9
|
+
* prompt or add a stray x-api-key header.
|
|
10
|
+
*/
|
|
11
|
+
export declare function planClaude(input: PlanInput): HarnessPlan;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { SESSION_HEADER, apiRootOf } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Builds the `claude` invocation.
|
|
4
|
+
*
|
|
5
|
+
* Auth goes through ANTHROPIC_AUTH_TOKEN (sent as `Authorization: Bearer`):
|
|
6
|
+
* unlike ANTHROPIC_API_KEY it never triggers the interactive "use this API
|
|
7
|
+
* key? No (recommended)" approval prompt, so the same plan works headless.
|
|
8
|
+
* Any inherited ANTHROPIC_API_KEY is removed so it cannot re-trigger that
|
|
9
|
+
* prompt or add a stray x-api-key header.
|
|
10
|
+
*/
|
|
11
|
+
export function planClaude(input) {
|
|
12
|
+
const args = [];
|
|
13
|
+
if (input.yolo)
|
|
14
|
+
args.push("--dangerously-skip-permissions");
|
|
15
|
+
else if (input.yellow)
|
|
16
|
+
args.push("--permission-mode", "acceptEdits");
|
|
17
|
+
else if (input.plan)
|
|
18
|
+
args.push("--permission-mode", "plan");
|
|
19
|
+
if (input.resumeId)
|
|
20
|
+
args.push("--resume", input.resumeId);
|
|
21
|
+
else if (input.resumeLast)
|
|
22
|
+
args.push("--continue");
|
|
23
|
+
else
|
|
24
|
+
args.push("--session-id", input.sessionId);
|
|
25
|
+
if (input.model)
|
|
26
|
+
args.push("--model", input.model);
|
|
27
|
+
if (input.prompt !== undefined)
|
|
28
|
+
args.push("-p", input.prompt);
|
|
29
|
+
args.push(...input.passthrough);
|
|
30
|
+
const headers = [input.env.ANTHROPIC_CUSTOM_HEADERS?.trim(), `${SESSION_HEADER}: ${input.sessionId}`]
|
|
31
|
+
.filter((h) => Boolean(h))
|
|
32
|
+
.join("\n");
|
|
33
|
+
const envSet = {
|
|
34
|
+
ANTHROPIC_BASE_URL: apiRootOf(input.baseUrl),
|
|
35
|
+
ANTHROPIC_AUTH_TOKEN: input.apiKey,
|
|
36
|
+
ANTHROPIC_CUSTOM_HEADERS: headers,
|
|
37
|
+
};
|
|
38
|
+
if (input.model)
|
|
39
|
+
envSet.ANTHROPIC_MODEL = input.model;
|
|
40
|
+
return {
|
|
41
|
+
command: "claude",
|
|
42
|
+
args,
|
|
43
|
+
envSet,
|
|
44
|
+
envUnset: ["ANTHROPIC_API_KEY"],
|
|
45
|
+
installHint: "install Claude Code: npm i -g @anthropic-ai/claude-code (or see https://code.claude.com)",
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEzF;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,KAAgB;IACzC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,KAAK,CAAC,IAAI;QAAE,IAAI,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;SACvD,IAAI,KAAK,CAAC,MAAM;QAAE,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;SAChE,IAAI,KAAK,CAAC,IAAI;QAAE,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;IAE5D,IAAI,KAAK,CAAC,QAAQ;QAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;SACrD,IAAI,KAAK,CAAC,UAAU;QAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;;QAC9C,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAEhD,IAAI,KAAK,CAAC,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACnD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;QAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9D,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;IAEhC,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,wBAAwB,EAAE,IAAI,EAAE,EAAE,GAAG,cAAc,KAAK,KAAK,CAAC,SAAS,EAAE,CAAC;SAClG,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;SACtC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,MAAM,GAA2B;QACrC,kBAAkB,EAAE,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;QAC5C,oBAAoB,EAAE,KAAK,CAAC,MAAM;QAClC,wBAAwB,EAAE,OAAO;KAClC,CAAC;IACF,IAAI,KAAK,CAAC,KAAK;QAAE,MAAM,CAAC,eAAe,GAAG,KAAK,CAAC,KAAK,CAAC;IAEtD,OAAO;QACL,OAAO,EAAE,QAAQ;QACjB,IAAI;QACJ,MAAM;QACN,QAAQ,EAAE,CAAC,mBAAmB,CAAC;QAC/B,WAAW,EAAE,0FAA0F;KACxG,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type HarnessPlan, type PlanInput } from "./types.js";
|
|
2
|
+
/** Quotes a string as a TOML basic string for `codex -c key=value`. */
|
|
3
|
+
export declare function tomlString(value: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* Builds the `codex` invocation.
|
|
6
|
+
*
|
|
7
|
+
* Codex ignores OPENAI_BASE_URL while a ChatGPT login exists and only speaks
|
|
8
|
+
* the Responses wire, so the endpoint is injected as a dedicated `ditto`
|
|
9
|
+
* model provider through `-c` overrides (nothing is written to
|
|
10
|
+
* ~/.codex/config.toml). The session header rides on the provider's
|
|
11
|
+
* http_headers so every request lands in the same Ditto thread.
|
|
12
|
+
*/
|
|
13
|
+
export declare function planCodex(input: PlanInput): HarnessPlan;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { CODEX_KEY_ENV, SESSION_HEADER } from "./types.js";
|
|
2
|
+
/** Quotes a string as a TOML basic string for `codex -c key=value`. */
|
|
3
|
+
export function tomlString(value) {
|
|
4
|
+
return JSON.stringify(value);
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Builds the `codex` invocation.
|
|
8
|
+
*
|
|
9
|
+
* Codex ignores OPENAI_BASE_URL while a ChatGPT login exists and only speaks
|
|
10
|
+
* the Responses wire, so the endpoint is injected as a dedicated `ditto`
|
|
11
|
+
* model provider through `-c` overrides (nothing is written to
|
|
12
|
+
* ~/.codex/config.toml). The session header rides on the provider's
|
|
13
|
+
* http_headers so every request lands in the same Ditto thread.
|
|
14
|
+
*/
|
|
15
|
+
export function planCodex(input) {
|
|
16
|
+
const args = [];
|
|
17
|
+
if (input.prompt !== undefined)
|
|
18
|
+
args.push("exec");
|
|
19
|
+
else if (input.resumeId || input.resumeLast)
|
|
20
|
+
args.push("resume");
|
|
21
|
+
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={${tomlString(SESSION_HEADER)}=${tomlString(input.sessionId)}}`);
|
|
22
|
+
if (input.model)
|
|
23
|
+
args.push("-m", input.model);
|
|
24
|
+
if (input.yolo)
|
|
25
|
+
args.push("--dangerously-bypass-approvals-and-sandbox");
|
|
26
|
+
else if (input.yellow)
|
|
27
|
+
args.push("-a", "on-request", "-s", "workspace-write");
|
|
28
|
+
if (input.prompt !== undefined) {
|
|
29
|
+
args.push("--skip-git-repo-check", ...input.passthrough, input.prompt);
|
|
30
|
+
}
|
|
31
|
+
else if (input.resumeId) {
|
|
32
|
+
args.push(...input.passthrough, input.resumeId);
|
|
33
|
+
}
|
|
34
|
+
else if (input.resumeLast) {
|
|
35
|
+
args.push("--last", ...input.passthrough);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
args.push(...input.passthrough);
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
command: "codex",
|
|
42
|
+
args,
|
|
43
|
+
envSet: { [CODEX_KEY_ENV]: input.apiKey },
|
|
44
|
+
envUnset: [],
|
|
45
|
+
installHint: "install Codex: npm i -g @openai/codex (or brew install codex)",
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=codex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/agents/codex.ts"],"names":[],"mappings":"AAAA,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;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS,CAAC,KAAgB;IACxC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;QAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SAC7C,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,UAAU;QAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEjE,IAAI,CAAC,IAAI,CACP,IAAI,EACJ,kBAAkB,UAAU,CAAC,OAAO,CAAC,EAAE,EACvC,IAAI,EACJ,8BAA8B,UAAU,CAAC,OAAO,CAAC,EAAE,EACnD,IAAI,EACJ,kCAAkC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAC7D,IAAI,EACJ,iCAAiC,UAAU,CAAC,aAAa,CAAC,EAAE,EAC5D,IAAI,EACJ,kCAAkC,UAAU,CAAC,WAAW,CAAC,EAAE,EAC3D,IAAI,EACJ,uCAAuC,UAAU,CAAC,cAAc,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CACpG,CAAC;IACF,IAAI,KAAK,CAAC,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAE9C,IAAI,KAAK,CAAC,IAAI;QAAE,IAAI,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;SACnE,IAAI,KAAK,CAAC,MAAM;QAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC;IAE9E,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACzE,CAAC;SAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClD,CAAC;SAAM,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;IAC5C,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;IAClC,CAAC;IAED,OAAO;QACL,OAAO,EAAE,OAAO;QAChB,IAAI;QACJ,MAAM,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE;QACzC,QAAQ,EAAE,EAAE;QACZ,WAAW,EAAE,+DAA+D;KAC7E,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type InferenceEndpoint } from "../api.js";
|
|
2
|
+
import { type Harness } from "./types.js";
|
|
3
|
+
export interface LaunchOptions {
|
|
4
|
+
endpoint?: string;
|
|
5
|
+
budget?: string;
|
|
6
|
+
expires?: string;
|
|
7
|
+
keepKey?: boolean;
|
|
8
|
+
session?: string;
|
|
9
|
+
resume?: string | boolean;
|
|
10
|
+
continue?: boolean;
|
|
11
|
+
yolo?: boolean;
|
|
12
|
+
yellow?: boolean;
|
|
13
|
+
plan?: boolean;
|
|
14
|
+
prompt?: string;
|
|
15
|
+
model?: string;
|
|
16
|
+
worktree?: string | boolean;
|
|
17
|
+
name?: string;
|
|
18
|
+
dryRun?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** Interactive numbered picker; also accepts a slug or id. Exported for `heyditto endpoints pick`. */
|
|
21
|
+
export declare function pickEndpoint(endpoints: InferenceEndpoint[], defaultSlug?: string): Promise<InferenceEndpoint>;
|
|
22
|
+
/** Refuses to launch against an endpoint the backend marked inactive (e.g. awaiting the user's plan). */
|
|
23
|
+
export declare function assertEndpointActive(endpoint: InferenceEndpoint): Promise<void>;
|
|
24
|
+
/** Launches a coding harness against a Ditto inference endpoint with a temporary key. */
|
|
25
|
+
export declare function launchHarness(harness: Harness, rawArgs: string[], options: LaunchOptions): Promise<void>;
|