github-router 0.3.276 → 0.3.282

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.
Files changed (106) hide show
  1. package/dist/{attribution-settings-VOPvSn6v.js → attribution-settings-srL3gBR9.js} +31 -44
  2. package/dist/attribution-settings-srL3gBR9.js.map +1 -0
  3. package/dist/{auth-CYoRwhC9.js → auth-VUL2Zxvw.js} +3 -3
  4. package/dist/{auth-CYoRwhC9.js.map → auth-VUL2Zxvw.js.map} +1 -1
  5. package/dist/browser-ext/manifest.json +1 -1
  6. package/dist/{check-usage-DDUyg8ZB.js → check-usage-CcLdFPGr.js} +4 -4
  7. package/dist/{check-usage-DDUyg8ZB.js.map → check-usage-CcLdFPGr.js.map} +1 -1
  8. package/dist/{claude-OTHh7iKz.js → claude-DJQjA5oQ.js} +52 -35
  9. package/dist/claude-DJQjA5oQ.js.map +1 -0
  10. package/dist/{codex-tCxK30Su.js → codex-BAXemWpJ.js} +5 -5
  11. package/dist/{codex-tCxK30Su.js.map → codex-BAXemWpJ.js.map} +1 -1
  12. package/dist/{debug-CJgsxoVw.js → debug-CtzYWxpJ.js} +2 -2
  13. package/dist/{debug-CJgsxoVw.js.map → debug-CtzYWxpJ.js.map} +1 -1
  14. package/dist/engine-BvLgh1QI.js +2 -0
  15. package/dist/{gate-discovery-nf7PGgnS.js → gate-discovery-BwtiYKvW.js} +5 -5
  16. package/dist/{gate-discovery-nf7PGgnS.js.map → gate-discovery-BwtiYKvW.js.map} +1 -1
  17. package/dist/{get-copilot-usage-D1OAH0EU.js → get-copilot-usage-B-EDAqQb.js} +2 -2
  18. package/dist/{get-copilot-usage-D1OAH0EU.js.map → get-copilot-usage-B-EDAqQb.js.map} +1 -1
  19. package/dist/hooks.mjs +37870 -0
  20. package/dist/hooks.sha256 +1 -0
  21. package/dist/{internal-artifact-open-BCz9lnq0.js → internal-artifact-open-Dj5Nlq0L.js} +2 -2
  22. package/dist/{internal-artifact-open-BCz9lnq0.js.map → internal-artifact-open-Dj5Nlq0L.js.map} +1 -1
  23. package/dist/{internal-first-mate-guard-7v2CtMA6.js → internal-first-mate-guard-CQdXWjNz.js} +1 -1
  24. package/dist/{internal-first-mate-guard-La0tIjTU.js → internal-first-mate-guard-DMgHg2s6.js} +5 -4
  25. package/dist/{internal-first-mate-guard-La0tIjTU.js.map → internal-first-mate-guard-DMgHg2s6.js.map} +1 -1
  26. package/dist/{internal-plan-review-jRMpHu68.js → internal-plan-review-DRFHET_B.js} +11 -4
  27. package/dist/internal-plan-review-DRFHET_B.js.map +1 -0
  28. package/dist/{internal-prompt-submit-CqWRFCuv.js → internal-prompt-submit-f1LR2P2G.js} +4 -4
  29. package/dist/{internal-prompt-submit-CqWRFCuv.js.map → internal-prompt-submit-f1LR2P2G.js.map} +1 -1
  30. package/dist/{internal-session-bind-BiHWDxuC.js → internal-session-bind-DhZhxJ3T.js} +2 -2
  31. package/dist/{internal-session-bind-BiHWDxuC.js.map → internal-session-bind-DhZhxJ3T.js.map} +1 -1
  32. package/dist/{internal-stop-hook-Ds9LwmZA.js → internal-stop-hook-514RJeHO.js} +68 -20
  33. package/dist/internal-stop-hook-514RJeHO.js.map +1 -0
  34. package/dist/{internal-stop-review-BOFj7R3q.js → internal-stop-review-BBsLcbPG.js} +2 -2
  35. package/dist/{internal-stop-review-BOFj7R3q.js.map → internal-stop-review-BBsLcbPG.js.map} +1 -1
  36. package/dist/{internal-worker-guard-Lu8VHj5k.js → internal-worker-guard-VucpClSi.js} +2 -2
  37. package/dist/{internal-worker-guard-Lu8VHj5k.js.map → internal-worker-guard-VucpClSi.js.map} +1 -1
  38. package/dist/{internal-workspace-header-BRMz0Yql.js → internal-workspace-header-OYgHEnFt.js} +2 -2
  39. package/dist/{internal-workspace-header-BRMz0Yql.js.map → internal-workspace-header-OYgHEnFt.js.map} +1 -1
  40. package/dist/lib/tree-sitter-pool/lifecycle-C7W8D2lx.js +165 -0
  41. package/dist/lib/tree-sitter-pool/lifecycle-Dx0SnP7Z.js +157 -0
  42. package/dist/lib/tree-sitter-pool/worker.js +287 -14
  43. package/dist/{lifecycle-LA4rAuAL.js → lifecycle-B7CHqKlF.js} +2 -2
  44. package/dist/{lifecycle-LA4rAuAL.js.map → lifecycle-B7CHqKlF.js.map} +1 -1
  45. package/dist/lifecycle-CbmHMMSD.js +2 -0
  46. package/dist/{lifecycle-AGXnd-ZY.js → lifecycle-D-rL81tT.js} +2 -2
  47. package/dist/{lifecycle-AGXnd-ZY.js.map → lifecycle-D-rL81tT.js.map} +1 -1
  48. package/dist/lifecycle-DTcZwa7U.js +2 -0
  49. package/dist/lifecycle-K9oVtGde.mjs +16 -0
  50. package/dist/main.js +18 -18
  51. package/dist/{mcp-workspace-header-CGJbNeHb.js → mcp-workspace-header-ucs2SDST.js} +5 -6
  52. package/dist/mcp-workspace-header-ucs2SDST.js.map +1 -0
  53. package/dist/{models-4Q45Q2Dw.js → models-C16mBK2M.js} +3 -3
  54. package/dist/{models-4Q45Q2Dw.js.map → models-C16mBK2M.js.map} +1 -1
  55. package/dist/{orchestration-CpkG8ScN.js → orchestration-CtM6FYNx.js} +2 -2
  56. package/dist/{orchestration-CpkG8ScN.js.map → orchestration-CtM6FYNx.js.map} +1 -1
  57. package/dist/package-root-B-osctCk.js +29 -0
  58. package/dist/package-root-B-osctCk.js.map +1 -0
  59. package/dist/paths-CV9K7Xqm.js +2 -0
  60. package/dist/{paths-j2B7b0DZ.js → paths-wLC0InjX.js} +28 -4
  61. package/dist/paths-wLC0InjX.js.map +1 -0
  62. package/dist/{peer-mcp-personas-DRL_xT4h.js → peer-mcp-personas-l4P4s1fK.js} +471 -186
  63. package/dist/peer-mcp-personas-l4P4s1fK.js.map +1 -0
  64. package/dist/{plan-review-hook-Dk5zTNke.js → plan-review-hook-Lf9ISdF6.js} +5 -6
  65. package/dist/plan-review-hook-Lf9ISdF6.js.map +1 -0
  66. package/dist/{prompt-submit-hook-lvTWwaTV.js → prompt-submit-hook-BlijaOn7.js} +6 -11
  67. package/dist/prompt-submit-hook-BlijaOn7.js.map +1 -0
  68. package/dist/{provision-HzZ547dW.js → provision-DlT34zcf.js} +4 -4
  69. package/dist/{provision-HzZ547dW.js.map → provision-DlT34zcf.js.map} +1 -1
  70. package/dist/self-invocation-CKMjcA5F.js +380 -0
  71. package/dist/self-invocation-CKMjcA5F.js.map +1 -0
  72. package/dist/{serve-CM3OmF4I.js → serve-orGUartp.js} +29 -22
  73. package/dist/serve-orGUartp.js.map +1 -0
  74. package/dist/{server-setup-C9r7jYnz.js → server-setup-BRBe8gW4.js} +63 -7
  75. package/dist/{server-setup-C9r7jYnz.js.map → server-setup-BRBe8gW4.js.map} +1 -1
  76. package/dist/{start-KAUCsDao.js → start-sutbbkwc.js} +3 -3
  77. package/dist/{start-KAUCsDao.js.map → start-sutbbkwc.js.map} +1 -1
  78. package/dist/{stop-gate-hook-CaUrldLh.js → stop-gate-hook-DgJ6sW8N.js} +100 -52
  79. package/dist/stop-gate-hook-DgJ6sW8N.js.map +1 -0
  80. package/dist/{stop-gate-policy-lAabj_pP.js → stop-gate-policy-DG5yYWGn.js} +2 -2
  81. package/dist/{stop-gate-policy-lAabj_pP.js.map → stop-gate-policy-DG5yYWGn.js.map} +1 -1
  82. package/dist/{token-CxPaBEUS.js → token-CnlB0884.js} +2 -2
  83. package/dist/token-CnlB0884.js.map +1 -0
  84. package/dist/{version-_Q1WpsQp.js → version-C8x2hQrZ.js} +14 -2
  85. package/dist/version-C8x2hQrZ.js.map +1 -0
  86. package/dist/{worker-dispatch-Bj1uYyG9.js → worker-dispatch-4O3IWtP0.js} +4 -4
  87. package/dist/worker-dispatch-4O3IWtP0.js.map +1 -0
  88. package/package.json +2 -2
  89. package/dist/attribution-settings-VOPvSn6v.js.map +0 -1
  90. package/dist/claude-OTHh7iKz.js.map +0 -1
  91. package/dist/engine-BKJKMAzh.js +0 -2
  92. package/dist/internal-plan-review-jRMpHu68.js.map +0 -1
  93. package/dist/internal-stop-hook-Ds9LwmZA.js.map +0 -1
  94. package/dist/lifecycle-DCrKbaIU.js +0 -2
  95. package/dist/lifecycle-KKSTKwd6.js +0 -2
  96. package/dist/mcp-workspace-header-CGJbNeHb.js.map +0 -1
  97. package/dist/paths-DN3Nio42.js +0 -2
  98. package/dist/paths-j2B7b0DZ.js.map +0 -1
  99. package/dist/peer-mcp-personas-DRL_xT4h.js.map +0 -1
  100. package/dist/plan-review-hook-Dk5zTNke.js.map +0 -1
  101. package/dist/prompt-submit-hook-lvTWwaTV.js.map +0 -1
  102. package/dist/serve-CM3OmF4I.js.map +0 -1
  103. package/dist/stop-gate-hook-CaUrldLh.js.map +0 -1
  104. package/dist/token-CxPaBEUS.js.map +0 -1
  105. package/dist/version-_Q1WpsQp.js.map +0 -1
  106. package/dist/worker-dispatch-Bj1uYyG9.js.map +0 -1
@@ -1,13 +1,14 @@
1
- import { t as getPackageVersion } from "./version-_Q1WpsQp.js";
2
- import { t as PATHS } from "./paths-j2B7b0DZ.js";
3
- import { A as state, C as GITHUB_GRAPHQL_URL, D as githubAgentGraphQLHeaders, E as copilotVersion, O as githubAgentHeaders, S as GITHUB_API_BASE_URL, T as copilotHeaders, b as sanitizeTransportText, d as resolveModel, f as sleep$2, g as HTTPError, h as isAllowedCopilotHost, i as tryRefreshAndRetry, v as classifyTransportError, w as copilotBaseUrl, x as withTransientRetry, y as fetchWithTransientRetry } from "./token-CxPaBEUS.js";
1
+ import { n as explicitPackageRoot } from "./package-root-B-osctCk.js";
2
+ import { t as getPackageVersion } from "./version-C8x2hQrZ.js";
3
+ import { t as PATHS } from "./paths-wLC0InjX.js";
4
+ import { A as state, C as GITHUB_GRAPHQL_URL, D as githubAgentGraphQLHeaders, E as copilotVersion, O as githubAgentHeaders, S as GITHUB_API_BASE_URL, T as copilotHeaders, b as sanitizeTransportText, d as resolveModel, f as sleep$2, g as HTTPError, h as isAllowedCopilotHost, i as tryRefreshAndRetry, v as classifyTransportError, w as copilotBaseUrl, x as withTransientRetry, y as fetchWithTransientRetry } from "./token-CnlB0884.js";
4
5
  import { a as resolveExecutable, c as runManagedExeCapture, i as parseIntEnv, l as spawnTaskkillBestEffort, r as parseBoolEnv } from "./exec-y8C_MU8A.js";
