github-router 0.3.246 → 0.3.248

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.
@@ -16338,25 +16338,25 @@ async function provisionColbert() {
16338
16338
  }
16339
16339
  async function provisionBinary(asset, dest) {
16340
16340
  const sidecar = `${dest}.sha256`;
16341
- if (existsSync(dest) && await sidecarMatches(sidecar, asset.sha256)) return;
16341
+ if (await installedArtifactIsIntact(sidecar, dest, asset.sha256)) return;
16342
16342
  await mkdir(path.dirname(dest), { recursive: true });
16343
16343
  const archive = await download(asset.url);
16344
16344
  verifySha(archive, asset.sha256, "colgrep binary");
16345
16345
  const member = await extractMember(asset, archive, "colgrep");
16346
16346
  if (!member) throw new Error("colgrep binary not found in archive");
16347
16347
  await atomicWrite(dest, member, true);
16348
- await writeFile(sidecar, asset.sha256).catch(() => {});
16348
+ await writeFile(sidecar, sidecarContent(asset.sha256, member)).catch(() => {});
16349
16349
  }
16350
16350
  async function provisionOrt(asset, dest) {
16351
16351
  const sidecar = `${dest}.sha256`;
16352
- if (existsSync(dest) && await sidecarMatches(sidecar, asset.sha256)) return;
16352
+ if (await installedArtifactIsIntact(sidecar, dest, asset.sha256)) return;
16353
16353
  await mkdir(path.dirname(dest), { recursive: true });
16354
16354
  const archive = await download(asset.url);
16355
16355
  verifySha(archive, asset.sha256, "ONNX Runtime");
16356
16356
  const member = await extractMember(asset, archive, asset.member ?? "");
16357
16357
  if (!member) throw new Error("ORT dylib not found in archive");
16358
16358
  await atomicWrite(dest, member, true);
16359
- await writeFile(sidecar, asset.sha256).catch(() => {});
16359
+ await writeFile(sidecar, sidecarContent(asset.sha256, member)).catch(() => {});
16360
16360
  if (process$1.platform !== "win32" && asset.soname) {
16361
16361
  const link = path.join(path.dirname(dest), asset.soname);
16362
16362
  await rm(link, { force: true }).catch(() => {});
@@ -16431,13 +16431,44 @@ async function atomicWrite(dest, bytes, executable) {
16431
16431
  }
16432
16432
  }
16433
16433
  }
