opencode-antigravity-auth-mf 11.3.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/LICENSE +21 -0
- package/README.md +630 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/src/antigravity/oauth.d.ts +31 -0
- package/dist/src/antigravity/oauth.d.ts.map +1 -0
- package/dist/src/antigravity/oauth.js +168 -0
- package/dist/src/antigravity/oauth.js.map +1 -0
- package/dist/src/constants.d.ts +99 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +135 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/hooks/auto-update-checker/cache.d.ts +3 -0
- package/dist/src/hooks/auto-update-checker/cache.d.ts.map +1 -0
- package/dist/src/hooks/auto-update-checker/cache.js +71 -0
- package/dist/src/hooks/auto-update-checker/cache.js.map +1 -0
- package/dist/src/hooks/auto-update-checker/checker.d.ts +16 -0
- package/dist/src/hooks/auto-update-checker/checker.d.ts.map +1 -0
- package/dist/src/hooks/auto-update-checker/checker.js +237 -0
- package/dist/src/hooks/auto-update-checker/checker.js.map +1 -0
- package/dist/src/hooks/auto-update-checker/constants.d.ts +9 -0
- package/dist/src/hooks/auto-update-checker/constants.d.ts.map +1 -0
- package/dist/src/hooks/auto-update-checker/constants.js +23 -0
- package/dist/src/hooks/auto-update-checker/constants.js.map +1 -0
- package/dist/src/hooks/auto-update-checker/index.d.ts +34 -0
- package/dist/src/hooks/auto-update-checker/index.d.ts.map +1 -0
- package/dist/src/hooks/auto-update-checker/index.js +125 -0
- package/dist/src/hooks/auto-update-checker/index.js.map +1 -0
- package/dist/src/hooks/auto-update-checker/types.d.ts +25 -0
- package/dist/src/hooks/auto-update-checker/types.d.ts.map +1 -0
- package/dist/src/hooks/auto-update-checker/types.js +1 -0
- package/dist/src/hooks/auto-update-checker/types.js.map +1 -0
- package/dist/src/plugin/accounts.d.ts +86 -0
- package/dist/src/plugin/accounts.d.ts.map +1 -0
- package/dist/src/plugin/accounts.js +609 -0
- package/dist/src/plugin/accounts.js.map +1 -0
- package/dist/src/plugin/auth.d.ts +21 -0
- package/dist/src/plugin/auth.d.ts.map +1 -0
- package/dist/src/plugin/auth.js +46 -0
- package/dist/src/plugin/auth.js.map +1 -0
- package/dist/src/plugin/cache/index.d.ts +5 -0
- package/dist/src/plugin/cache/index.d.ts.map +1 -0
- package/dist/src/plugin/cache/index.js +5 -0
- package/dist/src/plugin/cache/index.js.map +1 -0
- package/dist/src/plugin/cache/signature-cache.d.ts +111 -0
- package/dist/src/plugin/cache/signature-cache.d.ts.map +1 -0
- package/dist/src/plugin/cache/signature-cache.js +375 -0
- package/dist/src/plugin/cache/signature-cache.js.map +1 -0
- package/dist/src/plugin/cache.d.ts +44 -0
- package/dist/src/plugin/cache.d.ts.map +1 -0
- package/dist/src/plugin/cache.js +200 -0
- package/dist/src/plugin/cache.js.map +1 -0
- package/dist/src/plugin/cli.d.ts +19 -0
- package/dist/src/plugin/cli.d.ts.map +1 -0
- package/dist/src/plugin/cli.js +59 -0
- package/dist/src/plugin/cli.js.map +1 -0
- package/dist/src/plugin/config/index.d.ts +16 -0
- package/dist/src/plugin/config/index.d.ts.map +1 -0
- package/dist/src/plugin/config/index.js +16 -0
- package/dist/src/plugin/config/index.js.map +1 -0
- package/dist/src/plugin/config/loader.d.ts +37 -0
- package/dist/src/plugin/config/loader.d.ts.map +1 -0
- package/dist/src/plugin/config/loader.js +206 -0
- package/dist/src/plugin/config/loader.js.map +1 -0
- package/dist/src/plugin/config/schema.d.ts +411 -0
- package/dist/src/plugin/config/schema.d.ts.map +1 -0
- package/dist/src/plugin/config/schema.js +339 -0
- package/dist/src/plugin/config/schema.js.map +1 -0
- package/dist/src/plugin/core/streaming/index.d.ts +3 -0
- package/dist/src/plugin/core/streaming/index.d.ts.map +1 -0
- package/dist/src/plugin/core/streaming/index.js +3 -0
- package/dist/src/plugin/core/streaming/index.js.map +1 -0
- package/dist/src/plugin/core/streaming/transformer.d.ts +10 -0
- package/dist/src/plugin/core/streaming/transformer.d.ts.map +1 -0
- package/dist/src/plugin/core/streaming/transformer.js +255 -0
- package/dist/src/plugin/core/streaming/transformer.js.map +1 -0
- package/dist/src/plugin/core/streaming/types.d.ts +35 -0
- package/dist/src/plugin/core/streaming/types.d.ts.map +1 -0
- package/dist/src/plugin/core/streaming/types.js +1 -0
- package/dist/src/plugin/core/streaming/types.js.map +1 -0
- package/dist/src/plugin/debug.d.ts +68 -0
- package/dist/src/plugin/debug.d.ts.map +1 -0
- package/dist/src/plugin/debug.js +325 -0
- package/dist/src/plugin/debug.js.map +1 -0
- package/dist/src/plugin/errors.d.ts +28 -0
- package/dist/src/plugin/errors.d.ts.map +1 -0
- package/dist/src/plugin/errors.js +42 -0
- package/dist/src/plugin/errors.js.map +1 -0
- package/dist/src/plugin/image-saver.d.ts +25 -0
- package/dist/src/plugin/image-saver.d.ts.map +1 -0
- package/dist/src/plugin/image-saver.js +86 -0
- package/dist/src/plugin/image-saver.js.map +1 -0
- package/dist/src/plugin/logger.d.ts +54 -0
- package/dist/src/plugin/logger.d.ts.map +1 -0
- package/dist/src/plugin/logger.js +120 -0
- package/dist/src/plugin/logger.js.map +1 -0
- package/dist/src/plugin/project.d.ts +33 -0
- package/dist/src/plugin/project.d.ts.map +1 -0
- package/dist/src/plugin/project.js +234 -0
- package/dist/src/plugin/project.js.map +1 -0
- package/dist/src/plugin/recovery/constants.d.ts +22 -0
- package/dist/src/plugin/recovery/constants.d.ts.map +1 -0
- package/dist/src/plugin/recovery/constants.js +43 -0
- package/dist/src/plugin/recovery/constants.js.map +1 -0
- package/dist/src/plugin/recovery/index.d.ts +12 -0
- package/dist/src/plugin/recovery/index.d.ts.map +1 -0
- package/dist/src/plugin/recovery/index.js +12 -0
- package/dist/src/plugin/recovery/index.js.map +1 -0
- package/dist/src/plugin/recovery/storage.d.ts +24 -0
- package/dist/src/plugin/recovery/storage.d.ts.map +1 -0
- package/dist/src/plugin/recovery/storage.js +354 -0
- package/dist/src/plugin/recovery/storage.js.map +1 -0
- package/dist/src/plugin/recovery/types.d.ts +116 -0
- package/dist/src/plugin/recovery/types.d.ts.map +1 -0
- package/dist/src/plugin/recovery/types.js +6 -0
- package/dist/src/plugin/recovery/types.js.map +1 -0
- package/dist/src/plugin/recovery.d.ts +61 -0
- package/dist/src/plugin/recovery.d.ts.map +1 -0
- package/dist/src/plugin/recovery.js +376 -0
- package/dist/src/plugin/recovery.js.map +1 -0
- package/dist/src/plugin/refresh-queue.d.ts +101 -0
- package/dist/src/plugin/refresh-queue.d.ts.map +1 -0
- package/dist/src/plugin/refresh-queue.js +244 -0
- package/dist/src/plugin/refresh-queue.js.map +1 -0
- package/dist/src/plugin/request-helpers.d.ts +278 -0
- package/dist/src/plugin/request-helpers.d.ts.map +1 -0
- package/dist/src/plugin/request-helpers.js +2268 -0
- package/dist/src/plugin/request-helpers.js.map +1 -0
- package/dist/src/plugin/request.d.ts +91 -0
- package/dist/src/plugin/request.d.ts.map +1 -0
- package/dist/src/plugin/request.js +1302 -0
- package/dist/src/plugin/request.js.map +1 -0
- package/dist/src/plugin/rotation.d.ts +168 -0
- package/dist/src/plugin/rotation.d.ts.map +1 -0
- package/dist/src/plugin/rotation.js +302 -0
- package/dist/src/plugin/rotation.js.map +1 -0
- package/dist/src/plugin/server.d.ts +23 -0
- package/dist/src/plugin/server.d.ts.map +1 -0
- package/dist/src/plugin/server.js +324 -0
- package/dist/src/plugin/server.js.map +1 -0
- package/dist/src/plugin/storage.d.ts +92 -0
- package/dist/src/plugin/storage.d.ts.map +1 -0
- package/dist/src/plugin/storage.js +417 -0
- package/dist/src/plugin/storage.js.map +1 -0
- package/dist/src/plugin/stores/signature-store.d.ts +5 -0
- package/dist/src/plugin/stores/signature-store.d.ts.map +1 -0
- package/dist/src/plugin/stores/signature-store.js +25 -0
- package/dist/src/plugin/stores/signature-store.js.map +1 -0
- package/dist/src/plugin/thinking-recovery.d.ts +90 -0
- package/dist/src/plugin/thinking-recovery.d.ts.map +1 -0
- package/dist/src/plugin/thinking-recovery.js +316 -0
- package/dist/src/plugin/thinking-recovery.js.map +1 -0
- package/dist/src/plugin/token.d.ts +19 -0
- package/dist/src/plugin/token.d.ts.map +1 -0
- package/dist/src/plugin/token.js +128 -0
- package/dist/src/plugin/token.js.map +1 -0
- package/dist/src/plugin/transform/claude.d.ts +80 -0
- package/dist/src/plugin/transform/claude.d.ts.map +1 -0
- package/dist/src/plugin/transform/claude.js +265 -0
- package/dist/src/plugin/transform/claude.js.map +1 -0
- package/dist/src/plugin/transform/cross-model-sanitizer.d.ts +35 -0
- package/dist/src/plugin/transform/cross-model-sanitizer.d.ts.map +1 -0
- package/dist/src/plugin/transform/cross-model-sanitizer.js +225 -0
- package/dist/src/plugin/transform/cross-model-sanitizer.js.map +1 -0
- package/dist/src/plugin/transform/gemini.d.ts +112 -0
- package/dist/src/plugin/transform/gemini.d.ts.map +1 -0
- package/dist/src/plugin/transform/gemini.js +409 -0
- package/dist/src/plugin/transform/gemini.js.map +1 -0
- package/dist/src/plugin/transform/index.d.ts +15 -0
- package/dist/src/plugin/transform/index.d.ts.map +1 -0
- package/dist/src/plugin/transform/index.js +14 -0
- package/dist/src/plugin/transform/index.js.map +1 -0
- package/dist/src/plugin/transform/model-resolver.d.ts +101 -0
- package/dist/src/plugin/transform/model-resolver.d.ts.map +1 -0
- package/dist/src/plugin/transform/model-resolver.js +356 -0
- package/dist/src/plugin/transform/model-resolver.js.map +1 -0
- package/dist/src/plugin/transform/types.d.ts +106 -0
- package/dist/src/plugin/transform/types.d.ts.map +1 -0
- package/dist/src/plugin/transform/types.js +1 -0
- package/dist/src/plugin/transform/types.js.map +1 -0
- package/dist/src/plugin/types.d.ts +96 -0
- package/dist/src/plugin/types.d.ts.map +1 -0
- package/dist/src/plugin/types.js +1 -0
- package/dist/src/plugin/types.js.map +1 -0
- package/dist/src/plugin/usage-reporter.d.ts +23 -0
- package/dist/src/plugin/usage-reporter.d.ts.map +1 -0
- package/dist/src/plugin/usage-reporter.js +43 -0
- package/dist/src/plugin/usage-reporter.js.map +1 -0
- package/dist/src/plugin.d.ts +8 -0
- package/dist/src/plugin.d.ts.map +1 -0
- package/dist/src/plugin.js +1708 -0
- package/dist/src/plugin.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session recovery hook for handling recoverable errors.
|
|
3
|
+
*
|
|
4
|
+
* Supports:
|
|
5
|
+
* - tool_result_missing: When ESC is pressed during tool execution
|
|
6
|
+
* - thinking_block_order: When thinking blocks are corrupted/stripped
|
|
7
|
+
* - thinking_disabled_violation: Thinking in non-thinking model
|
|
8
|
+
*
|
|
9
|
+
* Based on oh-my-opencode/src/hooks/session-recovery/index.ts
|
|
10
|
+
*/
|
|
11
|
+
import { createLogger } from "./logger";
|
|
12
|
+
import { readParts, findMessagesWithThinkingBlocks, findMessagesWithOrphanThinking, findMessageByIndexNeedingThinking, prependThinkingPart, stripThinkingParts, } from "./recovery/storage";
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// Constants
|
|
15
|
+
// =============================================================================
|
|
16
|
+
const RECOVERY_RESUME_TEXT = "[session recovered - continuing previous task]";
|
|
17
|
+
// =============================================================================
|
|
18
|
+
// Error Detection
|
|
19
|
+
// =============================================================================
|
|
20
|
+
/**
|
|
21
|
+
* Extract a normalized error message string from an unknown error.
|
|
22
|
+
*/
|
|
23
|
+
function getErrorMessage(error) {
|
|
24
|
+
if (!error)
|
|
25
|
+
return "";
|
|
26
|
+
if (typeof error === "string")
|
|
27
|
+
return error.toLowerCase();
|
|
28
|
+
const errorObj = error;
|
|
29
|
+
const paths = [
|
|
30
|
+
errorObj.data,
|
|
31
|
+
errorObj.error,
|
|
32
|
+
errorObj,
|
|
33
|
+
errorObj.data?.error,
|
|
34
|
+
];
|
|
35
|
+
for (const obj of paths) {
|
|
36
|
+
if (obj && typeof obj === "object") {
|
|
37
|
+
const msg = obj.message;
|
|
38
|
+
if (typeof msg === "string" && msg.length > 0) {
|
|
39
|
+
return msg.toLowerCase();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
return JSON.stringify(error).toLowerCase();
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return "";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Extract the message index from an error message (e.g., "messages.79").
|
|
52
|
+
*/
|
|
53
|
+
function extractMessageIndex(error) {
|
|
54
|
+
const message = getErrorMessage(error);
|
|
55
|
+
const match = message.match(/messages\.(\d+)/);
|
|
56
|
+
if (!match || !match[1])
|
|
57
|
+
return null;
|
|
58
|
+
return parseInt(match[1], 10);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Detect the type of recoverable error from an error object.
|
|
62
|
+
*/
|
|
63
|
+
export function detectErrorType(error) {
|
|
64
|
+
const message = getErrorMessage(error);
|
|
65
|
+
// tool_result_missing: Happens when ESC is pressed during tool execution
|
|
66
|
+
if (message.includes("tool_use") && message.includes("tool_result")) {
|
|
67
|
+
return "tool_result_missing";
|
|
68
|
+
}
|
|
69
|
+
// thinking_block_order: Happens when thinking blocks are corrupted
|
|
70
|
+
if (message.includes("thinking") &&
|
|
71
|
+
(message.includes("first block") ||
|
|
72
|
+
message.includes("must start with") ||
|
|
73
|
+
message.includes("preceeding") ||
|
|
74
|
+
(message.includes("expected") && message.includes("found")))) {
|
|
75
|
+
return "thinking_block_order";
|
|
76
|
+
}
|
|
77
|
+
// thinking_disabled_violation: Thinking in non-thinking model
|
|
78
|
+
if (message.includes("thinking is disabled") && message.includes("cannot contain")) {
|
|
79
|
+
return "thinking_disabled_violation";
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Check if an error is recoverable.
|
|
85
|
+
*/
|
|
86
|
+
export function isRecoverableError(error) {
|
|
87
|
+
return detectErrorType(error) !== null;
|
|
88
|
+
}
|
|
89
|
+
function extractToolUseIds(parts) {
|
|
90
|
+
return parts
|
|
91
|
+
.filter((p) => p.type === "tool_use" && !!p.id)
|
|
92
|
+
.map((p) => p.id);
|
|
93
|
+
}
|
|
94
|
+
// =============================================================================
|
|
95
|
+
// Recovery Functions
|
|
96
|
+
// =============================================================================
|
|
97
|
+
/**
|
|
98
|
+
* Recover from tool_result_missing error by injecting synthetic tool_result blocks.
|
|
99
|
+
*/
|
|
100
|
+
async function recoverToolResultMissing(client, sessionID, failedMsg) {
|
|
101
|
+
// Try API parts first, fallback to filesystem if empty
|
|
102
|
+
let parts = failedMsg.parts || [];
|
|
103
|
+
if (parts.length === 0 && failedMsg.info?.id) {
|
|
104
|
+
const storedParts = readParts(failedMsg.info.id);
|
|
105
|
+
parts = storedParts.map((p) => ({
|
|
106
|
+
type: p.type === "tool" ? "tool_use" : p.type,
|
|
107
|
+
id: "callID" in p ? p.callID : p.id,
|
|
108
|
+
name: "tool" in p ? p.tool : undefined,
|
|
109
|
+
input: "state" in p ? p.state?.input : undefined,
|
|
110
|
+
}));
|
|
111
|
+
}
|
|
112
|
+
const toolUseIds = extractToolUseIds(parts);
|
|
113
|
+
if (toolUseIds.length === 0) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
const toolResultParts = toolUseIds.map((id) => ({
|
|
117
|
+
type: "tool_result",
|
|
118
|
+
tool_use_id: id,
|
|
119
|
+
content: "Operation cancelled by user (ESC pressed)",
|
|
120
|
+
}));
|
|
121
|
+
try {
|
|
122
|
+
await client.session.prompt({
|
|
123
|
+
path: { id: sessionID },
|
|
124
|
+
// @ts-expect-error - SDK types may not include tool_result parts
|
|
125
|
+
body: { parts: toolResultParts },
|
|
126
|
+
});
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Recover from thinking_block_order error by prepending thinking parts.
|
|
135
|
+
*/
|
|
136
|
+
async function recoverThinkingBlockOrder(sessionID, _failedMsg, error) {
|
|
137
|
+
// Try to find the target message index from error
|
|
138
|
+
const targetIndex = extractMessageIndex(error);
|
|
139
|
+
if (targetIndex !== null) {
|
|
140
|
+
const targetMessageID = findMessageByIndexNeedingThinking(sessionID, targetIndex);
|
|
141
|
+
if (targetMessageID) {
|
|
142
|
+
return prependThinkingPart(sessionID, targetMessageID);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Fallback: find all orphan thinking messages
|
|
146
|
+
const orphanMessages = findMessagesWithOrphanThinking(sessionID);
|
|
147
|
+
if (orphanMessages.length === 0) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
let anySuccess = false;
|
|
151
|
+
for (const messageID of orphanMessages) {
|
|
152
|
+
if (prependThinkingPart(sessionID, messageID)) {
|
|
153
|
+
anySuccess = true;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return anySuccess;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Recover from thinking_disabled_violation by stripping thinking parts.
|
|
160
|
+
*/
|
|
161
|
+
async function recoverThinkingDisabledViolation(sessionID, _failedMsg) {
|
|
162
|
+
const messagesWithThinking = findMessagesWithThinkingBlocks(sessionID);
|
|
163
|
+
if (messagesWithThinking.length === 0) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
let anySuccess = false;
|
|
167
|
+
for (const messageID of messagesWithThinking) {
|
|
168
|
+
if (stripThinkingParts(messageID)) {
|
|
169
|
+
anySuccess = true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return anySuccess;
|
|
173
|
+
}
|
|
174
|
+
// =============================================================================
|
|
175
|
+
// Resume Session Helper
|
|
176
|
+
// =============================================================================
|
|
177
|
+
function findLastUserMessage(messages) {
|
|
178
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
179
|
+
if (messages[i]?.info?.role === "user") {
|
|
180
|
+
return messages[i];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
function extractResumeConfig(userMessage, sessionID) {
|
|
186
|
+
return {
|
|
187
|
+
sessionID,
|
|
188
|
+
agent: userMessage?.info?.agent,
|
|
189
|
+
model: userMessage?.info?.model,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
async function resumeSession(client, config, directory) {
|
|
193
|
+
try {
|
|
194
|
+
await client.session.prompt({
|
|
195
|
+
path: { id: config.sessionID },
|
|
196
|
+
body: {
|
|
197
|
+
parts: [{ type: "text", text: RECOVERY_RESUME_TEXT }],
|
|
198
|
+
agent: config.agent,
|
|
199
|
+
model: config.model,
|
|
200
|
+
},
|
|
201
|
+
query: { directory },
|
|
202
|
+
});
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// =============================================================================
|
|
210
|
+
// Toast Messages
|
|
211
|
+
// =============================================================================
|
|
212
|
+
const TOAST_TITLES = {
|
|
213
|
+
tool_result_missing: "Tool Crash Recovery",
|
|
214
|
+
thinking_block_order: "Thinking Block Recovery",
|
|
215
|
+
thinking_disabled_violation: "Thinking Strip Recovery",
|
|
216
|
+
};
|
|
217
|
+
const TOAST_MESSAGES = {
|
|
218
|
+
tool_result_missing: "Injecting cancelled tool results...",
|
|
219
|
+
thinking_block_order: "Fixing message structure...",
|
|
220
|
+
thinking_disabled_violation: "Stripping thinking blocks...",
|
|
221
|
+
};
|
|
222
|
+
export function getRecoveryToastContent(errorType) {
|
|
223
|
+
if (!errorType) {
|
|
224
|
+
return {
|
|
225
|
+
title: "Session Recovery",
|
|
226
|
+
message: "Attempting to recover session...",
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
return {
|
|
230
|
+
title: TOAST_TITLES[errorType] || "Session Recovery",
|
|
231
|
+
message: TOAST_MESSAGES[errorType] || "Attempting to recover session...",
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
export function getRecoverySuccessToast() {
|
|
235
|
+
return {
|
|
236
|
+
title: "Session Recovered",
|
|
237
|
+
message: "Continuing where you left off...",
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
export function getRecoveryFailureToast() {
|
|
241
|
+
return {
|
|
242
|
+
title: "Recovery Failed",
|
|
243
|
+
message: "Please retry or start a new session.",
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Create a session recovery hook with the given configuration.
|
|
248
|
+
*/
|
|
249
|
+
export function createSessionRecoveryHook(ctx, config) {
|
|
250
|
+
// If session recovery is disabled, return null
|
|
251
|
+
if (!config.session_recovery) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
const { client, directory } = ctx;
|
|
255
|
+
const processingErrors = new Set();
|
|
256
|
+
let onAbortCallback = null;
|
|
257
|
+
let onRecoveryCompleteCallback = null;
|
|
258
|
+
const setOnAbortCallback = (callback) => {
|
|
259
|
+
onAbortCallback = callback;
|
|
260
|
+
};
|
|
261
|
+
const setOnRecoveryCompleteCallback = (callback) => {
|
|
262
|
+
onRecoveryCompleteCallback = callback;
|
|
263
|
+
};
|
|
264
|
+
const handleSessionRecovery = async (info) => {
|
|
265
|
+
// Validate input
|
|
266
|
+
if (!info || info.role !== "assistant" || !info.error)
|
|
267
|
+
return false;
|
|
268
|
+
const errorType = detectErrorType(info.error);
|
|
269
|
+
if (!errorType)
|
|
270
|
+
return false;
|
|
271
|
+
const sessionID = info.sessionID;
|
|
272
|
+
if (!sessionID)
|
|
273
|
+
return false;
|
|
274
|
+
// OpenCode's session.error event may not include messageID
|
|
275
|
+
// In that case, we need to fetch messages and find the latest assistant with error
|
|
276
|
+
let assistantMsgID = info.id;
|
|
277
|
+
let msgs;
|
|
278
|
+
const log = createLogger("session-recovery");
|
|
279
|
+
log.debug("Recovery attempt started", {
|
|
280
|
+
errorType,
|
|
281
|
+
sessionID,
|
|
282
|
+
providedMsgID: assistantMsgID ?? "none",
|
|
283
|
+
});
|
|
284
|
+
// Notify abort callback early
|
|
285
|
+
if (onAbortCallback) {
|
|
286
|
+
onAbortCallback(sessionID);
|
|
287
|
+
}
|
|
288
|
+
// Abort current request
|
|
289
|
+
await client.session.abort({ path: { id: sessionID } }).catch(() => { });
|
|
290
|
+
// Fetch messages - needed to find the failed message
|
|
291
|
+
const messagesResp = await client.session.messages({
|
|
292
|
+
path: { id: sessionID },
|
|
293
|
+
query: { directory },
|
|
294
|
+
});
|
|
295
|
+
msgs = messagesResp.data;
|
|
296
|
+
// If messageID wasn't provided, find the latest assistant message with an error
|
|
297
|
+
if (!assistantMsgID && msgs && msgs.length > 0) {
|
|
298
|
+
// Find the last assistant message (most recent is typically last in array)
|
|
299
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
300
|
+
const m = msgs[i];
|
|
301
|
+
if (m && m.info?.role === "assistant" && m.info?.id) {
|
|
302
|
+
assistantMsgID = m.info.id;
|
|
303
|
+
log.debug("Found assistant message ID from session messages", {
|
|
304
|
+
msgID: assistantMsgID,
|
|
305
|
+
msgIndex: i,
|
|
306
|
+
});
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
if (!assistantMsgID) {
|
|
312
|
+
log.debug("No assistant message ID found, cannot recover");
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
if (processingErrors.has(assistantMsgID))
|
|
316
|
+
return false;
|
|
317
|
+
processingErrors.add(assistantMsgID);
|
|
318
|
+
try {
|
|
319
|
+
const failedMsg = msgs?.find((m) => m.info?.id === assistantMsgID);
|
|
320
|
+
if (!failedMsg) {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
// Show toast notification
|
|
324
|
+
const toastContent = getRecoveryToastContent(errorType);
|
|
325
|
+
await client.tui
|
|
326
|
+
.showToast({
|
|
327
|
+
body: {
|
|
328
|
+
title: toastContent.title,
|
|
329
|
+
message: toastContent.message,
|
|
330
|
+
variant: "warning",
|
|
331
|
+
},
|
|
332
|
+
})
|
|
333
|
+
.catch(() => { });
|
|
334
|
+
// Perform recovery based on error type
|
|
335
|
+
let success = false;
|
|
336
|
+
if (errorType === "tool_result_missing") {
|
|
337
|
+
success = await recoverToolResultMissing(client, sessionID, failedMsg);
|
|
338
|
+
}
|
|
339
|
+
else if (errorType === "thinking_block_order") {
|
|
340
|
+
success = await recoverThinkingBlockOrder(sessionID, failedMsg, info.error);
|
|
341
|
+
if (success && config.auto_resume) {
|
|
342
|
+
const lastUser = findLastUserMessage(msgs ?? []);
|
|
343
|
+
const resumeConfig = extractResumeConfig(lastUser, sessionID);
|
|
344
|
+
await resumeSession(client, resumeConfig, directory);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
else if (errorType === "thinking_disabled_violation") {
|
|
348
|
+
success = await recoverThinkingDisabledViolation(sessionID, failedMsg);
|
|
349
|
+
if (success && config.auto_resume) {
|
|
350
|
+
const lastUser = findLastUserMessage(msgs ?? []);
|
|
351
|
+
const resumeConfig = extractResumeConfig(lastUser, sessionID);
|
|
352
|
+
await resumeSession(client, resumeConfig, directory);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return success;
|
|
356
|
+
}
|
|
357
|
+
catch (err) {
|
|
358
|
+
log.error("Recovery failed", { error: String(err) });
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
finally {
|
|
362
|
+
processingErrors.delete(assistantMsgID);
|
|
363
|
+
// Always notify recovery complete
|
|
364
|
+
if (sessionID && onRecoveryCompleteCallback) {
|
|
365
|
+
onRecoveryCompleteCallback(sessionID);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
return {
|
|
370
|
+
handleSessionRecovery,
|
|
371
|
+
isRecoverableError,
|
|
372
|
+
setOnAbortCallback,
|
|
373
|
+
setOnRecoveryCompleteCallback,
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
//# sourceMappingURL=recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.js","sourceRoot":"","sources":["../../../src/plugin/recovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proactive Token Refresh Queue
|
|
3
|
+
*
|
|
4
|
+
* Ported from LLM-API-Key-Proxy's BackgroundRefresher.
|
|
5
|
+
*
|
|
6
|
+
* This module provides background token refresh to ensure OAuth tokens
|
|
7
|
+
* remain valid without blocking user requests. It periodically checks
|
|
8
|
+
* all accounts and refreshes tokens that are approaching expiry.
|
|
9
|
+
*
|
|
10
|
+
* Features:
|
|
11
|
+
* - Non-blocking background refresh (doesn't block requests)
|
|
12
|
+
* - Configurable refresh buffer (default: 30 minutes before expiry)
|
|
13
|
+
* - Configurable check interval (default: 5 minutes)
|
|
14
|
+
* - Serialized refresh to prevent concurrent refresh storms
|
|
15
|
+
* - Integrates with existing AccountManager and token refresh logic
|
|
16
|
+
* - Silent operation: no console output, uses structured logger
|
|
17
|
+
*/
|
|
18
|
+
import type { AccountManager, ManagedAccount } from "./accounts";
|
|
19
|
+
import type { PluginClient } from "./types";
|
|
20
|
+
/** Configuration for the proactive refresh queue */
|
|
21
|
+
export interface ProactiveRefreshConfig {
|
|
22
|
+
/** Enable proactive token refresh (default: true) */
|
|
23
|
+
enabled: boolean;
|
|
24
|
+
/** Seconds before expiry to trigger proactive refresh (default: 1800 = 30 minutes) */
|
|
25
|
+
bufferSeconds: number;
|
|
26
|
+
/** Interval between refresh checks in seconds (default: 300 = 5 minutes) */
|
|
27
|
+
checkIntervalSeconds: number;
|
|
28
|
+
}
|
|
29
|
+
export declare const DEFAULT_PROACTIVE_REFRESH_CONFIG: ProactiveRefreshConfig;
|
|
30
|
+
/**
|
|
31
|
+
* Proactive Token Refresh Queue
|
|
32
|
+
*
|
|
33
|
+
* Runs in the background and proactively refreshes tokens before they expire.
|
|
34
|
+
* This ensures that user requests never block on token refresh.
|
|
35
|
+
*
|
|
36
|
+
* All logging is silent by default - uses structured logger that only outputs
|
|
37
|
+
* when OPENCODE_ANTIGRAVITY_CONSOLE_LOG=1 is set or TUI logging is available.
|
|
38
|
+
*/
|
|
39
|
+
export declare class ProactiveRefreshQueue {
|
|
40
|
+
private readonly config;
|
|
41
|
+
private readonly client;
|
|
42
|
+
private readonly providerId;
|
|
43
|
+
private accountManager;
|
|
44
|
+
private state;
|
|
45
|
+
constructor(client: PluginClient, providerId: string, config?: Partial<ProactiveRefreshConfig>);
|
|
46
|
+
/**
|
|
47
|
+
* Set the account manager to use for refresh operations.
|
|
48
|
+
* Must be called before start().
|
|
49
|
+
*/
|
|
50
|
+
setAccountManager(manager: AccountManager): void;
|
|
51
|
+
/**
|
|
52
|
+
* Check if a token needs proactive refresh.
|
|
53
|
+
* Returns true if the token expires within the buffer period.
|
|
54
|
+
*/
|
|
55
|
+
needsRefresh(account: ManagedAccount): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Check if a token is already expired.
|
|
58
|
+
*/
|
|
59
|
+
isExpired(account: ManagedAccount): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Get all accounts that need proactive refresh.
|
|
62
|
+
*/
|
|
63
|
+
getAccountsNeedingRefresh(): ManagedAccount[];
|
|
64
|
+
/**
|
|
65
|
+
* Perform a single refresh check iteration.
|
|
66
|
+
* This is called periodically by the background interval.
|
|
67
|
+
*/
|
|
68
|
+
private runRefreshCheck;
|
|
69
|
+
/**
|
|
70
|
+
* Refresh a single token.
|
|
71
|
+
*/
|
|
72
|
+
private refreshToken;
|
|
73
|
+
/**
|
|
74
|
+
* Start the background refresh queue.
|
|
75
|
+
*/
|
|
76
|
+
start(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Stop the background refresh queue.
|
|
79
|
+
*/
|
|
80
|
+
stop(): void;
|
|
81
|
+
/**
|
|
82
|
+
* Get current queue statistics.
|
|
83
|
+
*/
|
|
84
|
+
getStats(): {
|
|
85
|
+
isRunning: boolean;
|
|
86
|
+
isRefreshing: boolean;
|
|
87
|
+
lastCheckTime: number;
|
|
88
|
+
lastRefreshTime: number;
|
|
89
|
+
refreshCount: number;
|
|
90
|
+
errorCount: number;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Check if the queue is currently running.
|
|
94
|
+
*/
|
|
95
|
+
isRunning(): boolean;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Create a proactive refresh queue instance.
|
|
99
|
+
*/
|
|
100
|
+
export declare function createProactiveRefreshQueue(client: PluginClient, providerId: string, config?: Partial<ProactiveRefreshConfig>): ProactiveRefreshQueue;
|
|
101
|
+
//# sourceMappingURL=refresh-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-queue.d.ts","sourceRoot":"","sources":["../../../src/plugin/refresh-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,SAAS,CAAC;AAM9D,oDAAoD;AACpD,MAAM,WAAW,sBAAsB;IACrC,qDAAqD;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,sFAAsF;IACtF,aAAa,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,eAAO,MAAM,gCAAgC,EAAE,sBAI9C,CAAC;AAaF;;;;;;;;GAQG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,cAAc,CAA+B;IAErD,OAAO,CAAC,KAAK,CAQX;gBAGA,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC;IAU1C;;;OAGG;IACH,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIhD;;;OAGG;IACH,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO;IAa9C;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO;IAO3C;;OAEG;IACH,yBAAyB,IAAI,cAAc,EAAE;IAc7C;;;OAGG;YACW,eAAe;IA2D7B;;OAEG;YACW,YAAY;IAiB1B;;OAEG;IACH,KAAK,IAAI,IAAI;IAuCb;;OAEG;IACH,IAAI,IAAI,IAAI;IAkBZ;;OAEG;IACH,QAAQ,IAAI;QACV,SAAS,EAAE,OAAO,CAAC;QACnB,YAAY,EAAE,OAAO,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;QACtB,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACpB;IAID;;OAEG;IACH,SAAS,IAAI,OAAO;CAGrB;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,GACvC,qBAAqB,CAEvB"}
|