5
- import { i as registerExitHandlers$1, n as getInstanceUuid, r as recordWorkerRepo, t as WorktreeRegistry } from "./lifecycle-LA4rAuAL.js";
6
- import { t as MCP_WORKSPACE_HEADER } from "./mcp-workspace-header-CGJbNeHb.js";
6
+ import { i as registerExitHandlers$1, n as getInstanceUuid, r as recordWorkerRepo, t as WorktreeRegistry } from "./lifecycle-B7CHqKlF.js";
7
+ import { t as MCP_WORKSPACE_HEADER } from "./mcp-workspace-header-ucs2SDST.js";
7
8
  import { n as ArtifactError, r as applyInsecureTls, t as ArtifactClient } from "./client-CQMfroGV.js";
8
- import { n as isPidAlive$1, r as registerColbertExitHandlers, s as trackChild, t as getColbertInstanceUuid } from "./lifecycle-AGXnd-ZY.js";
9
- import { h as runGateChecks, m as sealedGateIds, p as resolveSealedGate } from "./stop-gate-hook-CaUrldLh.js";
10
- import { t as liveExec } from "./orchestration-CpkG8ScN.js";
9
+ import { n as isPidAlive$1, r as registerColbertExitHandlers, s as trackChild, t as getColbertInstanceUuid } from "./lifecycle-D-rL81tT.js";
10
+ import { f as resolveSealedGate, m as runGateChecks, p as sealedGateIds } from "./stop-gate-hook-DgJ6sW8N.js";
11
+ import { t as liveExec } from "./orchestration-CtM6FYNx.js";
11
12
  import { createRequire } from "node:module";
12
13
  import consola from "consola";