16434
- async function sidecarMatches(sidecar, sha256) {
16434
+ /**
16435
+ * Is the artifact already installed AND still the bytes we installed?
16436
+ *
16437
+ * Sidecar format is two whitespace-separated hashes: the ARCHIVE sha (which
16438
+ * manifest revision this came from) and the INSTALLED-FILE sha (what we wrote
16439
+ * to disk). Both are required.
16440
+ *
16441
+ * The archive hash alone is not enough, and trusting it caused a real outage.
16442
+ * `existsSync(dest) && sidecarMatches(archiveSha)` treats any file at the path
16443
+ * as good, so when a lane-1 test with a leaked `node:os` mock overwrote the
16444
+ * real `colgrep.exe` with a 6-byte stub, provisioning kept short-circuiting on
16445
+ * the still-valid sidecar and never re-downloaded. The smoke test then failed
16446
+ * every launch, removed `.smoke-ok`, and semantic search reported "unavailable
16447
+ * on this host" forever. Only manually deleting the binary could recover it.
16448
+ *
16449
+ * A legacy single-hash sidecar means the installed bytes were never recorded,
16450
+ * so their provenance is unknown. That returns false deliberately: one extra
16451
+ * download self-heals every install already corrupted by the above, which is
16452
+ * the whole point of checking.
16453
+ *
16454
+ * This matches what the model files already do (they hash installed content
16455
+ * before reuse); the binary and ORT were the two that skipped it.
16456
+ */
16457
+ async function installedArtifactIsIntact(sidecar, dest, archiveSha) {
16435
16458
  try {
16436
- return (await readFile(sidecar, "utf8")).trim() === sha256;
16459
+ if (!existsSync(dest)) return false;
16460
+ const [recordedArchive, recordedInstalled] = (await readFile(sidecar, "utf8")).trim().split(/\s+/);
16461
+ if (recordedArchive !== archiveSha) return false;
16462
+ if (!recordedInstalled) return false;
16463
+ return createHash("sha256").update(await readFile(dest)).digest("hex") === recordedInstalled;
16437
16464
  } catch {
16438
16465
  return false;
16439
16466
  }
16440
16467
  }
16468
+ /** Sidecar content pairing the archive revision with the installed bytes. */
16469
+ function sidecarContent(archiveSha, installed) {
16470
+ return `${archiveSha}\n${createHash("sha256").update(installed).digest("hex")}`;
16471
+ }
16441
16472
  /**
16442
16473
  * Post-provision smoke test. Runs ONE cheap colgrep invocation with the
16443
16474
  * EXACT isolating env the runner uses (`COLGREP_DATA_DIR`,
@@ -17689,18 +17720,30 @@ function lexicalSearchCodeMode(mode) {
17689
17720
  * Status-specific, actionable fallback hint. The semantic index isn't ready,
17690
17721
  * so the model got LEXICAL results (great for exact symbols, sparse for a
17691
17722
  * natural-language phrase since the lexical backend matches literally). Tell
17692
- * it both levers: retry `mode:"semantic"` shortly (the index is self-healing
17693
- * in the background) OR re-query now with specific symbol/keyword terms.
17723
+ * it both levers: retry `mode:"semantic"` (the index is self-healing in the
17724
+ * background) OR re-query now with specific symbol/keyword terms.
17725
+ *
17726
+ * "shortly" was too vague and cost a real recovery. A build takes MINUTES on a
17727
+ * large repo, and after a failed build the FIRST query is consumed triggering
17728
+ * the re-kick and still returns a fallback. So a caller who retried once,
17729
+ * seconds later, saw a second fallback and concluded the tool was broken
17730
+ * rather than mid-repair. Observed end to end on this repo: query, then
17731
+ * ~5 minutes of `building`, then `ready`. Naming the timescale and the
17732
+ * one-query-to-trigger behaviour is what turns "it's still broken" into
17733
+ * "it's coming back".
17734
+ *
17735
+ * The wording stays a range rather than a number: build time scales with
17736
+ * repository size, so a hard figure would be wrong for most callers.
17694
17737
  */
17695
17738
  const FALLBACK_GUIDANCE_MARKER = "retry mode:\"semantic\"";
17696
- const FALLBACK_GUIDANCE = `${FALLBACK_GUIDANCE_MARKER} shortly, or re-query now with specific symbol/keyword terms`;
17739
+ const FALLBACK_GUIDANCE = `${FALLBACK_GUIDANCE_MARKER} in a few minutes (a build takes minutes on a large repo), or re-query now with specific symbol/keyword terms`;
17697
17740
  function fallbackNoticeFor(status) {
17698
17741
  const tail = FALLBACK_GUIDANCE;
17699
17742
  switch (status) {
17700
- case "building": return `semantic index is building; returned lexical keyword matches ${tail}`;
17701
- case "stale": return `semantic index predates the current HEAD/tree (a background re-index was started); returned lexical keyword matches ${tail}`;
17702
- case "unavailable": return `no semantic index for this workspace yet (a background build was started); returned lexical keyword matches ${tail}`;
17703
- case "failed": return `semantic index unavailable (build failing see proxy logs); returned lexical keyword matches ${tail}`;
17743
+ case "building": return `semantic index is building; returned lexical keyword matches. ${tail}`;
17744
+ case "stale": return `semantic index predates the current HEAD/tree (a background re-index was started); returned lexical keyword matches. ${tail}`;
17745
+ case "unavailable": return `no semantic index for this workspace yet (a background build was started); returned lexical keyword matches. ${tail}`;
17746
+ case "failed": return `semantic index unavailable; this query started a background rebuild, so it returned lexical keyword matches. ${tail}`;
17704
17747
  default: return "returned lexical results";
17705
17748
  }
17706
17749
  }
@@ -23458,6 +23501,54 @@ function resolveModelAndThinking(opts) {
23458
23501
  if (!clamp) clamp = allowed[0];
23459
23502
  return mkOk(clamp);
23460
23503
  }
23504
+ /** Worker-usable models need a big enough window to be worth delegating to. */
23505
+ const CATALOG_MIN_CONTEXT = 2e5;
23506
+ /**
23507
+ * Derived view of the live catalog: every model a worker could actually be
23508
+ * pointed at, with the metadata needed to choose between them.
23509
+ *
23510
+ * DERIVED ONLY, and that is the whole design. A one-liner like "strong
23511
+ * reasoning, weak long-context recall" cannot be computed from catalog
23512
+ * metadata — it is editorial, it goes stale silently as vendors ship, and the
23513
+ * asymmetry is brutal: a MISSING characterization costs one suboptimal pick
23514
+ * the model recovers from, while a WRONG one misroutes invisibly at the call
23515
+ * site. So this ships facts and lets the caller judge.
23516
+ *
23517
+ * It exists because the hardcoded chains cannot discover anything. Models are
23518
+ * live in the catalog that appear nowhere in `src/` — nobody evaluated them
23519
+ * because nothing surfaced them. That is a DISCOVERABILITY gap, not a
23520
+ * capability gap, which is also why the per-mode and per-agent defaults are
23521
+ * deliberately left alone: they encode cross-lab DECORRELATION policy, not
23522
+ * just quality. `reviewerModel()` must differ from the implementer's lab so a
23523
+ * model never reviews its own output, and no capability table can express
23524
+ * "must differ from whoever produced this". `vendor` is included precisely so
23525
+ * a caller can reason about lab diversity without being handed a ranking.
23526
+ *
23527
+ * Efforts are clamped to WORKER_THINKING_LEVELS: nine live models advertise a
23528
+ * `max` tier above `xhigh` that the worker layer filters out, so showing the
23529
+ * raw array would advertise an effort no worker can request.
23530
+ */
23531
+ function buildCatalogView() {
23532
+ const rows = [];
23533
+ for (const model of state.models?.data ?? []) {
23534
+ const supports = model.capabilities?.supports;
23535
+ const limits = model.capabilities?.limits;
23536
+ if (supports?.tool_calls !== true) continue;
23537
+ const ctx = limits?.max_context_window_tokens ?? 0;
23538
+ if (ctx < CATALOG_MIN_CONTEXT) continue;
23539
+ const efforts = (supports.reasoning_effort ?? []).filter((effort) => WORKER_THINKING_LEVELS.includes(effort));
23540
+ if (efforts.length === 0) continue;
23541
+ rows.push({
23542
+ id: model.id,
23543
+ vendor: model.vendor,
23544
+ ctx,
23545
+ ...limits?.max_output_tokens ? { maxOut: limits.max_output_tokens } : {},
23546
+ efforts,
23547
+ ...model.model_picker_price_category ? { cost: model.model_picker_price_category } : {}
23548
+ });
23549
+ }
23550
+ return rows.sort((a, b) => a.id.localeCompare(b.id));
23551
+ }
23461
23552
  //#endregion
23462
23553
  //#region src/lib/worker-agent/session-defaults.ts
23463
23554
  const MODES = Object.freeze([
@@ -34085,10 +34176,11 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
34085
34176
  thinking
34086
34177
  });
34087
34178
  }
