opencodekit 0.18.24 → 0.18.25
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/dist/index.js +1 -1
- package/dist/template/.opencode/memory.db +0 -0
- package/dist/template/.opencode/memory.db-shm +0 -0
- package/dist/template/.opencode/memory.db-wal +0 -0
- package/dist/template/.opencode/plugin/copilot-auth.ts +111 -0
- package/dist/template/.opencode/plugin/lib/memory-hooks.ts +19 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -921,6 +921,7 @@ export const CopilotAuthPlugin: Plugin = async ({ client: sdk }) => {
|
|
|
921
921
|
let fallbacksUsed = 0;
|
|
922
922
|
let attempt = 0;
|
|
923
923
|
let recoveryCyclesUsed = 0;
|
|
924
|
+
let attempted400Recovery = false;
|
|
924
925
|
|
|
925
926
|
while (attempt <= RATE_LIMIT_CONFIG.maxRetries) {
|
|
926
927
|
try {
|
|
@@ -1067,6 +1068,116 @@ export const CopilotAuthPlugin: Plugin = async ({ client: sdk }) => {
|
|
|
1067
1068
|
);
|
|
1068
1069
|
}
|
|
1069
1070
|
|
|
1071
|
+
// Handle 400 Bad Request with auto-recovery
|
|
1072
|
+
if (response.status === 400 && !attempted400Recovery) {
|
|
1073
|
+
let errorDetail = "Bad Request";
|
|
1074
|
+
try {
|
|
1075
|
+
const clonedResponse = response.clone();
|
|
1076
|
+
const errorBody = await clonedResponse.json();
|
|
1077
|
+
errorDetail =
|
|
1078
|
+
errorBody?.error?.message ||
|
|
1079
|
+
errorBody?.message ||
|
|
1080
|
+
"Bad Request";
|
|
1081
|
+
} catch {}
|
|
1082
|
+
|
|
1083
|
+
log(
|
|
1084
|
+
"warn",
|
|
1085
|
+
`[400-RECOVERY] Bad Request from Copilot API`,
|
|
1086
|
+
{
|
|
1087
|
+
model: currentModel,
|
|
1088
|
+
error_detail: errorDetail,
|
|
1089
|
+
attempt,
|
|
1090
|
+
},
|
|
1091
|
+
);
|
|
1092
|
+
|
|
1093
|
+
// Check for recoverable 400 causes
|
|
1094
|
+
const isThinkingBlockError =
|
|
1095
|
+
/thinking.?block|invalid.*signature|reasoning.*invalid/i.test(
|
|
1096
|
+
errorDetail,
|
|
1097
|
+
);
|
|
1098
|
+
const isIdError =
|
|
1099
|
+
/invalid.*\bid\b|item.*\bid\b|unknown.*\bid\b|malformed.*\bid\b/i.test(
|
|
1100
|
+
errorDetail,
|
|
1101
|
+
);
|
|
1102
|
+
|
|
1103
|
+
if (isThinkingBlockError || isIdError) {
|
|
1104
|
+
let bodyObj: any;
|
|
1105
|
+
try {
|
|
1106
|
+
bodyObj =
|
|
1107
|
+
typeof activeFinalInit.body === "string"
|
|
1108
|
+
? JSON.parse(activeFinalInit.body)
|
|
1109
|
+
: activeFinalInit.body;
|
|
1110
|
+
} catch {
|
|
1111
|
+
// Can't parse body — not recoverable
|
|
1112
|
+
log(
|
|
1113
|
+
"warn",
|
|
1114
|
+
`[400-RECOVERY] Cannot parse request body, giving up`,
|
|
1115
|
+
);
|
|
1116
|
+
return response;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
// Cancel original response body only after confirming we can recover
|
|
1120
|
+
try {
|
|
1121
|
+
await response.body?.cancel();
|
|
1122
|
+
} catch {}
|
|
1123
|
+
|
|
1124
|
+
if (isThinkingBlockError && bodyObj?.messages) {
|
|
1125
|
+
// Strip ALL thinking/reasoning content aggressively
|
|
1126
|
+
bodyObj.messages = bodyObj.messages.map(
|
|
1127
|
+
(msg: any) => {
|
|
1128
|
+
if (msg.role !== "assistant") return msg;
|
|
1129
|
+
const {
|
|
1130
|
+
reasoning_text: _rt,
|
|
1131
|
+
reasoning_opaque: _ro,
|
|
1132
|
+
...cleaned
|
|
1133
|
+
} = msg;
|
|
1134
|
+
if (Array.isArray(cleaned.content)) {
|
|
1135
|
+
cleaned.content = cleaned.content.filter(
|
|
1136
|
+
(part: any) => part.type !== "thinking",
|
|
1137
|
+
);
|
|
1138
|
+
if (cleaned.content.length === 0)
|
|
1139
|
+
cleaned.content = null;
|
|
1140
|
+
}
|
|
1141
|
+
return cleaned;
|
|
1142
|
+
},
|
|
1143
|
+
);
|
|
1144
|
+
delete bodyObj.thinking_budget;
|
|
1145
|
+
recovered = true;
|
|
1146
|
+
log(
|
|
1147
|
+
"info",
|
|
1148
|
+
`[400-RECOVERY] Stripped all thinking/reasoning content for retry`,
|
|
1149
|
+
);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
if (isIdError && bodyObj?.input) {
|
|
1153
|
+
bodyObj.input = sanitizeResponseInputIds(
|
|
1154
|
+
bodyObj.input,
|
|
1155
|
+
);
|
|
1156
|
+
recovered = true;
|
|
1157
|
+
log(
|
|
1158
|
+
"info",
|
|
1159
|
+
`[400-RECOVERY] Re-sanitized Responses API IDs for retry`,
|
|
1160
|
+
);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
if (recovered) {
|
|
1164
|
+
attempted400Recovery = true;
|
|
1165
|
+
activeFinalInit = {
|
|
1166
|
+
...activeFinalInit,
|
|
1167
|
+
body: JSON.stringify(bodyObj),
|
|
1168
|
+
};
|
|
1169
|
+
attempt++;
|
|
1170
|
+
continue;
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
// Not recoverable — log detail and return original response
|
|
1175
|
+
log(
|
|
1176
|
+
"warn",
|
|
1177
|
+
`[400-RECOVERY] Non-recoverable 400: ${errorDetail}`,
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1070
1181
|
// Response transformation is handled by the custom SDK at
|
|
1071
1182
|
// .opencode/plugin/sdk/copilot/
|
|
1072
1183
|
return response;
|
|
@@ -179,8 +179,25 @@ export function createHooks(deps: HookDeps) {
|
|
|
179
179
|
statusCode === 400 ||
|
|
180
180
|
/bad request|invalid.*request/i.test(errorMsg)
|
|
181
181
|
) {
|
|
182
|
-
guidance
|
|
183
|
-
|
|
182
|
+
// Sub-classify 400 errors for more specific guidance
|
|
183
|
+
if (
|
|
184
|
+
/thinking.?block|invalid.*signature|reasoning/i.test(errorMsg)
|
|
185
|
+
) {
|
|
186
|
+
guidance =
|
|
187
|
+
"Thinking block error — start a new session to reset";
|
|
188
|
+
} else if (
|
|
189
|
+
/context.*(too|exceed|length|large|limit)|too.?long|max.?length|content.?length/i.test(errorMsg)
|
|
190
|
+
) {
|
|
191
|
+
guidance =
|
|
192
|
+
"Request too large — use /compact to reduce context";
|
|
193
|
+
} else if (
|
|
194
|
+
/invalid.*\bid\b|item.*\bid\b|unknown.*\bid\b|malformed.*\bid\b/i.test(errorMsg)
|
|
195
|
+
) {
|
|
196
|
+
guidance = "API format error — start a new session";
|
|
197
|
+
} else {
|
|
198
|
+
guidance =
|
|
199
|
+
"Bad request — try starting a new session or using /compact";
|
|
200
|
+
}
|
|
184
201
|
} else if (
|
|
185
202
|
/timeout|ETIMEDOUT|ECONNRESET|network|fetch failed/i.test(errorMsg)
|
|
186
203
|
) {
|