@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.
Files changed (46) hide show
  1. package/README.md +167 -1
  2. package/dist/agents/claude.d.ts +11 -0
  3. package/dist/agents/claude.js +48 -0
  4. package/dist/agents/claude.js.map +1 -0
  5. package/dist/agents/codex.d.ts +13 -0
  6. package/dist/agents/codex.js +48 -0
  7. package/dist/agents/codex.js.map +1 -0
  8. package/dist/agents/launch.d.ts +25 -0
  9. package/dist/agents/launch.js +376 -0
  10. package/dist/agents/launch.js.map +1 -0
  11. package/dist/agents/sessions.d.ts +28 -0
  12. package/dist/agents/sessions.js +63 -0
  13. package/dist/agents/sessions.js.map +1 -0
  14. package/dist/agents/types.d.ts +50 -0
  15. package/dist/agents/types.js +44 -0
  16. package/dist/agents/types.js.map +1 -0
  17. package/dist/agents/worktree.d.ts +19 -0
  18. package/dist/agents/worktree.js +72 -0
  19. package/dist/agents/worktree.js.map +1 -0
  20. package/dist/api.d.ts +178 -0
  21. package/dist/api.js +163 -0
  22. package/dist/api.js.map +1 -0
  23. package/dist/browser.d.ts +2 -0
  24. package/dist/browser.js +17 -0
  25. package/dist/browser.js.map +1 -0
  26. package/dist/cli.js +107 -24
  27. package/dist/cli.js.map +1 -1
  28. package/dist/commands.d.ts +77 -0
  29. package/dist/commands.js +638 -0
  30. package/dist/commands.js.map +1 -0
  31. package/dist/config.d.ts +8 -0
  32. package/dist/config.js +18 -1
  33. package/dist/config.js.map +1 -1
  34. package/dist/device-login.d.ts +28 -0
  35. package/dist/device-login.js +43 -0
  36. package/dist/device-login.js.map +1 -0
  37. package/dist/endpoint-format.d.ts +9 -0
  38. package/dist/endpoint-format.js +21 -0
  39. package/dist/endpoint-format.js.map +1 -0
  40. package/dist/mcp-session.d.ts +40 -0
  41. package/dist/mcp-session.js +133 -0
  42. package/dist/mcp-session.js.map +1 -0
  43. package/dist/store.d.ts +26 -0
  44. package/dist/store.js +61 -0
  45. package/dist/store.js.map +1 -1
  46. 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
- For a human-owned key, get one at **https://app.heyditto.ai/mcp/newkey**.
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>;