headroom-opencode 0.40.0 → 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-RFZCFX4B.js → chunk-XS6Z2EJR.js} +137 -21
- 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-RFZCFX4B.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");
|
|
@@ -210,7 +216,7 @@ function isExcludedHost(hostname3, excludeHosts) {
|
|
|
210
216
|
function isLlmEndpointPath(pathname) {
|
|
211
217
|
return pathname.endsWith("/chat/completions") || pathname.endsWith("/responses") || pathname.endsWith("/messages") || pathname.endsWith(":generateContent") || pathname.endsWith(":streamGenerateContent");
|
|
212
218
|
}
|
|
213
|
-
function
|
|
219
|
+
function isRoutableUpstream(url2, proxy, excludeHosts) {
|
|
214
220
|
if (url2.protocol !== "http:" && url2.protocol !== "https:") {
|
|
215
221
|
return false;
|
|
216
222
|
}
|
|
@@ -223,7 +229,17 @@ function shouldRoute(url2, proxy, excludeHosts) {
|
|
|
223
229
|
if (isExcludedHost(url2.hostname, excludeHosts)) {
|
|
224
230
|
return false;
|
|
225
231
|
}
|
|
226
|
-
return
|
|
232
|
+
return true;
|
|
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
|
+
}
|
|
227
243
|
}
|
|
228
244
|
function routedUrl(upstream, proxy) {
|
|
229
245
|
return new URL(`${upstream.pathname}${upstream.search}`, proxy.origin);
|
|
@@ -259,7 +275,7 @@ function requestUrl(input) {
|
|
|
259
275
|
}
|
|
260
276
|
return new URL(String(input));
|
|
261
277
|
}
|
|
262
|
-
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) {
|
|
263
279
|
const headers = new Headers(input instanceof Request ? input.headers : void 0);
|
|
264
280
|
if (init?.headers) {
|
|
265
281
|
new Headers(init.headers).forEach((value, key) => headers.set(key, value));
|
|
@@ -274,9 +290,12 @@ function mergeFetchHeaders(input, init, upstream, originalPath = void 0, project
|
|
|
274
290
|
if (project) {
|
|
275
291
|
headers.set(PROJECT_HEADER, project);
|
|
276
292
|
}
|
|
293
|
+
if (sessionToken) {
|
|
294
|
+
headers.set(SESSION_TOKEN_HEADER, sessionToken);
|
|
295
|
+
}
|
|
277
296
|
return headers;
|
|
278
297
|
}
|
|
279
|
-
function withRoutedFetchInput(input, init, proxy, project, excludeHosts) {
|
|
298
|
+
function withRoutedFetchInput(input, init, proxy, project, excludeHosts, sessionToken) {
|
|
280
299
|
const upstream = requestUrl(input);
|
|
281
300
|
if (!shouldRoute(upstream, proxy, excludeHosts)) {
|
|
282
301
|
return [input, init];
|
|
@@ -284,7 +303,7 @@ function withRoutedFetchInput(input, init, proxy, project, excludeHosts) {
|
|
|
284
303
|
const { url: nextUrl, originalPath } = routedUrlForOpenCode(upstream, proxy);
|
|
285
304
|
const nextInit = {
|
|
286
305
|
...init,
|
|
287
|
-
headers: mergeFetchHeaders(input, init, upstream, originalPath, project)
|
|
306
|
+
headers: mergeFetchHeaders(input, init, upstream, originalPath, project, sessionToken)
|
|
288
307
|
};
|
|
289
308
|
if (input instanceof Request) {
|
|
290
309
|
return [new Request(nextUrl, input), nextInit];
|
|
@@ -330,7 +349,7 @@ function urlFromRequestOptions(options) {
|
|
|
330
349
|
return void 0;
|
|
331
350
|
}
|
|
332
351
|
}
|
|
333
|
-
function headersForNodeRequest(options, upstream, originalPath, project) {
|
|
352
|
+
function headersForNodeRequest(options, upstream, originalPath, project, sessionToken) {
|
|
334
353
|
const headers = new Headers(options.headers);
|
|
335
354
|
headers.set(BASE_URL_HEADER, upstream.origin);
|
|
336
355
|
if (originalPath) {
|
|
@@ -339,6 +358,9 @@ function headersForNodeRequest(options, upstream, originalPath, project) {
|
|
|
339
358
|
if (project) {
|
|
340
359
|
headers.set(PROJECT_HEADER, project);
|
|
341
360
|
}
|
|
361
|
+
if (sessionToken) {
|
|
362
|
+
headers.set(SESSION_TOKEN_HEADER, sessionToken);
|
|
363
|
+
}
|
|
342
364
|
headers.delete("host");
|
|
343
365
|
const result = {};
|
|
344
366
|
headers.forEach((value, key) => {
|
|
@@ -346,7 +368,7 @@ function headersForNodeRequest(options, upstream, originalPath, project) {
|
|
|
346
368
|
});
|
|
347
369
|
return result;
|
|
348
370
|
}
|
|
349
|
-
function routedNodeOptions(parts, proxy, project, excludeHosts) {
|
|
371
|
+
function routedNodeOptions(parts, proxy, project, excludeHosts, sessionToken) {
|
|
350
372
|
if (!parts.url || !shouldRoute(parts.url, proxy, excludeHosts)) {
|
|
351
373
|
return void 0;
|
|
352
374
|
}
|
|
@@ -377,7 +399,7 @@ function routedNodeOptions(parts, proxy, project, excludeHosts) {
|
|
|
377
399
|
hostname: nextUrl.hostname,
|
|
378
400
|
port: nextUrl.port || void 0,
|
|
379
401
|
path: `${nextUrl.pathname}${nextUrl.search}`,
|
|
380
|
-
headers: headersForNodeRequest(parts.options, parts.url, originalPath, project)
|
|
402
|
+
headers: headersForNodeRequest(parts.options, parts.url, originalPath, project, sessionToken)
|
|
381
403
|
};
|
|
382
404
|
}
|
|
383
405
|
function wrapRequest(originalHttpRequest, originalHttpsRequest, originalRequest) {
|
|
@@ -388,7 +410,7 @@ function wrapRequest(originalHttpRequest, originalHttpsRequest, originalRequest)
|
|
|
388
410
|
}
|
|
389
411
|
const proxy = normalizeProxyUrl(state.proxyUrl);
|
|
390
412
|
const parts = splitNodeArgs(args);
|
|
391
|
-
const nextOptions = routedNodeOptions(parts, proxy, state.project, state.excludeHosts);
|
|
413
|
+
const nextOptions = routedNodeOptions(parts, proxy, state.project, state.excludeHosts, state.sessionToken);
|
|
392
414
|
if (!nextOptions) {
|
|
393
415
|
return Reflect.apply(originalRequest, this, args);
|
|
394
416
|
}
|
|
@@ -418,6 +440,7 @@ function installHeadroomTransport(options) {
|
|
|
418
440
|
existing.project = options.project;
|
|
419
441
|
existing.excludeHosts = excludeHosts;
|
|
420
442
|
existing.debug = Boolean(options.debug);
|
|
443
|
+
existing.sessionToken = options.sessionToken;
|
|
421
444
|
installProcessEnv(options.proxyUrl, excludeHosts);
|
|
422
445
|
return () => uninstallHeadroomTransport();
|
|
423
446
|
}
|
|
@@ -427,6 +450,7 @@ function installHeadroomTransport(options) {
|
|
|
427
450
|
project: options.project,
|
|
428
451
|
excludeHosts,
|
|
429
452
|
debug: Boolean(options.debug),
|
|
453
|
+
sessionToken: options.sessionToken,
|
|
430
454
|
originalFetch: globalThis.fetch,
|
|
431
455
|
originalHttpRequest: http.request,
|
|
432
456
|
originalHttpGet: http.get,
|
|
@@ -446,7 +470,7 @@ function installHeadroomTransport(options) {
|
|
|
446
470
|
return state.originalFetch(...args);
|
|
447
471
|
}
|
|
448
472
|
const proxy = normalizeProxyUrl(current.proxyUrl);
|
|
449
|
-
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);
|
|
450
474
|
return state.originalFetch(nextInput, nextInit);
|
|
451
475
|
};
|
|
452
476
|
http.request = wrapRequest(state.originalHttpRequest, state.originalHttpsRequest, state.originalHttpRequest);
|
|
@@ -12904,14 +12928,59 @@ function date4(params) {
|
|
|
12904
12928
|
config(en_default());
|
|
12905
12929
|
|
|
12906
12930
|
// src/plugin.ts
|
|
12931
|
+
var HEADROOM_PLUGIN_ID = "headroom";
|
|
12907
12932
|
function normalizeProxyUrl2(url2) {
|
|
12908
|
-
return url2
|
|
12933
|
+
return trimTrailingSlashes(url2);
|
|
12909
12934
|
}
|
|
12910
12935
|
function resolveProxyUrl(options) {
|
|
12911
12936
|
return normalizeProxyUrl2(
|
|
12912
12937
|
options?.proxyUrl ?? process.env.HEADROOM_PROXY_URL ?? process.env.HEADROOM_BASE_URL ?? getDefaultProxyUrl()
|
|
12913
12938
|
);
|
|
12914
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
|
+
}
|
|
12915
12984
|
var HeadroomPlugin = async (input, options = {}) => {
|
|
12916
12985
|
const pluginOptions = options;
|
|
12917
12986
|
const proxyUrl = resolveProxyUrl(pluginOptions);
|
|
@@ -12921,7 +12990,8 @@ var HeadroomPlugin = async (input, options = {}) => {
|
|
|
12921
12990
|
proxyUrl,
|
|
12922
12991
|
project,
|
|
12923
12992
|
excludeHosts: pluginOptions.excludeHosts,
|
|
12924
|
-
debug: pluginOptions.debug
|
|
12993
|
+
debug: pluginOptions.debug,
|
|
12994
|
+
sessionToken: resolveSessionToken(pluginOptions)
|
|
12925
12995
|
});
|
|
12926
12996
|
return {
|
|
12927
12997
|
dispose: async () => {
|
|
@@ -12939,24 +13009,70 @@ var HeadroomPlugin = async (input, options = {}) => {
|
|
|
12939
13009
|
})
|
|
12940
13010
|
},
|
|
12941
13011
|
"shell.env": async (_input, output) => {
|
|
12942
|
-
output.env
|
|
12943
|
-
output.env.HEADROOM_PROXY_URL = proxyUrl;
|
|
12944
|
-
output.env.HEADROOM_PROJECT = project;
|
|
12945
|
-
if (pluginOptions.backend) {
|
|
12946
|
-
output.env.HEADROOM_BACKEND = pluginOptions.backend;
|
|
12947
|
-
}
|
|
13012
|
+
Object.assign(output.env, headroomShellEnv(proxyUrl, project, pluginOptions));
|
|
12948
13013
|
}
|
|
12949
13014
|
};
|
|
12950
13015
|
};
|
|
12951
|
-
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;
|
|
12952
13064
|
|
|
12953
13065
|
export {
|
|
12954
13066
|
setDefaultProxyUrl,
|
|
12955
13067
|
getDefaultProxyUrl,
|
|
13068
|
+
trimTrailingSlashes,
|
|
12956
13069
|
createHeadroomRetrieveTool,
|
|
12957
13070
|
compressWithHeadroom,
|
|
12958
13071
|
installHeadroomTransport,
|
|
13072
|
+
HEADROOM_PLUGIN_ID,
|
|
12959
13073
|
HeadroomPlugin,
|
|
13074
|
+
headroomSetup,
|
|
13075
|
+
HeadroomOpenCodePlugin,
|
|
12960
13076
|
plugin_default
|
|
12961
13077
|
};
|
|
12962
|
-
//# sourceMappingURL=chunk-
|
|
13078
|
+
//# sourceMappingURL=chunk-XS6Z2EJR.js.map
|