opencode-copilot-account-switcher 0.14.18 → 0.14.20
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/plugin-hooks.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { appendFileSync } from "node:fs";
|
|
2
2
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
|
+
import { OpencodeClient as OpencodeV2Client } from "@opencode-ai/sdk/v2/client";
|
|
4
5
|
import { createCompactionLoopSafetyBypass, createLoopSafetySystemTransform, getLoopSafetyProviderScope, } from "./loop-safety-plugin.js";
|
|
5
6
|
import { COPILOT_PROVIDER_DESCRIPTOR } from "./providers/descriptor.js";
|
|
6
7
|
import { CODEX_PROVIDER_DESCRIPTOR } from "./providers/descriptor.js";
|
|
@@ -316,6 +317,17 @@ function getFinalSentRequestHeadersRecord(request, init) {
|
|
|
316
317
|
return sanitizeLoggedRequestHeadersRecord(Object.fromEntries(headers.entries()));
|
|
317
318
|
}
|
|
318
319
|
function hasWechatBridgeClientShape(value) {
|
|
320
|
+
if (typeof value !== "object" || value === null)
|
|
321
|
+
return false;
|
|
322
|
+
const client = value;
|
|
323
|
+
return typeof client.session?.list === "function"
|
|
324
|
+
&& typeof client.session?.status === "function"
|
|
325
|
+
&& typeof client.session?.todo === "function"
|
|
326
|
+
&& typeof client.session?.messages === "function"
|
|
327
|
+
&& typeof client.question?.list === "function"
|
|
328
|
+
&& typeof client.permission?.list === "function";
|
|
329
|
+
}
|
|
330
|
+
function hasWechatBridgeSessionShape(value) {
|
|
319
331
|
if (typeof value !== "object" || value === null)
|
|
320
332
|
return false;
|
|
321
333
|
const client = value;
|
|
@@ -324,6 +336,20 @@ function hasWechatBridgeClientShape(value) {
|
|
|
324
336
|
&& typeof client.session?.todo === "function"
|
|
325
337
|
&& typeof client.session?.messages === "function";
|
|
326
338
|
}
|
|
339
|
+
function toWechatBridgeClient(value) {
|
|
340
|
+
if (hasWechatBridgeClientShape(value)) {
|
|
341
|
+
return value;
|
|
342
|
+
}
|
|
343
|
+
if (!hasWechatBridgeSessionShape(value)) {
|
|
344
|
+
return undefined;
|
|
345
|
+
}
|
|
346
|
+
const transport = value._client;
|
|
347
|
+
if (typeof transport !== "object" || transport === null) {
|
|
348
|
+
return undefined;
|
|
349
|
+
}
|
|
350
|
+
const wrapped = new OpencodeV2Client({ client: transport });
|
|
351
|
+
return hasWechatBridgeClientShape(wrapped) ? wrapped : undefined;
|
|
352
|
+
}
|
|
327
353
|
function sanitizeLoggedRequestHeadersRecord(headers) {
|
|
328
354
|
const sanitized = { ...headers };
|
|
329
355
|
if (typeof sanitized.authorization === "string" && sanitized.authorization.length > 0) {
|
|
@@ -584,7 +610,7 @@ export function buildPluginHooks(input) {
|
|
|
584
610
|
const triggerBillingCompensation = input.triggerBillingCompensation ?? (async () => { });
|
|
585
611
|
const ensureWechatBrokerStarted = input.ensureWechatBrokerStarted ?? (async () => connectOrSpawnBroker());
|
|
586
612
|
const createWechatBridgeLifecycleImpl = input.createWechatBridgeLifecycleImpl ?? createWechatBridgeLifecycle;
|
|
587
|
-
const wechatBridgeClient =
|
|
613
|
+
const wechatBridgeClient = toWechatBridgeClient(input.client);
|
|
588
614
|
if (wechatBridgeClient) {
|
|
589
615
|
void showStatusToast({
|
|
590
616
|
client: input.client,
|
package/dist/wechat/bridge.d.ts
CHANGED
|
@@ -14,11 +14,11 @@ type WechatBridgeClient = {
|
|
|
14
14
|
todo: (sessionID: string) => Promise<Todo[]>;
|
|
15
15
|
messages: (sessionID: string) => Promise<SessionMessages>;
|
|
16
16
|
};
|
|
17
|
-
question
|
|
18
|
-
list
|
|
17
|
+
question: {
|
|
18
|
+
list: () => Promise<QuestionRequest[]>;
|
|
19
19
|
};
|
|
20
|
-
permission
|
|
21
|
-
list
|
|
20
|
+
permission: {
|
|
21
|
+
list: () => Promise<PermissionRequest[]>;
|
|
22
22
|
};
|
|
23
23
|
};
|
|
24
24
|
export type InstanceUnavailableKind = "sessionStatus" | "questionList" | "permissionList";
|
package/dist/wechat/bridge.js
CHANGED
|
@@ -72,17 +72,11 @@ export function createWechatBridge(input) {
|
|
|
72
72
|
? Math.max(1, Math.floor(input.liveReadTimeoutMs))
|
|
73
73
|
: DEFAULT_LIVE_READ_TIMEOUT_MS;
|
|
74
74
|
const unavailable = new Set();
|
|
75
|
-
const questionList = input.client.question?.list;
|
|
76
|
-
const permissionList = input.client.permission?.list;
|
|
77
75
|
const [sessionListResult, statusResult, questionResult, permissionResult] = await Promise.allSettled([
|
|
78
76
|
withTimeout(() => input.client.session.list(), liveReadTimeoutMs, "session.list"),
|
|
79
77
|
withTimeout(() => input.client.session.status(), liveReadTimeoutMs, "session.status"),
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
: Promise.reject(new Error("question.list unavailable")),
|
|
83
|
-
typeof permissionList === "function"
|
|
84
|
-
? withTimeout(() => permissionList(), liveReadTimeoutMs, "permission.list")
|
|
85
|
-
: Promise.reject(new Error("permission.list unavailable")),
|
|
78
|
+
withTimeout(() => input.client.question.list(), liveReadTimeoutMs, "question.list"),
|
|
79
|
+
withTimeout(() => input.client.permission.list(), liveReadTimeoutMs, "permission.list"),
|
|
86
80
|
]);
|
|
87
81
|
const sessions = sessionListResult.status === "fulfilled" ? sessionListResult.value : [];
|
|
88
82
|
const recentSessions = pickRecentSessions(sessions, 3);
|
|
@@ -22,6 +22,7 @@ type LaunchOptions = {
|
|
|
22
22
|
pid?: number | undefined;
|
|
23
23
|
unref?: (() => void) | undefined;
|
|
24
24
|
};
|
|
25
|
+
retireBrokerImpl?: (metadata: BrokerMetadata) => Promise<void> | void;
|
|
25
26
|
pingImpl?: (endpoint: string) => Promise<boolean>;
|
|
26
27
|
onLockAcquired?: (lock: LaunchLockContent) => void;
|
|
27
28
|
};
|
|
@@ -154,6 +154,47 @@ async function isBrokerAlive(brokerFilePath, pingImpl, expectedVersion) {
|
|
|
154
154
|
}
|
|
155
155
|
return metadata;
|
|
156
156
|
}
|
|
157
|
+
async function readVersionMismatchedBroker(brokerFilePath, expectedVersion) {
|
|
158
|
+
const metadata = await readBrokerMetadata(brokerFilePath);
|
|
159
|
+
if (!metadata) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
if (!isNonEmptyString(expectedVersion) || metadata.version === expectedVersion) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
return metadata;
|
|
166
|
+
}
|
|
167
|
+
async function defaultRetireBrokerImpl(metadata, pingImpl) {
|
|
168
|
+
if (metadata.pid === process.pid) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const reachable = await pingImpl(metadata.endpoint);
|
|
172
|
+
if (!reachable) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (!isProcessAlive(metadata.pid)) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
process.kill(metadata.pid, "SIGTERM");
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const startedAt = Date.now();
|
|
185
|
+
while (Date.now() - startedAt < 5000) {
|
|
186
|
+
if (!isProcessAlive(metadata.pid)) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
await delay(50);
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
process.kill(metadata.pid, "SIGKILL");
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// process already exited
|
|
196
|
+
}
|
|
197
|
+
}
|
|
157
198
|
function defaultSpawnImpl(endpoint, stateRoot) {
|
|
158
199
|
const entry = fileURLToPath(new URL("./broker-entry.js", import.meta.url));
|
|
159
200
|
const child = spawn(resolveBrokerSpawnCommand(), [entry, `--endpoint=${endpoint}`, `--state-root=${stateRoot}`], {
|
|
@@ -174,6 +215,7 @@ export async function connectOrSpawnBroker(options = {}) {
|
|
|
174
215
|
const expectedVersion = options.expectedVersion ?? await readCurrentPackageVersion();
|
|
175
216
|
const pingImpl = options.pingImpl ?? defaultPingImpl;
|
|
176
217
|
const spawnImpl = options.spawnImpl ?? defaultSpawnImpl;
|
|
218
|
+
const retireBrokerImpl = options.retireBrokerImpl ?? ((metadata) => defaultRetireBrokerImpl(metadata, pingImpl));
|
|
177
219
|
const endpointFactory = options.endpointFactory ?? (() => createDefaultBrokerEndpoint({ stateRoot }));
|
|
178
220
|
await mkdir(stateRoot, { recursive: true, mode: 0o700 });
|
|
179
221
|
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
@@ -192,6 +234,10 @@ export async function connectOrSpawnBroker(options = {}) {
|
|
|
192
234
|
if (secondCheck) {
|
|
193
235
|
return secondCheck;
|
|
194
236
|
}
|
|
237
|
+
const versionMismatchedBroker = await readVersionMismatchedBroker(brokerJsonFile, expectedVersion);
|
|
238
|
+
if (versionMismatchedBroker) {
|
|
239
|
+
await retireBrokerImpl(versionMismatchedBroker);
|
|
240
|
+
}
|
|
195
241
|
const endpoint = endpointFactory();
|
|
196
242
|
const child = spawnImpl(endpoint, stateRoot);
|
|
197
243
|
void child?.unref?.();
|