billion-context 0.1.97-pr.671.489 → 0.1.97
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 +23 -128
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +13 -38
- package/dist/mcp.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -48726,7 +48726,6 @@ function mergeCompress(global2, provider, model) {
|
|
|
48726
48726
|
const promptLevels = [global2?.prompts, provider?.prompts, model?.prompts].filter(Boolean);
|
|
48727
48727
|
const rangeOf = (s3) => s3?.minCompressRangeChars ?? s3?.minCompressRange;
|
|
48728
48728
|
const absorbLevels = [global2?.absorb, provider?.absorb, model?.absorb].filter(Boolean);
|
|
48729
|
-
const reasoningLevels = [global2?.reasoning, provider?.reasoning, model?.reasoning].filter(Boolean);
|
|
48730
48729
|
return {
|
|
48731
48730
|
modelContextLimit: pick("modelContextLimit"),
|
|
48732
48731
|
maxContextLimit: pick("maxContextLimit"),
|
|
@@ -48740,11 +48739,7 @@ function mergeCompress(global2, provider, model) {
|
|
|
48740
48739
|
acknowledgePromptsRisk: pick("acknowledgePromptsRisk"),
|
|
48741
48740
|
absorb: absorbLevels.length > 0 ? Object.assign({}, ...absorbLevels) : void 0,
|
|
48742
48741
|
stripImages: pick("stripImages"),
|
|
48743
|
-
stripImagesKeepRecent: pick("stripImagesKeepRecent")
|
|
48744
|
-
// `reasoning` is a third nested-object field merged sub-field-wise
|
|
48745
|
-
// exactly like `absorb`/`prompts`: a model-level `threshold` must not
|
|
48746
|
-
// discard a provider-level `drop: false`.
|
|
48747
|
-
reasoning: reasoningLevels.length > 0 ? Object.assign({}, ...reasoningLevels) : void 0
|
|
48742
|
+
stripImagesKeepRecent: pick("stripImagesKeepRecent")
|
|
48748
48743
|
};
|
|
48749
48744
|
}
|
|
48750
48745
|
function resolveCompress(routes, upstreamUrl, model, global2) {
|
|
@@ -48824,53 +48819,6 @@ function resolveRequestConfig(base, routes, embeddedUrl, model, native, globalCo
|
|
|
48824
48819
|
return applyCompressSettings(base, limit, compress);
|
|
48825
48820
|
}
|
|
48826
48821
|
|
|
48827
|
-
// src/reasoning-drop.ts
|
|
48828
|
-
var DEFAULT_COMPRESS_REASONING = { drop: true, threshold: 2048 };
|
|
48829
|
-
function resolveReasoningDrop(cfg) {
|
|
48830
|
-
let threshold = DEFAULT_COMPRESS_REASONING.threshold;
|
|
48831
|
-
if (cfg?.threshold !== void 0) {
|
|
48832
|
-
const t = cfg.threshold;
|
|
48833
|
-
if (typeof t === "number" && Number.isFinite(t) && t >= 0) {
|
|
48834
|
-
threshold = Math.floor(t);
|
|
48835
|
-
}
|
|
48836
|
-
}
|
|
48837
|
-
return { drop: cfg?.drop !== false, threshold };
|
|
48838
|
-
}
|
|
48839
|
-
function dropCompressReasoning(messages, cfg) {
|
|
48840
|
-
const { drop, threshold } = resolveReasoningDrop(cfg);
|
|
48841
|
-
if (!drop || messages.length === 0) return messages;
|
|
48842
|
-
try {
|
|
48843
|
-
const last = messages.length - 1;
|
|
48844
|
-
const resultAt = /* @__PURE__ */ new Map();
|
|
48845
|
-
for (let i = 0; i <= last; i++) {
|
|
48846
|
-
const m2 = messages[i];
|
|
48847
|
-
if (m2.contentType === "tool-result" && typeof m2.toolCallId === "string" && !resultAt.has(m2.toolCallId)) {
|
|
48848
|
-
resultAt.set(m2.toolCallId, i);
|
|
48849
|
-
}
|
|
48850
|
-
}
|
|
48851
|
-
const dropIdx = /* @__PURE__ */ new Set();
|
|
48852
|
-
for (let i = 0; i <= last; i++) {
|
|
48853
|
-
const m2 = messages[i];
|
|
48854
|
-
if (m2.contentType !== "tool-call" || m2.toolName !== "compress") continue;
|
|
48855
|
-
const ri2 = typeof m2.toolCallId === "string" ? resultAt.get(m2.toolCallId) : void 0;
|
|
48856
|
-
if (ri2 === void 0 || ri2 <= i || ri2 >= last) continue;
|
|
48857
|
-
let total = 0;
|
|
48858
|
-
let j2 = i - 1;
|
|
48859
|
-
while (j2 >= 0 && messages[j2].contentType === "reasoning") {
|
|
48860
|
-
total += (messages[j2].text ?? "").length;
|
|
48861
|
-
j2--;
|
|
48862
|
-
}
|
|
48863
|
-
if (total > threshold) {
|
|
48864
|
-
for (let k2 = j2 + 1; k2 < i; k2++) dropIdx.add(k2);
|
|
48865
|
-
}
|
|
48866
|
-
}
|
|
48867
|
-
if (dropIdx.size === 0) return messages;
|
|
48868
|
-
return messages.filter((_2, idx) => !dropIdx.has(idx));
|
|
48869
|
-
} catch {
|
|
48870
|
-
return messages;
|
|
48871
|
-
}
|
|
48872
|
-
}
|
|
48873
|
-
|
|
48874
48822
|
// src/strip-images.ts
|
|
48875
48823
|
var DEFAULT_STRIP_IMAGES_KEEP_RECENT = 5;
|
|
48876
48824
|
var IMAGE_PLACEHOLDER = "[image]";
|
|
@@ -56307,28 +56255,15 @@ function handlePluginManifest(res) {
|
|
|
56307
56255
|
statusEndpoint: "/__bili/plugin/status"
|
|
56308
56256
|
}));
|
|
56309
56257
|
}
|
|
56310
|
-
function conversationIdForSession(sessionId) {
|
|
56311
|
-
let bestId;
|
|
56312
|
-
let bestSeen = -Infinity;
|
|
56313
|
-
for (const [cid, entry] of conversations) {
|
|
56314
|
-
if (entry.sessionId === sessionId && entry.lastSeen > bestSeen) {
|
|
56315
|
-
bestId = cid;
|
|
56316
|
-
bestSeen = entry.lastSeen;
|
|
56317
|
-
}
|
|
56318
|
-
}
|
|
56319
|
-
return bestId;
|
|
56320
|
-
}
|
|
56321
56258
|
function handlePluginStatus(conversationId2, res, deps, fallbackLatest = false) {
|
|
56322
56259
|
let entry = conversations.get(conversationId2);
|
|
56323
56260
|
let session = entry ? peekSession(entry.sessionId) : void 0;
|
|
56324
56261
|
let viaFallback = false;
|
|
56325
|
-
let resolvedConversationId = conversationId2;
|
|
56326
56262
|
if ((!entry || !session) && fallbackLatest) {
|
|
56327
56263
|
const latest = listSessions().filter((s3) => s3.restored !== true).sort((a, b2) => (b2.lastSeen ?? 0) - (a.lastSeen ?? 0))[0];
|
|
56328
56264
|
if (latest) {
|
|
56329
56265
|
session = latest;
|
|
56330
56266
|
viaFallback = true;
|
|
56331
|
-
resolvedConversationId = conversationIdForSession(latest.id) ?? conversationId2;
|
|
56332
56267
|
} else {
|
|
56333
56268
|
res.writeHead(404, { "content-type": "application/json" });
|
|
56334
56269
|
res.end(JSON.stringify({ ok: false, error: "no session with activity since boot \u2014 issue a model request or pass the conversation id" }));
|
|
@@ -56378,7 +56313,7 @@ function handlePluginStatus(conversationId2, res, deps, fallbackLatest = false)
|
|
|
56378
56313
|
res.writeHead(200, { "content-type": "application/json" });
|
|
56379
56314
|
res.end(JSON.stringify({
|
|
56380
56315
|
ok: true,
|
|
56381
|
-
conversationId:
|
|
56316
|
+
conversationId: conversationId2,
|
|
56382
56317
|
fallback: viaFallback || void 0,
|
|
56383
56318
|
label: session.meta.label ?? null,
|
|
56384
56319
|
pluginAgent: session.metadata.pluginAgent ?? null,
|
|
@@ -56413,12 +56348,8 @@ async function handlePluginTool(payload, res, deps) {
|
|
|
56413
56348
|
const entry = conversations.get(conversationId2);
|
|
56414
56349
|
const session = entry ? peekSession(entry.sessionId) : void 0;
|
|
56415
56350
|
if (!entry || !session) {
|
|
56416
|
-
deps.log("warn", `[plugin] tool "${tool}" rejected for conversation ${conversationId2}: ${entry ? "id registered but session not resident in this proxy instance" : "id never registered (stale shim session id after host resume?)"}`);
|
|
56417
56351
|
res.writeHead(404, { "content-type": "application/json" });
|
|
56418
|
-
res.end(JSON.stringify({
|
|
56419
|
-
ok: false,
|
|
56420
|
-
error: !entry ? "unknown plugin conversation (no model request has arrived with this conversation id yet)" : "unknown plugin conversation (id registered but its session is not resident in this proxy instance \u2014 a fresh model request re-binds it)"
|
|
56421
|
-
}));
|
|
56352
|
+
res.end(JSON.stringify({ ok: false, error: "unknown plugin conversation (no model request has arrived with this conversation id yet)" }));
|
|
56422
56353
|
return;
|
|
56423
56354
|
}
|
|
56424
56355
|
if (!isProxyToolFor(tool, session, deps.config)) {
|
|
@@ -59283,14 +59214,13 @@ ${bodyBuffer.toString("utf8")}`);
|
|
|
59283
59214
|
await withSessionLock(session, async () => {
|
|
59284
59215
|
const runPrepare = () => {
|
|
59285
59216
|
const cs2 = resolveCompress(opts.routes, route?.rewrittenUrl, parsed.model, opts.compress);
|
|
59286
|
-
const reasoningCfg = cs2.reasoning;
|
|
59287
59217
|
const keepRecent = cs2.stripImagesKeepRecent ?? DEFAULT_STRIP_IMAGES_KEEP_RECENT;
|
|
59288
59218
|
const stripped = cs2.stripImages ? stripHistoricalImages(parsed, protocol, keepRecent) : { body: parsed, removed: 0 };
|
|
59289
59219
|
if (opts.debug && stripped.removed > 0) {
|
|
59290
59220
|
log2("info", `[debug] strip-images: dropped ${stripped.removed} historical image part(s), kept last ${keepRecent} (session=${session.id})`);
|
|
59291
59221
|
}
|
|
59292
59222
|
const work = stripped.body;
|
|
59293
|
-
return countTokens ? prepareCountTokens(work, core, reqConfig, log2, session) : protocol === "anthropic" ? prepareAnthropic(work, req, opts, core, reqConfig, reqPrompts, log2, session, pluginMode
|
|
59223
|
+
return countTokens ? prepareCountTokens(work, core, reqConfig, log2, session) : protocol === "anthropic" ? prepareAnthropic(work, req, opts, core, reqConfig, reqPrompts, log2, session, pluginMode) : protocol === "openai" ? prepareOpenai(work, req, opts, core, reqConfig, reqPrompts, log2, session, pluginMode, nativeWindow) : responsesCompact ? prepareResponsesCompact(stripped.removed > 0 ? Buffer.from(JSON.stringify(work)) : bodyBuffer, work, session, req, core, reqConfig, log2) : prepareResponses(work, req, opts, core, reqConfig, reqPrompts, log2, session, responsesIdentity, pluginMode, upstreamOrigin, nativeWindow);
|
|
59294
59224
|
};
|
|
59295
59225
|
const isCodexCompactTrigger = protocol === "responses" && !responsesCompact && isCodexClient(req.headers) && hasCompactionTrigger(parsed.input);
|
|
59296
59226
|
if (isCodexCompactTrigger) {
|
|
@@ -59378,13 +59308,6 @@ ${bodyBuffer.toString("utf8")}`);
|
|
|
59378
59308
|
}
|
|
59379
59309
|
}
|
|
59380
59310
|
var ACP_TAG_MARK = "<acp ";
|
|
59381
|
-
function withReasoningDrop(msgs, reasoning, log2, sessionId) {
|
|
59382
|
-
const out = dropCompressReasoning(msgs, reasoning);
|
|
59383
|
-
if (out.length !== msgs.length) {
|
|
59384
|
-
log2("info", `[${sessionId}] compress-reasoning: dropped ${msgs.length - out.length} reasoning message(s) from closed compress turns (#651)`);
|
|
59385
|
-
}
|
|
59386
|
-
return out;
|
|
59387
|
-
}
|
|
59388
59311
|
function stripKernelSummaries(messages, state) {
|
|
59389
59312
|
const carried = /* @__PURE__ */ new Set();
|
|
59390
59313
|
for (const b2 of state.blocks) {
|
|
@@ -59486,13 +59409,12 @@ function effectiveTokenCount(session, msgs) {
|
|
|
59486
59409
|
if (!session.metadata.anonymousPrefixAffinity) return 0;
|
|
59487
59410
|
return estimateCoreMessagesUpper(msgs);
|
|
59488
59411
|
}
|
|
59489
|
-
function prepareAnthropic(parsed, req, opts, core, config, prompts, log2, session, pluginMode
|
|
59412
|
+
function prepareAnthropic(parsed, req, opts, core, config, prompts, log2, session, pluginMode) {
|
|
59490
59413
|
const sessionId = session.id;
|
|
59491
59414
|
const stream2 = parsed.stream === true;
|
|
59492
59415
|
++session.stats.requests;
|
|
59493
59416
|
session.hostCreditTokens = 0;
|
|
59494
59417
|
const injectTools = opts.compress.injectTool && !pluginMode;
|
|
59495
|
-
const stripReasoning = (msgs) => withReasoningDrop(msgs, reasoning, log2, sessionId);
|
|
59496
59418
|
if (isAutoModeClassifier(parsed)) {
|
|
59497
59419
|
log2("info", `[${sessionId}] auto-mode classifier passthrough (skipping compress injection)`);
|
|
59498
59420
|
return { body: JSON.stringify(parsed), session, processedMessages: [], originalMessages: [], anthropicSystem: parsed.system, protocol: "anthropic", stream: stream2, compressInjected: false, pluginMode, nudge: void 0, prompts };
|
|
@@ -59530,7 +59452,7 @@ function prepareAnthropic(parsed, req, opts, core, config, prompts, log2, sessio
|
|
|
59530
59452
|
log2("info", diagTagSummary(turn.messages, sessionId, "text-only"));
|
|
59531
59453
|
const willInjectNudge = opts.compress.injectNudge && !!turn.nudge && (turn.nudge.shouldInject || emergencyNudge(turn.nudge));
|
|
59532
59454
|
log2("info", diagNudge(turn, sessionId, tokenCount, config.modelContextLimit, parsed.model, willInjectNudge));
|
|
59533
|
-
processedMessages =
|
|
59455
|
+
processedMessages = stripKernelSummaries(turn.messages, turn.state);
|
|
59534
59456
|
applyCompactionArchive(session, activeBefore, new Set(msgs.map((m2) => m2.id)), log2);
|
|
59535
59457
|
reapOrphanBlocks(session, msgs, deactivateBlock);
|
|
59536
59458
|
rebuiltMessages = coreToAnthropic(processedMessages, cacheControls);
|
|
@@ -59612,13 +59534,12 @@ function clampOutgoingOutput(rebuilt, field, ctx, sessionId, log2) {
|
|
|
59612
59534
|
log2("info", `[${sessionId}] output budget clamped ${raw} -> ${capped} (input~${inputEstimate}, window=${ctx.nativeWindow}); prevents input+output overflow (#453)`);
|
|
59613
59535
|
}
|
|
59614
59536
|
}
|
|
59615
|
-
function prepareOpenai(parsed, req, opts, core, config, prompts, log2, session, pluginMode, nativeWindow
|
|
59537
|
+
function prepareOpenai(parsed, req, opts, core, config, prompts, log2, session, pluginMode, nativeWindow) {
|
|
59616
59538
|
const sessionId = session.id;
|
|
59617
59539
|
const stream2 = parsed.stream === true;
|
|
59618
59540
|
++session.stats.requests;
|
|
59619
59541
|
session.hostCreditTokens = 0;
|
|
59620
59542
|
let openaiSystemText = "";
|
|
59621
|
-
const stripReasoning = (msgs) => withReasoningDrop(msgs, reasoning, log2, sessionId);
|
|
59622
59543
|
let openaiOutboundSystem;
|
|
59623
59544
|
let processedMessages = [];
|
|
59624
59545
|
let originalMessages = [];
|
|
@@ -59656,7 +59577,7 @@ function prepareOpenai(parsed, req, opts, core, config, prompts, log2, session,
|
|
|
59656
59577
|
log2("info", diagTagSummary(turn.messages, sessionId, "text-only"));
|
|
59657
59578
|
const willInjectNudge = opts.compress.injectNudge && !!turn.nudge && shouldInject && (turn.nudge.shouldInject || emergencyNudge(turn.nudge));
|
|
59658
59579
|
log2("info", diagNudge(turn, sessionId, tokenCount, config.modelContextLimit, parsed.model, willInjectNudge));
|
|
59659
|
-
processedMessages =
|
|
59580
|
+
processedMessages = stripKernelSummaries(turn.messages, turn.state);
|
|
59660
59581
|
applyCompactionArchive(session, activeBefore, new Set(msgs.map((m2) => m2.id)), log2);
|
|
59661
59582
|
reapOrphanBlocks(session, msgs, deactivateBlock);
|
|
59662
59583
|
rebuiltMessages = systemToUser(coreToOpenai(processedMessages));
|
|
@@ -59696,12 +59617,11 @@ function prepareOpenai(parsed, req, opts, core, config, prompts, log2, session,
|
|
|
59696
59617
|
markDirty(session);
|
|
59697
59618
|
return { body: JSON.stringify(rebuilt), session, processedMessages, originalMessages, protocol: "openai", stream: stream2, compressInjected: injectTools, pluginMode, nudge, prompts, openaiSystemText, renderTags: "text-only" };
|
|
59698
59619
|
}
|
|
59699
|
-
function prepareResponses(parsed, req, opts, core, config, prompts, log2, session, identity, pluginMode, upstreamOrigin, nativeWindow
|
|
59620
|
+
function prepareResponses(parsed, req, opts, core, config, prompts, log2, session, identity, pluginMode, upstreamOrigin, nativeWindow) {
|
|
59700
59621
|
const sessionId = session.id;
|
|
59701
59622
|
const stream2 = parsed.stream === true;
|
|
59702
59623
|
++session.stats.requests;
|
|
59703
59624
|
session.hostCreditTokens = 0;
|
|
59704
|
-
const stripReasoning = (msgs) => withReasoningDrop(msgs, reasoning, log2, sessionId);
|
|
59705
59625
|
if (reconcileNativeCompactionBoundary(session)) {
|
|
59706
59626
|
log2("info", `[${sessionId}] reconciled ACP state after native Responses compact boundary`);
|
|
59707
59627
|
}
|
|
@@ -59766,7 +59686,7 @@ function prepareResponses(parsed, req, opts, core, config, prompts, log2, sessio
|
|
|
59766
59686
|
log2("info", diagTagSummary(turn.messages, sessionId, "text-only"));
|
|
59767
59687
|
const willInjectNudge = opts.compress.injectNudge && !!turn.nudge && shouldInject && !isCompactionTrigger && (turn.nudge.shouldInject || emergencyNudge(turn.nudge));
|
|
59768
59688
|
log2("info", diagNudge(turn, sessionId, tokenCount, config.modelContextLimit, parsed.model, willInjectNudge));
|
|
59769
|
-
processedMessages = repairResponsesAssistantOrdering(
|
|
59689
|
+
processedMessages = repairResponsesAssistantOrdering(stripKernelSummaries(turn.messages, turn.state), originalMessages);
|
|
59770
59690
|
reapOrphanBlocks(session, msgs, deactivateBlock);
|
|
59771
59691
|
rebuiltInput = patchResponsesInput(projection, processedMessages);
|
|
59772
59692
|
const forgedSummaries = echoReplaced ? [] : session.metadata.codexForgedSummaries ?? [];
|
|
@@ -64401,7 +64321,6 @@ function resolveProxyOrigin() {
|
|
|
64401
64321
|
var TOOL_TIMEOUT_MS = 6e4;
|
|
64402
64322
|
var CONVERSATION_FROM_ENV = process.env.CLAUDE_CODE_SESSION_ID?.trim() || process.env.BILI_CONVERSATION_ID?.trim() || void 0;
|
|
64403
64323
|
var IDENTITY_BINDING = Boolean(process.env.CLAUDE_CODE_SESSION_ID?.trim());
|
|
64404
|
-
var ORPHAN_ADOPT = IDENTITY_BINDING && process.env.BILI_MCP_NO_ORPHAN_ADOPT !== "1";
|
|
64405
64324
|
var manifestTools = [];
|
|
64406
64325
|
var conversationId = CONVERSATION_FROM_ENV;
|
|
64407
64326
|
var registered = false;
|
|
@@ -64434,45 +64353,21 @@ function ensureManifest() {
|
|
|
64434
64353
|
return manifestPromise;
|
|
64435
64354
|
}
|
|
64436
64355
|
async function forwardTool(tool, args, timeoutMs = TOOL_TIMEOUT_MS) {
|
|
64437
|
-
|
|
64438
|
-
let res;
|
|
64439
|
-
try {
|
|
64440
|
-
res = await fetch(`${resolveProxyOrigin()}/__bili/plugin/tool`, {
|
|
64441
|
-
method: "POST",
|
|
64442
|
-
headers: { "content-type": "application/json" },
|
|
64443
|
-
body: JSON.stringify({ conversationId, tool, args }),
|
|
64444
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
64445
|
-
});
|
|
64446
|
-
} catch (err2) {
|
|
64447
|
-
if (err2 instanceof Error && err2.name === "TimeoutError") throw new Error(`tool forward timed out after ${timeoutMs}ms: ${tool}`);
|
|
64448
|
-
throw err2;
|
|
64449
|
-
}
|
|
64450
|
-
const data = await res.json();
|
|
64451
|
-
if (res.ok && data.ok) return data.result ?? "";
|
|
64452
|
-
if (res.status === 404 && attempt === 0 && ORPHAN_ADOPT && conversationId && typeof data.error === "string" && data.error.includes("no model request has arrived")) {
|
|
64453
|
-
if (await adoptLatestActiveConversation()) continue;
|
|
64454
|
-
}
|
|
64455
|
-
throw new Error(data.error ?? `tool forward failed: ${res.status}`);
|
|
64456
|
-
}
|
|
64457
|
-
}
|
|
64458
|
-
async function adoptLatestActiveConversation() {
|
|
64356
|
+
let res;
|
|
64459
64357
|
try {
|
|
64460
|
-
|
|
64461
|
-
|
|
64462
|
-
{
|
|
64463
|
-
|
|
64464
|
-
|
|
64465
|
-
|
|
64466
|
-
|
|
64467
|
-
|
|
64468
|
-
|
|
64469
|
-
`
|
|
64470
|
-
);
|
|
64471
|
-
conversationId = data.conversationId;
|
|
64472
|
-
return true;
|
|
64473
|
-
} catch {
|
|
64474
|
-
return false;
|
|
64358
|
+
res = await fetch(`${resolveProxyOrigin()}/__bili/plugin/tool`, {
|
|
64359
|
+
method: "POST",
|
|
64360
|
+
headers: { "content-type": "application/json" },
|
|
64361
|
+
body: JSON.stringify({ conversationId, tool, args }),
|
|
64362
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
64363
|
+
});
|
|
64364
|
+
} catch (err2) {
|
|
64365
|
+
if (err2 instanceof Error && err2.name === "TimeoutError") throw new Error(`tool forward timed out after ${timeoutMs}ms: ${tool}`);
|
|
64366
|
+
throw err2;
|
|
64475
64367
|
}
|
|
64368
|
+
const data = await res.json();
|
|
64369
|
+
if (!res.ok || !data.ok) throw new Error(data.error ?? `tool forward failed: ${res.status}`);
|
|
64370
|
+
return data.result ?? "";
|
|
64476
64371
|
}
|
|
64477
64372
|
var ERR_TOOL = -32602;
|
|
64478
64373
|
async function handleMessage(msg) {
|