headroom-opencode 0.39.1 → 0.41.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 +19 -15
- package/dist/{chunk-6I5ODRCW.js → chunk-XS6Z2EJR.js} +144 -32
- package/dist/chunk-XS6Z2EJR.js.map +1 -0
- package/dist/entry.opencode-C0sNp2fs.d.ts +21 -0
- package/dist/entry.opencode.d.ts +2 -1
- package/dist/entry.opencode.js +3 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.js +10 -3
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/dist/chunk-6I5ODRCW.js.map +0 -1
- package/dist/entry.opencode-CbfMY5Ox.d.ts +0 -12
package/README.md
CHANGED
|
@@ -35,32 +35,36 @@ The generated provider uses `@ai-sdk/openai-compatible` and points model request
|
|
|
35
35
|
|
|
36
36
|
## Native OpenCode Plugin
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
The package's default export is an OpenCode plugin that loads on both OpenCode 1.x and 2.x. Register it in `opencode.json`:
|
|
39
39
|
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
proxyUrl: process.env.HEADROOM_PROXY_URL ?? "http://127.0.0.1:8787",
|
|
46
|
-
});
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"plugin": [
|
|
43
|
+
["headroom-opencode", { "proxyUrl": "http://127.0.0.1:8787" }]
|
|
44
|
+
]
|
|
47
45
|
}
|
|
48
46
|
```
|
|
49
47
|
|
|
50
|
-
`
|
|
48
|
+
OpenCode 2.x migrates the 1.x `plugin` key automatically. To configure it the 2.x way, use `"plugins": [{ "package": "headroom-opencode", "options": { ... } }]`.
|
|
49
|
+
|
|
50
|
+
The default export is `{ id: "headroom", server, setup }`. OpenCode 1.x calls `server` (`HeadroomPlugin`) and 2.x calls `setup` (`headroomSetup`); each ignores the other's field. Both entry points:
|
|
51
|
+
|
|
52
|
+
- install Headroom transport interception for OpenCode provider traffic.
|
|
53
|
+
- expose the `headroom_retrieve` tool (a direct tool on 2.x, not only through code mode).
|
|
54
|
+
- add `HEADROOM_ACTIVE`, `HEADROOM_PROXY_URL`, `HEADROOM_PROJECT` (and `HEADROOM_BACKEND` when set) to shell command environments.
|
|
55
|
+
- default to `HEADROOM_PROXY_URL`, then `http://127.0.0.1:8787`, when no `proxyUrl` option is supplied.
|
|
56
|
+
- skip routing for hosts listed in `excludeHosts` (or `HEADROOM_OPENCODE_EXCLUDE_HOSTS`); those requests go straight upstream with no compression or telemetry.
|
|
57
|
+
|
|
58
|
+
On 2.x, setup returns a cleanup that releases the transport, so hot reloads do not stack interceptors.
|
|
51
59
|
|
|
52
|
-
-
|
|
53
|
-
- exposes the `headroom_retrieve` tool.
|
|
54
|
-
- publishes `HEADROOM_PROXY_URL` in the plugin output env.
|
|
55
|
-
- defaults to `http://127.0.0.1:8787` when no proxy URL is supplied.
|
|
56
|
-
- skips routing for hosts listed in `excludeHosts` (or `HEADROOM_OPENCODE_EXCLUDE_HOSTS`); those requests go straight upstream with no compression or telemetry.
|
|
60
|
+
OpenCode 2.x keeps its own reference to `fetch` from before plugins load, so patching `fetch` alone does not catch its model traffic. On 2.x the plugin also rewrites each remote model that uses the OpenAI chat-completions or responses format so that it points at the proxy. Headers name the real upstream, as the transport does. Models on other formats (Anthropic messages, Google) are left alone. `headroom wrap opencode` routes native Anthropic and OpenAI through the proxy separately, via their `baseURL`.
|
|
57
61
|
|
|
58
62
|
To keep a provider off the proxy, list its host. An entry matches the host and all of its subdomains, and `.example.com` / `*.example.com` are accepted as spellings of `example.com`:
|
|
59
63
|
|
|
60
64
|
```jsonc
|
|
61
65
|
// opencode.json
|
|
62
66
|
{
|
|
63
|
-
"plugin": [["/path/to/headroom/providers/opencode/_dist
|
|
67
|
+
"plugin": [["/path/to/headroom/providers/opencode/_dist", { "excludeHosts": ["opencode.ai"] }]]
|
|
64
68
|
}
|
|
65
69
|
```
|
|
66
70
|
|
|
@@ -13,8 +13,13 @@ function setDefaultProxyUrl(url2) {
|
|
|
13
13
|
function getDefaultProxyUrl() {
|
|
14
14
|
return _proxyUrlCache ?? process.env.HEADROOM_BASE_URL ?? "http://localhost:8787";
|
|
15
15
|
}
|
|
16
|
+
function trimTrailingSlashes(value) {
|
|
17
|
+
let end = value.length;
|
|
18
|
+
while (end > 0 && value.charCodeAt(end - 1) === 47) end--;
|
|
19
|
+
return value.slice(0, end);
|
|
20
|
+
}
|
|
16
21
|
function createHeadroomRetrieveTool(config2) {
|
|
17
|
-
const origin = config2.proxyBaseUrl
|
|
22
|
+
const origin = trimTrailingSlashes(config2.proxyBaseUrl);
|
|
18
23
|
return {
|
|
19
24
|
name: "headroom_retrieve",
|
|
20
25
|
description: "Retrieve original uncompressed content from Headroom's compression store. Use when compressed context mentions a hash and you need the full details. Pass the hash from the compression marker (24 hex characters). Retrieval is by hash and always returns the full original content.",
|
|
@@ -78,6 +83,7 @@ var fs = nodeRequire("node:fs");
|
|
|
78
83
|
var BASE_URL_HEADER = "x-headroom-base-url";
|
|
79
84
|
var ORIGINAL_PATH_HEADER = "x-headroom-original-path";
|
|
80
85
|
var PROJECT_HEADER = "x-headroom-project";
|
|
86
|
+
var SESSION_TOKEN_HEADER = "x-headroom-session-token";
|
|
81
87
|
var PROXY_ENV = "HEADROOM_OPENCODE_TRANSPORT_PROXY_URL";
|
|
82
88
|
var EXCLUDE_HOSTS_ENV = "HEADROOM_OPENCODE_EXCLUDE_HOSTS";
|
|
83
89
|
var STATE_KEY = /* @__PURE__ */ Symbol.for("headroom.opencode.transport");
|
|
@@ -134,6 +140,9 @@ function injectOptionsEnv(args, optionIndex, state) {
|
|
|
134
140
|
const callback = typeof nextArgs.at(-1) === "function" ? nextArgs.pop() : void 0;
|
|
135
141
|
const existing = isOptions(nextArgs[optionIndex]) ? { ...nextArgs[optionIndex] } : {};
|
|
136
142
|
existing.env = withShimEnv(existing.env, state.proxyUrl, state.excludeHosts);
|
|
143
|
+
if (process.platform === "win32" && existing.windowsHide === void 0) {
|
|
144
|
+
existing.windowsHide = true;
|
|
145
|
+
}
|
|
137
146
|
if (isOptions(nextArgs[optionIndex])) {
|
|
138
147
|
nextArgs[optionIndex] = existing;
|
|
139
148
|
} else {
|
|
@@ -204,7 +213,10 @@ function isExcludedHost(hostname3, excludeHosts) {
|
|
|
204
213
|
const normalized = hostname3.toLowerCase().replace(/^\[|\]$/g, "");
|
|
205
214
|
return excludeHosts.some((host) => normalized === host || normalized.endsWith(`.${host}`));
|
|
206
215
|
}
|
|
207
|
-
function
|
|
216
|
+
function isLlmEndpointPath(pathname) {
|
|
217
|
+
return pathname.endsWith("/chat/completions") || pathname.endsWith("/responses") || pathname.endsWith("/messages") || pathname.endsWith(":generateContent") || pathname.endsWith(":streamGenerateContent");
|
|
218
|
+
}
|
|
219
|
+
function isRoutableUpstream(url2, proxy, excludeHosts) {
|
|
208
220
|
if (url2.protocol !== "http:" && url2.protocol !== "https:") {
|
|
209
221
|
return false;
|
|
210
222
|
}
|
|
@@ -219,6 +231,16 @@ function shouldRoute(url2, proxy, excludeHosts) {
|
|
|
219
231
|
}
|
|
220
232
|
return true;
|
|
221
233
|
}
|
|
234
|
+
function shouldRoute(url2, proxy, excludeHosts) {
|
|
235
|
+
return isRoutableUpstream(url2, proxy, excludeHosts) && isLlmEndpointPath(url2.pathname);
|
|
236
|
+
}
|
|
237
|
+
function modelBaseRoutesThroughProxy(baseUrl, proxyUrl, excludeHosts = []) {
|
|
238
|
+
try {
|
|
239
|
+
return isRoutableUpstream(new URL(baseUrl), normalizeProxyUrl(proxyUrl), excludeHosts);
|
|
240
|
+
} catch {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
222
244
|
function routedUrl(upstream, proxy) {
|
|
223
245
|
return new URL(`${upstream.pathname}${upstream.search}`, proxy.origin);
|
|
224
246
|
}
|
|
@@ -253,7 +275,7 @@ function requestUrl(input) {
|
|
|
253
275
|
}
|
|
254
276
|
return new URL(String(input));
|
|
255
277
|
}
|
|
256
|
-
function mergeFetchHeaders(input, init, upstream, originalPath = void 0, project = void 0) {
|
|
278
|
+
function mergeFetchHeaders(input, init, upstream, originalPath = void 0, project = void 0, sessionToken = void 0) {
|
|
257
279
|
const headers = new Headers(input instanceof Request ? input.headers : void 0);
|
|
258
280
|
if (init?.headers) {
|
|
259
281
|
new Headers(init.headers).forEach((value, key) => headers.set(key, value));
|
|
@@ -268,9 +290,12 @@ function mergeFetchHeaders(input, init, upstream, originalPath = void 0, project
|
|
|
268
290
|
if (project) {
|
|
269
291
|
headers.set(PROJECT_HEADER, project);
|
|
270
292
|
}
|
|
293
|
+
if (sessionToken) {
|
|
294
|
+
headers.set(SESSION_TOKEN_HEADER, sessionToken);
|
|
295
|
+
}
|
|
271
296
|
return headers;
|
|
272
297
|
}
|
|
273
|
-
function withRoutedFetchInput(input, init, proxy, project, excludeHosts) {
|
|
298
|
+
function withRoutedFetchInput(input, init, proxy, project, excludeHosts, sessionToken) {
|
|
274
299
|
const upstream = requestUrl(input);
|
|
275
300
|
if (!shouldRoute(upstream, proxy, excludeHosts)) {
|
|
276
301
|
return [input, init];
|
|
@@ -278,7 +303,7 @@ function withRoutedFetchInput(input, init, proxy, project, excludeHosts) {
|
|
|
278
303
|
const { url: nextUrl, originalPath } = routedUrlForOpenCode(upstream, proxy);
|
|
279
304
|
const nextInit = {
|
|
280
305
|
...init,
|
|
281
|
-
headers: mergeFetchHeaders(input, init, upstream, originalPath, project)
|
|
306
|
+
headers: mergeFetchHeaders(input, init, upstream, originalPath, project, sessionToken)
|
|
282
307
|
};
|
|
283
308
|
if (input instanceof Request) {
|
|
284
309
|
return [new Request(nextUrl, input), nextInit];
|
|
@@ -324,7 +349,7 @@ function urlFromRequestOptions(options) {
|
|
|
324
349
|
return void 0;
|
|
325
350
|
}
|
|
326
351
|
}
|
|
327
|
-
function headersForNodeRequest(options, upstream, originalPath, project) {
|
|
352
|
+
function headersForNodeRequest(options, upstream, originalPath, project, sessionToken) {
|
|
328
353
|
const headers = new Headers(options.headers);
|
|
329
354
|
headers.set(BASE_URL_HEADER, upstream.origin);
|
|
330
355
|
if (originalPath) {
|
|
@@ -333,6 +358,9 @@ function headersForNodeRequest(options, upstream, originalPath, project) {
|
|
|
333
358
|
if (project) {
|
|
334
359
|
headers.set(PROJECT_HEADER, project);
|
|
335
360
|
}
|
|
361
|
+
if (sessionToken) {
|
|
362
|
+
headers.set(SESSION_TOKEN_HEADER, sessionToken);
|
|
363
|
+
}
|
|
336
364
|
headers.delete("host");
|
|
337
365
|
const result = {};
|
|
338
366
|
headers.forEach((value, key) => {
|
|
@@ -340,7 +368,7 @@ function headersForNodeRequest(options, upstream, originalPath, project) {
|
|
|
340
368
|
});
|
|
341
369
|
return result;
|
|
342
370
|
}
|
|
343
|
-
function routedNodeOptions(parts, proxy, project, excludeHosts) {
|
|
371
|
+
function routedNodeOptions(parts, proxy, project, excludeHosts, sessionToken) {
|
|
344
372
|
if (!parts.url || !shouldRoute(parts.url, proxy, excludeHosts)) {
|
|
345
373
|
return void 0;
|
|
346
374
|
}
|
|
@@ -371,7 +399,7 @@ function routedNodeOptions(parts, proxy, project, excludeHosts) {
|
|
|
371
399
|
hostname: nextUrl.hostname,
|
|
372
400
|
port: nextUrl.port || void 0,
|
|
373
401
|
path: `${nextUrl.pathname}${nextUrl.search}`,
|
|
374
|
-
headers: headersForNodeRequest(parts.options, parts.url, originalPath, project)
|
|
402
|
+
headers: headersForNodeRequest(parts.options, parts.url, originalPath, project, sessionToken)
|
|
375
403
|
};
|
|
376
404
|
}
|
|
377
405
|
function wrapRequest(originalHttpRequest, originalHttpsRequest, originalRequest) {
|
|
@@ -382,7 +410,7 @@ function wrapRequest(originalHttpRequest, originalHttpsRequest, originalRequest)
|
|
|
382
410
|
}
|
|
383
411
|
const proxy = normalizeProxyUrl(state.proxyUrl);
|
|
384
412
|
const parts = splitNodeArgs(args);
|
|
385
|
-
const nextOptions = routedNodeOptions(parts, proxy, state.project, state.excludeHosts);
|
|
413
|
+
const nextOptions = routedNodeOptions(parts, proxy, state.project, state.excludeHosts, state.sessionToken);
|
|
386
414
|
if (!nextOptions) {
|
|
387
415
|
return Reflect.apply(originalRequest, this, args);
|
|
388
416
|
}
|
|
@@ -399,18 +427,8 @@ function wrapGet(request) {
|
|
|
399
427
|
};
|
|
400
428
|
}
|
|
401
429
|
function wrapHttp2Connect(originalConnect) {
|
|
402
|
-
return function headroomHttp2Connect(
|
|
403
|
-
|
|
404
|
-
if (state) {
|
|
405
|
-
const proxy = normalizeProxyUrl(state.proxyUrl);
|
|
406
|
-
const upstream = authority instanceof URL ? authority : new URL(String(authority));
|
|
407
|
-
if (shouldRoute(upstream, proxy, state.excludeHosts)) {
|
|
408
|
-
throw new Error(
|
|
409
|
-
`Headroom OpenCode wrap blocked direct HTTP/2 connection to ${upstream.origin}. Use fetch, http, or https so traffic can be routed through Headroom.`
|
|
410
|
-
);
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
return Reflect.apply(originalConnect, this, [authority, ...args]);
|
|
430
|
+
return function headroomHttp2Connect(...args) {
|
|
431
|
+
return Reflect.apply(originalConnect, this, args);
|
|
414
432
|
};
|
|
415
433
|
}
|
|
416
434
|
function installHeadroomTransport(options) {
|
|
@@ -422,6 +440,7 @@ function installHeadroomTransport(options) {
|
|
|
422
440
|
existing.project = options.project;
|
|
423
441
|
existing.excludeHosts = excludeHosts;
|
|
424
442
|
existing.debug = Boolean(options.debug);
|
|
443
|
+
existing.sessionToken = options.sessionToken;
|
|
425
444
|
installProcessEnv(options.proxyUrl, excludeHosts);
|
|
426
445
|
return () => uninstallHeadroomTransport();
|
|
427
446
|
}
|
|
@@ -431,6 +450,7 @@ function installHeadroomTransport(options) {
|
|
|
431
450
|
project: options.project,
|
|
432
451
|
excludeHosts,
|
|
433
452
|
debug: Boolean(options.debug),
|
|
453
|
+
sessionToken: options.sessionToken,
|
|
434
454
|
originalFetch: globalThis.fetch,
|
|
435
455
|
originalHttpRequest: http.request,
|
|
436
456
|
originalHttpGet: http.get,
|
|
@@ -450,7 +470,7 @@ function installHeadroomTransport(options) {
|
|
|
450
470
|
return state.originalFetch(...args);
|
|
451
471
|
}
|
|
452
472
|
const proxy = normalizeProxyUrl(current.proxyUrl);
|
|
453
|
-
const [nextInput, nextInit] = withRoutedFetchInput(args[0], args[1], proxy, current.project, current.excludeHosts);
|
|
473
|
+
const [nextInput, nextInit] = withRoutedFetchInput(args[0], args[1], proxy, current.project, current.excludeHosts, current.sessionToken);
|
|
454
474
|
return state.originalFetch(nextInput, nextInit);
|
|
455
475
|
};
|
|
456
476
|
http.request = wrapRequest(state.originalHttpRequest, state.originalHttpsRequest, state.originalHttpRequest);
|
|
@@ -12908,14 +12928,59 @@ function date4(params) {
|
|
|
12908
12928
|
config(en_default());
|
|
12909
12929
|
|
|
12910
12930
|
// src/plugin.ts
|
|
12931
|
+
var HEADROOM_PLUGIN_ID = "headroom";
|
|
12911
12932
|
function normalizeProxyUrl2(url2) {
|
|
12912
|
-
return url2
|
|
12933
|
+
return trimTrailingSlashes(url2);
|
|
12913
12934
|
}
|
|
12914
12935
|
function resolveProxyUrl(options) {
|
|
12915
12936
|
return normalizeProxyUrl2(
|
|
12916
12937
|
options?.proxyUrl ?? process.env.HEADROOM_PROXY_URL ?? process.env.HEADROOM_BASE_URL ?? getDefaultProxyUrl()
|
|
12917
12938
|
);
|
|
12918
12939
|
}
|
|
12940
|
+
function resolveSessionToken(options) {
|
|
12941
|
+
return options?.sessionToken ?? process.env.HEADROOM_OPENCODE_SESSION_TOKEN;
|
|
12942
|
+
}
|
|
12943
|
+
function resolveExcludeHosts(options) {
|
|
12944
|
+
return normalizeExcludeHosts(options?.excludeHosts ?? process.env[EXCLUDE_HOSTS_ENV] ?? "");
|
|
12945
|
+
}
|
|
12946
|
+
function headroomShellEnv(proxyUrl, project, options) {
|
|
12947
|
+
return {
|
|
12948
|
+
HEADROOM_ACTIVE: "1",
|
|
12949
|
+
HEADROOM_PROXY_URL: proxyUrl,
|
|
12950
|
+
HEADROOM_PROJECT: project,
|
|
12951
|
+
...options.backend ? { HEADROOM_BACKEND: options.backend } : {}
|
|
12952
|
+
};
|
|
12953
|
+
}
|
|
12954
|
+
function openAiWireSuffix(pkg) {
|
|
12955
|
+
if (!pkg?.startsWith("@opencode/ai/providers/")) return void 0;
|
|
12956
|
+
if (pkg === "@opencode/ai/providers/openai-compatible" || pkg.endsWith("/chat")) {
|
|
12957
|
+
return "/chat/completions";
|
|
12958
|
+
}
|
|
12959
|
+
if (pkg.endsWith("-responses") || pkg.endsWith("/responses")) return "/responses";
|
|
12960
|
+
return void 0;
|
|
12961
|
+
}
|
|
12962
|
+
function routeModelsThroughProxy(models, proxyUrl, project, excludeHosts, sessionToken) {
|
|
12963
|
+
for (const model of models.list()) {
|
|
12964
|
+
const providerID = String(model.providerID);
|
|
12965
|
+
const modelID = String(model.id);
|
|
12966
|
+
const provider = models.provider.get(providerID)?.provider;
|
|
12967
|
+
const suffix = openAiWireSuffix(model.package ?? provider?.package);
|
|
12968
|
+
const baseURL = model.settings?.baseURL ?? provider?.settings?.baseURL;
|
|
12969
|
+
if (!suffix || typeof baseURL !== "string") continue;
|
|
12970
|
+
if (!modelBaseRoutesThroughProxy(baseURL, proxyUrl, excludeHosts)) continue;
|
|
12971
|
+
const upstream = new URL(baseURL);
|
|
12972
|
+
models.update(providerID, modelID, (draft) => {
|
|
12973
|
+
draft.settings = { ...draft.settings, baseURL: `${proxyUrl}/v1` };
|
|
12974
|
+
draft.headers = {
|
|
12975
|
+
...draft.headers,
|
|
12976
|
+
[BASE_URL_HEADER]: upstream.origin,
|
|
12977
|
+
[ORIGINAL_PATH_HEADER]: `${trimTrailingSlashes(upstream.pathname)}${suffix}`,
|
|
12978
|
+
[PROJECT_HEADER]: project,
|
|
12979
|
+
...sessionToken ? { [SESSION_TOKEN_HEADER]: sessionToken } : {}
|
|
12980
|
+
};
|
|
12981
|
+
});
|
|
12982
|
+
}
|
|
12983
|
+
}
|
|
12919
12984
|
var HeadroomPlugin = async (input, options = {}) => {
|
|
12920
12985
|
const pluginOptions = options;
|
|
12921
12986
|
const proxyUrl = resolveProxyUrl(pluginOptions);
|
|
@@ -12925,7 +12990,8 @@ var HeadroomPlugin = async (input, options = {}) => {
|
|
|
12925
12990
|
proxyUrl,
|
|
12926
12991
|
project,
|
|
12927
12992
|
excludeHosts: pluginOptions.excludeHosts,
|
|
12928
|
-
debug: pluginOptions.debug
|
|
12993
|
+
debug: pluginOptions.debug,
|
|
12994
|
+
sessionToken: resolveSessionToken(pluginOptions)
|
|
12929
12995
|
});
|
|
12930
12996
|
return {
|
|
12931
12997
|
dispose: async () => {
|
|
@@ -12943,24 +13009,70 @@ var HeadroomPlugin = async (input, options = {}) => {
|
|
|
12943
13009
|
})
|
|
12944
13010
|
},
|
|
12945
13011
|
"shell.env": async (_input, output) => {
|
|
12946
|
-
output.env
|
|
12947
|
-
output.env.HEADROOM_PROXY_URL = proxyUrl;
|
|
12948
|
-
output.env.HEADROOM_PROJECT = project;
|
|
12949
|
-
if (pluginOptions.backend) {
|
|
12950
|
-
output.env.HEADROOM_BACKEND = pluginOptions.backend;
|
|
12951
|
-
}
|
|
13012
|
+
Object.assign(output.env, headroomShellEnv(proxyUrl, project, pluginOptions));
|
|
12952
13013
|
}
|
|
12953
13014
|
};
|
|
12954
13015
|
};
|
|
12955
|
-
var
|
|
13016
|
+
var headroomSetup = async (ctx) => {
|
|
13017
|
+
const pluginOptions = ctx.options;
|
|
13018
|
+
const proxyUrl = resolveProxyUrl(pluginOptions);
|
|
13019
|
+
const project = pluginOptions.project ?? ctx.location.project.id ?? ctx.location.directory;
|
|
13020
|
+
const retrieveTool = createHeadroomRetrieveTool({ proxyBaseUrl: proxyUrl });
|
|
13021
|
+
const excludeHosts = resolveExcludeHosts(pluginOptions);
|
|
13022
|
+
const sessionToken = resolveSessionToken(pluginOptions);
|
|
13023
|
+
const uninstallTransport = installHeadroomTransport({
|
|
13024
|
+
proxyUrl,
|
|
13025
|
+
project,
|
|
13026
|
+
excludeHosts,
|
|
13027
|
+
debug: pluginOptions.debug,
|
|
13028
|
+
sessionToken
|
|
13029
|
+
});
|
|
13030
|
+
try {
|
|
13031
|
+
await ctx.model.transform((models) => {
|
|
13032
|
+
routeModelsThroughProxy(models, proxyUrl, project, excludeHosts, sessionToken);
|
|
13033
|
+
});
|
|
13034
|
+
await ctx.tool.transform((editor) => {
|
|
13035
|
+
editor.add({
|
|
13036
|
+
name: retrieveTool.name,
|
|
13037
|
+
description: retrieveTool.description,
|
|
13038
|
+
input: retrieveTool.parameters,
|
|
13039
|
+
// Offer the tool directly, like OpenCode's built-ins, rather than only
|
|
13040
|
+
// through the code-mode `execute` tool.
|
|
13041
|
+
options: { codemode: false },
|
|
13042
|
+
async execute(args) {
|
|
13043
|
+
return { content: await retrieveTool.execute(args) };
|
|
13044
|
+
}
|
|
13045
|
+
});
|
|
13046
|
+
});
|
|
13047
|
+
await ctx.shell.hook("create.before", (shell) => {
|
|
13048
|
+
Object.assign(shell.env, headroomShellEnv(proxyUrl, project, pluginOptions));
|
|
13049
|
+
});
|
|
13050
|
+
} catch (error45) {
|
|
13051
|
+
uninstallTransport();
|
|
13052
|
+
throw error45;
|
|
13053
|
+
}
|
|
13054
|
+
return () => {
|
|
13055
|
+
uninstallTransport();
|
|
13056
|
+
};
|
|
13057
|
+
};
|
|
13058
|
+
var HeadroomOpenCodePlugin = {
|
|
13059
|
+
id: HEADROOM_PLUGIN_ID,
|
|
13060
|
+
server: HeadroomPlugin,
|
|
13061
|
+
setup: headroomSetup
|
|
13062
|
+
};
|
|
13063
|
+
var plugin_default = HeadroomOpenCodePlugin;
|
|
12956
13064
|
|
|
12957
13065
|
export {
|
|
12958
13066
|
setDefaultProxyUrl,
|
|
12959
13067
|
getDefaultProxyUrl,
|
|
13068
|
+
trimTrailingSlashes,
|
|
12960
13069
|
createHeadroomRetrieveTool,
|
|
12961
13070
|
compressWithHeadroom,
|
|
12962
13071
|
installHeadroomTransport,
|
|
13072
|
+
HEADROOM_PLUGIN_ID,
|
|
12963
13073
|
HeadroomPlugin,
|
|
13074
|
+
headroomSetup,
|
|
13075
|
+
HeadroomOpenCodePlugin,
|
|
12964
13076
|
plugin_default
|
|
12965
13077
|
};
|
|
12966
|
-
//# sourceMappingURL=chunk-
|
|
13078
|
+
//# sourceMappingURL=chunk-XS6Z2EJR.js.map
|