codex-copilot-dx 0.6.13 → 0.6.15
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 +9 -6
- package/package.json +1 -1
- package/scripts/benchmark.mjs +74 -0
- package/src/adapter.mjs +6 -2
- package/src/anthropic-handler.mjs +38 -2
- package/src/anthropic.mjs +77 -24
- package/src/config.mjs +38 -3
- package/src/copilot-responses-compat.mjs +73 -0
- package/src/copilot-responses-policy.mjs +78 -0
- package/src/doctor.mjs +1 -2
- package/src/model-cache.mjs +36 -6
- package/src/observability.mjs +13 -1
- package/src/pm-studio-relay.mjs +6 -3
- package/src/profile-model-runtime.mjs +87 -13
- package/src/profile-routing.mjs +45 -7
- package/src/response-history.mjs +20 -3
- package/src/responses-bridge.mjs +44 -7
- package/src/responses-compaction.mjs +1 -50
- package/src/responses-handler.mjs +42 -9
- package/src/responses-proxy.mjs +118 -36
- package/src/responses-request.mjs +98 -105
- package/src/route-plan.mjs +51 -0
- package/src/startup.mjs +8 -2
- package/src/stream.mjs +27 -13
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
const DISPOSITIONS = new Set(["native", "relay", "reject"]);
|
|
4
|
+
const MAX_AFFINITY_MODEL_BYTES = 512;
|
|
5
|
+
|
|
6
|
+
function requiredString(value, name) {
|
|
7
|
+
const normalized = String(value || "").trim();
|
|
8
|
+
if (!normalized) throw new Error(`Route plan ${name} is required`);
|
|
9
|
+
return normalized;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function createRoutePlan({
|
|
13
|
+
disposition = "relay",
|
|
14
|
+
model,
|
|
15
|
+
origin,
|
|
16
|
+
profile,
|
|
17
|
+
protocol,
|
|
18
|
+
surface,
|
|
19
|
+
} = {}) {
|
|
20
|
+
if (!DISPOSITIONS.has(disposition)) {
|
|
21
|
+
throw new Error(`Unsupported route disposition: ${disposition}`);
|
|
22
|
+
}
|
|
23
|
+
return Object.freeze({
|
|
24
|
+
disposition,
|
|
25
|
+
origin: requiredString(origin, "origin"),
|
|
26
|
+
profile: requiredString(profile, "profile"),
|
|
27
|
+
protocol: requiredString(protocol, "protocol"),
|
|
28
|
+
model: requiredString(model, "model"),
|
|
29
|
+
surface: requiredString(surface, "surface"),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function routePlanAffinity(plan) {
|
|
34
|
+
if (!plan || typeof plan !== "object") return null;
|
|
35
|
+
const { origin, profile, protocol, model } = plan;
|
|
36
|
+
if (![origin, profile, protocol, model].every((value) => typeof value === "string" && value.length > 0)) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const boundedModel = Buffer.byteLength(model) <= MAX_AFFINITY_MODEL_BYTES
|
|
40
|
+
? model
|
|
41
|
+
: `sha256:${createHash("sha256").update(model).digest("hex")}`;
|
|
42
|
+
return Object.freeze({ origin, profile, protocol, model: boundedModel });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function sameRoutePlanAffinity(left, right) {
|
|
46
|
+
return Boolean(left && right)
|
|
47
|
+
&& left.origin === right.origin
|
|
48
|
+
&& left.profile === right.profile
|
|
49
|
+
&& left.protocol === right.protocol
|
|
50
|
+
&& left.model === right.model;
|
|
51
|
+
}
|
package/src/startup.mjs
CHANGED
|
@@ -2,9 +2,15 @@ export async function initializeModelRegistry({
|
|
|
2
2
|
loadCached,
|
|
3
3
|
currentModelDefs,
|
|
4
4
|
refresh,
|
|
5
|
+
onBackgroundError = () => {},
|
|
5
6
|
}) {
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
const cached = loadCached();
|
|
8
|
+
const loaded = cached === true || cached?.loaded === true;
|
|
9
|
+
if (loaded) {
|
|
10
|
+
const backgroundRefresh = cached?.stale === true
|
|
11
|
+
? runInBackground(refresh, onBackgroundError)
|
|
12
|
+
: null;
|
|
13
|
+
return { modelDefs: currentModelDefs(), source: "cache", backgroundRefresh };
|
|
8
14
|
}
|
|
9
15
|
|
|
10
16
|
return { modelDefs: await refresh(), source: "live", backgroundRefresh: null };
|
package/src/stream.mjs
CHANGED
|
@@ -4,33 +4,47 @@ import { loadRuntimeConfig } from "./runtime-config.mjs";
|
|
|
4
4
|
|
|
5
5
|
const MAX_SSE_BUFFER_BYTES = loadRuntimeConfig().maxSseBufferBytes;
|
|
6
6
|
|
|
7
|
-
function
|
|
8
|
-
if (
|
|
7
|
+
function appendLineFragment(parts, fragment, currentBytes, maxBufferBytes) {
|
|
8
|
+
if (!fragment) return currentBytes;
|
|
9
|
+
const nextBytes = currentBytes + Buffer.byteLength(fragment);
|
|
10
|
+
if (nextBytes > maxBufferBytes) {
|
|
9
11
|
throw new Error(`Upstream SSE buffer exceeds ${maxBufferBytes} bytes`);
|
|
10
12
|
}
|
|
13
|
+
parts.push(fragment);
|
|
14
|
+
return nextBytes;
|
|
11
15
|
}
|
|
12
16
|
|
|
13
17
|
export async function* webStreamLines(response, { onChunk, maxBufferBytes = MAX_SSE_BUFFER_BYTES } = {}) {
|
|
14
18
|
const reader = response.body.getReader();
|
|
15
19
|
const decoder = new TextDecoder();
|
|
16
|
-
let
|
|
20
|
+
let lineParts = [];
|
|
21
|
+
let lineBytes = 0;
|
|
17
22
|
try {
|
|
18
23
|
while (true) {
|
|
19
24
|
const { done, value } = await reader.read();
|
|
20
25
|
if (done) break;
|
|
21
26
|
onChunk?.(value);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const decoded = decoder.decode(value, { stream: true });
|
|
28
|
+
let start = 0;
|
|
29
|
+
while (start < decoded.length) {
|
|
30
|
+
const newline = decoded.indexOf("\n", start);
|
|
31
|
+
if (newline === -1) {
|
|
32
|
+
lineBytes = appendLineFragment(lineParts, decoded.slice(start), lineBytes, maxBufferBytes);
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
lineBytes = appendLineFragment(lineParts, decoded.slice(start, newline), lineBytes, maxBufferBytes);
|
|
36
|
+
const line = lineParts.length > 1 ? lineParts.join("") : (lineParts[0] || "");
|
|
37
|
+
yield line.endsWith("\r") ? line.slice(0, -1) : line;
|
|
38
|
+
lineParts = [];
|
|
39
|
+
lineBytes = 0;
|
|
40
|
+
start = newline + 1;
|
|
29
41
|
}
|
|
30
42
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
43
|
+
lineBytes = appendLineFragment(lineParts, decoder.decode(), lineBytes, maxBufferBytes);
|
|
44
|
+
if (lineParts.length > 0) {
|
|
45
|
+
const line = lineParts.length > 1 ? lineParts.join("") : lineParts[0];
|
|
46
|
+
yield line.endsWith("\r") ? line.slice(0, -1) : line;
|
|
47
|
+
}
|
|
34
48
|
} finally {
|
|
35
49
|
await reader.cancel().catch(() => {});
|
|
36
50
|
reader.releaseLock();
|