cursor-opencode-provider 0.4.3 → 0.6.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 +33 -23
- package/dist/context/agents.d.ts +1 -1
- package/dist/context/agents.js +1 -1
- package/dist/context/auth-store.js +2 -2
- package/dist/context/build.d.ts +11 -1
- package/dist/context/build.js +76 -25
- package/dist/context/frozen.d.ts +29 -0
- package/dist/context/frozen.js +168 -0
- package/dist/context/index.d.ts +3 -2
- package/dist/context/index.js +3 -2
- package/dist/context/paths.d.ts +34 -53
- package/dist/context/paths.js +54 -118
- package/dist/context/rules.d.ts +1 -0
- package/dist/context/rules.js +2 -2
- package/dist/image-save-tool.d.ts +19 -0
- package/dist/image-save-tool.js +25 -0
- package/dist/image-save.d.ts +58 -0
- package/dist/image-save.js +189 -0
- package/dist/image-staging.d.ts +59 -0
- package/dist/image-staging.js +91 -0
- package/dist/index.d.ts +1 -1
- package/dist/language-model.d.ts +13 -11
- package/dist/language-model.js +957 -150
- package/dist/plan-execution-kickoff.d.ts +55 -0
- package/dist/plan-execution-kickoff.js +162 -0
- package/dist/plugin-opencode2.js +52 -3
- package/dist/plugin-v2.d.ts +11 -9
- package/dist/plugin-v2.js +6 -13
- package/dist/plugin.d.ts +9 -0
- package/dist/plugin.js +61 -5
- package/dist/pricing-data.d.ts +16 -4
- package/dist/pricing-data.js +16 -4
- package/dist/protocol/ask-question.d.ts +133 -0
- package/dist/protocol/ask-question.js +320 -0
- package/dist/protocol/blob-reachability.d.ts +15 -0
- package/dist/protocol/blob-reachability.js +140 -0
- package/dist/protocol/blob-store.d.ts +37 -0
- package/dist/protocol/blob-store.js +115 -0
- package/dist/protocol/conversation-bind.d.ts +13 -0
- package/dist/protocol/conversation-bind.js +27 -1
- package/dist/protocol/conversation-persistence.d.ts +32 -0
- package/dist/protocol/conversation-persistence.js +504 -0
- package/dist/protocol/conversation-state.d.ts +16 -0
- package/dist/protocol/conversation-state.js +62 -0
- package/dist/protocol/create-plan.d.ts +141 -0
- package/dist/protocol/create-plan.js +373 -0
- package/dist/protocol/generate-image.d.ts +54 -0
- package/dist/protocol/generate-image.js +101 -0
- package/dist/protocol/interactions.d.ts +110 -8
- package/dist/protocol/interactions.js +295 -35
- package/dist/protocol/kv.d.ts +1 -0
- package/dist/protocol/kv.js +2 -0
- package/dist/protocol/messages.d.ts +2 -0
- package/dist/protocol/messages.js +148 -8
- package/dist/protocol/request.d.ts +2 -0
- package/dist/protocol/request.js +2 -0
- package/dist/protocol/switch-mode.d.ts +178 -0
- package/dist/protocol/switch-mode.js +417 -0
- package/dist/protocol/token-details.d.ts +33 -0
- package/dist/protocol/token-details.js +155 -0
- package/dist/protocol/tool-call-bridge.js +10 -5
- package/dist/protocol/tools.d.ts +44 -11
- package/dist/protocol/tools.js +171 -41
- package/dist/session.d.ts +39 -11
- package/dist/shared.d.ts +3 -0
- package/dist/shared.js +3 -0
- package/dist/usage.d.ts +42 -37
- package/dist/usage.js +201 -70
- package/dist/web-search-tool.d.ts +22 -26
- package/dist/web-search-tool.js +25 -15
- package/package.json +7 -4
package/dist/usage.js
CHANGED
|
@@ -5,89 +5,220 @@ export function turnEndedCounter(te, key) {
|
|
|
5
5
|
? Math.trunc(value)
|
|
6
6
|
: 0;
|
|
7
7
|
}
|
|
8
|
+
export function cursorUsageCountersFromTurnEnded(te) {
|
|
9
|
+
return {
|
|
10
|
+
inputTokens: turnEndedCounter(te, "input_tokens"),
|
|
11
|
+
outputTokens: turnEndedCounter(te, "output_tokens"),
|
|
12
|
+
cacheRead: turnEndedCounter(te, "cache_read"),
|
|
13
|
+
cacheWrite: turnEndedCounter(te, "cache_write"),
|
|
14
|
+
reasoningTokens: turnEndedCounter(te, "reasoning_tokens"),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
8
17
|
/**
|
|
9
|
-
* Map
|
|
10
|
-
*
|
|
11
|
-
* for a Run with no prior tool boundary; multi-step TurnEnded is cumulative.
|
|
12
|
-
*
|
|
13
|
-
* Contract: `input_tokens` is non-cached input; cache fields are separate.
|
|
14
|
-
* Cursor's agent wire currently sends `cache_write=0` even when later turns
|
|
15
|
-
* report large `cache_read`; we still forward the counter when non-zero.
|
|
16
|
-
* If production semantics differ (input_tokens already total), adjust here.
|
|
18
|
+
* Map Cursor counters to AI SDK V3. Cursor's `input_tokens` already includes
|
|
19
|
+
* cache reads/writes, and `output_tokens` already includes reasoning.
|
|
17
20
|
*/
|
|
18
|
-
export function
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
21
|
+
export function buildLanguageModelV3UsageFromCounters(counters, options = {}) {
|
|
22
|
+
const rawInput = Math.max(0, Math.trunc(counters.inputTokens));
|
|
23
|
+
const rawOutput = Math.max(0, Math.trunc(counters.outputTokens));
|
|
24
|
+
const rawCacheRead = Math.min(Math.max(0, Math.trunc(counters.cacheRead)), rawInput);
|
|
25
|
+
const rawCacheWrite = Math.min(Math.max(0, Math.trunc(counters.cacheWrite)), rawInput - rawCacheRead);
|
|
26
|
+
const rawReasoning = Math.min(Math.max(0, Math.trunc(counters.reasoningTokens)), rawOutput);
|
|
27
|
+
const contextTotal = options.contextTotalTokens;
|
|
28
|
+
const hasContextTotal = typeof contextTotal === "number" && Number.isFinite(contextTotal) && contextTotal >= 0;
|
|
29
|
+
const total = hasContextTotal ? Math.trunc(contextTotal) : rawInput + rawOutput;
|
|
30
|
+
const output = Math.min(rawOutput, total);
|
|
31
|
+
const input = Math.max(0, total - output);
|
|
32
|
+
// TurnEnded can aggregate several internal model calls, so its absolute input
|
|
33
|
+
// and cache counts can exceed the final checkpoint occupancy. Preserve the
|
|
34
|
+
// cache proportions while normalizing the partition to Cursor's context total.
|
|
35
|
+
const cacheRead = rawInput > 0
|
|
36
|
+
? Math.min(input, Math.round(input * rawCacheRead / rawInput))
|
|
37
|
+
: 0;
|
|
38
|
+
const cacheWrite = rawInput > 0
|
|
39
|
+
? Math.min(input - cacheRead, Math.round(input * rawCacheWrite / rawInput))
|
|
40
|
+
: 0;
|
|
41
|
+
const reasoning = rawOutput > 0
|
|
42
|
+
? Math.min(output, Math.round(output * rawReasoning / rawOutput))
|
|
43
|
+
: 0;
|
|
24
44
|
return {
|
|
25
45
|
inputTokens: {
|
|
26
|
-
total:
|
|
27
|
-
noCache:
|
|
28
|
-
cacheRead
|
|
29
|
-
cacheWrite
|
|
46
|
+
total: input,
|
|
47
|
+
noCache: Math.max(input - cacheRead - cacheWrite, 0),
|
|
48
|
+
cacheRead,
|
|
49
|
+
cacheWrite,
|
|
30
50
|
},
|
|
31
51
|
outputTokens: {
|
|
32
|
-
total:
|
|
33
|
-
text:
|
|
34
|
-
reasoning
|
|
52
|
+
total: output,
|
|
53
|
+
text: Math.max(output - reasoning, 0),
|
|
54
|
+
reasoning,
|
|
35
55
|
},
|
|
36
56
|
};
|
|
37
57
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const trustCeiling = Math.max(requestLocal * CUMULATIVE_TURN_ENDED_RATIO, MIN_TRUSTED_TURN_ENDED_TOTAL);
|
|
60
|
-
return total > trustCeiling;
|
|
58
|
+
export function buildLanguageModelV3UsageFromTurnEnded(te, options = {}) {
|
|
59
|
+
return buildLanguageModelV3UsageFromCounters(cursorUsageCountersFromTurnEnded(te), options);
|
|
60
|
+
}
|
|
61
|
+
function usageCount(value) {
|
|
62
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0
|
|
63
|
+
? Math.trunc(value)
|
|
64
|
+
: 0;
|
|
65
|
+
}
|
|
66
|
+
function usageRatio(part, total) {
|
|
67
|
+
return total > 0 ? `${(part / total * 100).toFixed(1)}%` : "n/a";
|
|
68
|
+
}
|
|
69
|
+
function categoryTokens(details) {
|
|
70
|
+
return new Map(details?.breakdown?.categories.map((category) => [
|
|
71
|
+
category.id || category.label || "(unnamed)",
|
|
72
|
+
category.estimatedTokens,
|
|
73
|
+
]) ?? []);
|
|
74
|
+
}
|
|
75
|
+
/** Compact, parseable category snapshot for checkpoint-by-checkpoint traces. */
|
|
76
|
+
export function formatCursorTokenCategories(details) {
|
|
77
|
+
const categories = Object.fromEntries(categoryTokens(details));
|
|
78
|
+
return Object.keys(categories).length > 0 ? JSON.stringify(categories) : "unavailable";
|
|
61
79
|
}
|
|
62
80
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* `est.outputTokens` accumulates model output across earlier tool boundaries.
|
|
67
|
-
* Move prior output into the current input estimate and report only this
|
|
68
|
-
* doStream request's output. Cache counters are intentionally absent: the
|
|
69
|
-
* only counters Cursor exposes at TurnEnded are cumulative for the whole Run.
|
|
81
|
+
* Explain Cursor's aggregate cache counters using the state visible to this
|
|
82
|
+
* client. `stepStarts` is deliberately not called a model-call count: Cursor
|
|
83
|
+
* does not expose per-model-call cache accounting on the Run stream.
|
|
70
84
|
*/
|
|
71
|
-
export function
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
export function formatCursorCacheDiagnostics(counters, current, prior, stats) {
|
|
86
|
+
const rawInput = Math.max(0, Math.trunc(counters.inputTokens));
|
|
87
|
+
const rawRead = Math.min(rawInput, Math.max(0, Math.trunc(counters.cacheRead)));
|
|
88
|
+
const rawWrite = Math.min(rawInput - rawRead, Math.max(0, Math.trunc(counters.cacheWrite)));
|
|
89
|
+
const rawUncached = Math.max(0, rawInput - rawRead - rawWrite);
|
|
90
|
+
const priorCategories = categoryTokens(prior);
|
|
91
|
+
const currentCategories = categoryTokens(current);
|
|
92
|
+
const categoriesComparable = !!prior?.breakdown && !!current?.breakdown;
|
|
93
|
+
const categoryDelta = {};
|
|
94
|
+
let sameSizedCategoryTokens = 0;
|
|
95
|
+
if (categoriesComparable) {
|
|
96
|
+
for (const id of new Set([...priorCategories.keys(), ...currentCategories.keys()])) {
|
|
97
|
+
const before = priorCategories.get(id);
|
|
98
|
+
const after = currentCategories.get(id);
|
|
99
|
+
if (before === undefined)
|
|
100
|
+
categoryDelta[id] = "new";
|
|
101
|
+
else if (after === undefined)
|
|
102
|
+
categoryDelta[id] = "removed";
|
|
103
|
+
else {
|
|
104
|
+
categoryDelta[id] = after - before;
|
|
105
|
+
if (after === before)
|
|
106
|
+
sameSizedCategoryTokens += after;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const continuity = stats.startedWithCheckpoint
|
|
111
|
+
? prior ? "warm" : "checkpoint-without-token-details"
|
|
112
|
+
: "cold";
|
|
113
|
+
const contextDelta = current && prior ? current.usedTokens - prior.usedTokens : undefined;
|
|
114
|
+
return [
|
|
115
|
+
"cache diagnosis:",
|
|
116
|
+
`sessionKey=${stats.sessionKey ?? "-"}`,
|
|
117
|
+
`conversationId=${stats.conversationId}`,
|
|
118
|
+
`conversationGroupId=${stats.conversationGroupId ?? "-"}`,
|
|
119
|
+
`model=${stats.modelId ?? "-"}`,
|
|
120
|
+
`continuity=${continuity}`,
|
|
121
|
+
`rawInput=${rawInput}`,
|
|
122
|
+
`rawCacheRead=${rawRead}`,
|
|
123
|
+
`rawCacheWrite=${rawWrite}`,
|
|
124
|
+
`rawUncached=${rawUncached}`,
|
|
125
|
+
`rawReadRatio=${usageRatio(rawRead, rawInput)}`,
|
|
126
|
+
`rawWriteRatio=${usageRatio(rawWrite, rawInput)}`,
|
|
127
|
+
`priorContext=${prior?.usedTokens ?? "unavailable"}`,
|
|
128
|
+
`currentContext=${current?.usedTokens ?? "unavailable"}`,
|
|
129
|
+
`contextDelta=${contextDelta ?? "unavailable"}`,
|
|
130
|
+
`rawReadVsPriorContext=${prior ? usageRatio(rawRead, prior.usedTokens) : "n/a"}`,
|
|
131
|
+
`sameSizedCategoryTokens=${categoriesComparable ? sameSizedCategoryTokens : "unavailable"}`,
|
|
132
|
+
`categoryDelta=${categoriesComparable && Object.keys(categoryDelta).length > 0 ? JSON.stringify(categoryDelta) : "unavailable"}`,
|
|
133
|
+
`requestContext=${stats.requestContextReused ? "reused" : "built"}`,
|
|
134
|
+
`requestContextHash=${stats.requestContextHash.slice(0, 16)}`,
|
|
135
|
+
`systemPromptHash=${stats.systemPromptHash?.slice(0, 16) ?? "none"}`,
|
|
136
|
+
`systemPromptSent=${!stats.startedWithCheckpoint}`,
|
|
137
|
+
`checkpointUpdates=${stats.checkpointUpdates}`,
|
|
138
|
+
`tokenDetailUpdates=${stats.tokenDetailUpdates}`,
|
|
139
|
+
`pumpPasses=${stats.pumpPasses}`,
|
|
140
|
+
`steps=${stats.stepStarts}/${stats.stepCompletes}`,
|
|
141
|
+
`displayToolCalls=${stats.displayToolCalls}`,
|
|
142
|
+
`execRequests=${stats.execRequests}`,
|
|
143
|
+
"perModelCallCache=unavailable",
|
|
144
|
+
].join(" ");
|
|
145
|
+
}
|
|
146
|
+
/** One-line proof that Cursor, AI SDK, and projected OpenCode totals agree. */
|
|
147
|
+
export function formatTurnUsageValidation(counters, usage, tokenDetails, contextSource) {
|
|
148
|
+
const input = usageCount(usage.inputTokens.total);
|
|
149
|
+
const noCache = usageCount(usage.inputTokens.noCache);
|
|
150
|
+
const cacheRead = usageCount(usage.inputTokens.cacheRead);
|
|
151
|
+
const cacheWrite = usageCount(usage.inputTokens.cacheWrite);
|
|
152
|
+
const inputParts = noCache + cacheRead + cacheWrite;
|
|
153
|
+
const output = usageCount(usage.outputTokens.total);
|
|
154
|
+
const text = usageCount(usage.outputTokens.text);
|
|
155
|
+
const reasoning = usageCount(usage.outputTokens.reasoning);
|
|
156
|
+
const outputParts = text + reasoning;
|
|
157
|
+
const sentTotal = input + output;
|
|
158
|
+
const projectedOpenCodeTotal = inputParts + outputParts;
|
|
159
|
+
const rawTotal = counters.inputTokens + counters.outputTokens;
|
|
160
|
+
const cursor = tokenDetails
|
|
161
|
+
? `${tokenDetails.usedTokens}/${tokenDetails.maxTokens}` +
|
|
162
|
+
`(${usageRatio(tokenDetails.usedTokens, tokenDetails.maxTokens)})`
|
|
163
|
+
: "unavailable";
|
|
164
|
+
const totalMatch = tokenDetails ? String(sentTotal === tokenDetails.usedTokens) : "unavailable";
|
|
165
|
+
const breakdown = tokenDetails?.breakdown;
|
|
166
|
+
const categorySum = breakdown?.categories.reduce((sum, category) => sum + category.estimatedTokens, 0);
|
|
167
|
+
const breakdownMatch = breakdown && categorySum !== undefined
|
|
168
|
+
? breakdown.totalUsedTokens === tokenDetails.usedTokens &&
|
|
169
|
+
categorySum === breakdown.totalUsedTokens
|
|
170
|
+
: undefined;
|
|
171
|
+
const rawCached = counters.cacheRead + counters.cacheWrite;
|
|
172
|
+
const sentCached = cacheRead + cacheWrite;
|
|
173
|
+
const cacheRatioMatch = tokenDetails
|
|
174
|
+
? counters.inputTokens > 0 && input > 0
|
|
175
|
+
? Math.abs(rawCached / counters.inputTokens - sentCached / input) <= 1 / input
|
|
176
|
+
: rawCached === 0 && sentCached === 0
|
|
177
|
+
: undefined;
|
|
178
|
+
const status = input === inputParts &&
|
|
179
|
+
output === outputParts &&
|
|
180
|
+
projectedOpenCodeTotal === sentTotal &&
|
|
181
|
+
(cacheRatioMatch ?? true) &&
|
|
182
|
+
(!tokenDetails || sentTotal === tokenDetails.usedTokens) &&
|
|
183
|
+
(breakdownMatch ?? true)
|
|
184
|
+
? "ok"
|
|
185
|
+
: "mismatch";
|
|
186
|
+
return [
|
|
187
|
+
"turn usage validation:",
|
|
188
|
+
`status=${status}`,
|
|
189
|
+
`source=${tokenDetails ? contextSource ?? "checkpoint-current-run" : "unavailable"}`,
|
|
190
|
+
`cursor=${cursor}`,
|
|
191
|
+
`rawTotal=${rawTotal}`,
|
|
192
|
+
`sentTotal=${sentTotal}`,
|
|
193
|
+
`totalMatch=${totalMatch}`,
|
|
194
|
+
`input=${input}`,
|
|
195
|
+
`inputParts=${inputParts}`,
|
|
196
|
+
`inputMatch=${input === inputParts}`,
|
|
197
|
+
`output=${output}`,
|
|
198
|
+
`outputParts=${outputParts}`,
|
|
199
|
+
`outputMatch=${output === outputParts}`,
|
|
200
|
+
`opencodeProjectedTotal=${projectedOpenCodeTotal}`,
|
|
201
|
+
`opencodeMatch=${projectedOpenCodeTotal === sentTotal}`,
|
|
202
|
+
`breakdownTotal=${breakdown?.totalUsedTokens ?? "unavailable"}`,
|
|
203
|
+
`categorySum=${categorySum ?? "unavailable"}`,
|
|
204
|
+
`breakdownMatch=${breakdownMatch ?? "unavailable"}`,
|
|
205
|
+
`rawCachedRatio=${usageRatio(rawCached, counters.inputTokens)}`,
|
|
206
|
+
`sentCachedRatio=${usageRatio(sentCached, input)}`,
|
|
207
|
+
`cacheRatioMatch=${cacheRatioMatch ?? "unavailable"}`,
|
|
208
|
+
].join(" ");
|
|
209
|
+
}
|
|
210
|
+
/** OpenCode requires a usage object at every step boundary. */
|
|
211
|
+
export function emptyLanguageModelV3Usage() {
|
|
212
|
+
return buildLanguageModelV3UsageFromCounters({
|
|
213
|
+
inputTokens: 0,
|
|
214
|
+
outputTokens: 0,
|
|
215
|
+
cacheRead: 0,
|
|
216
|
+
cacheWrite: 0,
|
|
217
|
+
reasoningTokens: 0,
|
|
218
|
+
});
|
|
88
219
|
}
|
|
89
|
-
/**
|
|
90
|
-
export function
|
|
220
|
+
/** Project nested V3 usage into the common flat AI-SDK counter shape. */
|
|
221
|
+
export function flatUsageFromV3(usage) {
|
|
91
222
|
const input = usage.inputTokens;
|
|
92
223
|
const output = usage.outputTokens;
|
|
93
224
|
const noCache = input.noCache ?? 0;
|
|
@@ -1,33 +1,29 @@
|
|
|
1
|
+
import { executeOpenCodeWebSearch } from "./web-tools.js";
|
|
2
|
+
type ToolFactory = {
|
|
3
|
+
tool: (input: Record<string, unknown>) => Record<string, unknown>;
|
|
4
|
+
schema: {
|
|
5
|
+
string: () => any;
|
|
6
|
+
number: () => any;
|
|
7
|
+
enum: (values: readonly string[]) => any;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
/** Build the classic OpenCode web-search tool with the host's own Zod helper. */
|
|
11
|
+
export declare function createOpenCodeWebSearchTool(factory: ToolFactory): Record<string, unknown>;
|
|
1
12
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* implementation in that module. 2.0's package root exports no `tool`, so
|
|
7
|
-
* importing it from a module on the 2.0 graph would throw during plugin load.
|
|
8
|
-
* Only `plugin.ts` (classic hooks) may import this file.
|
|
13
|
+
* Host-neutral JSON-schema fallback when the classic helper is unavailable.
|
|
14
|
+
* OpenCode's legacy schema adapter marks every listed property required, so
|
|
15
|
+
* expose only the genuinely required query rather than turning four optional
|
|
16
|
+
* tuning fields into mandatory inputs.
|
|
9
17
|
*/
|
|
10
18
|
export declare const openCodeWebSearchTool: {
|
|
11
19
|
description: string;
|
|
12
20
|
args: {
|
|
13
|
-
query:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
preferred: "preferred";
|
|
18
|
-
}>>;
|
|
19
|
-
type: import("zod").ZodOptional<import("zod").ZodEnum<{
|
|
20
|
-
fast: "fast";
|
|
21
|
-
auto: "auto";
|
|
22
|
-
deep: "deep";
|
|
23
|
-
}>>;
|
|
24
|
-
contextMaxCharacters: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
21
|
+
query: {
|
|
22
|
+
type: string;
|
|
23
|
+
description: string;
|
|
24
|
+
};
|
|
25
25
|
};
|
|
26
|
-
execute
|
|
27
|
-
query: string;
|
|
28
|
-
numResults?: number | undefined;
|
|
29
|
-
livecrawl?: "fallback" | "preferred" | undefined;
|
|
30
|
-
type?: "fast" | "auto" | "deep" | undefined;
|
|
31
|
-
contextMaxCharacters?: number | undefined;
|
|
32
|
-
}, context: import("@opencode-ai/plugin").ToolContext): Promise<import("@opencode-ai/plugin").ToolResult>;
|
|
26
|
+
execute: typeof executeOpenCodeWebSearch;
|
|
33
27
|
};
|
|
28
|
+
export type { ToolFactory as OpenCodeToolFactory };
|
|
29
|
+
export declare function createOpenCodeWebSearchToolFromPlugin(pluginModule: any): Record<string, unknown>;
|
package/dist/web-search-tool.js
CHANGED
|
@@ -1,22 +1,32 @@
|
|
|
1
|
-
import { tool } from "@opencode-ai/plugin";
|
|
2
1
|
import { executeOpenCodeWebSearch } from "./web-tools.js";
|
|
2
|
+
/** Build the classic OpenCode web-search tool with the host's own Zod helper. */
|
|
3
|
+
export function createOpenCodeWebSearchTool(factory) {
|
|
4
|
+
const schema = factory.schema;
|
|
5
|
+
return factory.tool({
|
|
6
|
+
description: "Search the web for current information using OpenCode's web search backend.",
|
|
7
|
+
args: {
|
|
8
|
+
query: schema.string().describe("Web search query"),
|
|
9
|
+
numResults: schema.number().int().min(1).max(20).optional(),
|
|
10
|
+
livecrawl: schema.enum(["fallback", "preferred"]).optional(),
|
|
11
|
+
type: schema.enum(["auto", "fast", "deep"]).optional(),
|
|
12
|
+
contextMaxCharacters: schema.number().int().positive().optional(),
|
|
13
|
+
},
|
|
14
|
+
execute: executeOpenCodeWebSearch,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
3
17
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* implementation in that module. 2.0's package root exports no `tool`, so
|
|
9
|
-
* importing it from a module on the 2.0 graph would throw during plugin load.
|
|
10
|
-
* Only `plugin.ts` (classic hooks) may import this file.
|
|
18
|
+
* Host-neutral JSON-schema fallback when the classic helper is unavailable.
|
|
19
|
+
* OpenCode's legacy schema adapter marks every listed property required, so
|
|
20
|
+
* expose only the genuinely required query rather than turning four optional
|
|
21
|
+
* tuning fields into mandatory inputs.
|
|
11
22
|
*/
|
|
12
|
-
export const openCodeWebSearchTool =
|
|
23
|
+
export const openCodeWebSearchTool = {
|
|
13
24
|
description: "Search the web for current information using OpenCode's web search backend.",
|
|
14
25
|
args: {
|
|
15
|
-
query:
|
|
16
|
-
numResults: tool.schema.number().int().min(1).max(20).optional(),
|
|
17
|
-
livecrawl: tool.schema.enum(["fallback", "preferred"]).optional(),
|
|
18
|
-
type: tool.schema.enum(["auto", "fast", "deep"]).optional(),
|
|
19
|
-
contextMaxCharacters: tool.schema.number().int().positive().optional(),
|
|
26
|
+
query: { type: "string", description: "Web search query" },
|
|
20
27
|
},
|
|
21
28
|
execute: executeOpenCodeWebSearch,
|
|
22
|
-
}
|
|
29
|
+
};
|
|
30
|
+
export function createOpenCodeWebSearchToolFromPlugin(pluginModule) {
|
|
31
|
+
return createOpenCodeWebSearchTool({ tool: pluginModule.tool, schema: pluginModule.tool.schema });
|
|
32
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cursor-opencode-provider",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Use Cursor subscription models from OpenCode via Cursor's Connect-RPC agent protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -55,6 +55,10 @@
|
|
|
55
55
|
"./auth": {
|
|
56
56
|
"types": "./dist/auth.d.ts",
|
|
57
57
|
"import": "./dist/auth.js"
|
|
58
|
+
},
|
|
59
|
+
"./image-save": {
|
|
60
|
+
"types": "./dist/image-save.d.ts",
|
|
61
|
+
"import": "./dist/image-save.js"
|
|
58
62
|
}
|
|
59
63
|
},
|
|
60
64
|
"files": [
|
|
@@ -80,11 +84,10 @@
|
|
|
80
84
|
"protobufjs": "^7.6.5"
|
|
81
85
|
},
|
|
82
86
|
"peerDependencies": {
|
|
83
|
-
"@opencode-ai/plugin": "^1.17.13"
|
|
84
|
-
"@opencode-compat/profile": ">=0.1.0"
|
|
87
|
+
"@opencode-ai/plugin": "^1.17.13"
|
|
85
88
|
},
|
|
86
89
|
"peerDependenciesMeta": {
|
|
87
|
-
"@opencode-
|
|
90
|
+
"@opencode-ai/plugin": {
|
|
88
91
|
"optional": true
|
|
89
92
|
}
|
|
90
93
|
},
|