cursor-opencode-provider 0.2.5 → 0.2.7
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 +27 -15
- package/dist/context/build.js +6 -1
- package/dist/context/env.d.ts +6 -0
- package/dist/context/env.js +34 -2
- package/dist/context/index.d.ts +1 -1
- package/dist/context/index.js +1 -1
- package/dist/context/paths.d.ts +41 -3
- package/dist/context/paths.js +121 -9
- package/dist/debug.d.ts +7 -0
- package/dist/debug.js +42 -0
- package/dist/index.d.ts +6 -0
- package/dist/language-model.d.ts +11 -1
- package/dist/language-model.js +47 -22
- package/dist/plugin-v2.js +4 -0
- package/dist/plugin.js +30 -4
- package/dist/protocol/messages.js +5 -1
- package/dist/protocol/request.d.ts +2 -0
- package/dist/protocol/request.js +5 -5
- package/dist/protocol/tools.d.ts +2 -2
- package/dist/protocol/tools.js +35 -38
- package/dist/session.d.ts +2 -0
- package/dist/shell-timeout.d.ts +48 -1
- package/dist/shell-timeout.js +308 -24
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ Add the package name to OpenCode config. OpenCode installs npm plugins with Bun
|
|
|
47
47
|
}
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
Pin a version if you want: `"cursor-opencode-provider@0.2.
|
|
50
|
+
Pin a version if you want: `"cursor-opencode-provider@0.2.6"`.
|
|
51
51
|
|
|
52
52
|
### From a local clone
|
|
53
53
|
|
|
@@ -102,15 +102,23 @@ Choose the **cursor** provider, then one of:
|
|
|
102
102
|
| **Cursor account (browser login)** | PKCE OAuth — opens cursor.com to sign in |
|
|
103
103
|
| **API key** | Paste a key from [cursor.com/settings](https://cursor.com/settings) (`sk-...`) |
|
|
104
104
|
|
|
105
|
-
After login, the plugin fetches your available models and writes them to
|
|
105
|
+
After login, the plugin fetches your available models and writes them to `<host-cache>/cursor-models.json` (default `~/.cache/opencode/`). On later startups, a missing, empty, expired, or old-schema cache is refreshed during config load when Cursor auth is available; an existing stale cache remains usable if refresh fails.
|
|
106
106
|
|
|
107
|
-
### Paths (
|
|
107
|
+
### Paths (host cache)
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
Model/version caches and Cursor project metadata live under a **host cache root**, resolved in this order:
|
|
110
|
+
|
|
111
|
+
1. Explicit `createCursor({ cacheDir })` / Effect v2 `Path.cache`
|
|
112
|
+
2. Optional `@opencode-compat/profile` `detect()` when that peer is installed and the host is supported
|
|
113
|
+
3. Local heuristic: `$MIMOCODE_HOME/cache`, then host-named dirs under `$XDG_CACHE_HOME` (Kilo, then MiMo, then OpenCode)
|
|
114
|
+
4. Default `~/.cache/opencode/`
|
|
115
|
+
|
|
116
|
+
| Kind | Default (OpenCode) | Notes |
|
|
117
|
+
|------|--------------------|-------|
|
|
118
|
+
| Model / version **cache** | `~/.cache/opencode/` | MiMo: `$MIMOCODE_HOME/cache` or `~/.cache/mimocode/`; Kilo: `~/.cache/kilo/` |
|
|
119
|
+
| Cursor **project metadata** (`agent-tools`, terminals, …) | `~/.cache/opencode/projects/<slug>/` | under `<host-cache>/projects/` |
|
|
120
|
+
| OpenCode **auth** (`auth.json`) | `~/.local/share/opencode/` | `$XDG_DATA_HOME/opencode/` when set |
|
|
121
|
+
| OpenCode **config** (AGENTS, skills, …) | `~/.config/opencode/` | still OpenCode-named for rule discovery |
|
|
114
122
|
|
|
115
123
|
### Select a model
|
|
116
124
|
|
|
@@ -157,6 +165,7 @@ const cursor = createCursor({
|
|
|
157
165
|
// apiBaseURL: "https://api2.cursor.sh",
|
|
158
166
|
// agentBaseURL: "https://agentn.us.api5.cursor.sh", // explicit Run host override
|
|
159
167
|
// telemetryEnabled: true, // opt in to GetServerConfig telemetry
|
|
168
|
+
// cacheDir: "/path/to/host/cache", // optional; else host heuristic / ~/.cache/opencode
|
|
160
169
|
// retry: { maxAttempts: 3, baseDelayMs: 500, maxDelayMs: 8_000 },
|
|
161
170
|
// continuation: { heartbeatMs: 5_000, semanticIdleMs: 120_000, hardCapMs: 600_000 },
|
|
162
171
|
})
|
|
@@ -165,7 +174,7 @@ const model = cursor.languageModel("composer-2.5")
|
|
|
165
174
|
// model implements AI SDK LanguageModelV3 (doStream / doGenerate)
|
|
166
175
|
```
|
|
167
176
|
|
|
168
|
-
Pass either `accessToken` (JWT from OAuth or key exchange) or `apiKey` (raw `sk-...` key). Optional: `apiBaseURL`, `agentBaseURL`, `headers`, `telemetryEnabled`, `retry`, and `continuation`.
|
|
177
|
+
Pass either `accessToken` (JWT from OAuth or key exchange) or `apiKey` (raw `sk-...` key). Optional: `apiBaseURL`, `agentBaseURL`, `cacheDir`, `headers`, `telemetryEnabled`, `retry`, and `continuation`. `cacheDir` pins the host cache root for model/version caches and Cursor project metadata; when omitted, the provider uses OCP `@opencode-compat/profile` detect (if installed) or the local MiMo/Kilo/OpenCode heuristic described in [Paths](#paths-host-cache). Transient failures resume from the latest checkpoint produced by that Run, matching Cursor CLI; without an eligible checkpoint, retries remain limited to replay-safe attempts so completed text or tool work is not duplicated. Pending-tool inactivity is renewed by OpenCode activity from the session or its descendants. The older `baseURL` option is still accepted as a legacy alias for `agentBaseURL`.
|
|
169
178
|
|
|
170
179
|
## Environment variables
|
|
171
180
|
|
|
@@ -176,7 +185,9 @@ Pass either `accessToken` (JWT from OAuth or key exchange) or `apiKey` (raw `sk-
|
|
|
176
185
|
| `CURSOR_GET_SERVER_CONFIG_TELEMETRY` | Set to `1` or `true` to opt the `GetServerConfig` lookup into telemetry in OpenCode/plugin usage |
|
|
177
186
|
| `CURSOR_PROVIDER_DEBUG` | Set to `1` or `true` to enable wire-level debug logging |
|
|
178
187
|
| `CURSOR_PROVIDER_DEBUG_FILE` | Debug log path (default: `debug-<pid>.log` under `$TMPDIR/cursor-provider-logs-<uid>/`) |
|
|
179
|
-
| `XDG_CACHE_HOME` |
|
|
188
|
+
| `XDG_CACHE_HOME` | Base for host cache dirs (`$XDG_CACHE_HOME/opencode/`, `…/mimocode/`, or `…/kilo/`) when no explicit `cacheDir` / OCP detect override |
|
|
189
|
+
| `MIMOCODE_HOME` | When set, host cache is `$MIMOCODE_HOME/cache` (MiMo) |
|
|
190
|
+
| `KILO_CONFIG_DIR` | When set (or `~/.config/kilo` exists), host cache is `$XDG_CACHE_HOME/kilo` |
|
|
180
191
|
| `XDG_DATA_HOME` | When set, OpenCode `auth.json` is read from `$XDG_DATA_HOME/opencode/` instead of `~/.local/share/opencode/` |
|
|
181
192
|
|
|
182
193
|
`createCursor({ agentBaseURL })` overrides the agent Run host. When unset, the provider resolves the host from Cursor's `GetServerConfig` API (`agentUrlConfig.agentnUrl`, region-specific — e.g. `agentn.us.api5.cursor.sh`, `agent-gcpp-uswest.api5.cursor.sh`) once per process and holds it in memory (never written to disk), so a held-open Run stream is never repointed mid-session. Explicit agent overrides and GetServerConfig results are validated as HTTPS `*.cursor.sh` hosts (Cursor's agent hostnames vary and may change); non-`cursor.sh` hosts are rejected. Shared HTTP/2 connections are rotated before they become server-aged, while existing Runs may finish on their original connection. The lookup sends `{ "telem_enabled": false }` by default; set `telemetryEnabled: true` in provider config, or `CURSOR_GET_SERVER_CONFIG_TELEMETRY=1` for OpenCode/plugin usage, to opt in. If the lookup fails or does not return a valid Cursor agent host, the model call fails clearly instead of falling back to `agentn.global.api5.cursor.sh`.
|
|
@@ -213,6 +224,7 @@ OpenCode
|
|
|
213
224
|
| `src/debug.ts` | Opt-in wire-level debug logging (`CURSOR_PROVIDER_DEBUG`) |
|
|
214
225
|
| `src/auth.ts` | PKCE OAuth, API key exchange, JWT refresh |
|
|
215
226
|
| `src/models.ts` | `AvailableModels` fetch and `cursor-models.json` cache |
|
|
227
|
+
| `src/context/paths.ts` | Host cache root + Cursor project metadata under `<host-cache>/projects/<slug>/` |
|
|
216
228
|
| `src/agent-url.ts` | `GetServerConfig` fetch + in-process memo (region-specific Run host) |
|
|
217
229
|
| `src/transport/connect.ts` | HTTP/2 bidi stream and unary RPC calls |
|
|
218
230
|
| `src/protocol/` | Protobuf encode/decode, checksum/device ids, exec + display tool-call mapping (`tool-call-bridge.ts`) |
|
|
@@ -241,8 +253,8 @@ The package root intentionally stays plugin-safe for OpenCode's classic loader.
|
|
|
241
253
|
| No Cursor models in the picker | Confirm Cursor auth (`opencode auth login` → **cursor**). Restart OpenCode — if auth is present and the cache is empty, models are fetched on startup. Confirm `provider.cursor.npm` is the package name (or a built `file://…/dist/index.js`). |
|
|
242
254
|
| Auth / 401 errors mid-session | Re-login. OAuth and exchanged API-key JWTs refresh automatically when near expiry; a revoked refresh token needs a fresh login. |
|
|
243
255
|
| “Too many connections from different devices” | Device IDs are derived from stable OS identifiers (same approach as the Cursor CLI). Avoid running multiple clients that invent different machine fingerprints for the same account. |
|
|
244
|
-
| Empty or stale model list | Delete
|
|
245
|
-
| Stream hangs or HTTP/2 errors | The provider keeps Cursor's Run open across OpenCode tool calls, rotates aged shared connections,
|
|
256
|
+
| Empty or stale model list | Delete `<host-cache>/cursor-models.json` (default `~/.cache/opencode/`, or MiMo/Kilo host cache) and restart OpenCode. Existing Cursor auth is enough to refill the cache; re-login only if auth itself is broken. Cache TTL is 24h; a failed background refresh keeps serving the previous cache. |
|
|
257
|
+
| Stream hangs or HTTP/2 errors | The provider keeps Cursor's Run open across OpenCode tool calls, rotates aged shared connections, resumes transient interruptions from the latest eligible Cursor checkpoint, and falls back to a fresh-history rebase only before stateful output when no checkpoint exists. Repeated interruption is surfaced as an error instead of a false successful stop; retry the turn after checking connectivity. With debug logging enabled, look for `Run interrupted`, `resuming … checkpoint`, or `rebasing fresh Run`. Restart OpenCode after rebuilding a local `file://` install. |
|
|
246
258
|
| No response / silent 200 + close | HTTP 200 alone is not a successful agent turn: the provider now requires Cursor's explicit `turn_ended`, captures HTTP/2 trailers/GOAWAY, and recovers once from bare EOF. The Run host still comes from in-memory `GetServerConfig` resolution; set `CURSOR_PROVIDER_DEBUG=1` to confirm the host and termination reason. |
|
|
247
259
|
| Visible `<shell_metadata>` timeout text | Rebuild and restart a local install. Cursor's shell timeout is carried on its exec request; the provider now removes OpenCode's internal timeout envelope before it is rendered or stored, then returns Cursor's typed timeout or background-handoff event instead of treating the text as successful stdout. |
|
|
248
260
|
| `Unsupported Cursor exec variant …` | The error names the canonical Cursor CLI request field, its expected result field, and this provider's handling classification. `handling=unsupported` is a known Cursor-native capability without a safe OpenCode AI SDK bridge; `unknown request field` indicates new protocol drift; `handling=opencode-tool` or `provider-control` indicates a provider decoder/dispatch regression. Enable the debug log and report the full named error. |
|
|
@@ -255,15 +267,15 @@ Project `instructions` may reference absolute or `~/` paths (OpenCode parity). S
|
|
|
255
267
|
## Known limitations
|
|
256
268
|
|
|
257
269
|
- **Personal use / ToS** — this provider speaks Cursor’s private agent protocol (CLI-shaped client identity). Use only with an account you own; Cursor may change or restrict the API without notice.
|
|
258
|
-
- **`request_context` from OpenCode** — each Run sends Cursor `RequestContext` built from OpenCode project context (workspace env, `AGENTS.md` / `instructions`, `.opencode` agents/skills/plugins, git, layout, plus `.claude`/`.agents` skill fallbacks). Its canonical root is also used by the [injected system guidance](#injected-system-guidance). Same discovery as OpenCode — including `.cursor/` paths only when listed in `instructions`. Cursor-only cloud/sandbox marketplace surfaces are omitted. OpenCode remains the permission authority: its coarse allow/ask/deny configuration is not fabricated into Cursor's unrelated allow/block instruction-list messages.
|
|
270
|
+
- **`request_context` from OpenCode** — each Run sends Cursor `RequestContext` built from OpenCode project context (workspace env, `AGENTS.md` / `instructions`, `.opencode` agents/skills/plugins, git, layout, plus `.claude`/`.agents` skill fallbacks). Its canonical root is also used by the [injected system guidance](#injected-system-guidance). Same discovery as OpenCode — including `.cursor/` paths only when listed in `instructions`. Cursor-only cloud/sandbox marketplace surfaces are omitted. `env.workspace_paths` / `process_working_directory` stay on the real git workspace; Cursor's metadata root (`project_folder`, MCP `workspace_project_dir`, terminals/transcripts) is advertised under `<host-cache>/projects/<slug>/` (default `~/.cache/opencode/projects/…`) so dumps like `agent-tools/` do not land in the repo. OpenCode remains the permission authority: its coarse allow/ask/deny configuration is not fabricated into Cursor's unrelated allow/block instruction-list messages.
|
|
259
271
|
- **Configured MCP tools keep their upstream server id** — OpenCode builtins and plugin/custom tools are advertised under a synthetic `opencode` MCP server. Tools whose flattened name matches an MCP server in merged `opencode.json` configuration (`github_create_pull_request`, …) are grouped into that server's `mcp_descriptors` / `provider_identifier` (`github`, …). Unknown underscore-containing names stay under `opencode` rather than being guessed incorrectly. Cursor's MCP-state exec probe is answered from the same advertised descriptors before the actual tool request, using the full canonical tool-definition identity required by native `get_mcp_tools`; exec still reconstructs the full OpenCode tool id.
|
|
260
272
|
- **Display completions are notifications, not execution requests** — Cursor `tool_call_*` frames use a typed `ToolCall` oneof. The provider decodes them for diagnostics but only mirrors finalized todo/plan state (`update_todos_tool_call` / `create_plan_tool_call`) into advertised OpenCode `todowrite`; the completed payload already contains the authoritative final list. Interactive, data-returning, and side-effecting completions are never replayed as new tools because their result could not be returned to Cursor. Exec-backed native subagent/Task and Pi read/bash/edit/write/grep/find/ls calls use their typed request/result fields instead. Unknown display variants are logged. All 37 Cursor CLI exec request/result pairs are inventoried by field and name; known-but-unsupported and future unknown exec variants fail explicitly rather than receiving a guessed response that could deadlock the Run.
|
|
261
273
|
- **Tool availability is per OpenCode agent** — Cursor can request native capabilities such as Task even when a child or restricted OpenCode agent did not advertise the corresponding host tool. The provider prompts Cursor with the exact current catalog and checks every decoded host-tool exec request against it. An unavailable request is answered on Cursor's correlated typed result channel and is never emitted as OpenCode's `invalid` tool.
|
|
262
|
-
- **Background shells are non-interactive** — Cursor's native background-shell spawn
|
|
274
|
+
- **Background shells are non-interactive** — Cursor's native background-shell spawn and soft-background shell-stream timeouts are bridged through OpenCode's foreground-only `bash` tool. With bash/zsh, the classic plugin keeps the original permission/UI command and executes the wrapper through `shell.env` (`BASH_ENV` / `ZDOTDIR`); OpenCode's non-interactive sh/dash argv ignores those startup variables, so the plugin uses a short `exec /bin/sh '<wrapper-file>'` command backed by the same private wrapper. Native background-spawn requests also carry a self-contained marker-producing fallback when the classic hooks are absent. Spawn/soft-bg wrappers detach with `nohup`, redirect output under `${TMPDIR:-/tmp}/cursor-opencode-{bg,shell}.*`, and return the real PID (or typed timeout/exit) to Cursor. Private markers and OpenCode's `<shell_metadata>` envelope are stripped before storage/render, with a short still-running / started / timed-out status line left for the bash bubble. Requests that require `write_shell_stdin` are rejected explicitly because OpenCode does not expose an interactive background-process lifecycle through its AI SDK tool interface. The POSIX wrap path is not implemented for native Windows PowerShell/`cmd`.
|
|
263
275
|
- **Cursor-native interaction queries remain headless** — Cursor UI/approval *queries* (as distinct from display tool calls) still cannot be surfaced through the AI SDK provider interface. The normal system prompt redirects questions, planning, plan-mode transitions, and known-URL fetching to equivalent OpenCode tools only when they are advertised (`question`, `todowrite`, `plan_enter` / `plan_exit`, `webfetch`); native web/PR/MCP/image/SCM requests are declined so they remain behind OpenCode's tools and permissions. Separately from display `create_plan_tool_call` → `todowrite` mirroring, interaction `create_plan_request_query` is auto-acked (CLI headless parity) with success and an empty `plan_uri`, so Cursor may treat the plan as accepted without an OpenCode UI confirm. Compaction prompts are unchanged. Unknown future interaction variants fail the turn explicitly instead of hanging the Run stream.
|
|
264
276
|
- **Compaction resets Cursor conversation state** — the classic plugin marks OpenCode's `compaction` agent explicitly. On those turns the provider mints an isolated Cursor `conversation_id`, drops the prior checkpoint + KV blobs, preserves real tool outputs as OpenCode-host observations in the seed history, and re-advertises the session's last tool catalog while refusing execution during the summary itself. The first normal turn then rebases once more onto a fresh conversation seeded with OpenCode's compacted prompt and normal system instructions, so the summary-agent checkpoint cannot suppress later tool calls. Ordinary no-tool / `toolChoice:none` calls do not reset conversation state.
|
|
265
277
|
- **Conversation bindings and compaction catalogs are bounded** — process-global per-session bindings, prior tool catalogs, and pending post-compaction rebases use a 256-session LRU bound. Evicting a conversation binding also drops its checkpoint and KV blobs.
|
|
266
|
-
- **Interrupted Runs
|
|
278
|
+
- **Interrupted Runs resume from checkpoints** — a remote EOF, Connect end-stream, or trailer error is never emitted as a successful `stop`. When the failed Run produced an eligible checkpoint, the provider opens a new RPC for the same conversation and sends that state with `ResumeAction`, so completed text and tool work are not replayed. Before any stateful output, an interruption without a checkpoint can still rebase from OpenCode history. Stateful interruptions without a checkpoint are surfaced because replay would be ambiguous; retry exhaustion remains explicit. A transport closure after `turn_ended` is treated as successful completion.
|
|
267
279
|
- **No fallback models** — if Cursor’s `AvailableModels` API is unreachable and there is no local cache, the provider exposes no models.
|
|
268
280
|
|
|
269
281
|
## License
|
package/dist/context/build.js
CHANGED
|
@@ -7,6 +7,8 @@ import { collectPlugins } from "./plugins.js";
|
|
|
7
7
|
import { collectGit } from "./git.js";
|
|
8
8
|
import { collectProjectLayout } from "./layout.js";
|
|
9
9
|
import { buildEnv } from "./env.js";
|
|
10
|
+
import { ensureOpencodeProjectDir } from "./paths.js";
|
|
11
|
+
import { traceRequestContextPaths } from "../debug.js";
|
|
10
12
|
/**
|
|
11
13
|
* Full RequestContext payload for live UMA + exec #10 reply.
|
|
12
14
|
* Sourced from OpenCode discovery (and .claude/.agents skill fallbacks).
|
|
@@ -27,6 +29,7 @@ export async function buildRequestContext(input) {
|
|
|
27
29
|
const mcpServerNames = Object.keys(config.mcp ?? {});
|
|
28
30
|
const flat = toolsToDescriptors(tools, providerIdentifier, mcpServerNames);
|
|
29
31
|
const nested = toolsToMcpDescriptors(tools, providerIdentifier, mcpServerNames);
|
|
32
|
+
const projectDir = ensureOpencodeProjectDir(workspaceRoot);
|
|
30
33
|
const ctx = {
|
|
31
34
|
env: buildEnv(workspaceRoot),
|
|
32
35
|
tools: flat,
|
|
@@ -50,7 +53,8 @@ export async function buildRequestContext(input) {
|
|
|
50
53
|
})),
|
|
51
54
|
mcp_file_system_options: {
|
|
52
55
|
enabled: true,
|
|
53
|
-
|
|
56
|
+
// Cursor metadata root (mcps / agent-tools), not the git workspace.
|
|
57
|
+
workspace_project_dir: projectDir,
|
|
54
58
|
mcp_descriptors: nested,
|
|
55
59
|
},
|
|
56
60
|
mcp_meta_tool_options: {
|
|
@@ -73,5 +77,6 @@ export async function buildRequestContext(input) {
|
|
|
73
77
|
.map((p) => `opencode-plugin:${p.source}:${p.id}`)
|
|
74
78
|
.join("\n");
|
|
75
79
|
}
|
|
80
|
+
traceRequestContextPaths("buildRequestContext", ctx);
|
|
76
81
|
return ctx;
|
|
77
82
|
}
|
package/dist/context/env.d.ts
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
1
|
export declare function buildEnv(workspaceRoot: string): Record<string, unknown>;
|
|
2
|
+
/**
|
|
3
|
+
* Real workspace root for path resolution (edits, reads, …).
|
|
4
|
+
* Uses `env.workspace_paths[0]` — never `project_folder` /
|
|
5
|
+
* `mcp_file_system_options.workspace_project_dir` (those are Cursor metadata roots).
|
|
6
|
+
*/
|
|
7
|
+
export declare function workspaceRootFromRequestContext(requestContext: Record<string, unknown> | undefined): string;
|
package/dist/context/env.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { homedir } from "node:os";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { trace } from "../debug.js";
|
|
4
|
+
import { ensureOpencodeProjectDir } from "./paths.js";
|
|
3
5
|
export function buildEnv(workspaceRoot) {
|
|
4
6
|
const cwd = path.resolve(workspaceRoot);
|
|
5
7
|
let timeZone = "UTC";
|
|
@@ -15,15 +17,45 @@ export function buildEnv(workspaceRoot) {
|
|
|
15
17
|
const r = process.release?.version;
|
|
16
18
|
return r ? `${p} ${r}` : p;
|
|
17
19
|
})();
|
|
18
|
-
|
|
20
|
+
// Cursor's project_folder is a metadata root (agent-tools, terminals, …),
|
|
21
|
+
// not the git workspace. Keep dumps under OpenCode cache.
|
|
22
|
+
const projectFolder = ensureOpencodeProjectDir(cwd);
|
|
23
|
+
const env = {
|
|
19
24
|
os_version: osVersion,
|
|
20
25
|
workspace_paths: [cwd],
|
|
21
26
|
shell: process.env.SHELL || "/bin/bash",
|
|
22
27
|
sandbox_enabled: false,
|
|
23
28
|
sandbox_supported: false,
|
|
24
29
|
time_zone: timeZone,
|
|
25
|
-
project_folder:
|
|
30
|
+
project_folder: projectFolder,
|
|
31
|
+
terminals_folder: path.join(projectFolder, "terminals"),
|
|
32
|
+
agent_transcripts_folder: path.join(projectFolder, "agent-transcripts"),
|
|
26
33
|
process_working_directory: process.cwd(),
|
|
27
34
|
is_working_dir_home_dir: path.resolve(process.cwd()) === path.resolve(home),
|
|
28
35
|
};
|
|
36
|
+
trace(`buildEnv: workspace_paths=${JSON.stringify(env.workspace_paths)} ` +
|
|
37
|
+
`project_folder=${env.project_folder} ` +
|
|
38
|
+
`terminals_folder=${env.terminals_folder} ` +
|
|
39
|
+
`agent_transcripts_folder=${env.agent_transcripts_folder} ` +
|
|
40
|
+
`process_working_directory=${env.process_working_directory}`);
|
|
41
|
+
return env;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Real workspace root for path resolution (edits, reads, …).
|
|
45
|
+
* Uses `env.workspace_paths[0]` — never `project_folder` /
|
|
46
|
+
* `mcp_file_system_options.workspace_project_dir` (those are Cursor metadata roots).
|
|
47
|
+
*/
|
|
48
|
+
export function workspaceRootFromRequestContext(requestContext) {
|
|
49
|
+
const env = requestContext?.env;
|
|
50
|
+
if (env && typeof env === "object") {
|
|
51
|
+
const paths = env.workspace_paths;
|
|
52
|
+
if (Array.isArray(paths) && typeof paths[0] === "string" && paths[0].trim()) {
|
|
53
|
+
const root = path.resolve(paths[0]);
|
|
54
|
+
trace(`workspaceRootFromRequestContext: using workspace_paths[0]=${root}`);
|
|
55
|
+
return root;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const fallback = process.cwd();
|
|
59
|
+
trace(`workspaceRootFromRequestContext: workspace_paths missing; fallback cwd=${fallback}`);
|
|
60
|
+
return fallback;
|
|
29
61
|
}
|
package/dist/context/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { buildRequestContext, type BuildRequestContextInput } from "./build.js";
|
|
2
|
-
export { opencodeGlobalCacheDir, opencodeGlobalConfigDir, opencodeGlobalDataDir } from "./paths.js";
|
|
2
|
+
export { adoptCompatHostCacheDir, getHostCacheDirOverride, opencodeGlobalCacheDir, opencodeGlobalConfigDir, opencodeGlobalDataDir, resolveHostCacheDir, setHostCacheDirOverride, } from "./paths.js";
|
package/dist/context/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { buildRequestContext } from "./build.js";
|
|
2
|
-
export { opencodeGlobalCacheDir, opencodeGlobalConfigDir, opencodeGlobalDataDir } from "./paths.js";
|
|
2
|
+
export { adoptCompatHostCacheDir, getHostCacheDirOverride, opencodeGlobalCacheDir, opencodeGlobalConfigDir, opencodeGlobalDataDir, resolveHostCacheDir, setHostCacheDirOverride, } from "./paths.js";
|
package/dist/context/paths.d.ts
CHANGED
|
@@ -1,8 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
export type HostPathEnv = NodeJS.ProcessEnv;
|
|
2
|
+
/**
|
|
3
|
+
* Pin the process-wide cache root. Highest precedence for {@link opencodeGlobalCacheDir}.
|
|
4
|
+
* Use for host-injected `Path.cache` or an explicit `createCursor({ cacheDir })`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function setHostCacheDirOverride(dir: string | undefined): void;
|
|
7
|
+
export declare function getHostCacheDirOverride(): string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Resolve the host cache directory without an override.
|
|
10
|
+
* Mirrors OCP HostProfile drafts: MiMo (`mimocode` / `$MIMOCODE_HOME`), Kilo (`kilo`),
|
|
11
|
+
* then OpenCode (`opencode`). Prefer fork config dirs when several exist.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveHostCacheDir(env?: HostPathEnv): string;
|
|
14
|
+
/**
|
|
15
|
+
* Best-effort: if `@opencode-compat/profile` is installed, adopt `detect().profile.paths.cacheDir`
|
|
16
|
+
* when the host is supported. No-op when OCP is absent or detection fails.
|
|
17
|
+
*/
|
|
18
|
+
export declare function adoptCompatHostCacheDir(): Promise<string | undefined>;
|
|
19
|
+
/** OpenCode / host global config dir (`~/.config/<app>`). Still OpenCode-named for rule discovery. */
|
|
2
20
|
export declare function opencodeGlobalConfigDir(): string;
|
|
3
21
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
22
|
+
* Host global cache dir for Cursor project metadata + model/version caches.
|
|
23
|
+
*
|
|
24
|
+
* Precedence:
|
|
25
|
+
* 1. {@link setHostCacheDirOverride} / `createCursor({ cacheDir })` (host `Path.cache`)
|
|
26
|
+
* 2. OCP `detect()` when {@link adoptCompatHostCacheDir} ran successfully
|
|
27
|
+
* 3. Local host heuristic ({@link resolveHostCacheDir})
|
|
6
28
|
*/
|
|
7
29
|
export declare function opencodeGlobalCacheDir(): string;
|
|
8
30
|
/**
|
|
@@ -11,4 +33,20 @@ export declare function opencodeGlobalCacheDir(): string;
|
|
|
11
33
|
* Auth credentials live here in `auth.json`.
|
|
12
34
|
*/
|
|
13
35
|
export declare function opencodeGlobalDataDir(): string;
|
|
36
|
+
/**
|
|
37
|
+
* Cursor-compatible path slug (`/Users/a/b` → `Users-a-b`).
|
|
38
|
+
* Used for per-workspace metadata under the host cache.
|
|
39
|
+
*/
|
|
40
|
+
export declare function slugifyWorkspacePath(workspaceRoot: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Cursor-style project metadata root for a workspace.
|
|
43
|
+
* Lives at `<host-cache>/projects/<slug>/` (OpenCode / MiMo / Kilo cache root).
|
|
44
|
+
*
|
|
45
|
+
* This is what Cursor's RequestContextEnv.project_folder / MCP
|
|
46
|
+
* workspace_project_dir point at — agent-tools, terminals, transcripts, etc.
|
|
47
|
+
* Must NOT be the git workspace, or those dumps land in the repo.
|
|
48
|
+
*/
|
|
49
|
+
export declare function opencodeProjectDir(workspaceRoot: string): string;
|
|
50
|
+
/** Ensure {@link opencodeProjectDir} exists (mode 0o700) and return it. */
|
|
51
|
+
export declare function ensureOpencodeProjectDir(workspaceRoot: string): string;
|
|
14
52
|
export declare function resolveHomeRelative(p: string): string;
|
package/dist/context/paths.js
CHANGED
|
@@ -1,21 +1,92 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
1
3
|
import { homedir } from "node:os";
|
|
2
4
|
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
import { trace } from "../debug.js";
|
|
6
|
+
/** Explicit host cache root (e.g. Effect v2 `Path.cache`, or `createCursor({ cacheDir })`). */
|
|
7
|
+
let hostCacheDirOverride;
|
|
8
|
+
function resolveHome(env = process.env) {
|
|
9
|
+
return env.HOME || env.USERPROFILE || homedir();
|
|
5
10
|
}
|
|
6
|
-
|
|
11
|
+
function xdgCacheHome(env = process.env) {
|
|
12
|
+
if (env.XDG_CACHE_HOME && env.XDG_CACHE_HOME.length > 0)
|
|
13
|
+
return env.XDG_CACHE_HOME;
|
|
14
|
+
return path.join(resolveHome(env), ".cache");
|
|
15
|
+
}
|
|
16
|
+
function xdgConfigHome(env = process.env) {
|
|
17
|
+
if (env.XDG_CONFIG_HOME && env.XDG_CONFIG_HOME.length > 0)
|
|
18
|
+
return env.XDG_CONFIG_HOME;
|
|
19
|
+
return path.join(resolveHome(env), ".config");
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Pin the process-wide cache root. Highest precedence for {@link opencodeGlobalCacheDir}.
|
|
23
|
+
* Use for host-injected `Path.cache` or an explicit `createCursor({ cacheDir })`.
|
|
24
|
+
*/
|
|
25
|
+
export function setHostCacheDirOverride(dir) {
|
|
26
|
+
hostCacheDirOverride = dir && dir.length > 0 ? path.resolve(dir) : undefined;
|
|
27
|
+
}
|
|
28
|
+
export function getHostCacheDirOverride() {
|
|
29
|
+
return hostCacheDirOverride;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the host cache directory without an override.
|
|
33
|
+
* Mirrors OCP HostProfile drafts: MiMo (`mimocode` / `$MIMOCODE_HOME`), Kilo (`kilo`),
|
|
34
|
+
* then OpenCode (`opencode`). Prefer fork config dirs when several exist.
|
|
35
|
+
*/
|
|
36
|
+
export function resolveHostCacheDir(env = process.env) {
|
|
37
|
+
const mimoHome = env.MIMOCODE_HOME;
|
|
38
|
+
if (mimoHome && mimoHome.length > 0) {
|
|
39
|
+
return path.join(mimoHome, "cache");
|
|
40
|
+
}
|
|
41
|
+
const configHome = xdgConfigHome(env);
|
|
42
|
+
const cacheHome = xdgCacheHome(env);
|
|
43
|
+
const kiloConfig = env.KILO_CONFIG_DIR;
|
|
44
|
+
// Prefer more specific fork dirs before OpenCode (same order as OCP detect).
|
|
45
|
+
if ((kiloConfig && kiloConfig.length > 0) || existsSync(path.join(configHome, "kilo"))) {
|
|
46
|
+
return path.join(cacheHome, "kilo");
|
|
47
|
+
}
|
|
48
|
+
if (existsSync(path.join(configHome, "mimocode"))) {
|
|
49
|
+
return path.join(cacheHome, "mimocode");
|
|
50
|
+
}
|
|
51
|
+
return path.join(cacheHome, "opencode");
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Best-effort: if `@opencode-compat/profile` is installed, adopt `detect().profile.paths.cacheDir`
|
|
55
|
+
* when the host is supported. No-op when OCP is absent or detection fails.
|
|
56
|
+
*/
|
|
57
|
+
export async function adoptCompatHostCacheDir() {
|
|
58
|
+
try {
|
|
59
|
+
const { detect } = await import("@opencode-compat/profile");
|
|
60
|
+
const result = detect();
|
|
61
|
+
if (!result.supported || result.id === "unknown")
|
|
62
|
+
return undefined;
|
|
63
|
+
const cacheDir = result.profile.paths.cacheDir;
|
|
64
|
+
if (!cacheDir || cacheDir.length === 0)
|
|
65
|
+
return undefined;
|
|
66
|
+
setHostCacheDirOverride(cacheDir);
|
|
67
|
+
trace(`host-cache: adopted OCP detect cacheDir=${cacheDir} host=${result.id}`);
|
|
68
|
+
return cacheDir;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** OpenCode / host global config dir (`~/.config/<app>`). Still OpenCode-named for rule discovery. */
|
|
7
75
|
export function opencodeGlobalConfigDir() {
|
|
8
76
|
return path.join(resolveHome(), ".config", "opencode");
|
|
9
77
|
}
|
|
10
78
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
79
|
+
* Host global cache dir for Cursor project metadata + model/version caches.
|
|
80
|
+
*
|
|
81
|
+
* Precedence:
|
|
82
|
+
* 1. {@link setHostCacheDirOverride} / `createCursor({ cacheDir })` (host `Path.cache`)
|
|
83
|
+
* 2. OCP `detect()` when {@link adoptCompatHostCacheDir} ran successfully
|
|
84
|
+
* 3. Local host heuristic ({@link resolveHostCacheDir})
|
|
13
85
|
*/
|
|
14
86
|
export function opencodeGlobalCacheDir() {
|
|
15
|
-
if (
|
|
16
|
-
return
|
|
17
|
-
|
|
18
|
-
return path.join(resolveHome(), ".cache", "opencode");
|
|
87
|
+
if (hostCacheDirOverride)
|
|
88
|
+
return hostCacheDirOverride;
|
|
89
|
+
return resolveHostCacheDir();
|
|
19
90
|
}
|
|
20
91
|
/**
|
|
21
92
|
* OpenCode global data dir (`~/.local/share/opencode`).
|
|
@@ -28,6 +99,47 @@ export function opencodeGlobalDataDir() {
|
|
|
28
99
|
}
|
|
29
100
|
return path.join(resolveHome(), ".local", "share", "opencode");
|
|
30
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Cursor-compatible path slug (`/Users/a/b` → `Users-a-b`).
|
|
104
|
+
* Used for per-workspace metadata under the host cache.
|
|
105
|
+
*/
|
|
106
|
+
export function slugifyWorkspacePath(workspaceRoot) {
|
|
107
|
+
const resolved = path.resolve(workspaceRoot);
|
|
108
|
+
return resolved
|
|
109
|
+
.replace(/[^a-zA-Z0-9]/g, "-")
|
|
110
|
+
.replace(/-+/g, "-")
|
|
111
|
+
.replace(/^-+|-+$/g, "");
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Cursor-style project metadata root for a workspace.
|
|
115
|
+
* Lives at `<host-cache>/projects/<slug>/` (OpenCode / MiMo / Kilo cache root).
|
|
116
|
+
*
|
|
117
|
+
* This is what Cursor's RequestContextEnv.project_folder / MCP
|
|
118
|
+
* workspace_project_dir point at — agent-tools, terminals, transcripts, etc.
|
|
119
|
+
* Must NOT be the git workspace, or those dumps land in the repo.
|
|
120
|
+
*/
|
|
121
|
+
export function opencodeProjectDir(workspaceRoot) {
|
|
122
|
+
const projectsRoot = path.join(opencodeGlobalCacheDir(), "projects");
|
|
123
|
+
const slug = slugifyWorkspacePath(workspaceRoot);
|
|
124
|
+
let dir = path.join(projectsRoot, slug);
|
|
125
|
+
// Mirror Cursor's long-path guard so nested agent-tools paths stay usable.
|
|
126
|
+
if (dir.length > 92) {
|
|
127
|
+
const hash = createHash("sha256").update(dir).digest("hex").slice(0, 7);
|
|
128
|
+
dir = `${dir.slice(0, Math.min(84, dir.length))}-${hash}`;
|
|
129
|
+
}
|
|
130
|
+
return dir;
|
|
131
|
+
}
|
|
132
|
+
/** Ensure {@link opencodeProjectDir} exists (mode 0o700) and return it. */
|
|
133
|
+
export function ensureOpencodeProjectDir(workspaceRoot) {
|
|
134
|
+
const resolved = path.resolve(workspaceRoot);
|
|
135
|
+
const dir = opencodeProjectDir(resolved);
|
|
136
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
137
|
+
trace(`project-dir: workspace=${resolved} slug=${slugifyWorkspacePath(resolved)} ` +
|
|
138
|
+
`dir=${dir} cache_root=${opencodeGlobalCacheDir()} ` +
|
|
139
|
+
`override=${hostCacheDirOverride ?? "(none)"} ` +
|
|
140
|
+
`xdg_cache_home=${process.env.XDG_CACHE_HOME ?? "(unset)"}`);
|
|
141
|
+
return dir;
|
|
142
|
+
}
|
|
31
143
|
export function resolveHomeRelative(p) {
|
|
32
144
|
if (p.startsWith("~/"))
|
|
33
145
|
return path.join(homedir(), p.slice(2));
|
package/dist/debug.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** Whether `CURSOR_PROVIDER_DEBUG` is enabled for this process. */
|
|
2
|
+
export declare function isDebugEnabled(): boolean;
|
|
1
3
|
/** Resolve the debug log path (env override or per-uid tmpdir default). */
|
|
2
4
|
export declare function resolveDebugLogPath(): string;
|
|
3
5
|
/**
|
|
@@ -8,3 +10,8 @@ export declare function ensureSecureDebugLog(filePath: string, options?: {
|
|
|
8
10
|
secureParent?: boolean;
|
|
9
11
|
}): void;
|
|
10
12
|
export declare function trace(msg: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Compact path-advertising summary for RequestContext troubleshooting.
|
|
15
|
+
* Safe: no tokens / file contents — only workspace vs metadata roots.
|
|
16
|
+
*/
|
|
17
|
+
export declare function traceRequestContextPaths(label: string, requestContext: Record<string, unknown> | undefined): void;
|
package/dist/debug.js
CHANGED
|
@@ -10,6 +10,11 @@ const DEBUG_ENABLED = process.env.CURSOR_PROVIDER_DEBUG === "1" ||
|
|
|
10
10
|
let _traceInitialized = false;
|
|
11
11
|
let _debugFile;
|
|
12
12
|
let _debugFileUsesManagedDirectory = false;
|
|
13
|
+
let _announcedLogPath = false;
|
|
14
|
+
/** Whether `CURSOR_PROVIDER_DEBUG` is enabled for this process. */
|
|
15
|
+
export function isDebugEnabled() {
|
|
16
|
+
return DEBUG_ENABLED;
|
|
17
|
+
}
|
|
13
18
|
/** Resolve the debug log path (env override or per-uid tmpdir default). */
|
|
14
19
|
export function resolveDebugLogPath() {
|
|
15
20
|
if (process.env.CURSOR_PROVIDER_DEBUG_FILE) {
|
|
@@ -41,6 +46,18 @@ export function ensureSecureDebugLog(filePath, options = {}) {
|
|
|
41
46
|
fs.writeFileSync(filePath, "", { mode: 0o600 });
|
|
42
47
|
fs.chmodSync(filePath, 0o600);
|
|
43
48
|
}
|
|
49
|
+
function announceLogPath(filePath) {
|
|
50
|
+
if (_announcedLogPath)
|
|
51
|
+
return;
|
|
52
|
+
_announcedLogPath = true;
|
|
53
|
+
try {
|
|
54
|
+
// Visible in the OpenCode / terminal session so operators know where to look.
|
|
55
|
+
console.error(`[cursor-provider] CURSOR_PROVIDER_DEBUG logging to ${filePath}`);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
/* ignore */
|
|
59
|
+
}
|
|
60
|
+
}
|
|
44
61
|
export function trace(msg) {
|
|
45
62
|
if (!DEBUG_ENABLED)
|
|
46
63
|
return;
|
|
@@ -53,6 +70,10 @@ export function trace(msg) {
|
|
|
53
70
|
ensureSecureDebugLog(_debugFile, { secureParent: _debugFileUsesManagedDirectory });
|
|
54
71
|
fs.writeFileSync(_debugFile, `--- cursor-provider debug (pid ${process.pid}) ${new Date().toISOString()} ---\n`, { mode: 0o600 });
|
|
55
72
|
_traceInitialized = true;
|
|
73
|
+
announceLogPath(_debugFile);
|
|
74
|
+
fs.appendFileSync(_debugFile, `[${new Date().toISOString()}] debug: enabled file=${_debugFile} ` +
|
|
75
|
+
`xdg_cache_home=${process.env.XDG_CACHE_HOME ?? "(unset)"} ` +
|
|
76
|
+
`cwd=${process.cwd()}\n`);
|
|
56
77
|
}
|
|
57
78
|
fs.appendFileSync(_debugFile, `[${new Date().toISOString()}] ${msg}\n`);
|
|
58
79
|
}
|
|
@@ -60,3 +81,24 @@ export function trace(msg) {
|
|
|
60
81
|
/* ignore */
|
|
61
82
|
}
|
|
62
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Compact path-advertising summary for RequestContext troubleshooting.
|
|
86
|
+
* Safe: no tokens / file contents — only workspace vs metadata roots.
|
|
87
|
+
*/
|
|
88
|
+
export function traceRequestContextPaths(label, requestContext) {
|
|
89
|
+
if (!DEBUG_ENABLED)
|
|
90
|
+
return;
|
|
91
|
+
const env = requestContext?.env && typeof requestContext.env === "object"
|
|
92
|
+
? requestContext.env
|
|
93
|
+
: undefined;
|
|
94
|
+
const mcp = requestContext?.mcp_file_system_options &&
|
|
95
|
+
typeof requestContext.mcp_file_system_options === "object"
|
|
96
|
+
? requestContext.mcp_file_system_options
|
|
97
|
+
: undefined;
|
|
98
|
+
trace(`${label}: workspace_paths=${JSON.stringify(env?.workspace_paths ?? null)} ` +
|
|
99
|
+
`process_working_directory=${JSON.stringify(env?.process_working_directory ?? null)} ` +
|
|
100
|
+
`project_folder=${JSON.stringify(env?.project_folder ?? null)} ` +
|
|
101
|
+
`terminals_folder=${JSON.stringify(env?.terminals_folder ?? null)} ` +
|
|
102
|
+
`agent_transcripts_folder=${JSON.stringify(env?.agent_transcripts_folder ?? null)} ` +
|
|
103
|
+
`workspace_project_dir=${JSON.stringify(mcp?.workspace_project_dir ?? null)}`);
|
|
104
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,12 @@ export type CreateCursorOptions = {
|
|
|
23
23
|
telemetryEnabled?: boolean;
|
|
24
24
|
/** OpenCode project / worktree directory for request_context collectors. */
|
|
25
25
|
workspaceRoot?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Host cache root for Cursor project metadata + model/version caches.
|
|
28
|
+
* Prefer the host's Path.cache (Effect v2) when available; otherwise the
|
|
29
|
+
* provider resolves OpenCode / MiMo / Kilo XDG cache dirs automatically.
|
|
30
|
+
*/
|
|
31
|
+
cacheDir?: string;
|
|
26
32
|
/** Held-stream policy. Defaults: heartbeat 5s, semantic idle 120s, tool inactivity 10m. */
|
|
27
33
|
continuation?: CursorContinuationOptions;
|
|
28
34
|
/** Fresh-turn retry policy. Defaults: 3 attempts, 500ms base, 8000ms cap. */
|
package/dist/language-model.d.ts
CHANGED
|
@@ -20,10 +20,17 @@ export declare function pumpWithRecovery(input: {
|
|
|
20
20
|
abortSignal?: AbortSignal;
|
|
21
21
|
promptTokens?: number;
|
|
22
22
|
retryPolicy?: CursorRetryPolicy;
|
|
23
|
-
recover: () => Promise<CursorSession>;
|
|
23
|
+
recover: (recovery: CursorRunRecovery) => Promise<CursorSession>;
|
|
24
24
|
onSession?: (session: CursorSession) => void;
|
|
25
25
|
maxRecoveries?: number;
|
|
26
26
|
}): Promise<CursorSession>;
|
|
27
|
+
export type CursorRunRecovery = {
|
|
28
|
+
kind: "rebase";
|
|
29
|
+
} | {
|
|
30
|
+
kind: "resume";
|
|
31
|
+
conversationId: string;
|
|
32
|
+
checkpoint: Uint8Array;
|
|
33
|
+
};
|
|
27
34
|
/**
|
|
28
35
|
* OpenCode re-sends the full tool-result history on every continuation. Prefer
|
|
29
36
|
* the newest result that still has a live pending exec on its tagged session.
|
|
@@ -50,6 +57,9 @@ export declare function pump(session: CursorSession, controller: ReadableStreamD
|
|
|
50
57
|
textId: string;
|
|
51
58
|
reasoningId: string;
|
|
52
59
|
promptTokens?: number;
|
|
60
|
+
requestUsage?: {
|
|
61
|
+
outputChars: number;
|
|
62
|
+
};
|
|
53
63
|
}, abortSignal?: AbortSignal): Promise<void>;
|
|
54
64
|
type ExtractedToolResult = {
|
|
55
65
|
toolCallId: string;
|