codex-copilot-dx 0.6.1 → 0.6.3
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 +42 -21
- package/bin/cli.mjs +12 -4
- package/bin/codex-copilot-dx.mjs +2 -1
- package/package.json +1 -1
- package/scripts/benchmark.mjs +95 -0
- package/src/adapter.mjs +5 -0
- package/src/auth.mjs +5 -0
- package/src/cli-auth.mjs +43 -12
- package/src/cli-options.mjs +141 -59
- package/src/cli-status.mjs +40 -3
- package/src/copilot-client.mjs +5 -0
- package/src/doctor.mjs +56 -3
- package/src/http-transport.mjs +1 -1
- package/src/observability.mjs +4 -4
- package/src/pm-studio-relay.mjs +14 -48
- package/src/pm-studio-status.mjs +130 -0
- package/src/profile-model-runtime.mjs +3 -2
- package/src/profile-routing.mjs +74 -0
- package/src/profile-runtime.mjs +13 -0
- package/src/response-history.mjs +4 -0
- package/src/responses-bridge.mjs +12 -6
- package/src/responses-byte-budget.mjs +63 -5
- package/src/responses-handler.mjs +60 -16
- package/src/responses-image-pressure.mjs +163 -0
- package/src/responses-proxy.mjs +7 -4
- package/src/responses-request.mjs +9 -1
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import {
|
|
2
|
+
responsesHistoricalImageStats,
|
|
3
|
+
trimResponsesHistoricalImages,
|
|
4
|
+
} from "./responses-byte-budget.mjs";
|
|
5
|
+
|
|
6
|
+
const MIB = 1024 * 1024;
|
|
7
|
+
|
|
8
|
+
export const DEFAULT_RESPONSES_IMAGE_PRESSURE_POLICY = Object.freeze({
|
|
9
|
+
triggerHistoricalImages: 24,
|
|
10
|
+
triggerBodyBytes: 18 * MIB,
|
|
11
|
+
pressureHistoricalImages: 16,
|
|
12
|
+
pressureBodyBytes: 16 * MIB,
|
|
13
|
+
recoveryHistoricalImages: 8,
|
|
14
|
+
recoveryBodyBytes: 10 * MIB,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
function normalizedPolicy(policy = {}) {
|
|
18
|
+
return { ...DEFAULT_RESPONSES_IMAGE_PRESSURE_POLICY, ...policy };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function bodyPayload(body) {
|
|
22
|
+
const bodyText = JSON.stringify(body);
|
|
23
|
+
return { bodyText, bodyBytes: Buffer.byteLength(bodyText) };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function applyResponsesImagePressure(reqContext, {
|
|
27
|
+
mode = "normal",
|
|
28
|
+
policy: policyOverrides,
|
|
29
|
+
} = {}) {
|
|
30
|
+
const policy = normalizedPolicy(policyOverrides);
|
|
31
|
+
const body = reqContext?.body;
|
|
32
|
+
const currentInputStart = Number.isFinite(reqContext?.currentInputStart)
|
|
33
|
+
? reqContext.currentInputStart
|
|
34
|
+
: 0;
|
|
35
|
+
const initial = bodyPayload(body);
|
|
36
|
+
const initialImages = responsesHistoricalImageStats(body?.input, currentInputStart);
|
|
37
|
+
const pressureEligible = initialImages.historicalImages > 0 && (
|
|
38
|
+
initialImages.historicalImages > policy.triggerHistoricalImages
|
|
39
|
+
|| initial.bodyBytes > policy.triggerBodyBytes
|
|
40
|
+
);
|
|
41
|
+
const recovery = mode === "recovery";
|
|
42
|
+
const maxHistoricalImages = recovery
|
|
43
|
+
? policy.recoveryHistoricalImages
|
|
44
|
+
: policy.pressureHistoricalImages;
|
|
45
|
+
const targetBytes = recovery ? policy.recoveryBodyBytes : policy.pressureBodyBytes;
|
|
46
|
+
const shouldAdapt = initialImages.historicalImages > 0 && (recovery
|
|
47
|
+
? initialImages.historicalImages > maxHistoricalImages || initial.bodyBytes > targetBytes
|
|
48
|
+
: pressureEligible);
|
|
49
|
+
|
|
50
|
+
if (!shouldAdapt) {
|
|
51
|
+
return {
|
|
52
|
+
mode: "normal",
|
|
53
|
+
pressureEligible,
|
|
54
|
+
adapted: false,
|
|
55
|
+
imagesOmitted: 0,
|
|
56
|
+
initialBodyBytes: initial.bodyBytes,
|
|
57
|
+
bodyBytes: initial.bodyBytes,
|
|
58
|
+
initialHistoricalImages: initialImages.historicalImages,
|
|
59
|
+
historicalImages: initialImages.historicalImages,
|
|
60
|
+
currentImages: initialImages.currentImages,
|
|
61
|
+
overBudget: false,
|
|
62
|
+
overImageBudget: false,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const trimmed = trimResponsesHistoricalImages(body, {
|
|
67
|
+
currentInputStart,
|
|
68
|
+
maxHistoricalImages,
|
|
69
|
+
targetBytes,
|
|
70
|
+
initialBodyText: initial.bodyText,
|
|
71
|
+
initialBodyBytes: initial.bodyBytes,
|
|
72
|
+
});
|
|
73
|
+
return {
|
|
74
|
+
mode: recovery ? "recovery" : "pressure",
|
|
75
|
+
pressureEligible: pressureEligible || recovery,
|
|
76
|
+
initialBodyBytes: initial.bodyBytes,
|
|
77
|
+
initialHistoricalImages: initialImages.historicalImages,
|
|
78
|
+
...trimmed,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function createResponsesImagePressureController({
|
|
83
|
+
now = Date.now,
|
|
84
|
+
maxEntries = 256,
|
|
85
|
+
recoveryTtlMs = 10 * 60 * 1000,
|
|
86
|
+
successesToClear = 2,
|
|
87
|
+
policy: policyOverrides,
|
|
88
|
+
} = {}) {
|
|
89
|
+
const policy = normalizedPolicy(policyOverrides);
|
|
90
|
+
const recovery = new Map();
|
|
91
|
+
const counters = {
|
|
92
|
+
adaptedRequests: 0,
|
|
93
|
+
imagesOmitted: 0,
|
|
94
|
+
recoveryActivations: 0,
|
|
95
|
+
timeoutsRecorded: 0,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const prune = () => {
|
|
99
|
+
const timestamp = now();
|
|
100
|
+
for (const [rootId, state] of recovery) {
|
|
101
|
+
if (state.expiresAt <= timestamp) recovery.delete(rootId);
|
|
102
|
+
}
|
|
103
|
+
while (recovery.size > maxEntries) recovery.delete(recovery.keys().next().value);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const modeFor = (rootId) => {
|
|
107
|
+
prune();
|
|
108
|
+
return rootId && recovery.has(rootId) ? "recovery" : "normal";
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
return Object.freeze({
|
|
112
|
+
apply(reqContext) {
|
|
113
|
+
const result = applyResponsesImagePressure(reqContext, {
|
|
114
|
+
mode: modeFor(reqContext?.historyRootId),
|
|
115
|
+
policy,
|
|
116
|
+
});
|
|
117
|
+
if (result.adapted) {
|
|
118
|
+
counters.adaptedRequests += 1;
|
|
119
|
+
counters.imagesOmitted += result.imagesOmitted;
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
},
|
|
123
|
+
markTimeout(rootId, { eligible = false } = {}) {
|
|
124
|
+
if (!rootId || !eligible) return false;
|
|
125
|
+
prune();
|
|
126
|
+
const existing = recovery.get(rootId);
|
|
127
|
+
recovery.delete(rootId);
|
|
128
|
+
recovery.set(rootId, { expiresAt: now() + recoveryTtlMs, successes: 0 });
|
|
129
|
+
counters.timeoutsRecorded += 1;
|
|
130
|
+
if (!existing) counters.recoveryActivations += 1;
|
|
131
|
+
prune();
|
|
132
|
+
return true;
|
|
133
|
+
},
|
|
134
|
+
markSuccess(rootId) {
|
|
135
|
+
if (!rootId) return false;
|
|
136
|
+
prune();
|
|
137
|
+
const state = recovery.get(rootId);
|
|
138
|
+
if (!state) return false;
|
|
139
|
+
state.successes += 1;
|
|
140
|
+
if (state.successes >= successesToClear) {
|
|
141
|
+
recovery.delete(rootId);
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
return false;
|
|
145
|
+
},
|
|
146
|
+
clear(rootId) {
|
|
147
|
+
return rootId ? recovery.delete(rootId) : false;
|
|
148
|
+
},
|
|
149
|
+
snapshot() {
|
|
150
|
+
prune();
|
|
151
|
+
return {
|
|
152
|
+
active_recovery_trees: recovery.size,
|
|
153
|
+
adapted_requests: counters.adaptedRequests,
|
|
154
|
+
historical_images_omitted: counters.imagesOmitted,
|
|
155
|
+
recovery_activations: counters.recoveryActivations,
|
|
156
|
+
timeouts_recorded: counters.timeoutsRecorded,
|
|
157
|
+
recovery_ttl_ms: recoveryTtlMs,
|
|
158
|
+
pressure_image_limit: policy.pressureHistoricalImages,
|
|
159
|
+
recovery_image_limit: policy.recoveryHistoricalImages,
|
|
160
|
+
};
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
}
|
package/src/responses-proxy.mjs
CHANGED
|
@@ -126,7 +126,7 @@ export async function proxyCopilotResponses(reqContext, req, res, upstream = cop
|
|
|
126
126
|
reqContext = opened.reqContext;
|
|
127
127
|
if (errorText !== undefined) {
|
|
128
128
|
sendUpstreamError(res, resp, errorText);
|
|
129
|
-
return;
|
|
129
|
+
return { successful: false, compacted: false };
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
if (reqContext.body.stream) {
|
|
@@ -158,7 +158,7 @@ export async function proxyCopilotResponses(reqContext, req, res, upstream = cop
|
|
|
158
158
|
if (!streamState.sawTerminal) throw incompleteUpstreamStream("a terminal Responses event");
|
|
159
159
|
storeCompletedResponse(reqContext, streamState.completed);
|
|
160
160
|
res.end();
|
|
161
|
-
return;
|
|
161
|
+
return { successful: Boolean(streamState.completed), compacted: false };
|
|
162
162
|
}
|
|
163
163
|
options.abort?.setTimeout(options.streamIdleTimeoutMs, "stream_idle_timeout");
|
|
164
164
|
buffer += decoder.decode(value, { stream: true });
|
|
@@ -170,12 +170,13 @@ export async function proxyCopilotResponses(reqContext, req, res, upstream = cop
|
|
|
170
170
|
if (streamState.sawTerminal) {
|
|
171
171
|
storeCompletedResponse(reqContext, streamState.completed);
|
|
172
172
|
res.end();
|
|
173
|
-
return;
|
|
173
|
+
return { successful: Boolean(streamState.completed), compacted: false };
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
176
|
} catch (e) {
|
|
177
177
|
logRequestFailure("Responses", e, options.abort);
|
|
178
178
|
await endStreamWithError(res, "responses", e, options.abort);
|
|
179
|
+
return { successful: false, compacted: false };
|
|
179
180
|
} finally {
|
|
180
181
|
await reader.cancel().catch(() => {});
|
|
181
182
|
reader.releaseLock();
|
|
@@ -199,7 +200,7 @@ export async function proxyCopilotResponses(reqContext, req, res, upstream = cop
|
|
|
199
200
|
contentType: "application/json",
|
|
200
201
|
}));
|
|
201
202
|
res.end(JSON.stringify(response));
|
|
202
|
-
return;
|
|
203
|
+
return { successful: true, compacted: true };
|
|
203
204
|
}
|
|
204
205
|
res.writeHead(resp.status, safeUpstreamResponseHeaders(resp.headers, {
|
|
205
206
|
contentType: "application/json",
|
|
@@ -216,7 +217,9 @@ export async function proxyCopilotResponses(reqContext, req, res, upstream = cop
|
|
|
216
217
|
response,
|
|
217
218
|
event: response,
|
|
218
219
|
});
|
|
220
|
+
return { successful: true, compacted: false };
|
|
219
221
|
} catch {}
|
|
220
222
|
}
|
|
223
|
+
return { successful: false, compacted: false };
|
|
221
224
|
}
|
|
222
225
|
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { responses as copilotResponses } from "./copilot.mjs";
|
|
2
2
|
import { httpError } from "./http-transport.mjs";
|
|
3
3
|
import { debugLog } from "./log.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
materializeResponseHistory,
|
|
6
|
+
rememberResponseHistoryNode,
|
|
7
|
+
responseHistoryRootId,
|
|
8
|
+
} from "./response-history.mjs";
|
|
5
9
|
import { enforceResponsesImageLimit } from "./responses-image-limit.mjs";
|
|
6
10
|
import { status } from "./status.mjs";
|
|
7
11
|
|
|
@@ -157,6 +161,7 @@ export async function openCopilotResponse(reqContext, upstream = copilotResponse
|
|
|
157
161
|
const resp = await upstream(reqContext.body, {
|
|
158
162
|
signal: options.signal,
|
|
159
163
|
currentInputStart: reqContext.currentInputStart,
|
|
164
|
+
onUpstreamStart: options.onUpstreamStart,
|
|
160
165
|
payloadPrepared,
|
|
161
166
|
});
|
|
162
167
|
payloadPrepared = true;
|
|
@@ -198,9 +203,11 @@ export function prepareResponsesRequest(reqBody, { mutate = false } = {}) {
|
|
|
198
203
|
);
|
|
199
204
|
const previousId = body.previous_response_id;
|
|
200
205
|
let historyItems = [];
|
|
206
|
+
let historyRootId = null;
|
|
201
207
|
|
|
202
208
|
if (previousId !== undefined && previousId !== null) {
|
|
203
209
|
historyItems = materializeResponseHistory(previousId);
|
|
210
|
+
historyRootId = responseHistoryRootId(previousId);
|
|
204
211
|
body.input = [...historyItems, ...currentInputItems];
|
|
205
212
|
} else {
|
|
206
213
|
body.input = currentInputItems;
|
|
@@ -232,6 +239,7 @@ export function prepareResponsesRequest(reqBody, { mutate = false } = {}) {
|
|
|
232
239
|
inputItems: body.input,
|
|
233
240
|
currentInputStart: retainedCurrentInputStart < 0 ? body.input.length : retainedCurrentInputStart,
|
|
234
241
|
historyParentId: previousId ?? null,
|
|
242
|
+
historyRootId,
|
|
235
243
|
historyInputItems,
|
|
236
244
|
takeHistoryOwnership: mutate,
|
|
237
245
|
};
|