13
14
  import { chmodSync, closeSync, constants, cpSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
@@ -11888,6 +11889,123 @@ function objectProp(description, properties, required) {
11888
11889
  function anyProp(description) {
11889
11890
  return { description };
11890
11891
  }
11892
+ //#endregion
11893
+ //#region src/lib/tree-sitter-assets/files.ts
11894
+ /** WASM assets code search loads from tree-sitter-wasms. */
11895
+ const TREE_SITTER_GRAMMAR_FILES = {
11896
+ typescript: "tree-sitter-typescript.wasm",
11897
+ tsx: "tree-sitter-tsx.wasm",
11898
+ javascript: "tree-sitter-javascript.wasm",
11899
+ python: "tree-sitter-python.wasm",
11900
+ go: "tree-sitter-go.wasm",
11901
+ rust: "tree-sitter-rust.wasm",
11902
+ java: "tree-sitter-java.wasm",
11903
+ c: "tree-sitter-c.wasm",
11904
+ cpp: "tree-sitter-cpp.wasm"
11905
+ };
11906
+ const TREE_SITTER_RUNTIME_FILE = "tree-sitter.wasm";
11907
+ //#endregion
11908
+ //#region src/lib/tree-sitter-assets/provision.ts
11909
+ const PUBLISH_ATTEMPTS = 3;
11910
+ let _provisioned$1 = false;
11911
+ let _inFlight$1;
11912
+ /**
11913
+ * Materialize every required WASM asset. Single-flight and success-cached;
11914
+ * transient failures remain retryable. Never throws to the launcher.
11915
+ */
11916
+ function provisionTreeSitterAssets() {
11917
+ if (_provisioned$1) return Promise.resolve();
11918
+ if (_inFlight$1) return _inFlight$1;
11919
+ _inFlight$1 = Promise.resolve().then(() => provisionImpl()).then((complete) => {
11920
+ if (complete) _provisioned$1 = true;
11921
+ }).finally(() => {
11922
+ _inFlight$1 = void 0;
11923
+ });
11924
+ return _inFlight$1;
11925
+ }
11926
+ function provisionImpl() {
11927
+ try {
11928
+ const require = createRequire(import.meta.url);
11929
+ const grammarPackage = require.resolve("tree-sitter-wasms/package.json");
11930
+ const grammarRoot = path.join(path.dirname(grammarPackage), "out");
11931
+ const runtime = require.resolve("web-tree-sitter/tree-sitter.wasm");
11932
+ const destination = PATHS.TREE_SITTER_ASSETS_DIR;
11933
+ mkdirSync(destination, { recursive: true });
11934
+ let complete = publishAsset(runtime, path.join(destination, TREE_SITTER_RUNTIME_FILE));
11935
+ for (const filename of Object.values(TREE_SITTER_GRAMMAR_FILES)) complete = publishAsset(path.join(grammarRoot, filename), path.join(destination, filename)) && complete;
11936
+ return complete;
11937
+ } catch (err) {
11938
+ consola.debug("[tree-sitter-assets] provisioning skipped:", err);
11939
+ return false;
11940
+ }
11941
+ }
11942
+ /**
11943
+ * Publish through a unique same-directory temporary file. Never remove the
11944
+ * destination first: a concurrent parser must see either the prior complete
11945
+ * file or the new complete file, never a missing/partial path. A losing racer
11946
+ * accepts the winner when its bytes match the source.
11947
+ */
11948
+ function publishAsset(source, destination) {
11949
+ let bytes;
11950
+ try {
11951
+ bytes = readFileSync(source);
11952
+ } catch {
11953
+ return false;
11954
+ }
11955
+ if (matchesContent(destination, bytes)) return true;
11956
+ for (let attempt = 0; attempt < PUBLISH_ATTEMPTS; attempt++) {
11957
+ const tmp = `${destination}.${process.pid}-${attempt}.tmp`;
11958
+ try {
11959
+ writeFileSync(tmp, bytes);
11960
+ renameSync(tmp, destination);
11961
+ return true;
11962
+ } catch {
11963
+ try {
11964
+ rmSync(tmp, { force: true });
11965
+ } catch {}
11966
+ if (matchesContent(destination, bytes)) return true;
11967
+ }
11968
+ }
11969
+ return false;
11970
+ }
11971
+ /**
11972
+ * Whether the published file is byte-identical to the source.
11973
+ *
11974
+ * Content, not size: a grammar upgrade that happens to keep the same byte
11975
+ * length would otherwise never propagate, and the stale copy would shadow the
11976
+ * package's newer file permanently — a silent, self-perpetuating wrong answer.
11977
+ * The size check first keeps the common case to one `stat`.
11978
+ */
11979
+ function matchesContent(file, bytes) {
11980
+ try {
11981
+ const stat = statSync(file);
11982
+ if (!stat.isFile() || stat.size !== bytes.byteLength) return false;
11983
+ return readFileSync(file).equals(bytes);
11984
+ } catch {
11985
+ return false;
11986
+ }
11987
+ }
11988
+ /**
11989
+ * Whether the stable directory holds the COMPLETE asset set: the runtime plus
11990
+ * every grammar.
11991
+ *
11992
+ * Callers must gate on the whole set, never on the one file they are about to
11993
+ * read. web-tree-sitter enforces a language-ABI version between the runtime and
11994
+ * the grammars, so adopting a stable runtime while grammars still come from the
11995
+ * package tree (or the reverse) can pair mismatched builds. That surfaces as a
11996
+ * caught `Language.load` failure, which silently disables structural ranking —
11997
+ * the exact silent degradation this whole change is meant to end.
11998
+ */
11999
+ function stableTreeSitterAssetsComplete() {
12000
+ const dir = PATHS.TREE_SITTER_ASSETS_DIR;
12001
+ return [TREE_SITTER_RUNTIME_FILE, ...Object.values(TREE_SITTER_GRAMMAR_FILES)].every((name) => {
12002
+ try {
12003
+ return statSync(path.join(dir, name)).isFile();
12004
+ } catch {
12005
+ return false;
12006
+ }
12007
+ });
12008
+ }
11891
12009
  /**
11892
12010
  * Extension → grammar key. Grammars not in this map skip structural
11893
12011
  * parsing (the hit falls back to the regex SYMBOL_REGEX heuristic for
@@ -11915,22 +12033,11 @@ const EXTENSION_TO_LANG = {
11915
12033
  ".hxx": "cpp"
11916
12034
  };
11917
12035
  /**
11918
- * Grammar key → wasm filename under `node_modules/tree-sitter-wasms/out/`.
11919
- * Resolved at runtime from `node_modules`; the file paths are stable
11920
- * because `tree-sitter-wasms` ships prebuilt binaries (no per-install
11921
- * codegen).
12036
+ * Grammar key → wasm filename. The stable APP_DIR copy is preferred; the
12037
+ * original `node_modules/tree-sitter-wasms/out/` directory remains the
12038
+ * first-run fallback while background provisioning completes.
11922
12039
  */
11923
- const GRAMMAR_FILES = {
11924
- typescript: "tree-sitter-typescript.wasm",
11925
- tsx: "tree-sitter-tsx.wasm",
11926
- javascript: "tree-sitter-javascript.wasm",
11927
- python: "tree-sitter-python.wasm",
11928
- go: "tree-sitter-go.wasm",
11929
- rust: "tree-sitter-rust.wasm",
11930
- java: "tree-sitter-java.wasm",
11931
- c: "tree-sitter-c.wasm",
11932
- cpp: "tree-sitter-cpp.wasm"
11933
- };
12040
+ const GRAMMAR_FILES = TREE_SITTER_GRAMMAR_FILES;
11934
12041
  /**
11935
12042
  * Per-language definition-shape node types. When a matched identifier
11936
12043
  * sits inside one of these nodes AND is at the node's "name" position,
@@ -12064,12 +12171,16 @@ function getLanguageKeyForPath(filePath) {
12064
12171
  }
12065
12172
  let _grammarBundle;
12066
12173
  /**
12067
- * Resolve the `tree-sitter-wasms/out/` directory at the package root.
12068
- * `require.resolve` is used through a try/catch — the bundled-only
12069
- * fallback runs in environments where node_modules has been pruned to
12070
- * just runtime deps.
12174
+ * Resolve the grammar directory. The stable APP_DIR copy wins only when the
12175
+ * COMPLETE set is present; otherwise `require.resolve` supplies the
12176
+ * package-tree fallback for first launch or a best-effort provisioning failure.
12177
+ *
12178
+ * All-or-nothing on purpose — see `stableTreeSitterAssetsComplete()`: mixing a
12179
+ * stable runtime with package-tree grammars can pair mismatched ABI builds and
12180
+ * silently disable structural ranking.
12071
12181
  */
12072
12182
  function resolveGrammarRoot() {
12183
+ if (stableTreeSitterAssetsComplete()) return PATHS.TREE_SITTER_ASSETS_DIR;
12073
12184
  try {
12074
12185
  const pkgPath = __require.resolve("tree-sitter-wasms/package.json");
12075
12186
  return path$1.join(path$1.dirname(pkgPath), "out");
@@ -12078,6 +12189,15 @@ function resolveGrammarRoot() {
12078
12189
  }
12079
12190
  }
12080
12191
  /**
12192
+ * web-tree-sitter normally resolves this sidecar relative to its JS module.
12193
+ * Prefer the durable copy, but only under the same all-present gate the
12194
+ * grammars use, so the runtime and the grammars always come from one install.
12195
+ */
12196
+ function parserInitOptions() {
12197
+ if (!stableTreeSitterAssetsComplete()) return void 0;
12198
+ return { locateFile: () => path$1.join(PATHS.TREE_SITTER_ASSETS_DIR, TREE_SITTER_RUNTIME_FILE) };
12199
+ }
12200
+ /**
12081
12201
  * Pre-load all grammars at module-init time so the first search
12082
12202
  * doesn't pay a ~500ms cold-start cost. The Promise is captured at
12083
12203
  * import time and awaited per-call; per-grammar failures are caught
@@ -12088,7 +12208,7 @@ function getGrammarBundle() {
12088
12208
  _grammarBundle = { ready: (async () => {
12089
12209
  const out = /* @__PURE__ */ new Map();
12090
12210
  try {
12091
- await Parser.init();
12211
+ await Parser.init(parserInitOptions());
12092
12212
  } catch (err) {
12093
12213
  consola.warn(`[code_search] tree-sitter Parser.init failed; structural ranking disabled: ${err.message}`);
12094
12214
  return out;
@@ -13271,16 +13391,19 @@ const STRUCTURAL_CACHE_MAX = 64;
13271
13391
  const SYMBOL_REGEX = /^(?:export\s+)?(?:default\s+)?(?:async\s+)?(?:public\s+|private\s+|protected\s+|static\s+|abstract\s+|readonly\s+)*(?:function|class|interface|type|enum|def|fn|trait|impl|module|namespace|const|let|var)\s+[A-Za-z_$]/;
13272
13392
  let _rgResolution;
13273
13393
  /**
13274
- * Tri-tier resolution. Memoized. Mirrors cc-backup
13394
+ * Four-tier resolution. Memoized. Mirrors cc-backup
13275
13395
  * `src/utils/ripgrep.ts:31-65`.
13276
13396
  *
13277
13397
  * 1. System rg on PATH — use the literal command name `"rg"` (NOT
13278
13398
  * the absolute path). This leverages NoDefaultCurrentDirectory-
13279
13399
  * InExePath on Windows, preventing PATH-hijacking via a
13280
13400
  * malicious ./rg.exe in the proxy's cwd.
13281
- * 2. Bundled via `@vscode/ripgrep` falls back to the per-platform
13401
+ * 2. Router-owned toolbelt copy under APP_DIR. Its absolute path is
13402
+ * safe because it cannot resolve to a planted binary in the cwd,
13403
+ * and it survives a temp-hosted bunx package tree being reaped.
13404
+ * 3. Bundled via `@vscode/ripgrep` — falls back to the per-platform
13282
13405
  * binary that `optionalDependencies` installed.
13283
- * 3. Throw — surfaced to the caller as an MCP isError response.
13406
+ * 4. Throw — surfaced to the caller as an MCP isError response.
13284
13407
  */
13285
13408
  function resolveRipgrep() {
13286
13409
  if (_rgResolution) return _rgResolution;
@@ -13291,6 +13414,14 @@ function resolveRipgrep() {
13291
13414
  };
13292
13415
  return _rgResolution;
13293
13416
  }
13417
+ const toolbeltPath = path$1.join(PATHS.TOOLBELT_BIN_DIR, process.platform === "win32" ? "rg.exe" : "rg");
13418
+ if (existsSync(toolbeltPath)) {
13419
+ _rgResolution = {
13420
+ rgPath: toolbeltPath,
13421
+ source: "toolbelt"
13422
+ };
13423
+ return _rgResolution;
13424
+ }
13294
13425
  try {
13295
13426
  const mod = __require("@vscode/ripgrep");
13296
13427
  if (mod.rgPath && existsSync(mod.rgPath)) {
@@ -17206,14 +17337,19 @@ function findPackageRoot(startDir, maxHops = 10) {
17206
17337
  }
17207
17338
  }
17208
17339
  /**
17209
- * Resolve the github-router package root. Uses two sources in order:
17210
- * 1. process.argv[1] the entrypoint script, walks up from there.
17211
- * 2. import.meta.url of THIS module, walks up from there.
17212
- * 3. process.cwd() as last resort.
17340
+ * Resolve the github-router package root. Uses sources in order:
17341
+ * 1. The explicit root baked into the relocated hook launcher's argv. From
17342
+ * `<APP_DIR>/hooks/`, neither entrypoint walk can find the package and cwd
17343
+ * is the user's workspace, so this source must win when present.
17344
+ * 2. process.argv[1] — the entrypoint script, walks up from there.
17345
+ * 3. import.meta.url of THIS module, walks up from there.
17346
+ * 4. process.cwd() as last resort.
17213
17347
  *
17214
- * Robust across bun (src/main.ts) and node (dist/main.js) launch paths.
17348
+ * Robust across relocated hooks, bun (src/main.ts), and node (dist/main.js).
17215
17349
  */
17216
17350
  function packageRoot() {
17351
+ const explicit = explicitPackageRoot();
17352
+ if (explicit) return explicit;
17217
17353
  const entryPath = typeof process$1?.argv?.[1] === "string" ? process$1.argv[1] : void 0;
17218
17354
  if (entryPath) {
17219
17355
  const fromEntry = findPackageRoot(path.dirname(entryPath));
@@ -18470,7 +18606,7 @@ function logAudit$1(record) {
18470
18606
  try {
18471
18607
  const fs = await import("node:fs/promises");
18472
18608
  const path = await import("node:path");
18473
- const { PATHS } = await import("./paths-DN3Nio42.js");
18609
+ const { PATHS } = await import("./paths-CV9K7Xqm.js");
18474
18610
  const dir = path.join(PATHS.APP_DIR, "browser-mcp");
18475
18611
  await fs.mkdir(dir, { recursive: true });
18476
18612
  const line = JSON.stringify({
@@ -22715,7 +22851,7 @@ const EMPTY_USAGE = {
22715
22851
  total: 0
22716
22852
  }
22717
22853
  };
22718
- const DEFAULT_MODEL$1 = {
22854
+ const DEFAULT_MODEL = {
22719
22855
  id: "unknown",
22720
22856
  name: "unknown",
22721
22857
  api: "unknown",
@@ -22737,7 +22873,7 @@ function createMutableAgentState(initialState) {
22737
22873
  let messages = initialState?.messages?.slice() ?? [];
22738
22874
  return {
22739
22875
  systemPrompt: initialState?.systemPrompt ?? "",
22740
- model: initialState?.model ?? DEFAULT_MODEL$1,
22876
+ model: initialState?.model ?? DEFAULT_MODEL,
22741
22877
  thinkingLevel: initialState?.thinkingLevel ?? "off",
22742
22878
  get tools() {
22743
22879
  return tools;
@@ -23462,18 +23598,174 @@ function resolveModelAndThinking(opts) {
23462
23598
  if (!clamp) clamp = allowed[0];
23463
23599
  return mkOk(clamp);
23464
23600
  }
23601
+ const CATALOG_PRICE_SCALE = 1e9;
23602
+ const TOKENS_PER_MILLION = 1e6;
23603
+ /**
23604
+ * Last-resort per-1M-token prices, recorded from the live catalog on
23605
+ * 2026-08-12. The LIVE catalog always wins; this only fills in when
23606
+ * `state.models` is unpopulated, which in practice means the startup catalog
23607
+ * fetch failed. Without it the injected roster degrades to bare names and the
23608
+ * model loses the cost signal entirely for that session.
23609
+ *
23610
+ * A hardcoded copy of a value that HAS a live source is a second source of
23611
+ * truth, and this one has already been observed to drift: two figures written
23612
+ * from memory into a commit message (`gpt-5.3-codex` 400/1600, `gpt-5.5`
23613
+ * 500/2000) were both wrong against the live catalog (175/1400 and 500/3000).
23614
+ * That is exactly the silent-misroute failure this table risks, so
23615
+ * `warnOnTokenPriceDrift()` compares it against the live catalog once at
23616
+ * startup and logs any disagreement rather than letting a stale number sit
23617
+ * here indefinitely.
23618
+ *
23619
+ * This is NOT the same trade as `INDICATIVE_TOKENS_PER_SECOND`: throughput
23620
+ * cannot be derived from the catalog at all, so hardcoding is the only option
23621
+ * there. Price can, so hardcoding is strictly a degraded fallback.
23622
+ */
23623
+ const FALLBACK_TOKEN_PRICES = Object.freeze({
23624
+ "gpt-5.6-luna": {
23625
+ in: 20,
23626
+ out: 120
23627
+ },
23628
+ "gpt-5.6-terra": {
23629
+ in: 200,
23630
+ out: 1200
23631
+ },
23632
+ "gpt-5.4-mini": {
23633
+ in: 75,
23634
+ out: 450
23635
+ },
23636
+ "claude-sonnet-5": {
23637
+ in: 200,
23638
+ out: 1e3
23639
+ },
23640
+ "gpt-5.3-codex": {
23641
+ in: 175,
23642
+ out: 1400
23643
+ },
23644
+ "claude-haiku-4.5": {
23645
+ in: 100,
23646
+ out: 500
23647
+ },
23648
+ "claude-opus-5": {
23649
+ in: 500,
23650
+ out: 2500
23651
+ },
23652
+ "gpt-5.6-sol": {
23653
+ in: 500,
23654
+ out: 3e3
23655
+ },
23656
+ "grok-4.5": {
23657
+ in: 200,
23658
+ out: 600
23659
+ },
23660
+ "gpt-5.5": {
23661
+ in: 500,
23662
+ out: 3e3
23663
+ },
23664
+ "gemini-3.6-flash": {
23665
+ in: 150,
23666
+ out: 750
23667
+ },
23668
+ "gemini-3.5-flash": {
23669
+ in: 150,
23670
+ out: 900
23671
+ },
23672
+ "gemini-3.1-pro-preview": {
23673
+ in: 200,
23674
+ out: 1200
23675
+ }
23676
+ });
23677
+ /**
23678
+ * Compare every `FALLBACK_TOKEN_PRICES` entry against the live catalog and warn
23679
+ * on disagreement. Call once after the catalog is populated. Makes fallback
23680
+ * staleness VISIBLE instead of silent: a stale entry only ever surfaces on the
23681
+ * degraded path, where nobody is looking, so without this it could be wrong for
23682
+ * months. Warn-only by design — a price mismatch must never block a launch.
23683
+ */
23684
+ function warnOnTokenPriceDrift() {
23685
+ for (const [id, hardcoded] of Object.entries(FALLBACK_TOKEN_PRICES)) {
23686
+ const live = livePricesFor(id);
23687
+ if (!live) continue;
23688
+ if (live.in !== hardcoded.in || live.out !== hardcoded.out) consola.warn(`[model-resolve] FALLBACK_TOKEN_PRICES is stale for ${id}: hardcoded ${hardcoded.in}/${hardcoded.out}, live catalog ${live.in}/${live.out}. Update the table in src/lib/worker-agent/model-resolve.ts.`);
23689
+ }
23690
+ }
23691
+ /** Live-catalog price lookup with no fallback. Split out so the drift check can
23692
+ * compare against the catalog without the fallback masking a disagreement. */
23693
+ function livePricesFor(modelId) {
23694
+ const prices = state.models?.data.find((model) => model.id === modelId)?.billing?.token_prices;
23695
+ if (!prices || typeof prices.batch_size !== "number" || !Number.isSafeInteger(prices.batch_size) || prices.batch_size <= 0 || typeof prices.input_price !== "number" || !Number.isFinite(prices.input_price) || prices.input_price < 0 || typeof prices.output_price !== "number" || !Number.isFinite(prices.output_price) || prices.output_price < 0) return;
23696
+ const toPerMillion = (price) => price / CATALOG_PRICE_SCALE * TOKENS_PER_MILLION / prices.batch_size;
23697
+ return {
23698
+ in: toPerMillion(prices.input_price),
23699
+ out: toPerMillion(prices.output_price)
23700
+ };
23701
+ }
23702
+ /**
23703
+ * A model's per-1M-token prices: live catalog first, then the dated fallback
23704
+ * table. Still returns undefined for a model in neither, so a caller never
23705
+ * mistakes a guess for a fact — the fallback covers models we have actually
23706
+ * recorded, not every id.
23707
+ */
23708
+ function catalogTokenPrices(modelId) {
23709
+ return livePricesFor(modelId) ?? FALLBACK_TOKEN_PRICES[modelId];
23710
+ }
23711
+ /**
23712
+ * Approximate output tokens/sec, median of n=3 per model, measured 2026-08-12
23713
+ * through this proxy. Reproduce with `bun scripts/bench-model-speed.ts` — the
23714
+ * harness is committed precisely so these numbers can be re-derived and
23715
+ * challenged instead of being trusted. Rounded coarsely on purpose: run-to-run
23716
+ * variance is large (`gpt-5.6-sol` measured 22 in an early n=1 pass and 74 at
23717
+ * n=3), so any digit beyond the leading one or two would be false precision.
23718
+ *
23719
+ * Wall clock includes time-to-first-token, which is why an early n=1 pass put
23720
+ * `gemini-3.1-pro-preview` at 9: that response emitted only 66 tokens, so TTFT
23721
+ * dominated. Reasoning tokens are timed but may not appear in `output_tokens`,
23722
+ * so heavy-reasoning models are penalised here.
23723
+ *
23724
+ * This is a deliberately hardcoded, coarse speed hint, indicative and never a
23725
+ * per-call benchmark: a recoverable speed retry is safer than a quality score
23726
+ * that silently misroutes.
23727
+ *
23728
+ * NOT the whole picture for agent work. The benchmark also measures p50 latency
23729
+ * to a trivial tool call, which is the workload an agent model actually spends
23730
+ * its turns on, and the ordering differs from raw generation: `gpt-5.6-sol`
23731
+ * generates at 75 but takes ~4.3s to reach a tool call, while `gpt-5.6-luna`
23732
+ * takes ~0.9s. That figure is deliberately NOT surfaced to the model, because a
23733
+ * second speed axis invites optimising a routing choice that policy already
23734
+ * settles (see the decorrelation note below).
23735
+ */
23736
+ const INDICATIVE_TOKENS_PER_SECOND = Object.freeze({
23737
+ "gpt-5.6-luna": 120,
23738
+ "gpt-5.6-terra": 100,
23739
+ "gpt-5.4-mini": 100,
23740
+ "claude-sonnet-5": 100,
23741
+ "gpt-5.3-codex": 85,
23742
+ "claude-haiku-4.5": 85,
23743
+ "claude-opus-5": 80,
23744
+ "gpt-5.6-sol": 75,
23745
+ "grok-4.5": 70,
23746
+ "gpt-5.5": 65,
23747
+ "gemini-3.6-flash": 45,
23748
+ "gemini-3.5-flash": 40,
23749
+ "gemini-3.1-pro-preview": 25
23750
+ });
23751
+ /** Returns the approximate, indicative output speed when it was measured. */
23752
+ function indicativeTokensPerSecond(modelId) {
23753
+ return INDICATIVE_TOKENS_PER_SECOND[modelId];
23754
+ }
23465
23755
  /** Worker-usable models need a big enough window to be worth delegating to. */
23466
23756
  const CATALOG_MIN_CONTEXT = 2e5;
23467
23757
  /**
23468
23758
  * Derived view of the live catalog: every model a worker could actually be
23469
23759
  * pointed at, with the metadata needed to choose between them.
23470
23760
  *
23471
- * DERIVED ONLY, and that is the whole design. A one-liner like "strong
23761
+ * Derived facts only, with one explicitly-labelled exception:
23762
+ * `INDICATIVE_TOKENS_PER_SECOND` is a dated, coarse measurement whose speed
23763
+ * signal is recoverable by retrying a slow selection. A one-liner like "strong
23472
23764
  * reasoning, weak long-context recall" cannot be computed from catalog
23473
23765
  * metadata — it is editorial, it goes stale silently as vendors ship, and the
23474
23766
  * asymmetry is brutal: a MISSING characterization costs one suboptimal pick
23475
23767
  * the model recovers from, while a WRONG one misroutes invisibly at the call
23476
- * site. So this ships facts and lets the caller judge.
23768
+ * site. So this ships facts, the recoverable speed hint, and no quality score.
23477
23769
  *
23478
23770
  * It exists because the hardcoded chains cannot discover anything. Models are
23479
23771
  * live in the catalog that appear nowhere in `src/` — nobody evaluated them
@@ -23499,13 +23791,16 @@ function buildCatalogView() {
23499
23791
  if (ctx < CATALOG_MIN_CONTEXT) continue;
23500
23792
  const efforts = (supports.reasoning_effort ?? []).filter((effort) => WORKER_THINKING_LEVELS.includes(effort));
23501
23793
  if (efforts.length === 0) continue;
23794
+ const prices = catalogTokenPrices(model.id);
23795
+ const tps = indicativeTokensPerSecond(model.id);
23502
23796
  rows.push({
23503
23797
  id: model.id,
23504
23798
  vendor: model.vendor,
23505
23799
  ctx,
23506
23800
  ...limits?.max_output_tokens ? { maxOut: limits.max_output_tokens } : {},
23507
23801
  efforts,
23508
- ...model.model_picker_price_category ? { cost: model.model_picker_price_category } : {}
23802
+ ...prices ?? {},
23803
+ ...tps === void 0 ? {} : { tps }
23509
23804
  });
23510
23805
  }
23511
23806
  return rows.sort((a, b) => a.id.localeCompare(b.id));
@@ -26511,13 +26806,12 @@ function geminiAvailable(source = state) {
26511
26806
  * one walk instead of hand-copying it. Ids are matched EXACTLY against
26512
26807
  * `catalog.id` — no slug translation, matching the pre-existing behavior.
26513
26808
  *
26514
- * `minContextTokens` is OPT-IN because the two constraints are genuinely
26515
- * per-agent: the `generic*` chains promise 1M end to end, while `scoutModel`
26516
- * deliberately keeps a 400K last resort for its wider availability. Enforcing
26517
- * the floor here rather than by comment is what stops a chain silently
26518
- * degrading when an id's advertised window shrinks upstream `withOneMSuffix`
26519
- * would then just omit the `[1m]` bracket, and the agent would be budgeted at
26520
- * Claude Code's 200K default with no signal that anything changed.
26809
+ * `minContextTokens` is OPT-IN because the constraint is genuinely per-agent:
26810
+ * the conditional cheaper-tier agents promise 1M end to end. Enforcing the
26811
+ * floor here rather than by comment is what stops a chain silently degrading
26812
+ * when an id's advertised window shrinks upstream `withOneMSuffix` would then
26813
+ * just omit the `[1m]` bracket, and the agent would be budgeted at Claude Code's
26814
+ * 200K default with no signal that anything changed.
26521
26815
  */
26522
26816
  function firstPresentInCatalog(chain, opts) {
26523
26817
  const models = state.models?.data;
@@ -26607,61 +26901,47 @@ function scribeModel() {
26607
26901
  * (same behavior as before `scout` existed) rather than to an expensive
26608
26902
  * impostor wearing the cheap agent's name.
26609
26903
  *
26610
- * `gpt-5.6-luna` sits between the two originals because the old chain fell
26611
- * straight from a 1M model to 400K `gpt-5.4-mini`, which loses the `[1m]`
26612
- * bracket and drops Claude Code's accounting to its 200K default. Luna is
26613
- * cheaper than mini, keeps 1M, and is cross-vendor from the primary, so it
26614
- * covers a Gemini-side outage that a same-vendor entry would not.
26904
+ * `gpt-5.6-luna` leads because it is the cheapest 1M-context model in the
26905
+ * catalog; `gemini-3.6-flash` remains the cross-vendor fallback so an OpenAI-side
26906
+ * outage does not remove the scout. Both entries must continue advertising at
26907
+ * least 1M context so Claude Code's `[1m]` accounting remains honest if an
26908
+ * upstream catalog entry shrinks.
26615
26909
  *
26616
- * Deliberately NO `minContextTokens` floor, unlike the `generic*` resolvers:
26617
- * `gpt-5.4-mini` is retained as the last resort precisely BECAUSE it is the
26618
- * widest-availability id here (its `restricted_to` includes `individual_trial`
26619
- * and `edu`, which neither flash nor luna does). On a thin non-enterprise
26620
- * catalog a 400K scout beats no scout.
26910
+ * This chain deliberately uses literal ids rather than `EXPLORE_DEFAULT_MODEL`:
26911
+ * the explore worker default and scout's cross-vendor fallback are independent
26912
+ * policies, so retuning one must not silently collapse the other. There is no
26913
+ * 400K last resort. On a catalog carrying neither chain member, `scout` is
26914
+ * dropped rather than inheriting the lead or presenting a narrower-context agent.
26621
26915
  */
26916
+ const SCOUT_MODEL_CHAIN = Object.freeze(["gpt-5.6-luna", "gemini-3.6-flash"]);
26622
26917
  function scoutModel() {
26623
- return firstPresentInCatalog([
26624
- EXPLORE_DEFAULT_MODEL,
26625
- "gpt-5.6-luna",
26626
- DEFAULT_MODEL
26627
- ], { requireToolCalls: true });
26628
- }
26629
- /** Model for `generic` — the mid-tier catch-all. Absent → the agent is dropped.
26630
- *
26631
- * `gpt-5.6-sol` is deliberately NOT in this chain: the OpenAI frontier coder is
26632
- * already `implementer`'s job, and a catch-all that quietly costs frontier
26633
- * rates is the opposite of what this agent is for. Both entries are 1M+ and
26634
- * mid-to-high capability, which is the most the description may claim. */
26635
- function genericModel() {
26636
- return firstPresentInCatalog(["gpt-5.6-terra", REVIEW_DEFAULT_MODEL], {
26918
+ return firstPresentInCatalog(SCOUT_MODEL_CHAIN, {
26637
26919
  requireToolCalls: true,
26638
26920
  minContextTokens: ONE_M_TOKENS
26639
26921
  });
26640
26922
  }
26641
- /** Model for `generic-fast` — the Gemini flash tier. Absent → dropped.
26923
+ /** Model for `implementer-fast` — the cheaper implementation tier. Absent →
26924
+ * the agent is dropped.
26642
26925
  *
26643
- * Both entries are the same vendor, context, price point and `minimal..high`
26644
- * effort ladder, so the agent's identity survives the fallback intact. That is
26645
- * why the fallback is `gemini-3.5-flash` and not `gpt-5.6-luna`, which would
26646
- * otherwise be the natural cross-vendor choice: luna is `genericCheapModel`'s
26647
- * only entry, and using it in both places would collapse two roster entries
26648
- * onto one model in the degraded case. */
26649
- function genericFastModel() {
26650
- return firstPresentInCatalog([EXPLORE_DEFAULT_MODEL, "gemini-3.5-flash"], {
26926
+ * `gpt-5.6-sol` is deliberately NOT in this chain: changes needing frontier
26927
+ * judgment already belong to `implementer`, while this agent handles
26928
+ * well-specified, mechanical changes at a lower tier. Both entries are 1M+;
26929
+ * their different speed and effort properties stay out of shared claims. */
26930
+ function implementerFastModel() {
26931
+ return firstPresentInCatalog(["gpt-5.6-terra", REVIEW_DEFAULT_MODEL], {
26651
26932
  requireToolCalls: true,
26652
26933
  minContextTokens: ONE_M_TOKENS
26653
26934
  });
26654
26935
  }
26655
- /** Model for `generic-cheap` — the cheapest catch-all. Absent → dropped.
26936
+ /** Model for `general-purpose-fast` — the fast, cheapest catch-all. Absent →
26937
+ * dropped.
26656
26938
  *
26657
- * Single-entry by design (see `genericFastModel` for why luna is not shared).
26658
- * `gpt-5.6-luna` is the cheapest id in the catalog and undercuts even the 400K
26659
- * `gpt-5.4-mini`, while carrying 1.05M context and the full `none..max` effort
26660
- * ladder so unlike the flash tier it propagates a CLI effort pick above
26661
- * `high` rather than clamping it. No `-mini`/`-lite`/`-haiku` model in the
26662
- * catalog serves 1M, which is why the cheap catch-all is a `gpt-5.6-*` slug
26663
- * rather than a mini one. */
26664
- function genericCheapModel() {
26939
+ * Single-entry by design. `gpt-5.6-luna` is the cheapest model in the live
26940
+ * catalog and measured fastest among the catch-all candidates, while carrying
26941
+ * 1.05M context and the full `none..max` effort ladder. No
26942
+ * `-mini`/`-lite`/`-haiku` model in the catalog serves 1M, which is why this
26943
+ * catch-all uses a `gpt-5.6-*` slug rather than a mini one. */
26944
+ function generalPurposeFastModel() {
26665
26945
  return firstPresentInCatalog(["gpt-5.6-luna"], {
26666
26946
  requireToolCalls: true,
26667
26947
  minContextTokens: ONE_M_TOKENS
@@ -26671,15 +26951,14 @@ function genericCheapModel() {
26671
26951
  * Gate for the worker tools (`explore`, `review`, `implement`).
26672
26952
  *
26673
26953
  * Returns true iff BOTH:
26674
- * 1. Copilot's live catalog (`state.models?.data`) contains the
26675
- * worker default model (`gpt-5.4-mini`, used by explore)
26676
- * AND that entry advertises `capabilities.supports.tool_calls ===
26677
- * true`. The worker loop is function-calling; a model that can't
26678
- * emit tool_calls is unusable, so dormant-register (omit from
26679
- * `tools/list`) keeps the surface honest. (The implement default
26680
- * `gpt-5.6-sol` is NOT gated here — if it's absent, implement calls
26681
- * surface a clean resolve error rather than disabling all worker
26682
- * tools, since explore/review still work.)
26954
+ * 1. Copilot's live catalog (`state.models?.data`) contains any model in the
26955
+ * ordered worker gate chain (`gpt-5.6-luna` → `gpt-5.4-mini`) and that
26956
+ * entry advertises `capabilities.supports.tool_calls === true`. Luna leads
26957
+ * on qualifying tiers; mini preserves the worker surface on individual
26958
+ * trial and education catalogs. The catalog is the entitlement signal.
26959
+ * The worker loop is function-calling, so a model without tool calls is
26960
+ * unusable. Per-mode defaults are NOT gated here — an absent mode default
26961
+ * surfaces a clean resolve error rather than disabling all worker tools.
26683
26962
  * 2. The operator hasn't set `GH_ROUTER_DISABLE_WORKER_TOOLS=1`
26684
26963
  * (opt-out — workers ship enabled by default per plan).
26685
26964
  *
@@ -26688,17 +26967,12 @@ function genericCheapModel() {
26688
26967
  * validation in the engine, which surfaces a clean `isError`
26689
26968
  * envelope with the catalog's eligible model ids on mismatch.
26690
26969
  *
26691
- * `WORKER_DEFAULT_MODEL` is imported (aliased from `DEFAULT_MODEL`)
26692
- * from `src/lib/worker-agent` so the engine owns the single source
26693
- * of truth.
26970
+ * `WORKER_DEFAULT_MODEL_CHAIN` is imported from `src/lib/worker-agent` so the
26971
+ * engine owns the single source of truth for both gating and fallback order.
26694
26972
  */
26695
26973
  function workerToolsEnabled() {
26696
26974
  if (process.env.GH_ROUTER_DISABLE_WORKER_TOOLS === "1") return false;
26697
- const models = state.models?.data;
26698
- if (!models) return false;
26699
- const found = models.find((m) => m.id === DEFAULT_MODEL);
26700
- if (!found) return false;
26701
- return found.capabilities?.supports?.tool_calls === true;
26975
+ return firstPresentInCatalog(DEFAULT_MODEL_CHAIN, { requireToolCalls: true }) != null;
26702
26976
  }
26703
26977
  /**
26704
26978
  * Gate for the compound L2 browser tools (`browser_act`, `browser_observe`,
@@ -26805,10 +27079,10 @@ function artifactToolsEnabled() {
26805
27079
  * browser is on disk. The browse agent drives the SAME Chrome/Edge
26806
27080
  * bridge as the raw `browser_*` tools, so it can't be useful without
26807
27081
  * that surface enabled.
26808
- * 2. The browse default model (`BROWSE_DEFAULT_MODEL`, `gpt-5.4-mini`)
27082
+ * 2. The browse default model (`BROWSE_DEFAULT_MODEL`, `gpt-5.6-luna`)
26809
27083
  * is in Copilot's live catalog AND `pickEndpoint()` resolves a
26810
27084
  * reachable endpoint for it. Unlike `workerToolsEnabled()` (which
26811
- * checks `tool_calls` on the gemini default), the browse default is
27085
+ * checks `tool_calls` on the shared gate sentinel), the browse default is
26812
27086
  * a `/responses`-only gpt-5.x model — `pickEndpoint` is the right
26813
27087
  * reachability probe (it returns undefined only when the model
26814
27088
  * serves neither chat nor responses).
@@ -31561,32 +31835,33 @@ async function saveOverflowPatch(dir) {
31561
31835
  */
31562
31836
  const WORKTREE_REGISTRY = new WorktreeRegistry();
31563
31837
  registerExitHandlers$1(WORKTREE_REGISTRY);
31564
- /** Worker-availability GATE sentinel + final fallback. `gpt-5.4-mini` cheap,
31565
- * broadly-available, tool-call-capable, 400k-context, with tight
31566
- * function-calling-loop discipline (earlier gemini-flash cheap defaults
31567
- * early-stopped with empty turns on the function-calling loop; gpt-5.4-mini
31568
- * does not). Exported and aliased as `WORKER_DEFAULT_MODEL`:
31569
- * `workerToolsEnabled()` gates the ENTIRE worker surface on this id being
31570
- * present with `tool_calls`. It is no longer `explore`'s default (see
31571
- * `EXPLORE_DEFAULT_MODEL`) it stays the gate sentinel because it's the
31572
- * cheapest broadly-present tool-caller, and the fallback for any unmatched
31573
- * mode. */
31574
- const DEFAULT_MODEL = "gpt-5.4-mini";
31838
+ /** Worker-availability gate + unmatched-mode fallback chain. Luna leads where
31839
+ * the live catalog grants access: it is cheaper, faster, and has a larger context
31840
+ * window than mini. Mini remains the broad-tier fallback because individual-trial
31841
+ * and education catalogs may omit Luna. The catalog itself is the entitlement
31842
+ * signal; `billing.restricted_to` describes model policy, not the user's tier.
31843
+ *
31844
+ * `workerToolsEnabled()` admits the worker surface when either entry is present
31845
+ * with `tool_calls`. `resolveDefaultModel()` picks the first usable live entry for
31846
+ * an unmatched worker mode. Per-mode defaults remain independent of the gate. */
31847
+ const DEFAULT_MODEL_CHAIN = Object.freeze(["gpt-5.6-luna", "gpt-5.4-mini"]);
31575
31848
  const DEFAULT_THINKING = "xhigh";
31576
- /** Default model for the READ-ONLY `explore` mode. `gemini-3.6-flash` at `high`
31577
- * (via `EXPLORE_DEFAULT_THINKING`; flash advertises no xhigh) — a fast, cheap,
31578
- * 1M-context tool-caller for read-only repo research. Routes over
31579
- * `/chat/completions` via the translation shim (the same proven path the
31580
- * `review` worker uses for gemini). Like `implement`'s gpt-5.6-sol this is NOT a
31581
- * `workerToolsEnabled` gate input if absent (e.g. a non-enterprise tier)
31582
- * `explore` errors helpfully at call time rather than vanishing the whole worker
31583
- * surface. The caller (the main model) overrides BOTH the model and the reasoning
31584
- * per call via the `model` / `thinking` args see the tier ladder (gpt-5.6-sol
31585
- * heavy / gpt-5.6-terra moderate / gemini-3.6-flash light) in the MCP tool desc. */
31586
- const EXPLORE_DEFAULT_MODEL = "gemini-3.6-flash";
31587
- /** Default thinking for `explore`. `high` (flash has no xhigh); explicit rather
31588
- * than inherited from `DEFAULT_THINKING` so the explore effort can't drift if the
31589
- * shared fallback changes. */
31849
+ function resolveDefaultModel() {
31850
+ const models = state.models?.data ?? [];
31851
+ return DEFAULT_MODEL_CHAIN.find((id) => models.some((model) => model.id === id && model.capabilities?.supports?.tool_calls === true)) ?? DEFAULT_MODEL_CHAIN[0];
31852
+ }
31853
+ /** Default model for the READ-ONLY `explore` mode. `gpt-5.6-luna` at `high`
31854
+ * (via `EXPLORE_DEFAULT_THINKING`) is the measured strict improvement over the
31855
+ * former Gemini Flash default: lower token cost, faster generation and tool-call
31856
+ * latency, a larger context window, and the full reasoning-effort ladder. `high`
31857
+ * is therefore a real selected tier rather than a clamp. Like `implement`'s
31858
+ * gpt-5.6-sol this per-mode default is NOT a `workerToolsEnabled` gate input — if
31859
+ * absent on a thin catalog, `explore` errors helpfully at call time rather than
31860
+ * vanishing the whole worker surface. The caller can override model and thinking
31861
+ * per call via the `model` / `thinking` args. */
31862
+ const EXPLORE_DEFAULT_MODEL = "gpt-5.6-luna";
31863
+ /** Default thinking for `explore`. Explicit rather than inherited from
31864
+ * `DEFAULT_THINKING` so the explore effort cannot drift with the fallback. */
31590
31865
  const EXPLORE_DEFAULT_THINKING = "high";
31591
31866
  /** Default model + thinking for the READ-ONLY `review` mode.
31592
31867
  * `gemini-3.1-pro-preview` at `xhigh` (clamped to `high` at call time — gemini
@@ -31603,41 +31878,44 @@ const EXPLORE_DEFAULT_THINKING = "high";
31603
31878
  const REVIEW_DEFAULT_MODEL = "gemini-3.1-pro-preview";
31604
31879
  const REVIEW_DEFAULT_THINKING = "xhigh";
31605
31880
  /** Default model + thinking for the READ+WRITE `implement` mode. `gpt-5.6-sol`
31606
- * at `xhigh` — the strongest reasoning tier in the catalog, 1M+ context,
31607
- * routed through `/responses` by the stream-fn endpoint split. Coding edits
31608
- * benefit from maximum reasoning; the higher per-call cost is justified for
31609
- * autonomous implementation. An explicit `opts.model` still wins. */
31881
+ * at `high` — a time-to-outcome default for the 1M+ context model, routed
31882
+ * through `/responses` by the stream-fn endpoint split. Any caller can restore
31883
+ * a higher tier per call via `thinking` or per session via `worker_defaults`;
31884
+ * precedence is per-call > session > built-in. */
31610
31885
  const IMPLEMENT_DEFAULT_MODEL = "gpt-5.6-sol";
31611
- const IMPLEMENT_DEFAULT_THINKING = "xhigh";
31612
- /** `test` starts with the same built-in pair as `implement`, but remains an
31613
- * independent mode so either can be overridden without affecting the other. */
31886
+ const IMPLEMENT_DEFAULT_THINKING = "high";
31887
+ /** `test` starts with the same time-to-outcome built-in pair as `implement`, but
31888
+ * remains independent so either mode can restore a higher tier per call via
31889
+ * `thinking` or per session via `worker_defaults`. Resolution precedence is
31890
+ * per-call > session > built-in. */
31614
31891
  const TEST_DEFAULT_MODEL = "gpt-5.6-sol";
31615
- const TEST_DEFAULT_THINKING = "xhigh";
31616
- /** Default model for `browse` mode. `gpt-5.4-mini` the Gate-B-winning
31617
- * browse model (small + fast enough to drive a tab at human pace, with
31618
- * enough tool-calling discipline to terminate). This is DISTINCT from the
31619
- * gemini worker `DEFAULT_MODEL`: browse is a different workload (drive a
31620
- * page, not read a repo) and was tuned separately. May be retuned after
31621
- * the flash-vs-mini eval settles. Routed through `/responses` by the
31622
- * stream-fn's endpoint split (it's a gpt-5.x model). Caller can override
31892
+ const TEST_DEFAULT_THINKING = "high";
31893
+ /** Default model for `browse` mode. `gpt-5.6-luna` has the same measured image
31894
+ * ceiling as `gpt-5.4-mini`, so screenshot-heavy sessions retain their input
31895
+ * capacity, and endpoint routing is derived from the live catalog. Luna's full
31896
+ * reasoning-effort ladder preserves the independent `high` browse default.
31897
+ * This is deliberately a per-mode default even though it also leads
31898
+ * `DEFAULT_MODEL_CHAIN`; the general worker gate remains tier-adaptive while
31899
+ * browse still applies its independent reachability gate. Caller can override
31623
31900
  * per call via the `model` arg.
31624
31901
  *
31625
31902
  * Exported so the MCP browse handler reads the same constant — drift
31626
31903
  * between the two would ship a tool whose docs disagree with its runtime
31627
31904
  * default. */
31628
- const BROWSE_DEFAULT_MODEL = "gpt-5.4-mini";
31905
+ const BROWSE_DEFAULT_MODEL = "gpt-5.6-luna";
31629
31906
  /** Default thinking for `browse`. Higher than the page-driving workload
31630
31907
  * strictly needs, but the termination discipline benefits from it. */
31631
31908
  const BROWSE_DEFAULT_THINKING = "high";
31632
- /** Default model + thinking for the read-only `plan` mode. `claude-opus-4.8`
31633
- * at `xhigh` planning is the highest-leverage read-only step (the plan
31634
- * shapes everything downstream), so it gets the strongest reasoning model
31635
- * rather than the lightweight `gemini-3.6-flash` explore default. Uses the DOTTED
31636
- * Copilot catalog id (the worker resolver exact-matches `catalog.id`, it does
31637
- * NOT translate the Anthropic dashed slug; `claude-opus-5` is a single-segment
31638
- * slug so dotted == dashed). Falls back to a helpful unknown-model error at call
31639
- * time if opus-5 isn't in the catalog (e.g. a non-enterprise tier), exactly like
31640
- * `implement`'s `gpt-5.6-sol`. Caller's `model` arg still wins. */
31909
+ /** Default model + thinking for the read-only `plan` mode. `claude-opus-5`
31910
+ * at `high` favours time-to-outcome while retaining the strongest planning
31911
+ * model rather than the lightweight `gpt-5.6-luna` explore default. Any
31912
+ * caller can restore a higher tier per call via `thinking` or per session via
31913
+ * `worker_defaults`; precedence is per-call > session > built-in. Uses the
31914
+ * DOTTED Copilot catalog id (the worker resolver exact-matches `catalog.id`, it
31915
+ * does NOT translate the Anthropic dashed slug; `claude-opus-5` is a
31916
+ * single-segment slug so dotted == dashed). Falls back to a helpful unknown-model
31917
+ * error at call time if opus-5 isn't in the catalog (e.g. a non-enterprise tier),
31918
+ * exactly like `implement`'s `gpt-5.6-sol`. */
31641
31919
  const PLAN_DEFAULT_MODEL = "claude-opus-5";
31642
31920
  const BUILT_IN_MODE_DEFAULTS = Object.freeze({
31643
31921
  explore: {
@@ -31650,7 +31928,7 @@ const BUILT_IN_MODE_DEFAULTS = Object.freeze({
31650
31928
  },
31651
31929
  plan: {
31652
31930
  model: PLAN_DEFAULT_MODEL,
31653
- thinking: "xhigh"
31931
+ thinking: "high"
31654
31932
  },
31655
31933
  implement: {
31656
31934
  model: IMPLEMENT_DEFAULT_MODEL,
@@ -31665,10 +31943,10 @@ const BUILT_IN_MODE_DEFAULTS = Object.freeze({
31665
31943
  thinking: BROWSE_DEFAULT_THINKING
31666
31944
  }
31667
31945
  });
31668
- /** Resolve the effective mode ladder without changing the gate sentinel. */
31946
+ /** Resolve the effective mode ladder without changing the worker gate. */
31669
31947
  function resolveModeDefaults(mode, ignoreSessionDefaults = false) {
31670
31948
  const builtIn = BUILT_IN_MODE_DEFAULTS[mode] ?? {
31671
- model: "gpt-5.4-mini",
31949
+ model: resolveDefaultModel(),
31672
31950
  thinking: DEFAULT_THINKING
31673
31951
  };
31674
31952
  const override = ignoreSessionDefaults ? {} : getWorkerSessionDefault(mode);
@@ -33720,7 +33998,7 @@ const PERSONAS_READ = Object.freeze([
33720
33998
  toolNameHttp: "codex_reviewer",
33721
33999
  model: "gpt-5.3-codex",
33722
34000
  endpoint: "/v1/responses",
33723
- description: "Line-level code reviewer backed by gpt-5.3-codex (OpenAI, ≈272K-token input window), a code-specialist reviewer that is fastest around high effort (~16s at high effort). It reviews concrete diffs, files, or function bodies and returns findings with severity, file:line locations, issue impact, and a minimal suggested fix. Use when the artifact is actual code and the goal is bug, edge-case, security, concurrency, resource, or idiom review. Not for architecture or tradeoff review, use codex_critic or gemini_critic; pass the diff or file content verbatim.",
34001
+ description: "Line-level code reviewer backed by gpt-5.3-codex (OpenAI, ≈272K-token input window), a code specialist for line-level review. It reviews concrete diffs, files, or function bodies and returns findings with severity, file:line locations, issue impact, and a minimal suggested fix. Use when the artifact is actual code and the goal is bug, edge-case, security, concurrency, resource, or idiom review. Not for architecture or tradeoff review, use codex_critic or gemini_critic; pass the diff or file content verbatim.",
33724
34002
  baseInstructions: REVIEWER_BASE,
33725
34003
  agentPrompt: "",
33726
34004
  writeCapable: false,
@@ -33912,13 +34190,8 @@ function buildPeerAwarenessSnippet(opts) {
33912
34190
  const codexCliClause = opts.codexCli ? " `mcp__codex-cli__codex` dispatches to `codex-implementer` (gpt-5.3-codex with workspace-write) for end-to-end coding tasks." : "";
33913
34191
  const para2Parts = [`\`mcp__${searchKey}__code\` is the one-stop code search (no extra model call). Its DEFAULT mode (or \`mode:"semantic"\`) ranks by MEANING via ColBERT over a per-workspace index, the first thing to reach for on intent/concept questions ("where is retry/backoff handled", "how does auth work"); when that index isn't ready it transparently falls back to lexical (the response \`source\` says which engine ran). Forced modes cover the rest: \`lexical\` (BM25F-ranked + tree-sitter, best for exact symbols), \`exact\`, \`regex\`, \`complete\` (exhaustive set), \`ast_pattern\`+\`ast_lang\` for multi-line AST shapes, \`scan\` for a whole-workspace symbol outline, \`multiline\` for cross-line regex. Multiple queries can run in a single turn. The index covers code-shaped files; for unstructured files (logs, \`.csv\`, \`.env*\`, config-only wiring), \`grep\`/\`glob\` still apply.`];
33914
34192
  if (opts.workerToolsAvailable) para2Parts.push(`\`worker-*\` are background Agent subagents (subagent_type) that run the matching worker in its own context and deliver the result as a completion notification, so a long run never blocks the turn: \`worker-explore\` (read-only research), \`worker-review\` (reads the code to verify a change or claim), \`worker-plan\` (ordered implementation plan), \`worker-implement\` (edit/write/bash; ALWAYS runs in an isolated git worktree and returns the diff via a saved patch file; for in-place edits use the \`implementer\` subagent), \`worker-test\` (independent test author; also always worktree-isolated)${opts.browseAvailable ? ", `worker-browse` (autonomous browser agent driving a real browser)" : ""}. The raw \`mcp__${workersKey}__*\` tools they call are guarded (a direct main-thread call is redirected to the matching agent); Workers themselves have \`code_search\`.`);
33915
- const catchAllNames = [
33916
- opts.genericAvailable === false ? void 0 : "`generic`",
33917
- opts.genericFastAvailable === false ? void 0 : "`generic-fast`",
33918
- opts.genericCheapAvailable === false ? void 0 : "`generic-cheap`"
33919
- ].filter((n) => n != null);
33920
- const catchAllClause = catchAllNames.length > 0 ? ` Catch-alls on non-lead models, for work no specialist fits, cheapest last: ${catchAllNames.join(", ")}.` : "";
33921
- para2Parts.push(`Native subagents (Task), each in its own context so heavy work never fills yours: \`implementer\` (you know what to build), \`reviewer\` (something exists and you want it assessed, including reproducing and root-causing a failure), \`brainstorm\` (you do not yet know which approach to take)${opts.scoutAvailable === false ? "" : ", `scout` (find or understand something in the repo, cheap)"}, \`scribe\` (docs and ADRs that trail the code).${catchAllClause}`);
34193
+ const catchAllClause = opts.generalPurposeFastAvailable === false ? "" : " Catch-all on a fast, economical non-lead model for work no specialist fits: `general-purpose-fast`.";
34194
+ para2Parts.push(`Native subagents (Task), each in its own context so heavy work never fills yours: \`implementer\` (coding changes needing judgment or with ambiguous scope)${opts.implementerFastAvailable === false ? "" : ", `implementer-fast` (well-specified, mechanical coding changes)"}, \`reviewer\` (something exists and you want it assessed, including reproducing and root-causing a failure), \`brainstorm\` (you do not yet know which approach to take)${opts.scoutAvailable === false ? "" : ", `scout` (find or understand something in the repo, cheap)"}, \`scribe\` (docs and ADRs that trail the code).${catchAllClause}`);
33922
34195
  if (opts.workerToolsAvailable) para2Parts.push(`For a bounded, well-scoped implementation, prefer the \`implementer\` subagent over \`worker-implement\`; reach for \`worker-implement\` only when you specifically need git-worktree isolation, parallel variants, or a throwaway experiment.`);
33923
34196
  if (opts.workerToolsAvailable) para2Parts.push(`\`mcp__${orchestrateKey}__decompose\` composes an open-ended ask into a typed, VERIFIED workflow IR (a strong driver decorrelated by a cross-lab critic, so the decompose step isn't a single point of failure), and \`mcp__${orchestrateKey}__run_workflow\` executes that IR through a frozen kernel delivering max(orchestrated, baseline) over a sealed executable gate, so it never ships worse than a plain single-model run. \`mcp__${orchestrateKey}__verify_workflow\` checks an IR's floor invariants before you run it, and \`mcp__${orchestrateKey}__attest_step\` audits that a finished run's producers were each checked by a different lab. They suit non-trivial, role-separated asks; a trivial ask does not need them.`);
33924
34197
  else para2Parts.push(`\`mcp__${orchestrateKey}__verify_workflow\` statically checks a workflow IR's floor invariants and \`mcp__${orchestrateKey}__attest_step\` audits a run's cross-lab lineage (the \`decompose\`/\`run_workflow\` composer + kernel need the worker backend, unavailable here).`);
@@ -33951,15 +34224,27 @@ function buildPeerAwarenessSnippet(opts) {
33951
34224
  */
33952
34225
  function buildPeerAwarenessSummary(opts) {
33953
34226
  const key = (g) => opts.groupKeys?.[g] ?? GROUP_META[g].preferredKey;
33954
- const summaryCatchAlls = [
33955
- opts.genericAvailable === false ? void 0 : "`generic`",
33956
- opts.genericFastAvailable === false ? void 0 : "`generic-fast`",
33957
- opts.genericCheapAvailable === false ? void 0 : "`generic-cheap`"
34227
+ const renderNative = (name) => {
34228
+ const modelId = opts.nativeAgentModels?.[name];
34229
+ if (!modelId) return `\`${name}\``;
34230
+ const prices = catalogTokenPrices(modelId);
34231
+ const tps = indicativeTokensPerSecond(modelId);
34232
+ if (!prices || tps == null) return `\`${name}\``;
34233
+ return `\`${name}\` ${prices.in}/${prices.out} ~${tps}t/s`;
34234
+ };
34235
+ const summaryNativeNames = [
34236
+ renderNative("implementer"),
34237
+ opts.implementerFastAvailable === false ? void 0 : renderNative("implementer-fast"),
34238
+ renderNative("reviewer"),
34239
+ renderNative("brainstorm"),
34240
+ opts.scoutAvailable === false ? void 0 : renderNative("scout"),
34241
+ renderNative("scribe"),
34242
+ opts.generalPurposeFastAvailable === false ? void 0 : renderNative("general-purpose-fast")
33958
34243
  ].filter((n) => n != null);
33959
34244
  const lines = [
33960
34245
  "## Injected capabilities (summary)",
33961
34246
  "",
33962
- `Native subagents (Task), each in its own context: \`implementer\` (you know what to build), \`reviewer\` (something exists and you want it assessed, including reproducing and root-causing a failure), \`brainstorm\` (you do not yet know which approach to take)${opts.scoutAvailable === false ? "" : ", `scout` (find or understand something in the repo, cheap)"}, \`scribe\` (docs and ADRs that trail the code).${summaryCatchAlls.length > 0 ? ` Catch-alls on non-lead models for work no specialist fits, cheapest last: ${summaryCatchAlls.join(", ")}.` : ""} They read the repo and can run things; the peer critics below cannot, so reach for \`reviewer\` when an assessment needs execution or repo context and for a critic when you already hold the artifact.`,
34247
+ `${summaryNativeNames.some((n) => /\d/.test(n)) ? "Native subagents (Task), own context. Cost is per 1M tokens in/out, tok/s approximate:" : "Native subagents (Task), each in its own context:"} ${summaryNativeNames.join(", ")}. Each agent's own description states when it applies. They read the repo and can run things; the peer critics below cannot, so reach for \`reviewer\` when an assessment needs execution or repo context and for a critic when you already hold the artifact.`,
33963
34248
  `A layer of MCP tools, background workers, and skills is injected into this session. Cross-lab peer critics under \`mcp__${key("peers")}__*\` (plus the \`peer-review-coordinator\` subagent) review plans and diffs adversarially, and Claude Code's built-in \`advisor\` catches approach drift. \`mcp__${key("search")}__code\` is meaning-first code search and \`mcp__${key("search")}__web\` returns citable web sources.`
33964
34249
  ];
33965
34250
  if (opts.workerToolsAvailable) lines.push(`Background \`worker-*\` agents (explore, review, plan, implement, test${opts.browseAvailable ? ", browse" : ""}) run delegated work in their own context without blocking your turn, and \`mcp__${key("orchestrate")}__*\` composes, verifies, and runs floor-raising workflows.`);
@@ -34262,7 +34547,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
34262
34547
  toolNameHttp: "explore",
34263
34548
  group: "workers",
34264
34549
  capability: "worker",
34265
- description: "Runs as the background `worker-explore` agent. Dispatch via the Agent tool (subagent_type: worker-explore) so the turn is never blocked; the result arrives as a completion notification. Read-only investigation by an autonomous worker (Pi runtime; default model `gemini-3.6-flash` at high reasoning, override via the `model` arg with any Copilot-catalog model that advertises `tool_calls`). It has read, glob, grep, semantic-first code search, web search, fetch_url, advisor, update_plan, and read-only toolbelt tools, and it returns a single text answer. Use for bounded research, repo discovery, dependency investigation, or multi-file reading that would otherwise consume the lead context window. Not for implementation, test authoring, or verification of a concrete diff; use implement, test, or review for those scopes. Brief the investigation goal and constraints, not step-by-step tool semantics. Strictly read-only: it changes nothing on disk, and its returned text is the only artifact it produces — route to `implement` or `test` when a file actually needs to change. If the result is too large to relay it is truncated to a preview and the FULL text is written to a file, whose absolute path is in the returned text; read that file rather than re-running the worker.",
34550
+ description: "Runs as the background `worker-explore` agent. Dispatch via the Agent tool (subagent_type: worker-explore) so the turn is never blocked; the result arrives as a completion notification. Read-only investigation by an autonomous worker (Pi runtime; default model `gpt-5.6-luna` at high reasoning, override via the `model` arg with any Copilot-catalog model that advertises `tool_calls`). It has read, glob, grep, semantic-first code search, web search, fetch_url, advisor, update_plan, and read-only toolbelt tools, and it returns a single text answer. Use for bounded research, repo discovery, dependency investigation, or multi-file reading that would otherwise consume the lead context window. Not for implementation, test authoring, or verification of a concrete diff; use implement, test, or review for those scopes. Brief the investigation goal and constraints, not step-by-step tool semantics. Strictly read-only: it changes nothing on disk, and its returned text is the only artifact it produces — route to `implement` or `test` when a file actually needs to change. If the result is too large to relay it is truncated to a preview and the FULL text is written to a file, whose absolute path is in the returned text; read that file rather than re-running the worker.",
34266
34551
  inputSchema: {
34267
34552
  type: "object",
34268
34553
  required: ["prompt"],
@@ -34274,7 +34559,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
34274
34559
  },
34275
34560
  model: {
34276
34561
  type: "string",
34277
- description: "Optional Copilot catalog model id (defaults to gemini-3.6-flash). Must advertise tool_calls support; the engine emits an isError envelope listing the eligible catalog models on mismatch. Override by task weight: `gpt-5.6-sol` (heavy/deep), `gpt-5.6-terra` (moderate), `gemini-3.6-flash` (light/cheap) — all 1M context; pair with thinking:'high'."
34562
+ description: "Optional Copilot catalog model id (defaults to gpt-5.6-luna). Must advertise tool_calls support; the engine emits an isError envelope listing the eligible catalog models on mismatch. Override by task weight: `gpt-5.6-sol` (heavy/deep), `gpt-5.6-terra` (moderate), `gpt-5.6-luna` (light/cheap) — all 1M context; pair with thinking:'high'."
34278
34563
  },
34279
34564
  thinking: {
34280
34565
  type: "string",
@@ -34303,7 +34588,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
34303
34588
  toolNameHttp: "implement",
34304
34589
  group: "workers",
34305
34590
  capability: "worker",
34306
- description: "Runs as the background `worker-implement` agent. Dispatch via the Agent tool (subagent_type: worker-implement) so the turn is never blocked; the result arrives as a completion notification. Delegates a scoped coding task to an autonomous worker (Pi runtime; default model `gpt-5.6-sol` at xhigh reasoning, override via `model` with any Copilot-catalog model that advertises `tool_calls`). It has the explore read-only tools plus edit, write, bash, and codex_review, and it returns its final text with any changed files or worktree diff. Use for bounded implementation work that may take a while or benefits from isolated worker context. Not for pure research, planning, review, or independent test authoring; use explore, plan, review, or test for those scopes. ALWAYS runs in an isolated git worktree and returns the diff via a saved patch file (a `--stat` summary + a bounded preview + the patch path; a small diff is inlined in full) — it never edits your working tree, and it HARD-ERRORS if the workspace is not a git repository. For in-place edits, use the native `implementer` subagent. If the result is too large to relay it is truncated to a preview and the FULL text is written to a file, whose absolute path is in the returned text; read that file rather than re-running the worker.",
34591
+ description: "Runs as the background `worker-implement` agent. Dispatch via the Agent tool (subagent_type: worker-implement) so the turn is never blocked; the result arrives as a completion notification. Delegates a scoped coding task to an autonomous worker (Pi runtime; default model `gpt-5.6-sol` at high reasoning, override via `model` with any Copilot-catalog model that advertises `tool_calls`). It has the explore read-only tools plus edit, write, bash, and codex_review, and it returns its final text with any changed files or worktree diff. Use for bounded implementation work that may take a while or benefits from isolated worker context. Not for pure research, planning, review, or independent test authoring; use explore, plan, review, or test for those scopes. ALWAYS runs in an isolated git worktree and returns the diff via a saved patch file (a `--stat` summary + a bounded preview + the patch path; a small diff is inlined in full) — it never edits your working tree, and it HARD-ERRORS if the workspace is not a git repository. For in-place edits, use the native `implementer` subagent. If the result is too large to relay it is truncated to a preview and the FULL text is written to a file, whose absolute path is in the returned text; read that file rather than re-running the worker.",
34307
34592
  inputSchema: {
34308
34593
  type: "object",
34309
34594
  required: ["prompt"],
@@ -34319,7 +34604,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
34319
34604
  },
34320
34605
  model: {
34321
34606
  type: "string",
34322
- description: "Optional Copilot catalog model id (defaults to gpt-5.6-sol). Must advertise tool_calls support; the engine emits an isError envelope listing the eligible catalog models on mismatch. Override by task weight: `gpt-5.6-sol` (heavy/deep), `gpt-5.6-terra` (moderate), `gemini-3.6-flash` (light/cheap) — all 1M context; pair with thinking:'high'."
34607
+ description: "Optional Copilot catalog model id (defaults to gpt-5.6-sol). Must advertise tool_calls support; the engine emits an isError envelope listing the eligible catalog models on mismatch. Override by task weight: `gpt-5.6-sol` (heavy/deep), `gpt-5.6-terra` (moderate), `gpt-5.6-luna` (light/cheap) — all 1M context; pair with thinking:'high'."
34323
34608
  },
34324
34609
  thinking: {
34325
34610
  type: "string",
@@ -34360,7 +34645,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
34360
34645
  },
34361
34646
  model: {
34362
34647
  type: "string",
34363
- description: "Optional Copilot catalog model id (defaults to gemini-3.1-pro-preview). Must advertise tool_calls support; the engine emits an isError envelope listing the eligible catalog models on mismatch. Override by task weight: `gpt-5.6-sol` (heavy/deep), `gpt-5.6-terra` (moderate), `gemini-3.6-flash` (light/cheap) — all 1M context; pair with thinking:'high'."
34648
+ description: "Optional Copilot catalog model id (defaults to gemini-3.1-pro-preview). Must advertise tool_calls support; the engine emits an isError envelope listing the eligible catalog models on mismatch. Override by task weight: `gpt-5.6-sol` (heavy/deep), `gpt-5.6-terra` (moderate), `gpt-5.6-luna` (light/cheap) — all 1M context; pair with thinking:'high'."
34364
34649
  },
34365
34650
  thinking: {
34366
34651
  type: "string",
@@ -34389,7 +34674,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
34389
34674
  toolNameHttp: "plan",
34390
34675
  group: "workers",
34391
34676
  capability: "worker",
34392
- description: "Runs as the background `worker-plan` agent. Dispatch via the Agent tool (subagent_type: worker-plan) so the turn is never blocked; the result arrives as a completion notification. Read-only implementation planning by an autonomous worker (Pi runtime; default model `claude-opus-5` at xhigh reasoning, override via `model` with any Copilot-catalog model that advertises `tool_calls`). It has the same read-only toolset as explore and returns a concrete, ordered implementation plan covering files, approach, risks, and how acceptance criteria will be verified. Use before coding when the task needs repo-grounded sequencing or acceptance criteria translated into implementation steps. Not for editing files, running an implementation, writing tests, or adversarial review; use implement, test, or review for those scopes. Strictly read-only: it changes nothing on disk, and its returned text is the only artifact it produces — route to `implement` or `test` when a file actually needs to change. If the result is too large to relay it is truncated to a preview and the FULL text is written to a file, whose absolute path is in the returned text; read that file rather than re-running the worker.",
34677
+ description: "Runs as the background `worker-plan` agent. Dispatch via the Agent tool (subagent_type: worker-plan) so the turn is never blocked; the result arrives as a completion notification. Read-only implementation planning by an autonomous worker (Pi runtime; default model `claude-opus-5` at high reasoning, override via `model` with any Copilot-catalog model that advertises `tool_calls`). It has the same read-only toolset as explore and returns a concrete, ordered implementation plan covering files, approach, risks, and how acceptance criteria will be verified. Use before coding when the task needs repo-grounded sequencing or acceptance criteria translated into implementation steps. Not for editing files, running an implementation, writing tests, or adversarial review; use implement, test, or review for those scopes. Strictly read-only: it changes nothing on disk, and its returned text is the only artifact it produces — route to `implement` or `test` when a file actually needs to change. If the result is too large to relay it is truncated to a preview and the FULL text is written to a file, whose absolute path is in the returned text; read that file rather than re-running the worker.",
34393
34678
  inputSchema: {
34394
34679
  type: "object",
34395
34680
  required: ["prompt"],
@@ -34430,7 +34715,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
34430
34715
  toolNameHttp: "test",
34431
34716
  group: "workers",
34432
34717
  capability: "worker",
34433
- description: "Runs as the background `worker-test` agent. Dispatch via the Agent tool (subagent_type: worker-test) so the turn is never blocked; the result arrives as a completion notification. Independent adversarial test authoring by an autonomous worker (Pi runtime; default model `gpt-5.6-sol` at xhigh reasoning, override via `model` with any Copilot-catalog model that advertises `tool_calls`). It has the same read/write toolset as implement and writes tests that try to break the implementation through edge cases, error paths, and acceptance criteria, then runs them and reports pass/fail. Use when a separate test author should challenge an implementation without modifying the production code to make tests pass. Not for implementing fixes, broad research, or code review; use implement, explore, or review for those scopes. ALWAYS runs in an isolated git worktree and returns the test diff via a saved patch file (a `--stat` summary + a bounded preview + the patch path; a small diff is inlined in full) — it never edits your working tree, and it HARD-ERRORS if the workspace is not a git repository. For in-place test authoring, use the native `implementer` subagent. If the result is too large to relay it is truncated to a preview and the FULL text is written to a file, whose absolute path is in the returned text; read that file rather than re-running the worker.",
34718
+ description: "Runs as the background `worker-test` agent. Dispatch via the Agent tool (subagent_type: worker-test) so the turn is never blocked; the result arrives as a completion notification. Independent adversarial test authoring by an autonomous worker (Pi runtime; default model `gpt-5.6-sol` at high reasoning, override via `model` with any Copilot-catalog model that advertises `tool_calls`). It has the same read/write toolset as implement and writes tests that try to break the implementation through edge cases, error paths, and acceptance criteria, then runs them and reports pass/fail. Use when a separate test author should challenge an implementation without modifying the production code to make tests pass. Not for implementing fixes, broad research, or code review; use implement, explore, or review for those scopes. ALWAYS runs in an isolated git worktree and returns the test diff via a saved patch file (a `--stat` summary + a bounded preview + the patch path; a small diff is inlined in full) — it never edits your working tree, and it HARD-ERRORS if the workspace is not a git repository. For in-place test authoring, use the native `implementer` subagent. If the result is too large to relay it is truncated to a preview and the FULL text is written to a file, whose absolute path is in the returned text; read that file rather than re-running the worker.",
34434
34719
  inputSchema: {
34435
34720
  type: "object",
34436
34721
  required: ["prompt"],
@@ -34677,7 +34962,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
34677
34962
  toolNameHttp: "browse",
34678
34963
  group: "workers",
34679
34964
  capability: "browse_agent",
34680
- description: "Runs as the background `worker-browse` agent. Dispatch via the Agent tool (subagent_type: worker-browse) so the turn is never blocked; the result arrives as a completion notification. A Pi-driven autonomous browser worker (default model `gpt-5.4-mini`) drives a real browser to accomplish `task`, keeps raw DOM and page snapshots inside its own context, and returns a single text result. Use for delegated multi-step web tasks such as comparing prices, logging into a dashboard, or summarizing pages when the lead does not need to steer each click. Not for direct in-context browser control, screenshots, or precise element interactions; use the `browser` MCP tools for those. Pass `sessionId` to continue a prior browse session, or omit it for a fresh isolated session; multiple calls run as parallel sessions on the shared browser. If the result is too large to relay it is truncated to a preview and the FULL text is written to a file, whose absolute path is in the returned text; read that file rather than re-running the worker.",
34965
+ description: "Runs as the background `worker-browse` agent. Dispatch via the Agent tool (subagent_type: worker-browse) so the turn is never blocked; the result arrives as a completion notification. A Pi-driven autonomous browser worker (default model `gpt-5.6-luna`) drives a real browser to accomplish `task`, keeps raw DOM and page snapshots inside its own context, and returns a single text result. Use for delegated multi-step web tasks such as comparing prices, logging into a dashboard, or summarizing pages when the lead does not need to steer each click. Not for direct in-context browser control, screenshots, or precise element interactions; use the `browser` MCP tools for those. Pass `sessionId` to continue a prior browse session, or omit it for a fresh isolated session; multiple calls run as parallel sessions on the shared browser. If the result is too large to relay it is truncated to a preview and the FULL text is written to a file, whose absolute path is in the returned text; read that file rather than re-running the worker.",
34681
34966
  inputSchema: {
34682
34967
  type: "object",
34683
34968
  required: ["task"],
@@ -35136,6 +35421,6 @@ function enumerateInjectedMcpToolNames(groupKeys, opts = {}) {
35136
35421
  return [...new Set(names)];
35137
35422
  }
35138
35423
  //#endregion
35139
- export { browserToolsEnabled as $, searchWeb as A, CONDENSED_OPERATING_SEQUENCE as At, buildAnthropicErrorEvent as B, UPSTREAM_INACTIVITY_TIMEOUT_MS as Bt, buildToolbeltAwareness as C, provisionBrowserAssets as Ct, TOOLBELT_TOOLS$1 as D, extractTarGzMember as Dt, vscodeRipgrepPath as E, provisionAndIndexColbert as Et, isAdvisorRequested as F, DEFAULT_CLAUDE_MODEL_FALLBACKS as Ft, relayAnthropicStream as G, withOneMSuffix as Gt, isControllerClosedError as H, pickClaudeDefault as Ht, formatThinkingRepairDecline as I, DEFAULT_CODEX_MODEL as It, agentToolsEnabled as J, handleMcpDelete as K, withInstallLock as Kt, rememberThinkingHistoryRepair as L, DEFAULT_CODEX_MODEL_FALLBACKS as Lt, ADVISOR_TOOL_INSTRUCTIONS as M, shouldUseInsecureTls as Mt, buildAdvisorStream as N, collapsePathKeys as Nt, assetFor as O, extractZipMember as Ot, injectAdvisorTool as P, toolbeltPathOverride as Pt, browserCompoundToolsEnabled as Q, repairKnownThinkingHistory as R, DEFAULT_PORT as Rt, availableToolCommands as S, parseJsonOrDiagnose as St, toolbeltSkipSet as T, colbertDegradedWarning as Tt, logStreamError as U, upstreamAllowH2 as Ut, buildOpenAIErrorEvent as V, generateRandomPort as Vt, readIteratorWithTimeout as W, upstreamMaxConnections as Wt, brainstormModel as X, artifactToolsEnabled as Y, browseAgentEnabled as Z, appendPlanReminder as _, pickEndpoint as _t, buildPeerAwarenessSnippet as a, nativeSubagentModel as at, runWorkerAgent as b, MAX_RESPONSE_BODY_BYTES as bt, personasFor as c, scribeModel as ct, EXPLORE_DEFAULT_MODEL as d, shimDefaultsToXhigh as dt, fleetToolsEnabled as et, EXPLORE_DEFAULT_THINKING as f, countTokens as ft, TEST_DEFAULT_MODEL as g, resolveMcpToolTimeoutMs as gt, REVIEW_DEFAULT_MODEL as h, assembleResponsesPayload as ht, buildAgentPrompt as i, genericModel as it, ADVISOR_INTERNAL_TOOL_NAME as j, DEFINITION_OF_GREATNESS as jt, satisfiesMinVersion as k, warmTreeSitterPool as kt, BROWSE_DEFAULT_MODEL as l, standInToolEnabled as lt, PLAN_DEFAULT_MODEL as m, getTokenCount as mt, MCP_GROUPS as n, genericCheapModel as nt, buildPeerAwarenessSummary as o, reviewerModel as ot, IMPLEMENT_DEFAULT_MODEL as p, createMessages as pt, handleMcpPost as q, assertMcpToolSurfaceConsistent as r, genericFastModel as rt, enumerateInjectedMcpToolNames as s, scoutModel as st, GROUP_META as t, geminiAvailable as tt, DEFAULT_MODEL as u, workerToolsEnabled as ut, resolveModeDefaults as v, createResponses as vt, toolbeltEnabled as w, hasSupportedBrowserInstalled as wt, buildEnv as x, readResponseBodyCapped as xt, resolveWorkerRunOpts as y, createChatCompletions as yt, repairRejectedThinkingHistory as z, UPSTREAM_FETCH_TIMEOUT_MS as zt };
35424
+ export { browserCompoundToolsEnabled as $, satisfiesMinVersion as A, warmTreeSitterPool as At, repairRejectedThinkingHistory as B, DEFAULT_PORT as Bt, availableToolCommands as C, parseJsonOrDiagnose as Ct, vscodeRipgrepPath as D, provisionAndIndexColbert as Dt, toolbeltSkipSet as E, colbertDegradedWarning as Et, injectAdvisorTool as F, collapsePathKeys as Ft, readIteratorWithTimeout as G, upstreamAllowH2 as Gt, buildOpenAIErrorEvent as H, UPSTREAM_INACTIVITY_TIMEOUT_MS as Ht, isAdvisorRequested as I, toolbeltPathOverride as It, handleMcpPost as J, withInstallLock as Jt, relayAnthropicStream as K, upstreamMaxConnections as Kt, formatThinkingRepairDecline as L, DEFAULT_CLAUDE_MODEL_FALLBACKS as Lt, ADVISOR_INTERNAL_TOOL_NAME as M, CONDENSED_OPERATING_SEQUENCE as Mt, ADVISOR_TOOL_INSTRUCTIONS as N, DEFINITION_OF_GREATNESS as Nt, TOOLBELT_TOOLS$1 as O, extractTarGzMember as Ot, buildAdvisorStream as P, shouldUseInsecureTls as Pt, browseAgentEnabled as Q, rememberThinkingHistoryRepair as R, DEFAULT_CODEX_MODEL as Rt, buildEnv as S, readResponseBodyCapped as St, toolbeltEnabled as T, hasSupportedBrowserInstalled as Tt, isControllerClosedError as U, generateRandomPort as Ut, buildAnthropicErrorEvent as V, UPSTREAM_FETCH_TIMEOUT_MS as Vt, logStreamError as W, pickClaudeDefault as Wt, artifactToolsEnabled as X, agentToolsEnabled as Y, brainstormModel as Z, appendPlanReminder as _, resolveMcpToolTimeoutMs as _t, buildPeerAwarenessSnippet as a, nativeSubagentModel as at, resolveWorkerRunOpts as b, createChatCompletions as bt, personasFor as c, scribeModel as ct, EXPLORE_DEFAULT_MODEL as d, shimDefaultsToXhigh as dt, browserToolsEnabled as et, EXPLORE_DEFAULT_THINKING as f, countTokens as ft, TEST_DEFAULT_MODEL as g, warnOnTokenPriceDrift as gt, REVIEW_DEFAULT_MODEL as h, assembleResponsesPayload as ht, buildAgentPrompt as i, implementerFastModel as it, searchWeb as j, provisionTreeSitterAssets as jt, assetFor as k, extractZipMember as kt, BROWSE_DEFAULT_MODEL as l, standInToolEnabled as lt, PLAN_DEFAULT_MODEL as m, getTokenCount as mt, MCP_GROUPS as n, geminiAvailable as nt, buildPeerAwarenessSummary as o, reviewerModel as ot, IMPLEMENT_DEFAULT_MODEL as p, createMessages as pt, handleMcpDelete as q, withOneMSuffix as qt, assertMcpToolSurfaceConsistent as r, generalPurposeFastModel as rt, enumerateInjectedMcpToolNames as s, scoutModel as st, GROUP_META as t, fleetToolsEnabled as tt, DEFAULT_MODEL_CHAIN as u, workerToolsEnabled as ut, resolveDefaultModel as v, pickEndpoint as vt, buildToolbeltAwareness as w, provisionBrowserAssets as wt, runWorkerAgent as x, MAX_RESPONSE_BODY_BYTES as xt, resolveModeDefaults as y, createResponses as yt, repairKnownThinkingHistory as z, DEFAULT_CODEX_MODEL_FALLBACKS as zt };
35140
35425
 
35141
- //# sourceMappingURL=peer-mcp-personas-DRL_xT4h.js.map
35426
+ //# sourceMappingURL=peer-mcp-personas-l4P4s1fK.js.map