34088
- const table = Object.fromEntries(WORKER_MODES.map((workerMode) => [workerMode, resolveModeDefaults(workerMode)]));
34179
+ const body = { ...Object.fromEntries(WORKER_MODES.map((workerMode) => [workerMode, resolveModeDefaults(workerMode)])) };
34180
+ if (!clearAll && !clear && mode === void 0) body.catalog = buildCatalogView();
34089
34181
  return { content: [{
34090
34182
  type: "text",
34091
- text: JSON.stringify(table)
34183
+ text: JSON.stringify(body)
34092
34184
  }] };
34093
34185
  }
34094
34186
  },
@@ -34972,4 +35064,4 @@ function enumerateInjectedMcpToolNames(groupKeys, opts = {}) {
34972
35064
  //#endregion
34973
35065
  export { searchWeb as $, DEFAULT_CLAUDE_MODEL_FALLBACKS as $t, trustRepo as A, state as An, getTokenCount as At, TEST_DEFAULT_MODEL as B, hasSupportedBrowserInstalled as Bt, fileLastPromptStore as C, fetchWithTransientRetry as Cn, scoutModel as Ct, repoRoot as D, copilotBaseUrl as Dn, shimDefaultsToXhigh as Dt, repoFingerprint as E, GITHUB_API_BASE_URL as En, workerToolsEnabled as Et, EXPLORE_DEFAULT_MODEL as F, createChatCompletions as Ft, buildEnv as G, CONDENSED_OPERATING_SEQUENCE as Gt, resolveModeDefaults as H, extractTarGzMember as Ht, EXPLORE_DEFAULT_THINKING as I, MAX_RESPONSE_BODY_BYTES as It, toolbeltEnabled as J, ArtifactClient as Jt, availableToolCommands as K, DEFINITION_OF_GREATNESS as Kt, IMPLEMENT_DEFAULT_MODEL as L, readResponseBodyCapped as Lt, resolveSealedGate as M, resolveMcpToolTimeoutMs as Mt, BROWSE_DEFAULT_MODEL as N, pickEndpoint as Nt, stopGateEnabledForRepo as O, copilotHeaders as On, countTokens as Ot, DEFAULT_MODEL as P, createResponses as Pt, assetFor as Q, toolbeltPathOverride as Qt, PLAN_DEFAULT_MODEL as R, parseJsonOrDiagnose as Rt, fileFindingsStore as S, getGitHubUser as Sn, reviewerModel as St, isSubagentContext as T, forwardError as Tn, standInToolEnabled as Tt, resolveWorkerRunOpts as U, extractZipMember as Ut, appendPlanReminder as V, provisionAndIndexColbert as Vt, runWorkerAgent as W, warmTreeSitterPool as Wt, vscodeRipgrepPath as X, buildWorkspaceHeaderJson as Xt, toolbeltSkipSet as Y, buildWorkspaceHeaderHelperCommand as Yt, TOOLBELT_TOOLS$1 as Z, collapsePathKeys as Zt, stopGateDisabled as _, isNullish as _n, browserCompoundToolsEnabled as _t, buildPeerAwarenessSnippet as a, generateRandomPort as an, buildAnthropicErrorEvent as at, stopReviewEnabled as b, sleep$3 as bn, geminiAvailable as bt, personasFor as c, withInstallLock as cn, logStreamError as ct, buildStopHookCommand as d, setupGitHubToken as dn, handleMcpDelete as dt, DEFAULT_CODEX_MODEL as en, ADVISOR_INTERNAL_TOOL_NAME as et, captureLaunchBaseline as f, tryRefreshAndRetry as fn, handleMcpPost as ft, launchBaselineKey as g, filterBetaHeader as gn, browseAgentEnabled as gt, injectStopHookIntoSettingsFile as h, cacheVSCodeVersion as hn, brainstormModel as ht, buildAgentPrompt as i, UPSTREAM_INACTIVITY_TIMEOUT_MS as in, isAdvisorRequested as it, liveExec as j, assembleResponsesPayload as jt, stopReviewStateDir as k, githubHeaders as kn, createMessages as kt, buildArtifactOpenHookCommand as l, setupCopilotToken as ln, readIteratorWithTimeout as lt, fileBlockBudget as m, cacheModels as mn, artifactToolsEnabled as mt, MCP_GROUPS as n, DEFAULT_PORT as nn, buildAdvisorStream as nt, buildPeerAwarenessSummary as o, pickClaudeDefault as on, buildOpenAIErrorEvent as ot, decideStopHook as p, cacheCopilotVersion as pn, agentToolsEnabled as pt, buildToolbeltAwareness as q, shouldUseInsecureTls as qt, assertMcpToolSurfaceConsistent as r, UPSTREAM_FETCH_TIMEOUT_MS as rn, injectAdvisorTool as rt, enumerateInjectedMcpToolNames as s, getPackageVersion as sn, isControllerClosedError as st, GROUP_META as t, DEFAULT_CODEX_MODEL_FALLBACKS as tn, ADVISOR_TOOL_INSTRUCTIONS as tt, buildSessionBindHookCommand as u, setupGitHubAgentToken as un, relayAnthropicStream as ut, stopGateId as v, resolveCodexModel as vn, browserToolsEnabled as vt, fileReviewDebounce as w, HTTPError as wn, scribeModel as wt, fileBaselineStore as x, getModels as xn, nativeSubagentModel as xt, stopGatePlanMode as y, resolveModel as yn, fleetToolsEnabled as yt, REVIEW_DEFAULT_MODEL as z, provisionBrowserAssets as zt };
34974
35066
 
34975
- //# sourceMappingURL=peer-mcp-personas-B4r1LmlQ.js.map
35067
+ //# sourceMappingURL=peer-mcp-personas-HWhxZUvf.js.map