github-router 0.3.248 → 0.3.249
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/engine-BuuHUb4t.js +2 -0
- package/dist/main.js +214 -12
- package/dist/main.js.map +1 -1
- package/dist/paths-BjTMI_xK.js.map +1 -1
- package/dist/{peer-mcp-personas-HWhxZUvf.js → peer-mcp-personas-DJzLpfDJ.js} +130 -18
- package/dist/{peer-mcp-personas-HWhxZUvf.js.map → peer-mcp-personas-DJzLpfDJ.js.map} +1 -1
- package/package.json +1 -1
- package/dist/engine-C1nJ6ue1.js +0 -2
|
@@ -19919,6 +19919,20 @@ function detectAgentCall(input) {
|
|
|
19919
19919
|
//#endregion
|
|
19920
19920
|
//#region src/services/copilot/endpoint.ts
|
|
19921
19921
|
/**
|
|
19922
|
+
* Catalog spellings that mean each of our two clients. Copilot is not
|
|
19923
|
+
* self-consistent about the `/v1` prefix — the live catalog advertises
|
|
19924
|
+
* `/v1/messages` prefixed but `/chat/completions` bare, and this repo's own
|
|
19925
|
+
* fixtures carry both forms — so an exact-match on the bare spelling alone
|
|
19926
|
+
* silently misses a real shape. `src/lib/model-validation.ts` already
|
|
19927
|
+
* normalizes the same way (`ENDPOINT_ALIASES`); this keeps the two agreeing.
|
|
19928
|
+
*
|
|
19929
|
+
* Matching is EXACT against this set, never a suffix/`includes` test: a
|
|
19930
|
+
* `ws:/responses` (websocket transport) entry is NOT the `/responses` HTTP
|
|
19931
|
+
* client and must keep resolving to "serves neither".
|
|
19932
|
+
*/
|
|
19933
|
+
const CHAT_ENDPOINTS = /* @__PURE__ */ new Set(["/chat/completions", "/v1/chat/completions"]);
|
|
19934
|
+
const RESPONSES_ENDPOINTS = /* @__PURE__ */ new Set(["/responses", "/v1/responses"]);
|
|
19935
|
+
/**
|
|
19922
19936
|
* Decide which endpoint to call for a model from its catalog
|
|
19923
19937
|
* `supported_endpoints`. Prefers `/chat/completions` when available (the
|
|
19924
19938
|
* simpler, more widely-supported shape) and falls back to `/responses` for
|
|
@@ -19934,19 +19948,37 @@ function detectAgentCall(input) {
|
|
|
19934
19948
|
function pickEndpoint(model) {
|
|
19935
19949
|
const eps = model.supported_endpoints;
|
|
19936
19950
|
if (!eps || eps.length === 0) return "chat";
|
|
19937
|
-
if (eps.
|
|
19938
|
-
if (eps.
|
|
19951
|
+
if (eps.some((e) => CHAT_ENDPOINTS.has(e))) return "chat";
|
|
19952
|
+
if (eps.some((e) => RESPONSES_ENDPOINTS.has(e))) return "responses";
|
|
19939
19953
|
}
|
|
19940
19954
|
/**
|
|
19941
|
-
* `pickEndpoint` by model id against the live catalog
|
|
19942
|
-
*
|
|
19943
|
-
*
|
|
19944
|
-
*
|
|
19955
|
+
* `pickEndpoint` by model id against the live catalog, WITHOUT collapsing
|
|
19956
|
+
* "absent from the catalog" into "serves neither of our endpoints".
|
|
19957
|
+
*
|
|
19958
|
+
* This function deliberately has no default. The predecessor
|
|
19959
|
+
* (`endpointForModelId`) returned `pickEndpoint(found) ?? "chat"`, which
|
|
19960
|
+
* coerced both cases to "chat" — defensible for an unknown id, silently wrong
|
|
19961
|
+
* for a catalog model serving only, say, `/v1/messages`: the caller would drive
|
|
19962
|
+
* it through the chat client and get an opaque upstream 400 with no local
|
|
19963
|
+
* signal about the real cause. `src/lib/browser-mcp/compressor.ts` already
|
|
19964
|
+
* treats that case correctly (`if (!endpoint) continue`); this makes the same
|
|
19965
|
+
* distinction available to callers that resolve by id.
|
|
19966
|
+
*
|
|
19967
|
+
* Callers that legitimately want the chat default for an unknown id can still
|
|
19968
|
+
* have it — they just have to write it, per case, on purpose.
|
|
19945
19969
|
*/
|
|
19946
|
-
function
|
|
19970
|
+
function resolveEndpointForModelId(id) {
|
|
19947
19971
|
const found = state.models?.data?.find((m) => m.id === id);
|
|
19948
|
-
if (!found) return "
|
|
19949
|
-
|
|
19972
|
+
if (!found) return { kind: "unknown-model" };
|
|
19973
|
+
const endpoint = pickEndpoint(found);
|
|
19974
|
+
if (endpoint) return {
|
|
19975
|
+
kind: "endpoint",
|
|
19976
|
+
endpoint
|
|
19977
|
+
};
|
|
19978
|
+
return {
|
|
19979
|
+
kind: "unreachable",
|
|
19980
|
+
endpoints: found.supported_endpoints ?? []
|
|
19981
|
+
};
|
|
19950
19982
|
}
|
|
19951
19983
|
//#endregion
|
|
19952
19984
|
//#region src/lib/browser-mcp/compressor.ts
|
|
@@ -24169,7 +24201,12 @@ async function runStreamLoop(stream, context, opts, options) {
|
|
|
24169
24201
|
return;
|
|
24170
24202
|
}
|
|
24171
24203
|
}
|
|
24172
|
-
|
|
24204
|
+
const resolution = resolveEndpointForModelId(resolved.modelId);
|
|
24205
|
+
if (resolution.kind === "unreachable") {
|
|
24206
|
+
pushUndrivableModelDiagnostic(stream, resolved, resolution.endpoints);
|
|
24207
|
+
return;
|
|
24208
|
+
}
|
|
24209
|
+
if (resolution.kind === "endpoint" && resolution.endpoint === "responses") {
|
|
24173
24210
|
await runResponsesStreamLoop(stream, context, opts, options);
|
|
24174
24211
|
return;
|
|
24175
24212
|
}
|
|
@@ -24993,6 +25030,33 @@ function pushBackstopDiagnostic(stream, resolved, assembledTokens, limitTokens)
|
|
|
24993
25030
|
error: final
|
|
24994
25031
|
});
|
|
24995
25032
|
}
|
|
25033
|
+
/**
|
|
25034
|
+
* Terminal diagnostic for a model the worker cannot drive AT ALL: it is in the
|
|
25035
|
+
* live catalog, but its `supported_endpoints` name neither `/chat/completions`
|
|
25036
|
+
* nor `/responses` — our only two clients. Fails here, locally, naming the
|
|
25037
|
+
* model and what it actually serves, instead of coercing it onto the chat
|
|
25038
|
+
* client and surfacing an opaque upstream `unsupported_api_for_model` 400.
|
|
25039
|
+
* Carried as assistant TEXT so the engine surfaces it as an `isError` result
|
|
25040
|
+
* (same shape as the request-boundary backstop).
|
|
25041
|
+
*/
|
|
25042
|
+
function pushUndrivableModelDiagnostic(stream, resolved, endpoints) {
|
|
25043
|
+
const served = endpoints.length > 0 ? endpoints.join(", ") : "(none advertised)";
|
|
25044
|
+
const text = `Cannot run: ${resolved.modelId} is in the Copilot catalog but serves neither /chat/completions nor /responses — the only two APIs a worker can drive. Its catalog supported_endpoints are: ${served}. Pick a different model for this call, or change the mode default via worker_defaults (a zero-arg worker_defaults call lists the models a worker can be pointed at).`;
|
|
25045
|
+
const final = {
|
|
25046
|
+
...makeBaseMessage(resolved),
|
|
25047
|
+
content: [{
|
|
25048
|
+
type: "text",
|
|
25049
|
+
text
|
|
25050
|
+
}],
|
|
25051
|
+
stopReason: "error",
|
|
25052
|
+
errorMessage: `model ${resolved.modelId} serves no worker-drivable endpoint (${served})`
|
|
25053
|
+
};
|
|
25054
|
+
stream.push({
|
|
25055
|
+
type: "error",
|
|
25056
|
+
reason: "error",
|
|
25057
|
+
error: final
|
|
25058
|
+
});
|
|
25059
|
+
}
|
|
24996
25060
|
function describeError(err) {
|
|
24997
25061
|
if (err instanceof HTTPError) return `${err.message} (status ${err.response.status})`;
|
|
24998
25062
|
if (err instanceof Error) return err.message;
|
|
@@ -30775,6 +30839,36 @@ function extractAssistantText(content) {
|
|
|
30775
30839
|
for (const part of content) if (part.type === "text") out += part.text;
|
|
30776
30840
|
return out;
|
|
30777
30841
|
}
|
|
30842
|
+
/**
|
|
30843
|
+
* Banner that prefixes text salvaged from an EARLIER assistant turn when the
|
|
30844
|
+
* run ends without a usable final answer.
|
|
30845
|
+
*
|
|
30846
|
+
* It is deliberately loud. Recovered text is partial work — the model was
|
|
30847
|
+
* mid-investigation when it went quiet — and returning it bare would let the
|
|
30848
|
+
* caller read an interim note as a conclusion. That is a different bug from
|
|
30849
|
+
* the one this recovery fixes, and a worse one: silently wrong beats loudly
|
|
30850
|
+
* missing only for the model that produced it.
|
|
30851
|
+
*/
|
|
30852
|
+
const RECOVERED_TEXT_BANNER = "[recovered from an earlier turn — this run ended without a final answer, so the text below is partial work in progress, NOT a conclusion. Treat it as leads to verify, not as the worker's answer.]";
|
|
30853
|
+
/**
|
|
30854
|
+
* Compose the recovered-text block for a run that is ending with nothing
|
|
30855
|
+
* usable in its final turn.
|
|
30856
|
+
*
|
|
30857
|
+
* Returns `""` in the two cases where recovery would be noise: the run DID
|
|
30858
|
+
* produce live text (nothing was lost), or no turn ever produced any.
|
|
30859
|
+
*
|
|
30860
|
+
* Scope note: `highWater` is the LAST non-empty assistant text, not a
|
|
30861
|
+
* concatenation of every non-empty turn. Accumulating them would turn a
|
|
30862
|
+
* recovered result into a transcript dump — mostly interim narration — where
|
|
30863
|
+
* the last turn is both the most complete and the one the model was building
|
|
30864
|
+
* toward when it stalled.
|
|
30865
|
+
*/
|
|
30866
|
+
function recoveredBlock(liveText, highWater) {
|
|
30867
|
+
if (liveText.trim()) return "";
|
|
30868
|
+
const recovered = highWater.trim();
|
|
30869
|
+
if (!recovered) return "";
|
|
30870
|
+
return `${RECOVERED_TEXT_BANNER}\n\n${recovered}`;
|
|
30871
|
+
}
|
|
30778
30872
|
const MAX_EMPTY_OUTPUT_NUDGES = 3;
|
|
30779
30873
|
const EMPTY_OUTPUT_NUDGES = [
|
|
30780
30874
|
"Summarize your findings so far.",
|
|
@@ -30951,6 +31045,7 @@ async function runWorkerAgentOnce(opts) {
|
|
|
30951
31045
|
const abortHandler = () => agent.abort();
|
|
30952
31046
|
if (opts.signal) opts.signal.addEventListener("abort", abortHandler, { once: true });
|
|
30953
31047
|
let finalText = "";
|
|
31048
|
+
let lastNonEmptyText = "";
|
|
30954
31049
|
let lastStopReason = null;
|
|
30955
31050
|
let nudgeCount = 0;
|
|
30956
31051
|
const maxEmptyOutputNudges = resolveMaxEmptyOutputNudges();
|
|
@@ -30977,6 +31072,7 @@ async function runWorkerAgentOnce(opts) {
|
|
|
30977
31072
|
const content = msg.content;
|
|
30978
31073
|
if (!Array.isArray(content)) return;
|
|
30979
31074
|
finalText = extractAssistantText(content);
|
|
31075
|
+
if (finalText.trim()) lastNonEmptyText = finalText;
|
|
30980
31076
|
const sr = msg.stopReason;
|
|
30981
31077
|
if (typeof sr === "string") lastStopReason = sr;
|
|
30982
31078
|
});
|
|
@@ -30999,30 +31095,41 @@ async function runWorkerAgentOnce(opts) {
|
|
|
30999
31095
|
try {
|
|
31000
31096
|
await ws.remove();
|
|
31001
31097
|
} catch {}
|
|
31002
|
-
const
|
|
31098
|
+
const liveAnswer = isBrowse ? terminalText ?? finalText : finalText;
|
|
31099
|
+
const recovered = recoveredBlock(liveAnswer, lastNonEmptyText);
|
|
31100
|
+
const text = isBrowse ? liveAnswer : diff ? `${finalText}\n\n${diff}` : finalText;
|
|
31003
31101
|
if (lastStopReason === "error" || lastStopReason === "aborted") {
|
|
31004
|
-
const diag =
|
|
31102
|
+
const diag = liveAnswer.trim();
|
|
31005
31103
|
let diagnostic;
|
|
31006
31104
|
if (lastStopReason === "aborted") diagnostic = wallClockExpired ? "[halted: wallclock]" : "[halted: cancelled]";
|
|
31007
31105
|
else diagnostic = diag || "Worker run failed before producing an answer — the model's input likely overflowed (a large tool result), or the upstream errored. Retry with a narrower task: target a specific section / file / element rather than reading everything at once.";
|
|
31008
31106
|
return {
|
|
31009
31107
|
text: lastStopReason === "aborted" ? [
|
|
31010
31108
|
diag,
|
|
31109
|
+
recovered,
|
|
31011
31110
|
diff,
|
|
31012
31111
|
diagnostic
|
|
31013
|
-
].filter(Boolean).join("\n\n") : [
|
|
31112
|
+
].filter(Boolean).join("\n\n") : [
|
|
31113
|
+
diagnostic,
|
|
31114
|
+
recovered,
|
|
31115
|
+
diff
|
|
31116
|
+
].filter(Boolean).join("\n\n"),
|
|
31014
31117
|
isError: true
|
|
31015
31118
|
};
|
|
31016
31119
|
}
|
|
31017
31120
|
if (budget.hardStopReason) return {
|
|
31018
|
-
text: [
|
|
31121
|
+
text: [
|
|
31122
|
+
text,
|
|
31123
|
+
recovered,
|
|
31124
|
+
`[halted: ${budget.hardStopReason}]`
|
|
31125
|
+
].filter(Boolean).join("\n\n"),
|
|
31019
31126
|
isError: true
|
|
31020
31127
|
};
|
|
31021
31128
|
if (!text.trim()) return {
|
|
31022
|
-
text: `${NO_OUTPUT_PREFIX} after ${nudgeCount} nudges (stopReason=${lastStopReason ?? "unknown"}, turns=${budget.turns}, elapsed=${budget.elapsedMs}ms)]; retry with a different model via worker_defaults, or narrow/split the task.`,
|
|
31129
|
+
text: [`${NO_OUTPUT_PREFIX} after ${nudgeCount} nudges (stopReason=${lastStopReason ?? "unknown"}, turns=${budget.turns}, elapsed=${budget.elapsedMs}ms)]; retry with a different model via worker_defaults, or narrow/split the task.`, recovered].filter(Boolean).join("\n\n"),
|
|
31023
31130
|
isError: true
|
|
31024
31131
|
};
|
|
31025
|
-
return { text };
|
|
31132
|
+
return { text: [text, recovered].filter(Boolean).join("\n\n") };
|
|
31026
31133
|
} catch (err) {
|
|
31027
31134
|
let diff = "";
|
|
31028
31135
|
try {
|
|
@@ -31035,7 +31142,12 @@ async function runWorkerAgentOnce(opts) {
|
|
|
31035
31142
|
} catch {}
|
|
31036
31143
|
const haltOrErr = err instanceof Error ? err.message : String(err);
|
|
31037
31144
|
const parts = [];
|
|
31038
|
-
|
|
31145
|
+
const liveAnswer = isBrowse ? terminalText ?? finalText : finalText;
|
|
31146
|
+
if (liveAnswer.trim()) parts.push(liveAnswer);
|
|
31147
|
+
else {
|
|
31148
|
+
const recovered = recoveredBlock(liveAnswer, lastNonEmptyText);
|
|
31149
|
+
if (recovered) parts.push(recovered);
|
|
31150
|
+
}
|
|
31039
31151
|
if (diff) parts.push(diff);
|
|
31040
31152
|
parts.push(haltOrErr);
|
|
31041
31153
|
return {
|
|
@@ -35064,4 +35176,4 @@ function enumerateInjectedMcpToolNames(groupKeys, opts = {}) {
|
|
|
35064
35176
|
//#endregion
|
|
35065
35177
|
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 };
|
|
35066
35178
|
|
|
35067
|
-
//# sourceMappingURL=peer-mcp-personas-
|
|
35179
|
+
//# sourceMappingURL=peer-mcp-personas-DJzLpfDJ.js.map
|