billion-context 0.1.140 → 0.1.142

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 CHANGED
@@ -43467,6 +43467,10 @@ var require_lib = __commonJS({
43467
43467
  }
43468
43468
  });
43469
43469
 
43470
+ // src/index.ts
43471
+ import { realpathSync as realpathSync2 } from "fs";
43472
+ import { fileURLToPath as fileURLToPath8 } from "url";
43473
+
43470
43474
  // node_modules/acp-kernel/dist/chunk-6RNVHY67.js
43471
43475
  import { createRequire } from "module";
43472
43476
  var require2 = createRequire(import.meta.url);
@@ -71415,24 +71419,20 @@ function withSearchContextConversationDescription(tools) {
71415
71419
  return copy;
71416
71420
  });
71417
71421
  }
71418
- function handlePluginManifest(res) {
71422
+ function handlePluginManifest(res, config) {
71423
+ const absorbOn = absorbEnabled(config);
71424
+ const rulesOn = rulesEnabled(config);
71419
71425
  res.writeHead(200, { "content-type": "application/json" });
71420
71426
  res.end(JSON.stringify({
71421
71427
  ok: true,
71422
71428
  protocolVersion: PLUGIN_PROTOCOL_VERSION,
71423
71429
  proxy: "billion-context",
71424
71430
  version: VERSION2,
71425
- // Absorb and acp_rule are advertised alongside the four ACP tools.
71426
- // Both are host-registered opt-in (not in the kernel's
71427
- // ACP_TOOL_NAMES), so the manifest must list them explicitly.
71428
- // Per-session enablement is enforced at execution (isProxyToolFor /
71429
- // executeProxyTool), not here — the manifest has no request context to
71430
- // know which route will win.
71431
- toolNames: [...ACP_TOOL_NAMES, ABSORB_TOOL_NAME, RULE_TOOL_NAME],
71431
+ toolNames: [...ACP_TOOL_NAMES, ...absorbOn ? [ABSORB_TOOL_NAME] : [], ...rulesOn ? [RULE_TOOL_NAME] : []],
71432
71432
  tools: {
71433
- anthropic: withSearchContextConversationDescription([...BILI_ACP_TOOLS_ANTHROPIC, ABSORB_TOOL, RULE_TOOL].map(withConversationIdParam)),
71434
- openai: withSearchContextConversationDescription([...BILI_ACP_TOOLS_OPENAI, ABSORB_TOOL_OPENAI, RULE_TOOL_OPENAI].map(withConversationIdParam)),
71435
- responses: withSearchContextConversationDescription([...BILI_ACP_TOOLS_RESPONSES, ABSORB_TOOL_RESPONSES, RULE_TOOL_RESPONSES].map(withConversationIdParam))
71433
+ anthropic: withSearchContextConversationDescription([...BILI_ACP_TOOLS_ANTHROPIC, ...absorbOn ? [ABSORB_TOOL] : [], ...rulesOn ? [RULE_TOOL] : []].map(withConversationIdParam)),
71434
+ openai: withSearchContextConversationDescription([...BILI_ACP_TOOLS_OPENAI, ...absorbOn ? [ABSORB_TOOL_OPENAI] : [], ...rulesOn ? [RULE_TOOL_OPENAI] : []].map(withConversationIdParam)),
71435
+ responses: withSearchContextConversationDescription([...BILI_ACP_TOOLS_RESPONSES, ...absorbOn ? [ABSORB_TOOL_RESPONSES] : [], ...rulesOn ? [RULE_TOOL_RESPONSES] : []].map(withConversationIdParam))
71436
71436
  },
71437
71437
  headers: { agent: PLUGIN_AGENT_HEADER, conversation: PLUGIN_CONVERSATION_HEADER, contextWindow: PLUGIN_CONTEXT_WINDOW_HEADER, maxOutput: PLUGIN_MAX_OUTPUT_HEADER, model: PLUGIN_MODEL_HEADER, instructionsMutable: PLUGIN_INSTRUCTIONS_MUTABLE_HEADER },
71438
71438
  toolEndpoint: "/__bili/plugin/tool",
@@ -71460,6 +71460,13 @@ function resolveConversation(conversationId2) {
71460
71460
  }
71461
71461
  return { session, entry };
71462
71462
  }
71463
+ function disabledOptionalToolNote(tool, session, config) {
71464
+ const absorbName = effectiveAbsorbConfig(session, config)?.toolName ?? ABSORB_TOOL_NAME;
71465
+ if (tool === absorbName) return `${tool} is not enabled on this bili proxy (compress.absorb.enabled is not true) \u2014 nothing was absorbed.`;
71466
+ if (tool === RULE_TOOL_NAME) return `${tool} is not enabled on this bili proxy (compress.rules.enabled is not true) \u2014 nothing was recorded.`;
71467
+ if (!ccrEnabled(session) && tool === retrieveToolName(session)) return `${tool} is not enabled on this bili proxy (compress.ccr.enabled is not true) \u2014 nothing was retrieved.`;
71468
+ return void 0;
71469
+ }
71463
71470
  function handlePluginStatus(conversationId2, res, deps, fallbackLatest = false) {
71464
71471
  const { session: resolvedSession, entry } = resolveConversation(conversationId2);
71465
71472
  let session = resolvedSession;
@@ -71577,6 +71584,13 @@ async function handlePluginTool(payload, res, deps) {
71577
71584
  return;
71578
71585
  }
71579
71586
  if (!isProxyToolFor(tool, session, deps.config)) {
71587
+ const note = disabledOptionalToolNote(tool, session, deps.config);
71588
+ if (note !== void 0) {
71589
+ deps.log("info", `[${session.id}] [plugin] ${tool} called but disabled \u2014 replied with explanation`);
71590
+ res.writeHead(200, { "content-type": "application/json" });
71591
+ res.end(JSON.stringify({ ok: true, result: note }));
71592
+ return;
71593
+ }
71580
71594
  const allowed = [...ACP_TOOL_NAMES];
71581
71595
  const absorb = effectiveAbsorbConfig(session, deps.config);
71582
71596
  if (absorb?.enabled === true) allowed.push(absorb.toolName ?? ABSORB_TOOL_NAME);
@@ -73073,13 +73087,48 @@ function artifactSeedHit(body) {
73073
73087
  return tagSeed || toolSeed;
73074
73088
  }
73075
73089
  function detectAcpArtifacts(body, parsed) {
73076
- if (body.includes("<acp ") && ACP_TAG_RE.test(body.toString("utf8"))) return "tags";
73090
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
73091
+ const encoded = JSON.stringify(historyTextOf(parsed));
73092
+ if (encoded.includes("<acp ") && ACP_TAG_RE.test(encoded)) return "tags";
73093
+ } else if (body.includes("<acp ") && ACP_TAG_RE.test(body.toString("utf8"))) {
73094
+ return "tags";
73095
+ }
73077
73096
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
73078
73097
  const names = historyToolCallNames(parsed);
73079
73098
  if (names.has("acp_status") && names.has("search_context")) return "tool-history";
73080
73099
  }
73081
73100
  return null;
73082
73101
  }
73102
+ function historyTextOf(parsed) {
73103
+ const parts = [];
73104
+ const container = Array.isArray(parsed.messages) ? parsed.messages : Array.isArray(parsed.input) ? parsed.input : Array.isArray(parsed.contents) ? parsed.contents : null;
73105
+ if (container) {
73106
+ for (const item of container) collectHistoryText(item, parts);
73107
+ }
73108
+ return parts.join("\n");
73109
+ }
73110
+ function collectHistoryText(item, out) {
73111
+ if (!item || typeof item !== "object" || Array.isArray(item)) return;
73112
+ const it2 = item;
73113
+ if (it2.role === "system" || it2.role === "developer") return;
73114
+ const content = it2.content;
73115
+ if (typeof content === "string") out.push(content);
73116
+ else if (Array.isArray(content)) {
73117
+ for (const block of content) {
73118
+ if (block && typeof block === "object" && !Array.isArray(block) && typeof block.text === "string") {
73119
+ out.push(block.text);
73120
+ }
73121
+ }
73122
+ }
73123
+ const parts = it2.parts;
73124
+ if (Array.isArray(parts)) {
73125
+ for (const part of parts) {
73126
+ if (part && typeof part === "object" && !Array.isArray(part) && typeof part.text === "string") {
73127
+ out.push(part.text);
73128
+ }
73129
+ }
73130
+ }
73131
+ }
73083
73132
  function historyToolCallNames(parsed) {
73084
73133
  const names = /* @__PURE__ */ new Set();
73085
73134
  const container = Array.isArray(parsed.messages) ? parsed.messages : Array.isArray(parsed.input) ? parsed.input : Array.isArray(parsed.contents) ? parsed.contents : null;
@@ -73243,6 +73292,10 @@ async function startServer(opts) {
73243
73292
  const log2 = (level, msg) => logMsg(opts, level, msg);
73244
73293
  const instanceId = randomUUID4();
73245
73294
  const instanceStartedAt = Date.now();
73295
+ const parentWatchPid = Number.parseInt(process.env.BILI_PARENT_PID ?? "", 10);
73296
+ const initialWatcherPid = Number.isInteger(parentWatchPid) && parentWatchPid > 0 && parentWatchPid !== process.pid ? parentWatchPid : null;
73297
+ const proxyWatchers = /* @__PURE__ */ new Set();
73298
+ if (initialWatcherPid !== null) proxyWatchers.add(initialWatcherPid);
73246
73299
  await initSessions();
73247
73300
  loadConversations();
73248
73301
  log2("info", `[persist] ${getStore().enabled ? "enabled" : "disabled"}`);
@@ -73263,7 +73316,7 @@ async function startServer(opts) {
73263
73316
  const server = http.createServer(async (req, res) => {
73264
73317
  armRequestWatchdog(req, res, log2);
73265
73318
  try {
73266
- await handle(req, res, opts, core, config, log2, instanceId, instanceStartedAt);
73319
+ await handle(req, res, opts, core, config, log2, instanceId, instanceStartedAt, proxyWatchers, initialWatcherPid);
73267
73320
  } catch (err2) {
73268
73321
  const msg = String(err2);
73269
73322
  const e = err2;
@@ -73419,10 +73472,30 @@ Content-Length: ${Buffer.byteLength(body)}\r
73419
73472
  if (process.platform === "win32") {
73420
73473
  process.on("SIGBREAK", () => shutdown("SIGBREAK"));
73421
73474
  }
73422
- const parentPid = Number.parseInt(process.env.BILI_PARENT_PID ?? "", 10);
73423
- if (Number.isInteger(parentPid) && parentPid > 0 && parentPid !== process.pid) {
73475
+ if (initialWatcherPid !== null) {
73476
+ let idleSince = null;
73477
+ let lastDead = [];
73424
73478
  const watcher = setInterval(() => {
73425
- if (!isPidAlive(parentPid)) shutdown(`parent-gone (pid ${parentPid})`);
73479
+ const dead = [];
73480
+ for (const pid of proxyWatchers) {
73481
+ if (!isPidAlive(pid)) {
73482
+ proxyWatchers.delete(pid);
73483
+ dead.push(pid);
73484
+ }
73485
+ }
73486
+ if (dead.length > 0) lastDead = dead;
73487
+ if (proxyWatchers.size > 0) {
73488
+ idleSince = null;
73489
+ return;
73490
+ }
73491
+ if (idleSince === null) {
73492
+ idleSince = Date.now();
73493
+ return;
73494
+ }
73495
+ if (Date.now() - idleSince >= WATCHER_IDLE_GRACE_MS) {
73496
+ const reason = lastDead.length === 1 && lastDead[0] === initialWatcherPid ? `parent-gone (pid ${lastDead[0]})` : `watchers-gone (pids: ${lastDead.join(", ")})`;
73497
+ shutdown(reason);
73498
+ }
73426
73499
  }, 2e3);
73427
73500
  watcher.unref?.();
73428
73501
  }
@@ -73458,7 +73531,8 @@ function adminTrustedHosts(bindHost, port) {
73458
73531
  return set;
73459
73532
  }
73460
73533
  var headroomFallbackLogged = /* @__PURE__ */ new Set();
73461
- async function handle(req, res, opts, core, config, log2, instanceId, instanceStartedAt) {
73534
+ var WATCHER_IDLE_GRACE_MS = 5e3;
73535
+ async function handle(req, res, opts, core, config, log2, instanceId, instanceStartedAt, proxyWatchers, initialWatcherPid) {
73462
73536
  const selfProbePath = selfAdminProbePath(req.url ?? "", req.socket.localPort);
73463
73537
  if (selfProbePath !== void 0) req.url = selfProbePath;
73464
73538
  const isAdminPath = req.url === "/__bili/" || req.url?.startsWith("/__bili/") || req.url === "/__acp/" || req.url?.startsWith("/__acp/");
@@ -73575,7 +73649,7 @@ async function handle(req, res, opts, core, config, log2, instanceId, instanceSt
73575
73649
  }
73576
73650
  return;
73577
73651
  }
73578
- if (req.method === "GET" && req.url === "/__bili/plugin/manifest") return handlePluginManifest(res);
73652
+ if (req.method === "GET" && req.url === "/__bili/plugin/manifest") return handlePluginManifest(res, config);
73579
73653
  if (req.method === "GET" && req.url?.startsWith("/__bili/plugin/status")) {
73580
73654
  const query = req.url.slice(req.url.indexOf("?") + 1);
73581
73655
  const params = new URLSearchParams(query);
@@ -73587,6 +73661,29 @@ async function handle(req, res, opts, core, config, log2, instanceId, instanceSt
73587
73661
  }
73588
73662
  return handlePluginStatus(conversationId2, res, { core, config, log: log2 }, params.get("fallback") === "latest");
73589
73663
  }
73664
+ if (req.method === "POST" && req.url === "/__bili/watcher") {
73665
+ try {
73666
+ const body = await readBody(req);
73667
+ const parsed2 = JSON.parse(body.toString("utf8"));
73668
+ const pid = parsed2.pid;
73669
+ if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 1 || pid === process.pid) {
73670
+ res.writeHead(400, { "content-type": "application/json" });
73671
+ res.end(JSON.stringify({ ok: false, error: "expected { pid: <integer> }" }));
73672
+ } else if (initialWatcherPid === null) {
73673
+ res.writeHead(409, { "content-type": "application/json" });
73674
+ res.end(JSON.stringify({ ok: false, error: "watchdog not armed (no parent pid) \u2014 this proxy does not take watchers" }));
73675
+ } else {
73676
+ proxyWatchers.add(pid);
73677
+ res.writeHead(200, { "content-type": "application/json" });
73678
+ res.end(JSON.stringify({ ok: true, watchers: proxyWatchers.size }));
73679
+ }
73680
+ return;
73681
+ } catch (err2) {
73682
+ res.writeHead(err2 instanceof BodyTooLargeError ? 413 : 400, { "content-type": "application/json" });
73683
+ res.end(JSON.stringify({ ok: false, error: String(err2) }));
73684
+ return;
73685
+ }
73686
+ }
73590
73687
  if (req.method === "POST" && req.url === "/__bili/plugin/tool") {
73591
73688
  try {
73592
73689
  const body = await readBody(req);
@@ -73894,7 +73991,8 @@ ${bodyBuffer.toString("utf8")}`);
73894
73991
  const sessionId = anonAffinity ? anonAffinity.sessionId : conversation;
73895
73992
  if (artifactSeed) {
73896
73993
  const artifactKind = detectAcpArtifacts(bodyBuffer, parsed);
73897
- if (artifactKind !== null && !hasProcessedState(sessionId, { protocol })) {
73994
+ const pluginAnnounced = pluginAgentHeader(req.headers) !== void 0;
73995
+ if (artifactKind !== null && !pluginAnnounced && !hasProcessedState(sessionId, { protocol })) {
73898
73996
  if (!warnedChainSessions.has(sessionId)) {
73899
73997
  warnedChainSessions.add(sessionId);
73900
73998
  if (warnedChainSessions.size > WARNED_CHAIN_SESSION_CAP) {
@@ -81073,10 +81171,26 @@ async function main() {
81073
81171
  }
81074
81172
 
81075
81173
  // src/index.ts
81076
- main().catch((err2) => {
81077
- console.error("bili: failed to start:", err2);
81078
- process.exit(1);
81079
- });
81174
+ function invokedAsScript() {
81175
+ const argv1 = process.argv[1];
81176
+ if (!argv1) return false;
81177
+ let self2;
81178
+ let invoked;
81179
+ try {
81180
+ self2 = realpathSync2(fileURLToPath8(import.meta.url));
81181
+ invoked = realpathSync2(argv1);
81182
+ } catch {
81183
+ return false;
81184
+ }
81185
+ if (process.platform === "win32") return self2.toLowerCase() === invoked.toLowerCase();
81186
+ return self2 === invoked;
81187
+ }
81188
+ if (invokedAsScript()) {
81189
+ main().catch((err2) => {
81190
+ console.error("bili: failed to start:", err2);
81191
+ process.exit(1);
81192
+ });
81193
+ }
81080
81194
  /*! Bundled license information:
81081
81195
 
81082
81196
  undici/lib/web/fetch/body.js: