github-router 0.3.168 → 0.3.176
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/README.md +5 -5
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/{engine-RA1Orodr.js → engine-BWoDQ-3C.js} +1 -1
- package/dist/main.js +572 -188
- package/dist/main.js.map +1 -1
- package/dist/{peer-mcp-personas-D826LsJJ.js → peer-mcp-personas-BKkdfOyK.js} +591 -427
- package/dist/peer-mcp-personas-BKkdfOyK.js.map +1 -0
- package/package.json +1 -1
- package/dist/peer-mcp-personas-D826LsJJ.js.map +0 -1
|
@@ -1072,13 +1072,15 @@ function pickClaudeDefault(opusFamily = DEFAULT_OPUS_FAMILY) {
|
|
|
1072
1072
|
return bareSlug;
|
|
1073
1073
|
}
|
|
1074
1074
|
/**
|
|
1075
|
-
* Default model for `github-router codex`. `gpt-5.
|
|
1076
|
-
* `/responses` model; the fallback chain
|
|
1077
|
-
*
|
|
1078
|
-
* "best available `/responses` model"
|
|
1075
|
+
* Default model for `github-router codex`. `gpt-5.6-sol` is the flagship
|
|
1076
|
+
* `/responses` model; the fallback chain (led by `gpt-5.5`) handles older
|
|
1077
|
+
* Copilot tiers or a rollout-lag window where sol hasn't appeared yet.
|
|
1078
|
+
* `resolveCodexModel` provides a final "best available `/responses` model"
|
|
1079
|
+
* safety net beyond this list.
|
|
1079
1080
|
*/
|
|
1080
|
-
const DEFAULT_CODEX_MODEL = "gpt-5.
|
|
1081
|
+
const DEFAULT_CODEX_MODEL = "gpt-5.6-sol";
|
|
1081
1082
|
const DEFAULT_CODEX_MODEL_FALLBACKS = [
|
|
1083
|
+
"gpt-5.5",
|
|
1082
1084
|
"gpt-5.4",
|
|
1083
1085
|
"gpt-5.3-codex",
|
|
1084
1086
|
"gpt-5.2-codex"
|
|
@@ -1565,7 +1567,7 @@ function tool(toolNameHttp, description, inputSchema, handler) {
|
|
|
1565
1567
|
};
|
|
1566
1568
|
}
|
|
1567
1569
|
const ARTIFACT_TOOLS = Object.freeze([
|
|
1568
|
-
tool("artifact_open", "
|
|
1570
|
+
tool("artifact_open", "Opens a workspace file in ai-or-die's Artifact review panel for human review, replacing the current review if one is already open. The caller provides a workspace-relative or absolute file path and can set mode:\"interactive\" when the HTML carries data-aod-* action controls. It returns the review URL/session identifiers plus next-step guidance for draining feedback. Use it when the user should review a durable artifact before work continues; it is not for one-line status updates or non-file content. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$2({
|
|
1569
1571
|
file: stringProp$2("Workspace-relative or absolute file path to show in the Artifact panel."),
|
|
1570
1572
|
mode: enumProp$1(["static", "interactive"], "Advisory. \"interactive\" signals the HTML contains data-aod-* action controls the panel should wire; \"static\" (default) is a read-and-annotate artifact.")
|
|
1571
1573
|
}, ["file"]), async (args, signal) => {
|
|
@@ -1584,7 +1586,7 @@ const ARTIFACT_TOOLS = Object.freeze([
|
|
|
1584
1586
|
next_step: "Tell the user to review at the Artifact panel, then call artifact_await to receive their feedback."
|
|
1585
1587
|
});
|
|
1586
1588
|
}),
|
|
1587
|
-
tool("artifact_update", "
|
|
1589
|
+
tool("artifact_update", "Replaces the current Artifact review's content in place without opening a separate review. The caller provides exactly one of file, a workspace-relative or absolute file path, or html, raw HTML written into the existing review sandbox; html requires an already-open review, and idempotencyKey can make retries deduplicate on the server. It returns a minimal success signal plus next-step guidance for awaiting further feedback. Use it when revised content should replace what the human is already reviewing; use artifact_refresh instead when the existing on-disk artifact only needs to be reloaded. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$2({
|
|
1588
1590
|
file: stringProp$2("Workspace-relative or absolute file path to become the review's new content."),
|
|
1589
1591
|
html: stringProp$2("Raw HTML to write into the review's existing sandboxed file, then reload."),
|
|
1590
1592
|
idempotencyKey: stringProp$2("Optional stable key so a retried update is de-duplicated by the server.")
|
|
@@ -1595,27 +1597,19 @@ const ARTIFACT_TOOLS = Object.freeze([
|
|
|
1595
1597
|
const html = optionalString$2(args, "html");
|
|
1596
1598
|
if (file === void 0 === (html === void 0)) throw new ArtifactToolInputError("INVALID_ARGUMENT", "artifact_update requires EXACTLY ONE of arguments.file or arguments.html");
|
|
1597
1599
|
const idempotencyKey = optionalString$2(args, "idempotencyKey");
|
|
1598
|
-
return ok$2({
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
}),
|
|
1605
|
-
ok: true,
|
|
1606
|
-
next_step: "The panel now shows the updated content. Call artifact_await for further feedback."
|
|
1607
|
-
});
|
|
1600
|
+
return ok$2(formatUpdateSuccess(await clientFromEnv(env).update({
|
|
1601
|
+
file,
|
|
1602
|
+
html,
|
|
1603
|
+
idempotencyKey,
|
|
1604
|
+
signal
|
|
1605
|
+
})));
|
|
1608
1606
|
}),
|
|
1609
|
-
tool("artifact_refresh", "
|
|
1607
|
+
tool("artifact_refresh", "Reloads the currently-open Artifact review from its existing on-disk file without changing the content source. The tool takes no inputs and returns a minimal success signal plus next-step guidance for awaiting feedback. Use it after an out-of-band edit changes the reviewed file on disk and the panel needs to pick up that version. Do not use it to replace the artifact with a new file or raw HTML; use artifact_update for that. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$2({}, []), async (_args, signal) => {
|
|
1610
1608
|
const env = readArtifactEnv();
|
|
1611
1609
|
if (!env) return missingEnvResult();
|
|
1612
|
-
return ok$2(
|
|
1613
|
-
...await clientFromEnv(env).refresh(signal),
|
|
1614
|
-
ok: true,
|
|
1615
|
-
next_step: "The panel reloaded the artifact. Call artifact_await for feedback."
|
|
1616
|
-
});
|
|
1610
|
+
return ok$2(formatRefreshSuccess(await clientFromEnv(env).refresh(signal)));
|
|
1617
1611
|
}),
|
|
1618
|
-
tool("artifact_await", "
|
|
1612
|
+
tool("artifact_await", "Waits for the human's next Artifact review events and returns a typed drain containing comments, structured action-button or checkbox events, status, cursor, and next-step guidance. The caller can pass the cursor from a previous response to receive only newer events and can provide timeoutMs as the server long-hold budget. It may return an empty events list on a quiet long-hold; callers should pass the returned cursor on the next artifact_await call. Use it as the primary review-feedback drain after artifact_open or artifact_update; it supersedes artifact_poll, which is legacy comments-only. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$2({
|
|
1619
1613
|
cursor: stringProp$2("High-water cursor from the previous artifact_await response. Omit on the first call."),
|
|
1620
1614
|
timeoutMs: numberProp$2("Optional server long-hold budget in ms (default ~25000).")
|
|
1621
1615
|
}, []), async (args, signal) => {
|
|
@@ -1629,35 +1623,23 @@ const ARTIFACT_TOOLS = Object.freeze([
|
|
|
1629
1623
|
signal
|
|
1630
1624
|
})));
|
|
1631
1625
|
}),
|
|
1632
|
-
tool("artifact_dismiss", "
|
|
1626
|
+
tool("artifact_dismiss", "Hides the ai-or-die Artifact panel UI while keeping the current review alive. The tool takes no inputs and returns a minimal success signal plus next-step guidance for reopening or awaiting later feedback. Use it when the panel should get out of the way but queued feedback should remain preserved, the channel should stay open, and the review should be re-openable. Do not use it when the review loop is finished; use artifact_end to close the review instead. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$2({}, []), async (_args, signal) => {
|
|
1633
1627
|
const env = readArtifactEnv();
|
|
1634
1628
|
if (!env) return missingEnvResult();
|
|
1635
|
-
return ok$2(
|
|
1636
|
-
...await clientFromEnv(env).dismiss(signal),
|
|
1637
|
-
ok: true,
|
|
1638
|
-
next_step: "The panel is hidden but the review is still live. Re-open the artifact or call artifact_await when ready."
|
|
1639
|
-
});
|
|
1629
|
+
return ok$2(formatDismissSuccess(await clientFromEnv(env).dismiss(signal)));
|
|
1640
1630
|
}),
|
|
1641
|
-
tool("artifact_reply", "
|
|
1631
|
+
tool("artifact_reply", "Sends the agent's reply back to the ai-or-die Artifact review panel after applying or responding to human feedback. The caller provides the reply text, and the tool returns a minimal success signal plus next-step guidance for either continuing the review loop or moving on. Use it to acknowledge what changed, answer a reviewer question, or summarize how feedback was handled after artifact_await returns events. Do not use it to replace panel content, wait for more feedback, hide the UI, or close the review. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$2({ text: stringProp$2("Agent reply text to deliver to the human Artifact review panel.") }, ["text"]), async (args, signal) => {
|
|
1642
1632
|
const env = readArtifactEnv();
|
|
1643
1633
|
if (!env) return missingEnvResult();
|
|
1644
1634
|
const text = requiredString$2(args, "text");
|
|
1645
|
-
return ok$2(
|
|
1646
|
-
...await clientFromEnv(env).agentReply(text, signal),
|
|
1647
|
-
ok: true,
|
|
1648
|
-
next_step: "Wait for further human review, or continue if the review loop is complete."
|
|
1649
|
-
});
|
|
1635
|
+
return ok$2(formatReplySuccess(await clientFromEnv(env).agentReply(text, signal)));
|
|
1650
1636
|
}),
|
|
1651
|
-
tool("artifact_end", "
|
|
1637
|
+
tool("artifact_end", "Ends and closes the ai-or-die Artifact review panel when the review loop is complete. The tool takes no inputs and returns a minimal success signal plus terminal next-step guidance. Use it after the human review is finished and no further feedback should arrive. Do not use it for a temporary hide or pause; use artifact_dismiss when the review should stay live. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$2({}, []), async (_args, signal) => {
|
|
1652
1638
|
const env = readArtifactEnv();
|
|
1653
1639
|
if (!env) return missingEnvResult();
|
|
1654
|
-
return ok$2(
|
|
1655
|
-
...await clientFromEnv(env).end(signal),
|
|
1656
|
-
ok: true,
|
|
1657
|
-
next_step: "Artifact review loop ended."
|
|
1658
|
-
});
|
|
1640
|
+
return ok$2(formatEndSuccess(await clientFromEnv(env).end(signal)));
|
|
1659
1641
|
}),
|
|
1660
|
-
tool("artifact_poll", "
|
|
1642
|
+
tool("artifact_poll", "Provides the frozen legacy polling path for Artifact review feedback. The caller may provide timeoutMs as an advisory per-call budget, and the tool returns the old comments-only payload with status, prompts, and next-step guidance rather than typed action events or a cursor. Use it only for compatibility with older clients or flows that still require the old payload shape. New callers should use artifact_await instead because it returns typed comments and structured action-button or checkbox events. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$2({ timeoutMs: numberProp$2("Optional per-call budget hint in ms (advisory).") }, []), async (_args, signal) => {
|
|
1661
1643
|
const env = readArtifactEnv();
|
|
1662
1644
|
if (!env) return missingEnvResult();
|
|
1663
1645
|
return ok$2(formatPollResponse(await pollUntilReady(clientFromEnv(env), signal)));
|
|
@@ -1735,6 +1717,50 @@ function formatPollResponse(response) {
|
|
|
1735
1717
|
next_step: response.next_step ?? defaultPollNextStep(response.status)
|
|
1736
1718
|
});
|
|
1737
1719
|
}
|
|
1720
|
+
function formatUpdateSuccess(response) {
|
|
1721
|
+
return definedObject$1({
|
|
1722
|
+
ok: true,
|
|
1723
|
+
viewUrl: stringField$1(response, "viewUrl"),
|
|
1724
|
+
next_step: "The panel now shows the updated content. Call artifact_await for further feedback."
|
|
1725
|
+
});
|
|
1726
|
+
}
|
|
1727
|
+
function formatRefreshSuccess(response) {
|
|
1728
|
+
return definedObject$1({
|
|
1729
|
+
ok: true,
|
|
1730
|
+
viewUrl: stringField$1(response, "viewUrl"),
|
|
1731
|
+
panelUrl: stringField$1(response, "panelUrl"),
|
|
1732
|
+
status: stringField$1(response, "status"),
|
|
1733
|
+
visibility: stringField$1(response, "visibility"),
|
|
1734
|
+
next_step: "The panel reloaded the artifact. Call artifact_await for feedback."
|
|
1735
|
+
});
|
|
1736
|
+
}
|
|
1737
|
+
function formatDismissSuccess(response) {
|
|
1738
|
+
return definedObject$1({
|
|
1739
|
+
ok: true,
|
|
1740
|
+
viewUrl: stringField$1(response, "viewUrl"),
|
|
1741
|
+
panelUrl: stringField$1(response, "panelUrl"),
|
|
1742
|
+
status: stringField$1(response, "status"),
|
|
1743
|
+
visibility: stringField$1(response, "visibility"),
|
|
1744
|
+
next_step: "The panel is hidden but the review is still live. Re-open the artifact or call artifact_await when ready."
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
function formatReplySuccess(response) {
|
|
1748
|
+
return definedObject$1({
|
|
1749
|
+
ok: true,
|
|
1750
|
+
reply: response.reply,
|
|
1751
|
+
delivered: booleanField(response, "delivered"),
|
|
1752
|
+
confirmed: booleanField(response, "confirmed"),
|
|
1753
|
+
status: stringField$1(response, "status"),
|
|
1754
|
+
next_step: "Wait for further human review, or continue if the review loop is complete."
|
|
1755
|
+
});
|
|
1756
|
+
}
|
|
1757
|
+
function formatEndSuccess(response) {
|
|
1758
|
+
return definedObject$1({
|
|
1759
|
+
ok: true,
|
|
1760
|
+
status: response.status,
|
|
1761
|
+
next_step: "Artifact review loop ended."
|
|
1762
|
+
});
|
|
1763
|
+
}
|
|
1738
1764
|
/**
|
|
1739
1765
|
* Shape the typed drain for the model: pass events through verbatim (unknown
|
|
1740
1766
|
* `kind`s preserved — the model ignores what it does not understand), echo the
|
|
@@ -1839,6 +1865,14 @@ function definedObject$1(input) {
|
|
|
1839
1865
|
for (const [key, value] of Object.entries(input)) if (value !== void 0) result[key] = value;
|
|
1840
1866
|
return result;
|
|
1841
1867
|
}
|
|
1868
|
+
function stringField$1(input, key) {
|
|
1869
|
+
const value = input[key];
|
|
1870
|
+
return typeof value === "string" ? value : void 0;
|
|
1871
|
+
}
|
|
1872
|
+
function booleanField(input, key) {
|
|
1873
|
+
const value = input[key];
|
|
1874
|
+
return typeof value === "boolean" ? value : void 0;
|
|
1875
|
+
}
|
|
1842
1876
|
function objectSchema$2(properties, required) {
|
|
1843
1877
|
return {
|
|
1844
1878
|
type: "object",
|
|
@@ -3596,10 +3630,10 @@ function createFleetTools(options = {}) {
|
|
|
3596
3630
|
};
|
|
3597
3631
|
}
|
|
3598
3632
|
return Object.freeze([
|
|
3599
|
-
tool$1("list_instances", "
|
|
3633
|
+
tool$1("list_instances", "Lists registered remote ai-or-die fleet instances and probes whether each instance is currently reachable. It takes no input; the registry decides which instances exist, and credentials or tunnel tokens are not returned. It returns instances with id, label, reachable status, sessionCount and lastSeen for reachable hosts, or error and hint for unreachable hosts. It is useful as the discovery entry point before list_sessions, create_session, or other fleet tools that need an instance id. It is not for local repository search or for reading sessions; use local tools for this machine and list_sessions after choosing an instance.", objectSchema$1({}, []), async () => {
|
|
3600
3634
|
return ok$1({ instances: await mapWithConcurrency(await getRegistry().listInstances(), fleetFanoutConcurrency(LIST_INSTANCES_FANOUT_CONCURRENCY), (instance) => probeInstance(instance)) });
|
|
3601
3635
|
}),
|
|
3602
|
-
tool$1("list_sessions", "
|
|
3636
|
+
tool$1("list_sessions", "Lists sessions on one remote ai-or-die fleet instance and returns session ids that can be used by the other fleet session tools. The optional instance input is an id or label; when it is omitted, the registry default or sole instance is used. It returns resolvedInstance and sessions, with each sessionId globalized as instanceId:localSessionId. It is useful after list_instances to choose a remote session to inspect, message, drive, or stop. It is not a fleet-wide listing and does not read transcript output; call it per instance, and use read_session for a session's text tail.", objectSchema$1({ instance: stringProp$1("Instance id or label. Defaults to the registry default, or the sole instance.") }, []), async (args, signal) => {
|
|
3603
3637
|
const instance = await resolve(optionalString$1(args, "instance"));
|
|
3604
3638
|
const response = await clientFor(instance).listSessions(signal);
|
|
3605
3639
|
return ok$1({
|
|
@@ -3607,11 +3641,10 @@ function createFleetTools(options = {}) {
|
|
|
3607
3641
|
sessions: response.sessions.map((session) => globalizeSession(instance.id, session))
|
|
3608
3642
|
});
|
|
3609
3643
|
}),
|
|
3610
|
-
tool$1("read_session", "
|
|
3644
|
+
tool$1("read_session", "Reads recent text output from an addressed remote ai-or-die fleet session. The required sessionId must be a global id in instanceId:localSessionId form; the optional instance input is only a cross-check and must resolve to the same instance. It returns resolvedInstance, sessionId, text, truncated, source, and the session status snapshot. It is useful for inspecting the transcript tail after send_message, await_turn, or drive_task. It is not for lifecycle-only checks or live waiting; use session_status for point-in-time state and await_turn to wait for new events.", objectSchema$1({
|
|
3611
3645
|
sessionId: stringProp$1("Global session id in the form instanceId:localSessionId."),
|
|
3612
3646
|
instance: stringProp$1("Optional instance id/label; when supplied it must agree with sessionId."),
|
|
3613
|
-
lines: numberProp$1("Number of recent lines to read.")
|
|
3614
|
-
format: stringProp$1("Reserved for future formatting; results are JSON text today.")
|
|
3647
|
+
lines: numberProp$1("Number of recent lines to read.")
|
|
3615
3648
|
}, ["sessionId"]), async (args, signal) => {
|
|
3616
3649
|
const { instance, localId, globalId } = await resolveSession(args);
|
|
3617
3650
|
const lines = optionalNumber$1(args, "lines");
|
|
@@ -3622,7 +3655,7 @@ function createFleetTools(options = {}) {
|
|
|
3622
3655
|
sessionId: globalId
|
|
3623
3656
|
});
|
|
3624
3657
|
}),
|
|
3625
|
-
tool$1("session_status", "
|
|
3658
|
+
tool$1("session_status", "Fetches the lifecycle and interaction status for an addressed remote ai-or-die fleet session. The required sessionId must be a global id in instanceId:localSessionId form; the optional instance input is only a cross-check and must resolve to the same instance. It returns resolvedInstance, sessionId, and a status object that can include lifecycle, interactionState, canAcceptInput, blockReason, and awaiting details. It is useful before deciding whether a session can accept a message or is awaiting a prompt. It is not a transcript reader or event watcher; use read_session for output text and await_turn for turn-completion events.", objectSchema$1({
|
|
3626
3659
|
sessionId: stringProp$1("Global session id in the form instanceId:localSessionId."),
|
|
3627
3660
|
instance: stringProp$1("Optional instance id/label; when supplied it must agree with sessionId.")
|
|
3628
3661
|
}, ["sessionId"]), async (args, signal) => {
|
|
@@ -3634,7 +3667,7 @@ function createFleetTools(options = {}) {
|
|
|
3634
3667
|
sessionId: globalId
|
|
3635
3668
|
});
|
|
3636
3669
|
}),
|
|
3637
|
-
tool$1("send_message", "
|
|
3670
|
+
tool$1("send_message", "Sends a free-text message to an existing remote ai-or-die fleet session. The required sessionId must be global, message is the text to deliver, requireIdle defaults to true, waitForIdleMs can wait briefly for readiness, awaitMs waits only for best-effort delivery confirmation, and idempotencyKey is usually auto-generated unless retrying the same send. It returns resolvedInstance, sessionId, delivered, confirmed, submitted when the remote proves the composer accepted the message, and confirmationPending/confirmationTimedOut when delivery succeeded but the turn outran the await window; delivered:false or notReady is reported as an error result. It is useful for sending the next free-text instruction to an idle session, especially with awaitMs:0 followed by await_turn for the actual turn boundary. It is not for answering an awaited choice prompt or sending control keys; use respond for prompts and send_keys for submit, interrupt, or literal key sequences.", objectSchema$1({
|
|
3638
3671
|
sessionId: stringProp$1("Global session id in the form instanceId:localSessionId."),
|
|
3639
3672
|
instance: stringProp$1("Optional instance id/label; when supplied it must agree with sessionId."),
|
|
3640
3673
|
message: stringProp$1("Message text to deliver to the session."),
|
|
@@ -3691,7 +3724,7 @@ function createFleetTools(options = {}) {
|
|
|
3691
3724
|
...isError ? { message: "message was not delivered to the session by the upstream instance" } : confirmationTimedOut ? { message: "delivered; turn completion not confirmed in the await window. Use await_turn filtered to this sessionId to observe completion (the idempotencyKey makes a retried send safe)." } : {}
|
|
3692
3725
|
}, isError);
|
|
3693
3726
|
}),
|
|
3694
|
-
tool$1("send_keys", "
|
|
3727
|
+
tool$1("send_keys", "Sends key input to an existing remote ai-or-die fleet session. The required sessionId must be global; provide exactly one of op or keys, where op is a named operation (`submit` for Enter or `interrupt` for Ctrl-C) and keys is a literal key sequence; raw only applies to literal keys. It returns resolvedInstance, sessionId, delivered, duplicated when an idempotency retry was deduped, and the mapped key name when op was used. It is useful for control-key actions such as submitting a typed prompt or interrupting a busy turn without stopping the session. It is not the normal free-text path and not the prompt-answer path; use send_message for free text and respond for awaited prompts.", objectSchema$1({
|
|
3695
3728
|
sessionId: stringProp$1("Global session id in the form instanceId:localSessionId."),
|
|
3696
3729
|
instance: stringProp$1("Optional instance id/label; when supplied it must agree with sessionId."),
|
|
3697
3730
|
op: stringProp$1("Higher-level named op: 'submit' (Enter) or 'interrupt' (Ctrl-C). Mapped to the ai-or-die named key with raw off. Do NOT also pass keys."),
|
|
@@ -3726,10 +3759,11 @@ function createFleetTools(options = {}) {
|
|
|
3726
3759
|
op,
|
|
3727
3760
|
mappedKeys: keys
|
|
3728
3761
|
},
|
|
3729
|
-
|
|
3762
|
+
delivered: response.delivered,
|
|
3763
|
+
...response.duplicated === void 0 ? {} : { duplicated: response.duplicated }
|
|
3730
3764
|
});
|
|
3731
3765
|
}),
|
|
3732
|
-
tool$1("respond", "
|
|
3766
|
+
tool$1("respond", "Answers an awaited prompt in an existing remote ai-or-die fleet session by selecting a choice, selecting an exact option value, or sending explicit keys. The required sessionId must be global; choose the answer mode that matches the prompt, and idempotencyKey is usually auto-generated unless retrying the same response. It returns resolvedInstance, sessionId, delivered, duplicated when an idempotency retry was deduped, and any awaitingKind or mappedKeys supplied by the remote; delivered:false is reported as an error result. It is useful only when session_status or await_turn shows the session is waiting for a prompt or choice. It is not for ordinary free-text instructions or control keys; use send_message for free text and send_keys for submit or interrupt.", objectSchema$1({
|
|
3733
3767
|
sessionId: stringProp$1("Global session id in the form instanceId:localSessionId."),
|
|
3734
3768
|
instance: stringProp$1("Optional instance id/label; when supplied it must agree with sessionId."),
|
|
3735
3769
|
choice: stringProp$1("Named or numbered choice to select."),
|
|
@@ -3745,23 +3779,35 @@ function createFleetTools(options = {}) {
|
|
|
3745
3779
|
idempotencyKey: optionalString$1(args, "idempotencyKey") ?? randomUUID()
|
|
3746
3780
|
});
|
|
3747
3781
|
const response = await clientFor(instance).respond(localId, input, signal);
|
|
3748
|
-
|
|
3782
|
+
const delivered = response.delivered !== false;
|
|
3783
|
+
return jsonResult$1({
|
|
3749
3784
|
resolvedInstance: publicInstance(instance),
|
|
3750
3785
|
sessionId: globalId,
|
|
3751
|
-
...response
|
|
3752
|
-
|
|
3786
|
+
...response,
|
|
3787
|
+
delivered,
|
|
3788
|
+
...delivered ? {} : { message: "response was not delivered to the session by the upstream instance" }
|
|
3789
|
+
}, !delivered);
|
|
3753
3790
|
}),
|
|
3754
|
-
tool$1("create_session", "
|
|
3791
|
+
tool$1("create_session", "Creates a new session on a specific remote ai-or-die fleet instance. The instance input is required and never defaults; agent is required and must be one of claude, codex, copilot, gemini, or terminal; start:true is required for the session to actually run and be driveable. It returns resolvedInstance plus the remote create response, with sessionId converted to the global instanceId:localSessionId form when creation succeeds. It is useful when the user wants a new remote session to run on a named fleet host before using drive_task, send_message, or await_turn. It is not for selecting or inspecting an existing session; use list_instances and list_sessions first when the target is unknown.", objectSchema$1({
|
|
3755
3792
|
instance: stringProp$1("Required instance id or label. Create never uses the registry default."),
|
|
3756
|
-
agent:
|
|
3793
|
+
agent: {
|
|
3794
|
+
...stringProp$1("Required agent/runtime to create on the instance. Valid values: claude, codex, copilot, gemini, terminal."),
|
|
3795
|
+
enum: [
|
|
3796
|
+
"claude",
|
|
3797
|
+
"codex",
|
|
3798
|
+
"copilot",
|
|
3799
|
+
"gemini",
|
|
3800
|
+
"terminal"
|
|
3801
|
+
]
|
|
3802
|
+
},
|
|
3757
3803
|
name: stringProp$1("Optional display name for the session."),
|
|
3758
3804
|
workingDir: stringProp$1("Optional working directory on the remote instance."),
|
|
3759
3805
|
idempotencyKey: stringProp$1("Optional caller idempotency key; auto-generated when omitted."),
|
|
3760
|
-
start: booleanProp("
|
|
3761
|
-
readyTimeoutMs: numberProp$1("
|
|
3762
|
-
permissionMode: stringProp$1("
|
|
3763
|
-
agentArgs: arrayProp("
|
|
3764
|
-
disableStopGate: booleanProp("
|
|
3806
|
+
start: booleanProp("Set true to start the remote session immediately; without start:true the created session is not running or driveable."),
|
|
3807
|
+
readyTimeoutMs: numberProp$1("Bounded milliseconds to wait for the agent to become driveable before returning. The response carries ready, bound, and blocker."),
|
|
3808
|
+
permissionMode: stringProp$1("Claude-only permission mode for the launched agent: plan, acceptEdits, default, or bypassPermissions. Rejected with BAD_REQUEST if unknown or if agentArgs also sets it."),
|
|
3809
|
+
agentArgs: arrayProp("Claude-only extra launcher args appended after the github-router prefix. Do not include --permission-mode or --dangerously-skip-permissions; use permissionMode instead."),
|
|
3810
|
+
disableStopGate: booleanProp("Claude-only option to disable the structural Stop-gate on the launched session by injecting --no-stop-gate into agentArgs, so a driven session's turn-end does not hang on a blocking Stop hook. Requires a remote github-router that understands the flag.")
|
|
3765
3811
|
}, ["instance", "agent"]), async (args, signal) => {
|
|
3766
3812
|
const instance = await resolve(requiredString$1(args, "instance"));
|
|
3767
3813
|
const agent = requiredString$1(args, "agent");
|
|
@@ -3789,7 +3835,7 @@ function createFleetTools(options = {}) {
|
|
|
3789
3835
|
sessionId: localSessionId ? encodeSessionId(instance.id, localSessionId) : response.sessionId
|
|
3790
3836
|
});
|
|
3791
3837
|
}),
|
|
3792
|
-
tool$1("stop_session", "
|
|
3838
|
+
tool$1("stop_session", "Terminates an existing remote ai-or-die fleet session. The required sessionId must be global; instance is only a cross-check, mode is an optional remote-understood stop mode, and idempotencyKey is usually auto-generated unless retrying the same stop. It returns resolvedInstance, sessionId, stopped, and lifecycle. It is useful when the remote session should be ended and its in-flight turn should be killed. It is destructive and irreversible, with no resume companion; to merely unstick or interrupt a busy session without terminating it, use send_keys with op `interrupt`.", objectSchema$1({
|
|
3793
3839
|
sessionId: stringProp$1("Global session id in the form instanceId:localSessionId."),
|
|
3794
3840
|
instance: stringProp$1("Optional instance id/label; when supplied it must agree with sessionId."),
|
|
3795
3841
|
idempotencyKey: stringProp$1("Optional caller idempotency key; auto-generated when omitted."),
|
|
@@ -3807,10 +3853,10 @@ function createFleetTools(options = {}) {
|
|
|
3807
3853
|
...response
|
|
3808
3854
|
});
|
|
3809
3855
|
}),
|
|
3810
|
-
tool$1("await_turn", "Long-
|
|
3856
|
+
tool$1("await_turn", "Long-polls session events across remote ai-or-die fleet instances. The caller selects targets with instances, sessionIds, or neither for every registered instance; timeoutMs bounds each per-instance long poll, kinds filters event kinds, and watcherId isolates cursor state for concurrent watchers. It returns resolvedInstances, time-sorted stamped events, gaps, cursors, more, optional per-session settled classifications, and optional per-instance errors. It is useful after send_message with awaitMs:0 to observe the real turn boundary; a settled status such as turn_ended or waiting_input is the reliable completion signal, while idle flickers are not completion. It is not a transcript reader or a one-shot task driver; use read_session for text output and drive_task when sending one prompt and waiting for its report should be a single composite operation.", objectSchema$1({
|
|
3811
3857
|
instances: arrayProp("Instance ids or labels to poll. Omit with sessionIds to target those session instances; omit both to poll every registered instance."),
|
|
3812
3858
|
sessionIds: arrayProp("Global session ids to filter to."),
|
|
3813
|
-
timeoutMs: numberProp$1(
|
|
3859
|
+
timeoutMs: numberProp$1(`Long-poll timeout per instance in milliseconds (default ${AWAIT_TURN_DEFAULT_TIMEOUT_MS}).`),
|
|
3814
3860
|
kinds: arrayProp("Optional event kinds to filter to."),
|
|
3815
3861
|
watcherId: stringProp$1("Optional stable id for this watcher. Use a distinct value for concurrent watchers over the same target set to keep cursors isolated.")
|
|
3816
3862
|
}, []), async (args, signal) => {
|
|
@@ -3873,7 +3919,7 @@ function createFleetTools(options = {}) {
|
|
|
3873
3919
|
...errors.length > 0 ? { errors } : {}
|
|
3874
3920
|
});
|
|
3875
3921
|
}),
|
|
3876
|
-
tool$1("drive_task", "
|
|
3922
|
+
tool$1("drive_task", "Drives one prompt on an existing remote ai-or-die fleet session to completion and returns a parsed operator report. The required sessionId must be global, prompt is the single instruction to send, timeoutMs controls when a hung turn is interrupted for recovery, and expectReport defaults to true so a nonce-guarded OPERATOR REPORT trailer is appended and parsed. It returns resolvedInstance, sessionId, state, summary, ask, artifact, raw, settled, submitted, reportFound, and recovery fields such as interrupted or recovered; state must be read together with settled and interrupted because a timeout recovery can leave work needing verification. It is useful as the composite path that performs the safe send_message plus await_turn plus read_session sequence for one already-created session. It is not a session creator, a multi-turn conversation loop, or a simple transcript read; use create_session first when needed, send_message and await_turn when controlling each step manually, and read_session when only the transcript tail is needed.", objectSchema$1({
|
|
3877
3923
|
sessionId: stringProp$1("Global session id in the form instanceId:localSessionId."),
|
|
3878
3924
|
instance: stringProp$1("Optional instance id/label; when supplied it must agree with sessionId."),
|
|
3879
3925
|
prompt: stringProp$1("The task/prompt to drive on the session."),
|
|
@@ -3898,7 +3944,7 @@ function createFleetTools(options = {}) {
|
|
|
3898
3944
|
...result
|
|
3899
3945
|
}, result.error !== void 0);
|
|
3900
3946
|
}),
|
|
3901
|
-
tool$1("read_file", "
|
|
3947
|
+
tool$1("read_file", "Reads a file from one remote ai-or-die fleet instance's filesystem. The required path is passed to the remote host as an unsanitized read request; this router does not confine it to a local workspace, and path policy is delegated to the remote instance. It returns resolvedInstance plus the remote file-content response. It is useful for reading a known file on a remote fleet host after choosing an instance. It is not for local files, directory browsing, text search, git revisions, or session transcripts; use local Read for this machine, list_dir to browse remote directories, search to find remote files, git_show for revision content, and read_session for terminal output.", objectSchema$1({
|
|
3902
3948
|
instance: stringProp$1("Instance id or label. Defaults to the registry default, or the sole instance."),
|
|
3903
3949
|
path: stringProp$1("Remote file path to read.")
|
|
3904
3950
|
}, ["path"]), async (args, signal) => {
|
|
@@ -3909,7 +3955,7 @@ function createFleetTools(options = {}) {
|
|
|
3909
3955
|
...response
|
|
3910
3956
|
});
|
|
3911
3957
|
}),
|
|
3912
|
-
tool$1("list_dir", "
|
|
3958
|
+
tool$1("list_dir", "Lists a directory on one remote ai-or-die fleet instance. The required path is the remote directory path, and instance can select a registered host or default to the registry default or sole instance. It returns resolvedInstance plus the remote directory-listing response. It is useful for browsing a remote workspace before choosing a file to read or search. It is not for local directories, file contents, git revisions, or session transcripts; use local filesystem tools for this machine, read_file for remote file contents, git_show for revision content, and read_session for terminal output.", objectSchema$1({
|
|
3913
3959
|
instance: stringProp$1("Instance id or label. Defaults to the registry default, or the sole instance."),
|
|
3914
3960
|
path: stringProp$1("Remote directory path to list.")
|
|
3915
3961
|
}, ["path"]), async (args, signal) => {
|
|
@@ -3920,7 +3966,7 @@ function createFleetTools(options = {}) {
|
|
|
3920
3966
|
...response
|
|
3921
3967
|
});
|
|
3922
3968
|
}),
|
|
3923
|
-
tool$1("search", "
|
|
3969
|
+
tool$1("search", "Searches files on one remote ai-or-die fleet instance's workspace, where a fleet instance is a registered remote host exposed through the fleet MCP server. The required query is sent to that remote instance, and path can narrow the remote search scope; this does not search the local repository or the web. It returns resolvedInstance plus the remote search response. It is useful when the target content lives on a remote fleet host. It is not for this checkout, semantic code discovery, or internet research; use mcp__search__code for the local workspace and mcp__search__web for web search.", objectSchema$1({
|
|
3924
3970
|
instance: stringProp$1("Instance id or label. Defaults to the registry default, or the sole instance."),
|
|
3925
3971
|
query: stringProp$1("Search query."),
|
|
3926
3972
|
path: stringProp$1("Optional path scope.")
|
|
@@ -3932,18 +3978,16 @@ function createFleetTools(options = {}) {
|
|
|
3932
3978
|
...response
|
|
3933
3979
|
});
|
|
3934
3980
|
}),
|
|
3935
|
-
tool$1("git_show", "
|
|
3981
|
+
tool$1("git_show", "Shows git content on one remote ai-or-die fleet instance, such as a file at a specific revision or a commit object. The required path identifies the remote repository path or file path, and the optional ref is a git commit-ish such as HEAD, a branch, a tag, or a commit SHA. It returns resolvedInstance plus the remote git-show response. It is useful when the caller needs repository content as it existed at a revision on the remote host. It is not for current working-tree reads, directory listings, local git commands, or web search; use read_file for current remote file content and local tools for this checkout.", objectSchema$1({
|
|
3936
3982
|
instance: stringProp$1("Instance id or label. Defaults to the registry default, or the sole instance."),
|
|
3937
3983
|
path: stringProp$1("Remote repository path or file path for git-show."),
|
|
3938
|
-
ref: stringProp$1("Optional git ref
|
|
3939
|
-
rev: stringProp$1("Optional git revision alias."),
|
|
3940
|
-
commit: stringProp$1("Optional commit id.")
|
|
3984
|
+
ref: stringProp$1("Optional git ref, revision, or commit-ish, such as HEAD, a branch, a tag, or a commit SHA.")
|
|
3941
3985
|
}, ["path"]), async (args, signal) => {
|
|
3942
3986
|
const instance = await resolve(optionalString$1(args, "instance"));
|
|
3943
|
-
const response = await clientFor(instance).gitShow({
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
}, signal);
|
|
3987
|
+
const response = await clientFor(instance).gitShow(definedObject({
|
|
3988
|
+
path: requiredString$1(args, "path"),
|
|
3989
|
+
ref: optionalString$1(args, "ref")
|
|
3990
|
+
}), signal);
|
|
3947
3991
|
return ok$1({
|
|
3948
3992
|
resolvedInstance: publicInstance(instance),
|
|
3949
3993
|
...response
|
|
@@ -6037,10 +6081,12 @@ const T0_MODEL_CHAIN = [
|
|
|
6037
6081
|
const T1_MODEL_CHAIN = [
|
|
6038
6082
|
"gpt-5.4-mini",
|
|
6039
6083
|
"gpt-5-mini",
|
|
6084
|
+
"gpt-5.6-sol",
|
|
6040
6085
|
"gpt-5.5",
|
|
6041
6086
|
"gemini-3.1-pro-preview"
|
|
6042
6087
|
];
|
|
6043
6088
|
const T2_MODEL_CHAIN = [
|
|
6089
|
+
"gpt-5.6-sol",
|
|
6044
6090
|
"gpt-5.5",
|
|
6045
6091
|
"claude-opus-4.8",
|
|
6046
6092
|
"gemini-3.1-pro-preview"
|
|
@@ -6942,7 +6988,7 @@ async function observeUnit(unit) {
|
|
|
6942
6988
|
* present — an explicitly-chosen model that Copilot can't serve THROWS rather
|
|
6943
6989
|
* than being silently swapped for a fallback (a silent class-switch could send
|
|
6944
6990
|
* the task to a weaker/wrong model the operator never asked for).
|
|
6945
|
-
* - `chosen` unset: default to {@link DEFAULT_CODEX_MODEL} (gpt-5.
|
|
6991
|
+
* - `chosen` unset: default to {@link DEFAULT_CODEX_MODEL} (gpt-5.6-sol), walking
|
|
6946
6992
|
* {@link DEFAULT_CODEX_MODEL_FALLBACKS} only when a catalog says the preferred
|
|
6947
6993
|
* default is absent (older Copilot tiers).
|
|
6948
6994
|
*
|
|
@@ -9282,7 +9328,7 @@ function buildRoleAgent(role) {
|
|
|
9282
9328
|
"Verification commands and outcomes",
|
|
9283
9329
|
"Risks and follow-ups"
|
|
9284
9330
|
],
|
|
9285
|
-
model: "gpt-5.
|
|
9331
|
+
model: "gpt-5.6-sol"
|
|
9286
9332
|
},
|
|
9287
9333
|
reviewer: {
|
|
9288
9334
|
description: "Adversarial code reviewer for concrete diffs; reports real findings with severity and file:line.",
|
|
@@ -9362,7 +9408,7 @@ function buildRoleAgent(role) {
|
|
|
9362
9408
|
"Commands run and outcomes",
|
|
9363
9409
|
"Failures that require implementation work"
|
|
9364
9410
|
],
|
|
9365
|
-
model: "gpt-5.
|
|
9411
|
+
model: "gpt-5.6-sol"
|
|
9366
9412
|
}
|
|
9367
9413
|
}[role];
|
|
9368
9414
|
const modelLine = spec.model === void 0 ? "" : `model: ${spec.model}\n`;
|
|
@@ -10421,13 +10467,13 @@ function createFirstMateTools(depsOverride = {}) {
|
|
|
10421
10467
|
};
|
|
10422
10468
|
}
|
|
10423
10469
|
return Object.freeze([
|
|
10424
|
-
tool$1("start_mission", "
|
|
10470
|
+
tool$1("start_mission", "Registers a first-mate mission in the local durable controller for one or more GitHub repositories; it does not dispatch work or touch GitHub on this call. Inputs provide the mission goal, owner/name repos, user-blessed acceptance criteria, and optional priority, house rules, default cloud-agent model, plan gate, and CI requirement. Returns the new mission id and normalized repo list so later wakes can decompose and dispatch units. Use when the operator has accepted mission scope and wants the first-mate loop to own tracking. It is not for one-off status reads, adding units to an existing mission, or missions whose acceptance criteria are still unsettled.", objectSchema({
|
|
10425
10471
|
goal: stringProp("Mission goal."),
|
|
10426
10472
|
repos: stringArrayProp("Repositories as owner/name strings."),
|
|
10427
10473
|
acceptance_criteria: stringProp("User-blessed acceptance criteria for the mission."),
|
|
10428
10474
|
priority: numberProp("Optional numeric priority; higher values are handled by controller policy."),
|
|
10429
10475
|
house_rules: stringProp("Optional repository or operator constraints."),
|
|
10430
|
-
default_model: stringProp("Model the GitHub cloud coding agent uses for this mission's tasks; defaults to gpt-5.
|
|
10476
|
+
default_model: stringProp("Model the GitHub cloud coding agent uses for this mission's tasks; defaults to gpt-5.6-sol."),
|
|
10431
10477
|
plan_gate: enumProp(["hard", "soft"], "Plan-review gate. hard (default) requires the flow's review before build and re-plans on a rejecting review; soft auto-advances a passing plan review to build without human approval but escalates a rejecting review to a human."),
|
|
10432
10478
|
ci_required: boolProp("When true, refuse merge approval if the repository reports no CI for the PR head.")
|
|
10433
10479
|
}, [
|
|
@@ -10460,7 +10506,7 @@ function createFirstMateTools(depsOverride = {}) {
|
|
|
10460
10506
|
repos
|
|
10461
10507
|
});
|
|
10462
10508
|
}),
|
|
10463
|
-
tool$1("scaffold_repo", "
|
|
10509
|
+
tool$1("scaffold_repo", "Seeds first-mate and agentic-dev convention files into a GitHub repository by creating a scaffold branch, committing deterministic files, and opening a pull request; it does not write directly to the default branch. Inputs name the owner/name repo, optional base ref, handling mode, and optional detection overrides for stack, OS, package manager, commands, and UI evidence. Returns the pull request plus committed, preserved, and per-file report data, or a no-op note when nothing needs seeding. Use when preparing an owned repository for the first-mate cloud-agent workflow. It is not for arbitrary third-party repositories, normal feature work, or repeated runs unless the operator intentionally wants missing or enhanced convention files.", objectSchema({
|
|
10464
10510
|
repo: stringProp("Repository as an owner/name string."),
|
|
10465
10511
|
mode: enumProp([
|
|
10466
10512
|
"add-missing-only",
|
|
@@ -10521,7 +10567,7 @@ function createFirstMateTools(depsOverride = {}) {
|
|
|
10521
10567
|
report: plan.reports
|
|
10522
10568
|
});
|
|
10523
10569
|
}),
|
|
10524
|
-
tool$1("advance", "
|
|
10570
|
+
tool$1("advance", "Wakes the first-mate controller once, optionally applying model answers and human decisions before driving eligible missions. Inputs can supply prior request answers, bound returned request count, provider concurrency, scope the wake to one mission, or include inactive missions in the returned view. Returns the compact board, inactive summary, pending model and human requests, applied answer count, next wake timing, and whether this caller actually drove or deferred to another driver. Use when the operator is advancing the durable loop, responding to needsModel/needsHuman, or scheduling the next wake from nextWakeSeconds. It is not for read-only status checks; board reads the whole portfolio without a wake, and mission_status reads a mission-id-scoped status view.", objectSchema({
|
|
10525
10571
|
model_answers: arrayOfObjectsProp("Optional model judgments to apply before the wake.", {
|
|
10526
10572
|
requestId: stringProp("Request id from a previous needsModel entry."),
|
|
10527
10573
|
verdict: anyProp("Structured verdict for the request kind.")
|
|
@@ -10575,7 +10621,7 @@ function createFirstMateTools(depsOverride = {}) {
|
|
|
10575
10621
|
drove: result.drove !== false
|
|
10576
10622
|
});
|
|
10577
10623
|
}),
|
|
10578
|
-
tool$1("board", "
|
|
10624
|
+
tool$1("board", "Reads the compact first-mate portfolio board without waking the controller, dispatching work, or applying answers. Inputs only choose whether inactive missions are included; active missions are returned by default with inactive counts summarized separately. Returns the same board shape that advance returns as a side effect, including mission phase counts, blocked counts, unit rows, and inactive summary. Use when the operator needs a whole-portfolio snapshot. It is not for driving progress or applying pending requests; advance does that, and mission_status is the read path scoped to a single mission id.", objectSchema({ include_all: boolProp("When true, include inactive missions in the board. Default returns active missions only and summarizes inactive counts.") }, []), async (args) => {
|
|
10579
10625
|
const includeAll = optionalBoolean(args, "include_all") ?? false;
|
|
10580
10626
|
const [missions, units] = await Promise.all([readMissions(), loadAllUnits()]);
|
|
10581
10627
|
return ok({
|
|
@@ -10583,7 +10629,7 @@ function createFirstMateTools(depsOverride = {}) {
|
|
|
10583
10629
|
inactiveSummary: summarizeInactiveMissions(missions)
|
|
10584
10630
|
});
|
|
10585
10631
|
}),
|
|
10586
|
-
tool$1("merge_pr", "
|
|
10632
|
+
tool$1("merge_pr", "Merges a live GitHub pull request immediately, which is irreversible through this tool once GitHub accepts the merge. Inputs identify the repo and PR, bind the action to the exact reviewed head SHA, optionally bind the reviewed base branch, select the merge method, and can explicitly override ownership with allow_unowned. Returns GitHub's merge result and merge SHA after the live PR passes head-SHA and optional base concurrency checks, ownership checks, OPEN/not-draft/mergeable checks, and available CI or workflow checks. Use only after out-of-band human authorization for this exact head; this tool does not consult the first-mate approval ledger. It is not for PRs that are not agent-authored or correlated to a first-mate unit (unit.pr === pr) unless allow_unowned is intentionally set; a repo with no configured CI can merge on operator review plus the non-CI guards.", objectSchema({
|
|
10587
10633
|
repo: stringProp("Repository as an owner/name string."),
|
|
10588
10634
|
pr: numberProp("Pull request number."),
|
|
10589
10635
|
expected_head_sha: stringProp("The exact head commit SHA the operator reviewed. The merge is REJECTED if the live head has moved from this value; re-review the new head before merging."),
|
|
@@ -10593,7 +10639,7 @@ function createFirstMateTools(depsOverride = {}) {
|
|
|
10593
10639
|
"squash",
|
|
10594
10640
|
"rebase"
|
|
10595
10641
|
], "Merge method. Defaults to squash."),
|
|
10596
|
-
allow_unowned: boolProp("Set true to merge a PR that is neither agent-authored nor
|
|
10642
|
+
allow_unowned: boolProp("Set true to merge a PR that is neither agent-authored nor correlated to a first-mate unit (unit.pr === pr). Dangerous, explicit opt-in; the override is audit-logged.")
|
|
10597
10643
|
}, [
|
|
10598
10644
|
"repo",
|
|
10599
10645
|
"pr",
|
|
@@ -10625,10 +10671,10 @@ function createFirstMateTools(depsOverride = {}) {
|
|
|
10625
10671
|
sha: merged.sha
|
|
10626
10672
|
});
|
|
10627
10673
|
}),
|
|
10628
|
-
tool$1("close_pr", "
|
|
10674
|
+
tool$1("close_pr", "Closes a live GitHub pull request without merging it and reconciles any correlated first-mate units as terminal in the local ledger. Inputs identify the owner/name repo and PR, with allow_unowned as an explicit override for PRs outside first-mate ownership. Returns the closed state plus reconciliation counts, or an already-closed note when the PR was previously closed. Use when the operator wants to stop an open PR rather than merge it. It is not for merged PRs, or for PRs that are not agent-authored or correlated to a first-mate unit (unit.pr === pr), unless allow_unowned is intentionally set.", objectSchema({
|
|
10629
10675
|
repo: stringProp("Repository as an owner/name string."),
|
|
10630
10676
|
pr: numberProp("Pull request number."),
|
|
10631
|
-
allow_unowned: boolProp("Set true to close a PR that is neither agent-authored nor
|
|
10677
|
+
allow_unowned: boolProp("Set true to close a PR that is neither agent-authored nor correlated to a first-mate unit (unit.pr === pr). Explicit opt-in; audit-logged.")
|
|
10632
10678
|
}, ["repo", "pr"]), async (args) => {
|
|
10633
10679
|
const repoSlug = requiredString(args, "repo");
|
|
10634
10680
|
const repo = parseRepoSlug(repoSlug);
|
|
@@ -10655,10 +10701,10 @@ function createFirstMateTools(depsOverride = {}) {
|
|
|
10655
10701
|
reconciled
|
|
10656
10702
|
});
|
|
10657
10703
|
}),
|
|
10658
|
-
tool$1("mark_ready", "
|
|
10704
|
+
tool$1("mark_ready", "Marks an open draft GitHub pull request ready for review through GitHub's ready-for-review mutation. Inputs identify the owner/name repo and PR, with allow_unowned as an explicit override for PRs outside first-mate ownership. Returns whether the PR is ready and whether it was already non-draft. Use when a first-mate or operator-owned draft PR should enter human or CI review. It is not for closed or merged PRs, or for PRs that are not agent-authored or correlated to a first-mate unit (unit.pr === pr), unless allow_unowned is intentionally set.", objectSchema({
|
|
10659
10705
|
repo: stringProp("Repository as an owner/name string."),
|
|
10660
10706
|
pr: numberProp("Pull request number."),
|
|
10661
|
-
allow_unowned: boolProp("Set true to mark a PR ready when it is neither agent-authored nor
|
|
10707
|
+
allow_unowned: boolProp("Set true to mark a PR ready when it is neither agent-authored nor correlated to a first-mate unit (unit.pr === pr). Explicit opt-in; audit-logged.")
|
|
10662
10708
|
}, ["repo", "pr"]), async (args) => {
|
|
10663
10709
|
const repoSlug = requiredString(args, "repo");
|
|
10664
10710
|
const repo = parseRepoSlug(repoSlug);
|
|
@@ -10681,7 +10727,7 @@ function createFirstMateTools(depsOverride = {}) {
|
|
|
10681
10727
|
alreadyReady: false
|
|
10682
10728
|
});
|
|
10683
10729
|
}),
|
|
10684
|
-
tool$1("add_units", "
|
|
10730
|
+
tool$1("add_units", "Adds dispatchable units to an existing active first-mate mission without dispatching them immediately. Inputs name the mission and unit list; each unit supplies a title plus optional repo, provider, same-call dependency indices, and model override. Returns the mission id and the units actually added after validation and deduplication. Use when the operator has decomposed additional work for a mission that is already active. It is not for creating a new mission, adding work to inactive missions, or expressing dependencies on units from earlier calls; dependsOn indices are 0-based within this submitted list, invalid or self indices are ignored, and cycles are rejected.", objectSchema({
|
|
10685
10731
|
mission_id: stringProp("Mission id to add units to."),
|
|
10686
10732
|
units: arrayOfObjectsProp("Units to add to the mission.", {
|
|
10687
10733
|
title: stringProp("Unit title."),
|
|
@@ -10711,7 +10757,7 @@ function createFirstMateTools(depsOverride = {}) {
|
|
|
10711
10757
|
added: await addUnitsToMission(mission, units, deps, existingUnits)
|
|
10712
10758
|
});
|
|
10713
10759
|
}),
|
|
10714
|
-
tool$1("abandon_mission", "
|
|
10760
|
+
tool$1("abandon_mission", "Marks a first-mate mission abandoned in the local durable ledgers so it drops from the active board, and terminalizes live units without merging. Inputs name the mission and can include a short operator reason returned in the tool result. Returns the abandoned mission id and the number of units marked terminal. Use when the operator is permanently retiring a mission from first-mate tracking. It is local-ledger-only and terminal, not a remote cancellation tool: open PRs stay open and GitHub cloud agents keep running unless the operator closes or stops that work separately.", objectSchema({
|
|
10715
10761
|
mission_id: stringProp("Mission id to abandon."),
|
|
10716
10762
|
reason: stringProp("Optional short reason for the abandonment.")
|
|
10717
10763
|
}, ["mission_id"]), async (args) => {
|
|
@@ -10742,7 +10788,7 @@ function createFirstMateTools(depsOverride = {}) {
|
|
|
10742
10788
|
...reason !== void 0 ? { reason } : {}
|
|
10743
10789
|
});
|
|
10744
10790
|
}),
|
|
10745
|
-
tool$1("mission_status", "
|
|
10791
|
+
tool$1("mission_status", "Reads compact first-mate mission status without waking the controller or dispatching work. Inputs can filter by mission_id and can include inactive missions; active missions are returned by default with inactive counts summarized separately. Returns mission status rows built from the same board data, including counts, blocked count, unit rows, and done/failed summary. Use when the operator needs a mission-id-scoped read or a compact status list. It is not for the whole portfolio board without a mission filter, which is board, and it is not for driving progress, which is advance.", objectSchema({
|
|
10746
10792
|
mission_id: stringProp("Optional mission id to filter to."),
|
|
10747
10793
|
include_all: boolProp("When true, include inactive missions in the status list. Default returns active missions only and summarizes inactive counts.")
|
|
10748
10794
|
}, []), async (args) => {
|
|
@@ -18487,7 +18533,7 @@ function toolEnvelope(data, isError) {
|
|
|
18487
18533
|
* and (3) opens a WS to the bridge, sends the tool call, awaits the
|
|
18488
18534
|
* response with a per-tool timeout.
|
|
18489
18535
|
*
|
|
18490
|
-
* Each entry carries
|
|
18536
|
+
* Each entry carries a browser capability tag so `browserToolsEnabled()`
|
|
18491
18537
|
* in `src/routes/mcp/handler.ts` drops them at both list-time and
|
|
18492
18538
|
* call-time when the operator hasn't opted in via `--browse` or
|
|
18493
18539
|
* `GH_ROUTER_ENABLE_BROWSE=1`.
|
|
@@ -18505,7 +18551,7 @@ function toolEnvelope(data, isError) {
|
|
|
18505
18551
|
const BROWSER_TOOLS = Object.freeze([
|
|
18506
18552
|
{
|
|
18507
18553
|
toolNameHttp: "browser_list_tabs",
|
|
18508
|
-
description: "
|
|
18554
|
+
description: "Lists open tabs across all browser windows. It takes no input and returns each tab's id, URL, title, active flag, and window id. The returned tab ids are the inputs used by tab-scoped browser tools, especially for pre-existing tabs that were not opened by browser_open_tab. It is a power-tier discovery tool for tab selection and inventory, not a page-content reader or navigation tool.",
|
|
18509
18555
|
inputSchema: {
|
|
18510
18556
|
type: "object",
|
|
18511
18557
|
additionalProperties: false,
|
|
@@ -18518,7 +18564,7 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18518
18564
|
},
|
|
18519
18565
|
{
|
|
18520
18566
|
toolNameHttp: "browser_open_tab",
|
|
18521
|
-
description: "
|
|
18567
|
+
description: "Opens a URL in a new browser tab, or navigates the currently active tab when reuseActive is true, then waits briefly for the tab load state to reach complete. It takes a URL and optional reuseActive flag, and returns the tab id, final URL, and a synthetic statusCode load flag where 200 means the tab reported complete and 0 means it did not. The statusCode is not the page's HTTP response code, so a loaded 404 page can still return 200. Use this to establish a tab before other browser tools; blocked URLs return {blocked, reason}, including browser settings/preferences/extensions/flags pages, file:// by default, and extension options/popup pages, while devtools:// is allowed.",
|
|
18522
18568
|
inputSchema: {
|
|
18523
18569
|
type: "object",
|
|
18524
18570
|
required: ["url"],
|
|
@@ -18526,11 +18572,11 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18526
18572
|
properties: {
|
|
18527
18573
|
url: {
|
|
18528
18574
|
type: "string",
|
|
18529
|
-
description: "
|
|
18575
|
+
description: "URL to load. Browser-internal settings, preferences, extensions, flags, password/management pages, extension options/popup pages, and file:// URLs by default are blocked before dispatch."
|
|
18530
18576
|
},
|
|
18531
18577
|
reuseActive: {
|
|
18532
18578
|
type: "boolean",
|
|
18533
|
-
description: "When true,
|
|
18579
|
+
description: "When true, navigates the currently active tab instead of opening a new tab. Default false. Use browser_navigate when you already know the target tab id."
|
|
18534
18580
|
}
|
|
18535
18581
|
}
|
|
18536
18582
|
},
|
|
@@ -18541,7 +18587,7 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18541
18587
|
},
|
|
18542
18588
|
{
|
|
18543
18589
|
toolNameHttp: "browser_close_tab",
|
|
18544
|
-
description: "
|
|
18590
|
+
description: "Closes one or more browser tabs by id. It takes a non-empty tabIds array, usually obtained from browser_list_tabs, and returns {closed: N} after requesting Chrome to remove those tabs. This is a power-tier tab lifecycle tool for cleanup or closing known throwaway tabs. Avoid using it when the user may still need a tab, and prefer leaving the tab open if the id was not freshly discovered or created for the current task.",
|
|
18545
18591
|
inputSchema: {
|
|
18546
18592
|
type: "object",
|
|
18547
18593
|
required: ["tabIds"],
|
|
@@ -18549,7 +18595,7 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18549
18595
|
properties: { tabIds: {
|
|
18550
18596
|
type: "array",
|
|
18551
18597
|
items: { type: "number" },
|
|
18552
|
-
description: "
|
|
18598
|
+
description: "Non-empty array of tab ids to close, usually from browser_list_tabs or browser_open_tab."
|
|
18553
18599
|
} }
|
|
18554
18600
|
},
|
|
18555
18601
|
capability: "browser_power",
|
|
@@ -18559,7 +18605,7 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18559
18605
|
},
|
|
18560
18606
|
{
|
|
18561
18607
|
toolNameHttp: "browser_navigate",
|
|
18562
|
-
description: "
|
|
18608
|
+
description: "Navigates an existing tab by going to a URL, moving back or forward in history, or reloading. It takes a tab id plus an action, with url required only for action='goto', and returns {finalUrl, statusCode} for completed navigation or {blocked, reason} for a policy-blocked URL. The statusCode is a synthetic load-complete flag, not the page's HTTP response code. Use this when the target tab already exists; use browser_open_tab to create a new tab, and expect the same URL policy blocks as open_tab, including browser-internal pages, file:// by default, and extension options/popup pages.",
|
|
18563
18609
|
inputSchema: {
|
|
18564
18610
|
type: "object",
|
|
18565
18611
|
required: ["tabId", "action"],
|
|
@@ -18567,7 +18613,7 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18567
18613
|
properties: {
|
|
18568
18614
|
tabId: {
|
|
18569
18615
|
type: "number",
|
|
18570
|
-
description: "Tab id from browser_list_tabs
|
|
18616
|
+
description: "Tab id from browser_list_tabs or browser_open_tab."
|
|
18571
18617
|
},
|
|
18572
18618
|
action: {
|
|
18573
18619
|
type: "string",
|
|
@@ -18577,15 +18623,15 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18577
18623
|
"forward",
|
|
18578
18624
|
"reload"
|
|
18579
18625
|
],
|
|
18580
|
-
description: "
|
|
18626
|
+
description: "Navigation action: goto a URL, go back, go forward, or reload the current page."
|
|
18581
18627
|
},
|
|
18582
18628
|
url: {
|
|
18583
18629
|
type: "string",
|
|
18584
|
-
description: "
|
|
18630
|
+
description: "URL to load when action='goto'. Ignored for back, forward, and reload."
|
|
18585
18631
|
},
|
|
18586
18632
|
hard: {
|
|
18587
18633
|
type: "boolean",
|
|
18588
|
-
description: "Reload only:
|
|
18634
|
+
description: "Reload only: when true, bypasses cache like Ctrl+Shift+R. Default false."
|
|
18589
18635
|
}
|
|
18590
18636
|
}
|
|
18591
18637
|
},
|
|
@@ -18596,7 +18642,7 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18596
18642
|
},
|
|
18597
18643
|
{
|
|
18598
18644
|
toolNameHttp: "browser_screenshot",
|
|
18599
|
-
description: "
|
|
18645
|
+
description: "Captures a screenshot of the visible area of a tab, as PNG by default or JPEG when requested. It takes a tab id and optional format, then returns base64-encoded image bytes plus contentType. The tab must be active in its window, so this tool auto-activates the tab if needed and that changes which tab is focused. Use screenshot for visual layout, canvas, SVG, maps, or image-only regions; prefer browser_observe when page text and actionable state are enough.",
|
|
18600
18646
|
inputSchema: {
|
|
18601
18647
|
type: "object",
|
|
18602
18648
|
required: ["tabId"],
|
|
@@ -18604,12 +18650,12 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18604
18650
|
properties: {
|
|
18605
18651
|
tabId: {
|
|
18606
18652
|
type: "number",
|
|
18607
|
-
description: "Tab id from browser_list_tabs
|
|
18653
|
+
description: "Tab id from browser_list_tabs or browser_open_tab."
|
|
18608
18654
|
},
|
|
18609
18655
|
format: {
|
|
18610
18656
|
type: "string",
|
|
18611
18657
|
enum: ["png", "jpeg"],
|
|
18612
|
-
description: "Image format. Default 'png'."
|
|
18658
|
+
description: "Image format for the returned screenshot. Default 'png'; use 'jpeg' when smaller image bytes are preferable."
|
|
18613
18659
|
}
|
|
18614
18660
|
}
|
|
18615
18661
|
},
|
|
@@ -18620,7 +18666,7 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18620
18666
|
},
|
|
18621
18667
|
{
|
|
18622
18668
|
toolNameHttp: "browser_read_page",
|
|
18623
|
-
description: "
|
|
18669
|
+
description: "Returns a compressed page snapshot for a tab: visible text, interactive elements with refs, viewport metadata, and visualSurfaces for canvas or SVG regions that need vision. It takes a tab id and optional mode, and each element includes a ref plus bbox in CSS viewport pixels, the same coordinate space used by browser_mouse, browser_drag, and scroll at-pointer. Refs persist across snapshots of the same document until navigation or DOM replacement, and are a better input to follow-up actions than brittle CSS selectors. Use read_page when enumeration, coordinates, refs, or raw snapshot structure are needed; prefer browser_act or browser_find for intent-driven interaction, browser_observe for a short natural-language page summary, and browser_screenshot for visual pixels.",
|
|
18624
18670
|
inputSchema: {
|
|
18625
18671
|
type: "object",
|
|
18626
18672
|
required: ["tabId"],
|
|
@@ -18628,12 +18674,12 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18628
18674
|
properties: {
|
|
18629
18675
|
tabId: {
|
|
18630
18676
|
type: "number",
|
|
18631
|
-
description: "Tab id from browser_list_tabs
|
|
18677
|
+
description: "Tab id from browser_list_tabs or browser_open_tab."
|
|
18632
18678
|
},
|
|
18633
18679
|
mode: {
|
|
18634
18680
|
type: "string",
|
|
18635
18681
|
enum: ["summary", "full"],
|
|
18636
|
-
description: "Snapshot scope. Default 'summary'
|
|
18682
|
+
description: "Snapshot scope. Default 'summary' focuses on viewport-visible text and elements; 'full' asks for a broader page-wide snapshot. The default CDP extractor caps around 500 elements and 32 KiB text, with legacy fallback caps possibly lower or higher by mode."
|
|
18637
18683
|
}
|
|
18638
18684
|
}
|
|
18639
18685
|
},
|
|
@@ -18644,13 +18690,16 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18644
18690
|
},
|
|
18645
18691
|
{
|
|
18646
18692
|
toolNameHttp: "browser_scroll",
|
|
18647
|
-
description: "
|
|
18693
|
+
description: "Scrolls a tab or a scrollable region inside a tab. It takes a tab id, target mode, and mode-specific fields for page top/bottom, pixel deltas, element centering, or wheel scrolling at a pointer. The at-pointer path dispatches a real wheel event at a ref, selector, or CSS viewport coordinate, which is the path for chat panes, infinite lists, and modal bodies with their own scroll containers. Use browser_act with action='scroll_into_view' or intent mode for simple element reveal; use browser_scroll when page-level movement, precise deltas, or sub-container wheel scrolling are needed.",
|
|
18648
18694
|
inputSchema: {
|
|
18649
18695
|
type: "object",
|
|
18650
18696
|
required: ["tabId", "target"],
|
|
18651
18697
|
additionalProperties: false,
|
|
18652
18698
|
properties: {
|
|
18653
|
-
tabId: {
|
|
18699
|
+
tabId: {
|
|
18700
|
+
type: "number",
|
|
18701
|
+
description: "Tab id from browser_list_tabs or browser_open_tab."
|
|
18702
|
+
},
|
|
18654
18703
|
target: {
|
|
18655
18704
|
type: "string",
|
|
18656
18705
|
enum: [
|
|
@@ -18660,39 +18709,39 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18660
18709
|
"element",
|
|
18661
18710
|
"at-pointer"
|
|
18662
18711
|
],
|
|
18663
|
-
description: "Scroll target
|
|
18712
|
+
description: "Scroll target mode: page top, page bottom, pixel delta, element centering, or wheel event at a pointer."
|
|
18664
18713
|
},
|
|
18665
18714
|
pixels: {
|
|
18666
18715
|
type: "number",
|
|
18667
|
-
description: "Pixel delta when target=pixels. Positive scrolls down
|
|
18716
|
+
description: "Pixel delta when target='pixels'. Positive scrolls down and negative scrolls up."
|
|
18668
18717
|
},
|
|
18669
18718
|
ref: {
|
|
18670
18719
|
type: "string",
|
|
18671
|
-
description: "Element ref. For target=element,
|
|
18720
|
+
description: "Element ref. For target='element', the element is centered; for target='at-pointer', the element bbox center becomes the wheel position."
|
|
18672
18721
|
},
|
|
18673
18722
|
selector: {
|
|
18674
18723
|
type: "string",
|
|
18675
|
-
description: "CSS selector. For target=at-pointer,
|
|
18724
|
+
description: "CSS selector fallback when no ref is available. For target='at-pointer', resolves to the element bbox center."
|
|
18676
18725
|
},
|
|
18677
18726
|
x: {
|
|
18678
18727
|
type: "number",
|
|
18679
|
-
description: "Pointer x
|
|
18728
|
+
description: "Pointer x in CSS viewport pixels for target='at-pointer'. Pair with y. Exactly one of ref, selector, or x+y is required for at-pointer."
|
|
18680
18729
|
},
|
|
18681
18730
|
y: {
|
|
18682
18731
|
type: "number",
|
|
18683
|
-
description: "Pointer y
|
|
18732
|
+
description: "Pointer y in CSS viewport pixels for target='at-pointer'. Pair with x."
|
|
18684
18733
|
},
|
|
18685
18734
|
deltaX: {
|
|
18686
18735
|
type: "number",
|
|
18687
|
-
description: "Wheel delta x
|
|
18736
|
+
description: "Wheel delta x in CSS pixels for target='at-pointer'. Default 0. Clamped to absolute value 10000."
|
|
18688
18737
|
},
|
|
18689
18738
|
deltaY: {
|
|
18690
18739
|
type: "number",
|
|
18691
|
-
description: "Wheel delta y
|
|
18740
|
+
description: "Wheel delta y in CSS pixels for target='at-pointer'. Positive scrolls down. Default 0. Clamped to absolute value 10000; at least one of deltaX or deltaY must be non-zero."
|
|
18692
18741
|
},
|
|
18693
18742
|
force: {
|
|
18694
18743
|
type: "boolean",
|
|
18695
|
-
description: "
|
|
18744
|
+
description: "For target='at-pointer', skips the pre-wheel elementFromPoint hit-test. Default false. Set true only when an overlay covers the target but forwards wheel events."
|
|
18696
18745
|
}
|
|
18697
18746
|
}
|
|
18698
18747
|
},
|
|
@@ -18703,16 +18752,19 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18703
18752
|
},
|
|
18704
18753
|
{
|
|
18705
18754
|
toolNameHttp: "browser_keyboard",
|
|
18706
|
-
description: "
|
|
18755
|
+
description: "Sends a discrete key or chord to the focused element or browser via CDP Input.dispatchKeyEvent. It takes a tab id and a keys string such as 'Control+L', 'Command+L', 'Enter', 'Escape', or 'ArrowDown', and returns the extension dispatch result. Browser-level shortcuts such as Ctrl+T and Ctrl+W actually fire because this uses chrome.debugger input rather than synthetic DOM events. Use keyboard for shortcuts and non-printable control keys; prefer browser_type for literal text entry into a focused field and browser_act with action='fill' for plain form values.",
|
|
18707
18756
|
inputSchema: {
|
|
18708
18757
|
type: "object",
|
|
18709
18758
|
required: ["tabId", "keys"],
|
|
18710
18759
|
additionalProperties: false,
|
|
18711
18760
|
properties: {
|
|
18712
|
-
tabId: {
|
|
18761
|
+
tabId: {
|
|
18762
|
+
type: "number",
|
|
18763
|
+
description: "Tab id from browser_list_tabs or browser_open_tab."
|
|
18764
|
+
},
|
|
18713
18765
|
keys: {
|
|
18714
18766
|
type: "string",
|
|
18715
|
-
description: "Key or chord.
|
|
18767
|
+
description: "Key or chord. Join modifiers with '+', using Control, Ctrl, Alt, Shift, Meta, Command, or Cmd. A single named key such as Enter or Escape is also valid."
|
|
18716
18768
|
}
|
|
18717
18769
|
}
|
|
18718
18770
|
},
|
|
@@ -18723,13 +18775,16 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18723
18775
|
},
|
|
18724
18776
|
{
|
|
18725
18777
|
toolNameHttp: "browser_wait",
|
|
18726
|
-
description: "
|
|
18778
|
+
description: "Waits for a tab condition without mutating the page. It takes a tab id, an until mode, and the matching operand: a CSS selector for element appearance, a JavaScript regex string for URL matching, or networkIdle for the heuristic of tab status complete plus 500 ms quiet. It returns {ok: true, elapsedMs} on success and {ok: false, reason: 'timeout'} when the condition is not reached before the timeout. Use wait after navigation or actions that trigger asynchronous rendering; do not use it as a page reader, and prefer browser_observe or browser_read_page when the task is to inspect current content.",
|
|
18727
18779
|
inputSchema: {
|
|
18728
18780
|
type: "object",
|
|
18729
18781
|
required: ["tabId", "until"],
|
|
18730
18782
|
additionalProperties: false,
|
|
18731
18783
|
properties: {
|
|
18732
|
-
tabId: {
|
|
18784
|
+
tabId: {
|
|
18785
|
+
type: "number",
|
|
18786
|
+
description: "Tab id from browser_list_tabs or browser_open_tab."
|
|
18787
|
+
},
|
|
18733
18788
|
until: {
|
|
18734
18789
|
type: "string",
|
|
18735
18790
|
enum: [
|
|
@@ -18737,19 +18792,19 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18737
18792
|
"url",
|
|
18738
18793
|
"networkIdle"
|
|
18739
18794
|
],
|
|
18740
|
-
description: "
|
|
18795
|
+
description: "Condition to wait for: selector, URL regex match, or network-idle heuristic."
|
|
18741
18796
|
},
|
|
18742
18797
|
selector: {
|
|
18743
18798
|
type: "string",
|
|
18744
|
-
description: "CSS selector when until=selector."
|
|
18799
|
+
description: "CSS selector required when until='selector'."
|
|
18745
18800
|
},
|
|
18746
18801
|
urlPattern: {
|
|
18747
18802
|
type: "string",
|
|
18748
|
-
description: "
|
|
18803
|
+
description: "JavaScript regex source string required when until='url'."
|
|
18749
18804
|
},
|
|
18750
18805
|
timeoutMs: {
|
|
18751
18806
|
type: "number",
|
|
18752
|
-
description: "
|
|
18807
|
+
description: "Maximum wait in milliseconds. Default 10000, hard cap 60000."
|
|
18753
18808
|
}
|
|
18754
18809
|
}
|
|
18755
18810
|
},
|
|
@@ -18760,20 +18815,23 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18760
18815
|
},
|
|
18761
18816
|
{
|
|
18762
18817
|
toolNameHttp: "browser_eval_js",
|
|
18763
|
-
description: "
|
|
18818
|
+
description: "Evaluates a JavaScript expression in the tab's main world, equivalent to typing in the DevTools console. It takes a tab id, expression, and optional timeout, awaits promises returned by the expression, and returns {result} or {error}. The expression can read or mutate the page, storage, cookies, or location, so this is the power-tier escape hatch for behaviors the structured browser tools do not cover. Prefer dedicated tools for navigation, clicking, filling, extraction, diagnostics, and screenshots; note that URL policy checks only apply directly to browser_open_tab and browser_navigate, while extension-side navigation blocking still applies to many browser-internal pages.",
|
|
18764
18819
|
inputSchema: {
|
|
18765
18820
|
type: "object",
|
|
18766
18821
|
required: ["tabId", "expression"],
|
|
18767
18822
|
additionalProperties: false,
|
|
18768
18823
|
properties: {
|
|
18769
|
-
tabId: {
|
|
18824
|
+
tabId: {
|
|
18825
|
+
type: "number",
|
|
18826
|
+
description: "Tab id from browser_list_tabs or browser_open_tab."
|
|
18827
|
+
},
|
|
18770
18828
|
expression: {
|
|
18771
18829
|
type: "string",
|
|
18772
|
-
description: "
|
|
18830
|
+
description: "JavaScript expression to evaluate. Size should stay small for reliability, but no schema length cap is enforced. Top-level await is not supported; wrap async work in (async () => ...)()."
|
|
18773
18831
|
},
|
|
18774
18832
|
timeoutMs: {
|
|
18775
18833
|
type: "number",
|
|
18776
|
-
description: "
|
|
18834
|
+
description: "Maximum evaluation time in milliseconds. Default 5000, hard cap 30000."
|
|
18777
18835
|
}
|
|
18778
18836
|
}
|
|
18779
18837
|
},
|
|
@@ -18784,7 +18842,7 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18784
18842
|
},
|
|
18785
18843
|
{
|
|
18786
18844
|
toolNameHttp: "browser_download",
|
|
18787
|
-
description: "
|
|
18845
|
+
description: "Triggers a browser download from a direct URL and waits for the extension's completion signal. It takes a tab id for association, source='url', the URL, and optional saveAs path, then returns {downloadId, path, bytes, mimeType} when Chrome reports the download complete. The file lands in Chrome's default Downloads directory unless saveAs provides a relative filename or subdirectory, and conflicts are auto-uniquified by the browser. Use this for known direct download URLs; it does not click page links, and the extension currently waits up to 60 seconds internally, so downloads that finish after 60 seconds can report timeout even though the outer wire budget is larger.",
|
|
18788
18846
|
inputSchema: {
|
|
18789
18847
|
type: "object",
|
|
18790
18848
|
required: ["tabId", "url"],
|
|
@@ -18792,20 +18850,20 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18792
18850
|
properties: {
|
|
18793
18851
|
tabId: {
|
|
18794
18852
|
type: "number",
|
|
18795
|
-
description: "Tab id
|
|
18853
|
+
description: "Tab id for association and logging; the download itself is window-scoped, not tab-scoped."
|
|
18796
18854
|
},
|
|
18797
18855
|
source: {
|
|
18798
18856
|
type: "string",
|
|
18799
18857
|
enum: ["url"],
|
|
18800
|
-
description: "Download source. Only 'url' supported in v1; click-then-wait
|
|
18858
|
+
description: "Download source. Only 'url' is supported in v1; click-then-wait is not on this surface."
|
|
18801
18859
|
},
|
|
18802
18860
|
url: {
|
|
18803
18861
|
type: "string",
|
|
18804
|
-
description: "Direct URL to download.
|
|
18862
|
+
description: "Direct URL to download. No schema length cap is enforced."
|
|
18805
18863
|
},
|
|
18806
18864
|
saveAs: {
|
|
18807
18865
|
type: "string",
|
|
18808
|
-
description: "Optional filename
|
|
18866
|
+
description: "Optional relative filename or subdirectory under Downloads. Chrome enforces download-path restrictions and auto-uniquifies conflicts."
|
|
18809
18867
|
}
|
|
18810
18868
|
}
|
|
18811
18869
|
},
|
|
@@ -18816,13 +18874,16 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18816
18874
|
},
|
|
18817
18875
|
{
|
|
18818
18876
|
toolNameHttp: "browser_mouse",
|
|
18819
|
-
description: "
|
|
18877
|
+
description: "Moves, clicks, double-clicks, presses, or releases the mouse through real CDP Input.dispatchMouseEvent calls. It takes a tab id, action, exactly one target form (ref, selector, or x+y CSS viewport coordinates), and optional button, trajectory, and force settings. Use mouse for hover-to-reveal menus, canvas/map/image-map clicks, event.isTrusted checks, precise coordinate targeting, or low-level press/release sequences that browser_act cannot express. Prefer browser_act for ordinary element clicks and fills; by default ref/selector targets are hit-tested with elementFromPoint and fail with target_obscured unless force is true.",
|
|
18820
18878
|
inputSchema: {
|
|
18821
18879
|
type: "object",
|
|
18822
18880
|
required: ["tabId", "action"],
|
|
18823
18881
|
additionalProperties: false,
|
|
18824
18882
|
properties: {
|
|
18825
|
-
tabId: {
|
|
18883
|
+
tabId: {
|
|
18884
|
+
type: "number",
|
|
18885
|
+
description: "Tab id from browser_list_tabs or browser_open_tab."
|
|
18886
|
+
},
|
|
18826
18887
|
action: {
|
|
18827
18888
|
type: "string",
|
|
18828
18889
|
enum: [
|
|
@@ -18832,19 +18893,19 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18832
18893
|
"down",
|
|
18833
18894
|
"up"
|
|
18834
18895
|
],
|
|
18835
|
-
description: "
|
|
18896
|
+
description: "Mouse action. move positions the cursor for hover; click sends press+release; dblclick sends two press/release cycles; down presses only; up releases only."
|
|
18836
18897
|
},
|
|
18837
18898
|
ref: {
|
|
18838
18899
|
type: "string",
|
|
18839
|
-
description: "Element ref from browser_read_page
|
|
18900
|
+
description: "Element ref from browser_read_page or browser_find. Resolves to bbox center. Exactly one of ref, selector, or x+y is required."
|
|
18840
18901
|
},
|
|
18841
18902
|
selector: {
|
|
18842
18903
|
type: "string",
|
|
18843
|
-
description: "CSS selector
|
|
18904
|
+
description: "CSS selector fallback. Resolves to bbox center. Exactly one of ref, selector, or x+y is required."
|
|
18844
18905
|
},
|
|
18845
18906
|
x: {
|
|
18846
18907
|
type: "number",
|
|
18847
|
-
description: "Target x in CSS viewport pixels. Pair with y. Use when working from a screenshot or eval_js output."
|
|
18908
|
+
description: "Target x in CSS viewport pixels. Pair with y. Use when working from a screenshot, canvas coordinate, or eval_js output."
|
|
18848
18909
|
},
|
|
18849
18910
|
y: {
|
|
18850
18911
|
type: "number",
|
|
@@ -18857,19 +18918,19 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18857
18918
|
"right",
|
|
18858
18919
|
"middle"
|
|
18859
18920
|
],
|
|
18860
|
-
description: "Mouse button for click
|
|
18921
|
+
description: "Mouse button for click, dblclick, down, or up. Default 'left'. Ignored for action='move'."
|
|
18861
18922
|
},
|
|
18862
18923
|
steps: {
|
|
18863
18924
|
type: "number",
|
|
18864
|
-
description: "
|
|
18925
|
+
description: "Trajectory step count. Values greater than 1 interpolate the cursor approach over multiple mouseMoved events. Default 1. Clamped to [1, 100]."
|
|
18865
18926
|
},
|
|
18866
18927
|
stepDelayMs: {
|
|
18867
18928
|
type: "number",
|
|
18868
|
-
description: "Pause between interpolated mouseMoved events when steps
|
|
18929
|
+
description: "Pause between interpolated mouseMoved events when steps is greater than 1. Default 8. Clamped to [0, 50]."
|
|
18869
18930
|
},
|
|
18870
18931
|
force: {
|
|
18871
18932
|
type: "boolean",
|
|
18872
|
-
description: "
|
|
18933
|
+
description: "For ref or selector targets, skips the elementFromPoint hit-test. Default false. Use only when an overlay covers the target but forwards pointer events."
|
|
18873
18934
|
}
|
|
18874
18935
|
}
|
|
18875
18936
|
},
|
|
@@ -18880,20 +18941,23 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18880
18941
|
},
|
|
18881
18942
|
{
|
|
18882
18943
|
toolNameHttp: "browser_drag",
|
|
18883
|
-
description: "
|
|
18944
|
+
description: "Drags from a source target to a destination target through CDP input events. It takes a tab id, one source target, one destination target, and optional button, trajectory, mode, and force settings; targets can be refs, selectors, or CSS viewport coordinates. Auto mode chooses HTML5 native drag-and-drop for draggable='true' sources, using Input.setInterceptDrags plus Input.dispatchDragEvent, and otherwise uses pointer drag events for libraries such as react-dnd, Sortable.js, and mouse-event-based handlers. Use drag for actual drag-and-drop interactions; use browser_mouse for simple clicks, hover, or isolated press/release gestures. Returns {ok: true, mode_used, from, to} so the caller can verify whether pointer or html5 ran and which coordinates were used.",
|
|
18884
18945
|
inputSchema: {
|
|
18885
18946
|
type: "object",
|
|
18886
18947
|
required: ["tabId"],
|
|
18887
18948
|
additionalProperties: false,
|
|
18888
18949
|
properties: {
|
|
18889
|
-
tabId: {
|
|
18950
|
+
tabId: {
|
|
18951
|
+
type: "number",
|
|
18952
|
+
description: "Tab id from browser_list_tabs or browser_open_tab."
|
|
18953
|
+
},
|
|
18890
18954
|
fromRef: {
|
|
18891
18955
|
type: "string",
|
|
18892
|
-
description: "Source ref from browser_read_page
|
|
18956
|
+
description: "Source element ref from browser_read_page or browser_find. Preferred when available."
|
|
18893
18957
|
},
|
|
18894
18958
|
fromSelector: {
|
|
18895
18959
|
type: "string",
|
|
18896
|
-
description: "Source CSS selector
|
|
18960
|
+
description: "Source CSS selector fallback when no source ref is available."
|
|
18897
18961
|
},
|
|
18898
18962
|
fromX: {
|
|
18899
18963
|
type: "number",
|
|
@@ -18905,11 +18969,11 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18905
18969
|
},
|
|
18906
18970
|
toRef: {
|
|
18907
18971
|
type: "string",
|
|
18908
|
-
description: "Destination ref from browser_read_page
|
|
18972
|
+
description: "Destination element ref from browser_read_page or browser_find. Preferred when available."
|
|
18909
18973
|
},
|
|
18910
18974
|
toSelector: {
|
|
18911
18975
|
type: "string",
|
|
18912
|
-
description: "Destination CSS selector
|
|
18976
|
+
description: "Destination CSS selector fallback when no destination ref is available."
|
|
18913
18977
|
},
|
|
18914
18978
|
toX: {
|
|
18915
18979
|
type: "number",
|
|
@@ -18922,15 +18986,15 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18922
18986
|
button: {
|
|
18923
18987
|
type: "string",
|
|
18924
18988
|
enum: ["left", "middle"],
|
|
18925
|
-
description: "Mouse button held during drag. Default 'left'."
|
|
18989
|
+
description: "Mouse button held during the drag. Default 'left'."
|
|
18926
18990
|
},
|
|
18927
18991
|
steps: {
|
|
18928
18992
|
type: "number",
|
|
18929
|
-
description: "Intermediate mouseMoved events from
|
|
18993
|
+
description: "Intermediate mouseMoved events from source to destination with the button held. Drag-detect libraries often need a trajectory. Default 15. Clamped to [1, 100]."
|
|
18930
18994
|
},
|
|
18931
18995
|
stepDelayMs: {
|
|
18932
18996
|
type: "number",
|
|
18933
|
-
description: "Pause between intermediate moves. Default 12. Clamped to [0, 50]."
|
|
18997
|
+
description: "Pause between intermediate moves in milliseconds. Default 12. Clamped to [0, 50]."
|
|
18934
18998
|
},
|
|
18935
18999
|
mode: {
|
|
18936
19000
|
type: "string",
|
|
@@ -18939,11 +19003,11 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18939
19003
|
"pointer",
|
|
18940
19004
|
"html5"
|
|
18941
19005
|
],
|
|
18942
|
-
description: "Drag mode. 'auto'
|
|
19006
|
+
description: "Drag mode. 'auto' is the default and picks html5 if the source has draggable='true', else pointer. Override only when auto detection chooses the wrong path."
|
|
18943
19007
|
},
|
|
18944
19008
|
force: {
|
|
18945
19009
|
type: "boolean",
|
|
18946
|
-
description: "
|
|
19010
|
+
description: "Skips the pre-press elementFromPoint hit-test on the source only. Default false. The destination is used as-is."
|
|
18947
19011
|
}
|
|
18948
19012
|
}
|
|
18949
19013
|
},
|
|
@@ -18954,20 +19018,23 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18954
19018
|
},
|
|
18955
19019
|
{
|
|
18956
19020
|
toolNameHttp: "browser_type",
|
|
18957
|
-
description: "
|
|
19021
|
+
description: "Types text into the currently focused element one character at a time via CDP Input.dispatchKeyEvent. It takes a tab id, text, and optional per-character delay; each character fires keyboard/input events, which supports autocomplete, chips, search-as-you-type fields, and handlers that listen on keydown rather than only reading element.value. Special text characters map to named keys: \\n sends Enter, \\t sends Tab, and \\b sends Backspace; other control characters below 0x20 are rejected with an actionable error. Use browser_type when real keystrokes matter, use browser_act with action='fill' for plain form-value entry, and use browser_keyboard for shortcuts or named control keys such as Control+L or Escape.",
|
|
18958
19022
|
inputSchema: {
|
|
18959
19023
|
type: "object",
|
|
18960
19024
|
required: ["tabId", "text"],
|
|
18961
19025
|
additionalProperties: false,
|
|
18962
19026
|
properties: {
|
|
18963
|
-
tabId: {
|
|
19027
|
+
tabId: {
|
|
19028
|
+
type: "number",
|
|
19029
|
+
description: "Tab id from browser_list_tabs or browser_open_tab. The text goes to whatever element is currently focused in that tab."
|
|
19030
|
+
},
|
|
18964
19031
|
text: {
|
|
18965
19032
|
type: "string",
|
|
18966
|
-
description: "
|
|
19033
|
+
description: "Text to type, up to 4096 Unicode code points. Newline, tab, and backspace are dispatched as Enter, Tab, and Backspace."
|
|
18967
19034
|
},
|
|
18968
19035
|
delayMs: {
|
|
18969
19036
|
type: "number",
|
|
18970
|
-
description: "Pause between characters. Default 0. Clamped to [0, 50]. Set
|
|
19037
|
+
description: "Pause between characters in milliseconds. Default 0. Clamped to [0, 50]. Set above 0 for debounced search-as-you-type inputs."
|
|
18971
19038
|
}
|
|
18972
19039
|
}
|
|
18973
19040
|
},
|
|
@@ -18978,17 +19045,20 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
18978
19045
|
},
|
|
18979
19046
|
{
|
|
18980
19047
|
toolNameHttp: "browser_diagnostics",
|
|
18981
|
-
description: "
|
|
19048
|
+
description: "Drains buffered console messages or network responses for a tab, with filtering before the result is returned. It takes a tab id, kind='console' or 'network', and optional level, regex, and limit filters, then returns {kind, total, returned, entries}; total is the pre-filter count and returned is the post-filter limited count. The first call for a tab lazily attaches chrome.debugger, so very-early load events from before that call are missed. Use diagnostics to investigate console errors, warnings, and request URLs; do not use it as a page-content reader, and raise limit or loosen regex when returned equals the requested limit.",
|
|
18982
19049
|
inputSchema: {
|
|
18983
19050
|
type: "object",
|
|
18984
19051
|
required: ["tabId", "kind"],
|
|
18985
19052
|
additionalProperties: false,
|
|
18986
19053
|
properties: {
|
|
18987
|
-
tabId: {
|
|
19054
|
+
tabId: {
|
|
19055
|
+
type: "number",
|
|
19056
|
+
description: "Tab id from browser_list_tabs or browser_open_tab."
|
|
19057
|
+
},
|
|
18988
19058
|
kind: {
|
|
18989
19059
|
type: "string",
|
|
18990
19060
|
enum: ["console", "network"],
|
|
18991
|
-
description: "
|
|
19061
|
+
description: "Diagnostic stream to drain: console messages or network responses."
|
|
18992
19062
|
},
|
|
18993
19063
|
level: {
|
|
18994
19064
|
type: "string",
|
|
@@ -19000,15 +19070,15 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
19000
19070
|
"debug",
|
|
19001
19071
|
"all"
|
|
19002
19072
|
],
|
|
19003
|
-
description: "Console only. Default 'all'. Ignored when kind=network."
|
|
19073
|
+
description: "Console only. Default 'all'. Ignored when kind='network'."
|
|
19004
19074
|
},
|
|
19005
19075
|
regex: {
|
|
19006
19076
|
type: "string",
|
|
19007
|
-
description: "Optional
|
|
19077
|
+
description: "Optional JavaScript regex source string. For console, matches message text; for network, matches request URL."
|
|
19008
19078
|
},
|
|
19009
19079
|
limit: {
|
|
19010
19080
|
type: "number",
|
|
19011
|
-
description: "
|
|
19081
|
+
description: "Maximum entries to return after filtering. Default 100. Hard cap 1000."
|
|
19012
19082
|
}
|
|
19013
19083
|
}
|
|
19014
19084
|
},
|
|
@@ -19056,20 +19126,23 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
19056
19126
|
},
|
|
19057
19127
|
{
|
|
19058
19128
|
toolNameHttp: "browser_find",
|
|
19059
|
-
description: "
|
|
19129
|
+
description: "Finds up to 5 page elements that match a natural-language intent. It takes a tab id and intent, reads a fresh snapshot internally, and returns ranked candidates with refs, roles, names, bboxes, and match reasons when available. The returned refs can be passed to browser_act in REF mode or to low-level power tools such as browser_mouse. Use find when a specific element is needed and a short candidate list is better than the full browser_read_page snapshot; use read_page when broad enumeration or raw text/context is needed.",
|
|
19060
19130
|
inputSchema: {
|
|
19061
19131
|
type: "object",
|
|
19062
19132
|
required: ["tabId", "intent"],
|
|
19063
19133
|
additionalProperties: false,
|
|
19064
19134
|
properties: {
|
|
19065
|
-
tabId: {
|
|
19135
|
+
tabId: {
|
|
19136
|
+
type: "number",
|
|
19137
|
+
description: "Tab id from browser_list_tabs or browser_open_tab."
|
|
19138
|
+
},
|
|
19066
19139
|
intent: {
|
|
19067
19140
|
type: "string",
|
|
19068
|
-
description: "Natural-language description of
|
|
19141
|
+
description: "Natural-language description of the element to find, such as 'the search box at the top' or 'the Submit button'."
|
|
19069
19142
|
}
|
|
19070
19143
|
}
|
|
19071
19144
|
},
|
|
19072
|
-
capability: "
|
|
19145
|
+
capability: "browser_compound",
|
|
19073
19146
|
async handler(args, signal) {
|
|
19074
19147
|
const tabId = typeof args.tabId === "number" ? args.tabId : void 0;
|
|
19075
19148
|
const intent = typeof args.intent === "string" ? args.intent : "";
|
|
@@ -19095,20 +19168,23 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
19095
19168
|
},
|
|
19096
19169
|
{
|
|
19097
19170
|
toolNameHttp: "browser_act",
|
|
19098
|
-
description: "
|
|
19171
|
+
description: "Performs a high-level click, fill, type, select, or scroll-into-view action against a tab. It has two modes: INTENT mode takes a natural-language intent and resolves the element/action internally, while REF mode takes a ref from browser_find or browser_read_page plus optional action and value for direct dispatch without a compressor round trip. Visual fallback can click canvas or SVG regions by combining screenshot analysis with a coordinate click when text-based matching fails. Use act for ordinary page interaction before reaching for browser_mouse, browser_type, browser_keyboard, or browser_scroll; single-action results include {ok, action_taken, target_ref, navigated}, multi-step intents return summary/steps fields, and visual fallback returns click_visual with x/y coordinates.",
|
|
19099
19172
|
inputSchema: {
|
|
19100
19173
|
type: "object",
|
|
19101
19174
|
required: ["tabId"],
|
|
19102
19175
|
additionalProperties: false,
|
|
19103
19176
|
properties: {
|
|
19104
|
-
tabId: {
|
|
19177
|
+
tabId: {
|
|
19178
|
+
type: "number",
|
|
19179
|
+
description: "Tab id from browser_list_tabs or browser_open_tab."
|
|
19180
|
+
},
|
|
19105
19181
|
intent: {
|
|
19106
19182
|
type: "string",
|
|
19107
|
-
description: "Natural-language description of the action
|
|
19183
|
+
description: "Natural-language description of the action for INTENT mode. If both intent and ref are provided, ref mode wins and intent is ignored."
|
|
19108
19184
|
},
|
|
19109
19185
|
ref: {
|
|
19110
19186
|
type: "string",
|
|
19111
|
-
description: "Element ref from browser_find
|
|
19187
|
+
description: "Element ref from browser_find or browser_read_page for REF mode, which dispatches directly without a compressor round trip."
|
|
19112
19188
|
},
|
|
19113
19189
|
action: {
|
|
19114
19190
|
type: "string",
|
|
@@ -19119,15 +19195,15 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
19119
19195
|
"select",
|
|
19120
19196
|
"scroll_into_view"
|
|
19121
19197
|
],
|
|
19122
|
-
description: "REF mode
|
|
19198
|
+
description: "REF mode action. Defaults to 'click'. Ignored in INTENT mode, where the resolved action comes from the intent and matched element."
|
|
19123
19199
|
},
|
|
19124
19200
|
value: {
|
|
19125
19201
|
type: "string",
|
|
19126
|
-
description: "
|
|
19202
|
+
description: "String value for fill, type, or select actions. In INTENT mode, this is available to the resolver when the action requires a value."
|
|
19127
19203
|
}
|
|
19128
19204
|
}
|
|
19129
19205
|
},
|
|
19130
|
-
capability: "
|
|
19206
|
+
capability: "browser_compound",
|
|
19131
19207
|
async handler(args, signal) {
|
|
19132
19208
|
const tabId = typeof args.tabId === "number" ? args.tabId : void 0;
|
|
19133
19209
|
if (!tabId) return toolEnvelope({ error: "tabId required" }, true);
|
|
@@ -19220,16 +19296,19 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
19220
19296
|
},
|
|
19221
19297
|
{
|
|
19222
19298
|
toolNameHttp: "browser_observe",
|
|
19223
|
-
description: "
|
|
19299
|
+
description: "Produces a short natural-language description of the current page's user-actionable state, including visible forms, buttons, links, and content sections. It takes a tab id and optional intent focus, then returns a 2-4 sentence summary plus whether visualSurfaces such as canvas or SVG are present. Use observe before browser_act when the page state is unknown, or after navigation to confirm what loaded. Prefer observe over screenshot when text and controls are enough; switch to browser_screenshot for visual layout or canvas/SVG details, and use browser_read_page when raw refs, bboxes, or element lists are needed.",
|
|
19224
19300
|
inputSchema: {
|
|
19225
19301
|
type: "object",
|
|
19226
19302
|
required: ["tabId"],
|
|
19227
19303
|
additionalProperties: false,
|
|
19228
19304
|
properties: {
|
|
19229
|
-
tabId: {
|
|
19305
|
+
tabId: {
|
|
19306
|
+
type: "number",
|
|
19307
|
+
description: "Tab id from browser_list_tabs or browser_open_tab."
|
|
19308
|
+
},
|
|
19230
19309
|
intent: {
|
|
19231
19310
|
type: "string",
|
|
19232
|
-
description: "Optional natural-language focus
|
|
19311
|
+
description: "Optional natural-language focus for the summary, such as 'describe the form' or 'what is in the sidebar'."
|
|
19233
19312
|
}
|
|
19234
19313
|
}
|
|
19235
19314
|
},
|
|
@@ -19243,7 +19322,7 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
19243
19322
|
},
|
|
19244
19323
|
{
|
|
19245
19324
|
toolNameHttp: "browser_extract",
|
|
19246
|
-
description: "
|
|
19325
|
+
description: "Extracts structured data from the current page into a JSON object matching the provided schema. It takes a tab id, a schema or schema-shaped descriptor, and a plain-language instruction; the inner compressor reads the page snapshot and returns only the typed object rather than the raw element list. Use extract when the desired output shape is known, such as rows of {title, author, url}; use browser_observe for a prose overview and browser_read_page when the lead model needs raw refs, bboxes, or page text. Bad schemas or wrong-shape compressor results are returned as fixable error envelopes so the caller can simplify the schema or clarify the instruction.",
|
|
19247
19326
|
inputSchema: {
|
|
19248
19327
|
type: "object",
|
|
19249
19328
|
required: [
|
|
@@ -19253,11 +19332,14 @@ const BROWSER_TOOLS = Object.freeze([
|
|
|
19253
19332
|
],
|
|
19254
19333
|
additionalProperties: false,
|
|
19255
19334
|
properties: {
|
|
19256
|
-
tabId: {
|
|
19257
|
-
|
|
19335
|
+
tabId: {
|
|
19336
|
+
type: "number",
|
|
19337
|
+
description: "Tab id from browser_list_tabs or browser_open_tab."
|
|
19338
|
+
},
|
|
19339
|
+
schema: { description: "JSON schema, or a schema-shaped descriptor, for the desired output shape." },
|
|
19258
19340
|
instruction: {
|
|
19259
19341
|
type: "string",
|
|
19260
|
-
description: "
|
|
19342
|
+
description: "Plain-language extraction instruction, such as 'the visible PR list' or 'all product cards with price and URL'."
|
|
19261
19343
|
}
|
|
19262
19344
|
}
|
|
19263
19345
|
},
|
|
@@ -23416,7 +23498,8 @@ async function countTokens(body, extraHeaders, callerSignal, retryTransient = fa
|
|
|
23416
23498
|
*
|
|
23417
23499
|
* Returns true iff Copilot's live catalog (`state.models?.data`) contains
|
|
23418
23500
|
* ALL THREE peer models the consensus protocol needs:
|
|
23419
|
-
* - `gpt-5.5`
|
|
23501
|
+
* - an OpenAI frontier model (`gpt-5.6-sol`, else `gpt-5.5` — see
|
|
23502
|
+
* `resolveOpenAiFrontier`)
|
|
23420
23503
|
* - `claude-opus-4-7` (opus_critic's model)
|
|
23421
23504
|
* - any `gemini-3.X.*pro` (gemini_critic's model family — matches the
|
|
23422
23505
|
* same regex `geminiAvailable()` uses, so the gate stays in sync if
|
|
@@ -23432,22 +23515,47 @@ async function countTokens(body, extraHeaders, callerSignal, retryTransient = fa
|
|
|
23432
23515
|
* slug too — `state.models?.data` mirrors Copilot's catalog where these
|
|
23433
23516
|
* land under the dotted slug, so we match by Copilot's actual id shape.
|
|
23434
23517
|
*/
|
|
23518
|
+
function geminiAvailable(source = state) {
|
|
23519
|
+
const models = source.models?.data;
|
|
23520
|
+
if (!models) return false;
|
|
23521
|
+
return models.some((m) => /^gemini-3\..*pro/i.test(m.id));
|
|
23522
|
+
}
|
|
23523
|
+
/**
|
|
23524
|
+
* OpenAI frontier reasoning models in preference order. `gpt-5.6-sol` is the
|
|
23525
|
+
* current default; `gpt-5.5` is retained as a fallback. Both share the same
|
|
23526
|
+
* `pro_plus/business/enterprise/max` restriction tier, so the fallback only
|
|
23527
|
+
* matters during a rollout-lag window where the newer slug hasn't yet appeared
|
|
23528
|
+
* in the account's catalog.
|
|
23529
|
+
*/
|
|
23530
|
+
const OPENAI_FRONTIER_MODELS = ["gpt-5.6-sol", "gpt-5.5"];
|
|
23531
|
+
/**
|
|
23532
|
+
* First available OpenAI frontier model in the live catalog (prefer
|
|
23533
|
+
* `gpt-5.6-sol`, fall back to `gpt-5.5`). Returns undefined when neither is
|
|
23534
|
+
* present. With `requireToolCalls`, only returns a model whose catalog entry
|
|
23535
|
+
* advertises `tool_calls`.
|
|
23536
|
+
*/
|
|
23537
|
+
function resolveOpenAiFrontier(opts) {
|
|
23538
|
+
const models = state.models?.data;
|
|
23539
|
+
if (!models) return void 0;
|
|
23540
|
+
for (const id of OPENAI_FRONTIER_MODELS) {
|
|
23541
|
+
const found = models.find((m) => m.id === id);
|
|
23542
|
+
if (!found) continue;
|
|
23543
|
+
if (opts?.requireToolCalls && found.capabilities?.supports?.tool_calls !== true) continue;
|
|
23544
|
+
return id;
|
|
23545
|
+
}
|
|
23546
|
+
}
|
|
23435
23547
|
function standInToolEnabled() {
|
|
23436
23548
|
const models = state.models?.data;
|
|
23437
23549
|
if (!models) return false;
|
|
23438
|
-
const
|
|
23550
|
+
const hasOpenAi = resolveOpenAiFrontier() != null;
|
|
23439
23551
|
const hasOpus = models.some((m) => m.id === "claude-opus-4-7" || m.id === "claude-opus-4.7");
|
|
23440
|
-
const hasGeminiPro =
|
|
23441
|
-
return
|
|
23552
|
+
const hasGeminiPro = geminiAvailable();
|
|
23553
|
+
return hasOpenAi && hasOpus && hasGeminiPro;
|
|
23442
23554
|
}
|
|
23443
|
-
|
|
23444
|
-
|
|
23555
|
+
/** Return the native implementer subagent model iff it is live with tool calls.
|
|
23556
|
+
* Prefers `gpt-5.6-sol`, falls back to `gpt-5.5`. */
|
|
23445
23557
|
function implementerSubagentModel() {
|
|
23446
|
-
|
|
23447
|
-
if (!models) return void 0;
|
|
23448
|
-
const found = models.find((m) => m.id === IMPLEMENTER_SUBAGENT_MODEL);
|
|
23449
|
-
if (!found) return void 0;
|
|
23450
|
-
return found.capabilities?.supports?.tool_calls === true ? IMPLEMENTER_SUBAGENT_MODEL : void 0;
|
|
23558
|
+
return resolveOpenAiFrontier({ requireToolCalls: true });
|
|
23451
23559
|
}
|
|
23452
23560
|
/**
|
|
23453
23561
|
* Gate for the worker tools (`explore`, `review`, `implement`).
|
|
@@ -23459,7 +23567,7 @@ function implementerSubagentModel() {
|
|
|
23459
23567
|
* true`. The worker loop is function-calling; a model that can't
|
|
23460
23568
|
* emit tool_calls is unusable, so dormant-register (omit from
|
|
23461
23569
|
* `tools/list`) keeps the surface honest. (The implement default
|
|
23462
|
-
* `gpt-5.
|
|
23570
|
+
* `gpt-5.6-sol` is NOT gated here — if it's absent, implement calls
|
|
23463
23571
|
* surface a clean resolve error rather than disabling all worker
|
|
23464
23572
|
* tools, since explore/review still work.)
|
|
23465
23573
|
* 2. The operator hasn't set `GH_ROUTER_DISABLE_WORKER_TOOLS=1`
|
|
@@ -23483,8 +23591,8 @@ function workerToolsEnabled() {
|
|
|
23483
23591
|
return found.capabilities?.supports?.tool_calls === true;
|
|
23484
23592
|
}
|
|
23485
23593
|
/**
|
|
23486
|
-
* Gate for the compound L2 browser tools (`
|
|
23487
|
-
*
|
|
23594
|
+
* Gate for the compound L2 browser tools (`browser_act`, `browser_observe`,
|
|
23595
|
+
* `browser_extract`, `browser_find`).
|
|
23488
23596
|
*
|
|
23489
23597
|
* Returns true iff `compressorAvailable()` — i.e. at least one model in
|
|
23490
23598
|
* the compressor fallback chain (`gpt-5.4-mini` → `claude-sonnet-4.6` →
|
|
@@ -23507,19 +23615,19 @@ function browserCompoundToolsEnabled() {
|
|
|
23507
23615
|
* Gate for the L0/L1 power browser tools (`browser_read_page`,
|
|
23508
23616
|
* `browser_mouse`, `browser_drag`, `browser_type`, `browser_keyboard`,
|
|
23509
23617
|
* `browser_scroll`, `browser_eval_js`, `browser_diagnostics`,
|
|
23510
|
-
* `
|
|
23511
|
-
* `
|
|
23618
|
+
* `browser_close_tab`, `browser_list_tabs`, `browser_wait`,
|
|
23619
|
+
* `browser_download`).
|
|
23512
23620
|
*
|
|
23513
23621
|
* Returns true iff `state.powerBrowseEnabled` (set by `--power-browse`
|
|
23514
23622
|
* or `GH_ROUTER_ENABLE_POWER_BROWSE=1`). When off, the default
|
|
23515
|
-
* `--browse` surface exposes
|
|
23516
|
-
* `
|
|
23517
|
-
*
|
|
23518
|
-
*
|
|
23623
|
+
* `--browse` surface exposes the base lead tools (`navigate`, `screenshot`,
|
|
23624
|
+
* `open_tab`) and, when the compound gate passes, `act`, `observe`,
|
|
23625
|
+
* `extract`, and `find`. Power mode adds the raw primitives for users who
|
|
23626
|
+
* want direct coord/keystroke control.
|
|
23519
23627
|
*
|
|
23520
23628
|
* `handler.ts` filter chain ANDs this with `browserToolsEnabled()`
|
|
23521
|
-
* (defense-in-depth
|
|
23522
|
-
* setup path already forces basic on when power is on).
|
|
23629
|
+
* (defense-in-depth: power without the base browser server is meaningless and
|
|
23630
|
+
* the setup path already forces basic on when power is on).
|
|
23523
23631
|
*/
|
|
23524
23632
|
function browserPowerToolsEnabled() {
|
|
23525
23633
|
return state.powerBrowseEnabled === true;
|
|
@@ -23715,15 +23823,10 @@ function checkAuth(c) {
|
|
|
23715
23823
|
};
|
|
23716
23824
|
return { ok: true };
|
|
23717
23825
|
}
|
|
23718
|
-
function geminiAvailable() {
|
|
23719
|
-
const models = state.models?.data;
|
|
23720
|
-
if (!models) return false;
|
|
23721
|
-
return models.some((m) => /^gemini-3\..*pro/i.test(m.id));
|
|
23722
|
-
}
|
|
23723
23826
|
/**
|
|
23724
23827
|
* The 1M-context Opus 4.6 variant (`claude-opus-4.6-1m`, `max_prompt_tokens`
|
|
23725
23828
|
* 936K). opus_critic prefers it so it can take large artifacts in one shot
|
|
23726
|
-
* (the whole point of pairing it with gpt-5.
|
|
23829
|
+
* (the whole point of pairing it with gpt-5.6-sol as the big-window peers);
|
|
23727
23830
|
* falls back to the 200K `claude-opus-4-6` when the catalog doesn't carry
|
|
23728
23831
|
* a 1M 4.6 slug. The regex is version-anchored to 4.6 AND requires a
|
|
23729
23832
|
* `-1m` suffix boundary (not a permissive `.*1m`), so it does NOT
|
|
@@ -23933,7 +24036,7 @@ async function predictedWindowOverflow(persona, prompt, context) {
|
|
|
23933
24036
|
}
|
|
23934
24037
|
if (tokens <= budget) return void 0;
|
|
23935
24038
|
const opusHint = OPUS_1M_RE.test(id) ? "" : " / `opus_critic` (Opus-4.7 1M ≈ 936K tokens, when the enterprise catalog carries it)";
|
|
23936
|
-
return `pre-flight rejected: this ${persona.toolNameHttp} brief is ≈${tokens} tokens, over the ${budget}-token budget for ${persona.model} (its ${maxPromptTokens}-token prompt window minus a ${PEER_PROMPT_TOKEN_RESERVE}-token framing reserve). Do NOT summarize or truncate the artifact to fit. Route the full artifact to a larger-window peer — \`codex_critic\` (gpt-5.
|
|
24039
|
+
return `pre-flight rejected: this ${persona.toolNameHttp} brief is ≈${tokens} tokens, over the ${budget}-token budget for ${persona.model} (its ${maxPromptTokens}-token prompt window minus a ${PEER_PROMPT_TOKEN_RESERVE}-token framing reserve). Do NOT summarize or truncate the artifact to fit. Route the full artifact to a larger-window peer — \`codex_critic\` (gpt-5.6-sol ≈ 1M tokens)${opusHint} — or split it into focused sub-calls BY CONCERN and call them in parallel, then aggregate.`;
|
|
23937
24040
|
}
|
|
23938
24041
|
/**
|
|
23939
24042
|
* JSON-path pre-flight predictedTooLong gate. Returns a JSON-RPC result
|
|
@@ -23992,7 +24095,7 @@ function jsonPathPreflightCap(body, scope) {
|
|
|
23992
24095
|
* the `stand_in` orchestrator in `src/lib/stand-in.ts` — can reuse the
|
|
23993
24096
|
* same per-endpoint request shaping without re-implementing it. The
|
|
23994
24097
|
* stand_in tool needs to drive its own per-round system prompts across
|
|
23995
|
-
* three concrete models (gpt-5.
|
|
24098
|
+
* three concrete models (gpt-5.6-sol, claude-opus-4-7, gemini-3.1-pro-preview),
|
|
23996
24099
|
* each on a different endpoint; doing that with a `PersonaSpec` would
|
|
23997
24100
|
* require either inventing throwaway personas per round or duplicating
|
|
23998
24101
|
* the dispatch switch.
|
|
@@ -24683,13 +24786,13 @@ const ADVISOR_CLIENT_TOOL_NAME = "advisor";
|
|
|
24683
24786
|
* times per session per cc-backup ADVISOR_TOOL_INSTRUCTIONS. */
|
|
24684
24787
|
const ADVISOR_MAX_TURNS = 16;
|
|
24685
24788
|
/** Default advisor model + reasoning effort. Per gemini-critic + user
|
|
24686
|
-
* direction: hardcode to a cross-lab model (gpt-5.
|
|
24789
|
+
* direction: hardcode to a cross-lab model (gpt-5.6-sol — Copilot's
|
|
24687
24790
|
* /responses-only flagship) at xhigh effort. The cross-lab choice
|
|
24688
24791
|
* gives a true "second set of eyes" instead of the main model
|
|
24689
24792
|
* reviewing itself; xhigh effort buys the deep-dive reasoning that
|
|
24690
24793
|
* matches Anthropic's own ADVISOR (which uses a stronger reviewer
|
|
24691
24794
|
* model — Opus 4.6/Sonnet 4.6 typically). */
|
|
24692
|
-
const ADVISOR_DEFAULT_MODEL = "gpt-5.
|
|
24795
|
+
const ADVISOR_DEFAULT_MODEL = "gpt-5.6-sol";
|
|
24693
24796
|
const ADVISOR_DEFAULT_EFFORT = "xhigh";
|
|
24694
24797
|
/** ADVISOR_TOOL_INSTRUCTIONS verbatim from cc-backup
|
|
24695
24798
|
* src/utils/advisor.ts — describes when the model should invoke
|
|
@@ -24786,7 +24889,7 @@ const ADVISOR_FALLBACK_MAX_TOKENS = 24e4;
|
|
|
24786
24889
|
* budget is `max_prompt_tokens - reserve`. Generous on purpose: a 400
|
|
24787
24890
|
* `model_max_prompt_tokens_exceeded` degrades to a silent advisor
|
|
24788
24891
|
* fallback, and the marginal window we give up is irrelevant next to
|
|
24789
|
-
* gpt-5.
|
|
24892
|
+
* gpt-5.6-sol's ~1M. */
|
|
24790
24893
|
const ADVISOR_PROMPT_TOKEN_RESERVE = 8e3;
|
|
24791
24894
|
/**
|
|
24792
24895
|
* Derive the TOKEN budget for the rendered transcript from the advisor
|
|
@@ -24805,7 +24908,7 @@ function resolveAdvisorMaxTokens(advisorModel) {
|
|
|
24805
24908
|
/**
|
|
24806
24909
|
* Render an Anthropic-shape conversation (messages array with
|
|
24807
24910
|
* role/content blocks) as a single human-readable text blob. Used
|
|
24808
|
-
* as the input to the advisor model (gpt-5.
|
|
24911
|
+
* as the input to the advisor model (gpt-5.6-sol via /v1/responses
|
|
24809
24912
|
* doesn't have a 1:1 mapping for Anthropic's tool_use/tool_result
|
|
24810
24913
|
* blocks; serializing to text preserves the semantics — the advisor
|
|
24811
24914
|
* just needs to READ the conversation, not produce more of it).
|
|
@@ -24887,7 +24990,7 @@ function truncateTailToUnits(text, maxUnits, measure) {
|
|
|
24887
24990
|
* Routes by model family:
|
|
24888
24991
|
* - gpt-5.x / codex / o-series (have `/responses` in supported_endpoints):
|
|
24889
24992
|
* use createResponses with `reasoning.effort` set. This is the
|
|
24890
|
-
* default path — gpt-5.
|
|
24993
|
+
* default path — gpt-5.6-sol at xhigh effort.
|
|
24891
24994
|
* - claude-* (no `/responses`): fall back to createMessages.
|
|
24892
24995
|
*
|
|
24893
24996
|
* The conversation is serialized to text via renderConversationAsText
|
|
@@ -26990,7 +27093,7 @@ function advisorTool(getMessages) {
|
|
|
26990
27093
|
return {
|
|
26991
27094
|
name: "advisor",
|
|
26992
27095
|
label: "Advisor",
|
|
26993
|
-
description: "Consult a stronger reviewer model (cross-lab: gpt-5.
|
|
27096
|
+
description: "Consult a stronger reviewer model (cross-lab: gpt-5.6-sol xhigh by default) on a specific concern. Use BEFORE substantive work, WHEN stuck, or WHEN considering a change of approach. The advisor automatically receives the recent conversation transcript as context — give it a focused `concern`, not background.",
|
|
26994
27097
|
parameters: ADVISOR_PARAMS,
|
|
26995
27098
|
async execute(_toolCallId, params, signal) {
|
|
26996
27099
|
if (networkDisabled()) throw new Error("rejected: network disabled");
|
|
@@ -27485,7 +27588,7 @@ const DEFAULT_THINKING = "xhigh";
|
|
|
27485
27588
|
* (via `DEFAULT_THINKING`) — a strong, NATIVE (no-shim) tool-caller for repo
|
|
27486
27589
|
* research. Native Claude models run as workers over `/chat/completions`, the
|
|
27487
27590
|
* same path proven by `PLAN_DEFAULT_MODEL` (claude-opus-4.8). Like `implement`'s
|
|
27488
|
-
* gpt-5.
|
|
27591
|
+
* gpt-5.6-sol this is NOT a `workerToolsEnabled` gate input — if absent (e.g. a
|
|
27489
27592
|
* non-enterprise tier) `explore` errors helpfully at call time rather than
|
|
27490
27593
|
* vanishing the whole worker surface. The caller (the main model) overrides
|
|
27491
27594
|
* BOTH the model and the reasoning per call via the `model` / `thinking` args. */
|
|
@@ -27493,7 +27596,7 @@ const EXPLORE_DEFAULT_MODEL = "claude-sonnet-5";
|
|
|
27493
27596
|
/** Default model + thinking for the READ-ONLY `review` mode.
|
|
27494
27597
|
* `gemini-3.1-pro-preview` at `xhigh` (clamped to `high` at call time — gemini
|
|
27495
27598
|
* advertises no xhigh). DELIBERATELY DECORRELATED FROM THE IMPLEMENTER: bounded
|
|
27496
|
-
* implementation now defaults to gpt-5.
|
|
27599
|
+
* implementation now defaults to gpt-5.6-sol (OpenAI) — both the `implement` worker
|
|
27497
27600
|
* and the native `implementer` subagent — and the main orchestrator is Opus
|
|
27498
27601
|
* (Anthropic), so review runs on a THIRD lab (Google) to maximize blind-spot
|
|
27499
27602
|
* diversity. A reviewer sharing the implementer's lab catches a correlated slice
|
|
@@ -27504,12 +27607,12 @@ const EXPLORE_DEFAULT_MODEL = "claude-sonnet-5";
|
|
|
27504
27607
|
* `model` arg (e.g. `claude-opus-4.8` for an Anthropic-lab reviewer). */
|
|
27505
27608
|
const REVIEW_DEFAULT_MODEL = "gemini-3.1-pro-preview";
|
|
27506
27609
|
const REVIEW_DEFAULT_THINKING = "xhigh";
|
|
27507
|
-
/** Default model + thinking for the READ+WRITE `implement` mode. `gpt-5.
|
|
27610
|
+
/** Default model + thinking for the READ+WRITE `implement` mode. `gpt-5.6-sol`
|
|
27508
27611
|
* at `xhigh` — the strongest reasoning tier in the catalog, 1M+ context,
|
|
27509
27612
|
* routed through `/responses` by the stream-fn endpoint split. Coding edits
|
|
27510
27613
|
* benefit from maximum reasoning; the higher per-call cost is justified for
|
|
27511
27614
|
* autonomous implementation. An explicit `opts.model` still wins. */
|
|
27512
|
-
const IMPLEMENT_DEFAULT_MODEL = "gpt-5.
|
|
27615
|
+
const IMPLEMENT_DEFAULT_MODEL = "gpt-5.6-sol";
|
|
27513
27616
|
const IMPLEMENT_DEFAULT_THINKING = "xhigh";
|
|
27514
27617
|
/** Default model for `browse` mode. `gpt-5.4-mini` — the Gate-B-winning
|
|
27515
27618
|
* browse model (small + fast enough to drive a tab at human pace, with
|
|
@@ -27534,7 +27637,7 @@ const BROWSE_DEFAULT_THINKING = "high";
|
|
|
27534
27637
|
* Copilot catalog id (the worker resolver exact-matches `catalog.id`, it does
|
|
27535
27638
|
* NOT translate the Anthropic dashed slug). Falls back to a helpful
|
|
27536
27639
|
* unknown-model error at call time if opus-4.8 isn't in the catalog (e.g. a
|
|
27537
|
-
* non-enterprise tier), exactly like `implement`'s `gpt-5.
|
|
27640
|
+
* non-enterprise tier), exactly like `implement`'s `gpt-5.6-sol`. Caller's `model`
|
|
27538
27641
|
* arg still wins. */
|
|
27539
27642
|
const PLAN_DEFAULT_MODEL = "claude-opus-4.8";
|
|
27540
27643
|
const PLAN_DEFAULT_THINKING = "xhigh";
|
|
@@ -27889,8 +27992,8 @@ function appendPlanReminder(messages, planState) {
|
|
|
27889
27992
|
*/
|
|
27890
27993
|
const STAND_IN_MODELS = Object.freeze([
|
|
27891
27994
|
{
|
|
27892
|
-
key: "gpt-5.
|
|
27893
|
-
model: "gpt-5.
|
|
27995
|
+
key: "gpt-5.6-sol",
|
|
27996
|
+
model: "gpt-5.6-sol",
|
|
27894
27997
|
endpoint: "/v1/responses",
|
|
27895
27998
|
effort: "xhigh"
|
|
27896
27999
|
},
|
|
@@ -28015,10 +28118,11 @@ async function runStandIn(input, signal) {
|
|
|
28015
28118
|
};
|
|
28016
28119
|
}
|
|
28017
28120
|
async function callAndParse(cfg, instructions, userText, signal) {
|
|
28121
|
+
const model = cfg.key === "gpt-5.6-sol" ? resolveOpenAiFrontier() ?? cfg.model : cfg.model;
|
|
28018
28122
|
let raw;
|
|
28019
28123
|
try {
|
|
28020
28124
|
raw = await dispatchModelCall({
|
|
28021
|
-
model
|
|
28125
|
+
model,
|
|
28022
28126
|
endpoint: cfg.endpoint,
|
|
28023
28127
|
instructions,
|
|
28024
28128
|
userText,
|
|
@@ -28042,7 +28146,7 @@ async function callAndParse(cfg, instructions, userText, signal) {
|
|
|
28042
28146
|
let retryRaw;
|
|
28043
28147
|
try {
|
|
28044
28148
|
retryRaw = await dispatchModelCall({
|
|
28045
|
-
model
|
|
28149
|
+
model,
|
|
28046
28150
|
endpoint: cfg.endpoint,
|
|
28047
28151
|
instructions,
|
|
28048
28152
|
userText: userText + RETRY_PROMPT_SUFFIX,
|
|
@@ -28220,6 +28324,142 @@ function round2(n) {
|
|
|
28220
28324
|
* into each sub-orchestration. The verifier only range-checks the declaration. */
|
|
28221
28325
|
const MAX_RECURSION_DEPTH = 3;
|
|
28222
28326
|
|
|
28327
|
+
//#endregion
|
|
28328
|
+
//#region src/lib/orchestration/select.ts
|
|
28329
|
+
const subsetOf = (a, b) => {
|
|
28330
|
+
for (const x of a) if (!b.has(x)) return false;
|
|
28331
|
+
return true;
|
|
28332
|
+
};
|
|
28333
|
+
function selectChampion(orchestrated, baseline, canonicalGateIds, tiePolicy) {
|
|
28334
|
+
if (!subsetOf(orchestrated.passed, orchestrated.ran)) return {
|
|
28335
|
+
winner: "baseline",
|
|
28336
|
+
reason: "orchestrated outcome malformed (passed not a subset of ran)"
|
|
28337
|
+
};
|
|
28338
|
+
if (!subsetOf(baseline.passed, baseline.ran)) return {
|
|
28339
|
+
winner: "baseline",
|
|
28340
|
+
reason: "baseline outcome malformed (passed not a subset of ran)"
|
|
28341
|
+
};
|
|
28342
|
+
if (canonicalGateIds.size === 0) return {
|
|
28343
|
+
winner: "baseline",
|
|
28344
|
+
reason: "no executable gate for this ask — ship the baseline (judgment-only)"
|
|
28345
|
+
};
|
|
28346
|
+
for (const id of canonicalGateIds) if (!orchestrated.ran.has(id)) return {
|
|
28347
|
+
winner: "baseline",
|
|
28348
|
+
reason: `orchestrated did not run canonical gate "${id}"`
|
|
28349
|
+
};
|
|
28350
|
+
let baselinePass = 0;
|
|
28351
|
+
let orchestratedPass = 0;
|
|
28352
|
+
for (const id of canonicalGateIds) {
|
|
28353
|
+
if (baseline.passed.has(id)) baselinePass += 1;
|
|
28354
|
+
if (orchestrated.passed.has(id)) orchestratedPass += 1;
|
|
28355
|
+
else if (baseline.passed.has(id)) return {
|
|
28356
|
+
winner: "baseline",
|
|
28357
|
+
reason: `orchestrated regresses on canonical check "${id}" the baseline passed`
|
|
28358
|
+
};
|
|
28359
|
+
}
|
|
28360
|
+
if (orchestratedPass > baselinePass) return {
|
|
28361
|
+
winner: "orchestrated",
|
|
28362
|
+
reason: "orchestrated passes strictly more canonical executable checks"
|
|
28363
|
+
};
|
|
28364
|
+
if (tiePolicy === "superset") return {
|
|
28365
|
+
winner: "orchestrated",
|
|
28366
|
+
reason: "orchestrated matches the baseline on the canonical checks (superset policy)"
|
|
28367
|
+
};
|
|
28368
|
+
return {
|
|
28369
|
+
winner: "baseline",
|
|
28370
|
+
reason: "orchestrated does not pass strictly more canonical checks than the baseline (strict policy)"
|
|
28371
|
+
};
|
|
28372
|
+
}
|
|
28373
|
+
|
|
28374
|
+
//#endregion
|
|
28375
|
+
//#region src/lib/orchestration/gate-runner.ts
|
|
28376
|
+
async function runGateChecks(checks, cwd, exec) {
|
|
28377
|
+
const results = await Promise.all(checks.map(async (c) => {
|
|
28378
|
+
try {
|
|
28379
|
+
const r = await exec({
|
|
28380
|
+
command: c.command,
|
|
28381
|
+
cwd
|
|
28382
|
+
});
|
|
28383
|
+
return {
|
|
28384
|
+
id: c.id,
|
|
28385
|
+
passed: r.exitCode === 0
|
|
28386
|
+
};
|
|
28387
|
+
} catch {
|
|
28388
|
+
return {
|
|
28389
|
+
id: c.id,
|
|
28390
|
+
passed: false
|
|
28391
|
+
};
|
|
28392
|
+
}
|
|
28393
|
+
}));
|
|
28394
|
+
const passed = /* @__PURE__ */ new Set();
|
|
28395
|
+
const ran = /* @__PURE__ */ new Set();
|
|
28396
|
+
for (const r of results) {
|
|
28397
|
+
ran.add(r.id);
|
|
28398
|
+
if (r.passed) passed.add(r.id);
|
|
28399
|
+
}
|
|
28400
|
+
return {
|
|
28401
|
+
passed,
|
|
28402
|
+
ran
|
|
28403
|
+
};
|
|
28404
|
+
}
|
|
28405
|
+
|
|
28406
|
+
//#endregion
|
|
28407
|
+
//#region src/lib/orchestration/gate-registry.ts
|
|
28408
|
+
/**
|
|
28409
|
+
* Built-in sealed gates. Commands follow this repo's TS/Bun conventions (the
|
|
28410
|
+
* `bun run <script>` indirection means a repo without that script simply fails
|
|
28411
|
+
* the check, which the selector treats as not-passed rather than a crash). New
|
|
28412
|
+
* ecosystems get a new sealed id here, never a caller-supplied command.
|
|
28413
|
+
*/
|
|
28414
|
+
const SEALED_GATES = {
|
|
28415
|
+
"default-ci": [
|
|
28416
|
+
{
|
|
28417
|
+
id: "typecheck",
|
|
28418
|
+
command: "bun run typecheck"
|
|
28419
|
+
},
|
|
28420
|
+
{
|
|
28421
|
+
id: "test",
|
|
28422
|
+
command: "bun test"
|
|
28423
|
+
},
|
|
28424
|
+
{
|
|
28425
|
+
id: "lint",
|
|
28426
|
+
command: "bun run lint"
|
|
28427
|
+
}
|
|
28428
|
+
],
|
|
28429
|
+
"typecheck-test": [{
|
|
28430
|
+
id: "typecheck",
|
|
28431
|
+
command: "bun run typecheck"
|
|
28432
|
+
}, {
|
|
28433
|
+
id: "test",
|
|
28434
|
+
command: "bun test"
|
|
28435
|
+
}],
|
|
28436
|
+
"typecheck-only": [{
|
|
28437
|
+
id: "typecheck",
|
|
28438
|
+
command: "bun run typecheck"
|
|
28439
|
+
}]
|
|
28440
|
+
};
|
|
28441
|
+
/** The set of sealed gate ids, used as the kernel's `knownGateIds` so the IR
|
|
28442
|
+
* verifier rejects an executable gate that references an unregistered id. */
|
|
28443
|
+
function sealedGateIds() {
|
|
28444
|
+
return new Set(Object.keys(SEALED_GATES));
|
|
28445
|
+
}
|
|
28446
|
+
/**
|
|
28447
|
+
* Resolve a sealed gate by id. Returns a DEFENSIVE CLONE (fresh objects) so a
|
|
28448
|
+
* caller can never mutate the registry's command set. `undefined` for an
|
|
28449
|
+
* unknown id, which `run_workflow` rejects before executing anything.
|
|
28450
|
+
*/
|
|
28451
|
+
function resolveSealedGate(gateId) {
|
|
28452
|
+
const checks = SEALED_GATES[gateId];
|
|
28453
|
+
if (!checks) return void 0;
|
|
28454
|
+
return {
|
|
28455
|
+
id: gateId,
|
|
28456
|
+
checks: checks.map((c) => ({
|
|
28457
|
+
id: c.id,
|
|
28458
|
+
command: c.command
|
|
28459
|
+
}))
|
|
28460
|
+
};
|
|
28461
|
+
}
|
|
28462
|
+
|
|
28223
28463
|
//#endregion
|
|
28224
28464
|
//#region src/lib/orchestration/verify.ts
|
|
28225
28465
|
const VALID_ROLES = new Set([
|
|
@@ -28244,6 +28484,7 @@ const VALID_ON_FAIL = new Set([
|
|
|
28244
28484
|
"escalate"
|
|
28245
28485
|
]);
|
|
28246
28486
|
function verifyWorkflowIR(ir, opts = {}) {
|
|
28487
|
+
const knownGateIds = opts.knownGateIds ?? sealedGateIds();
|
|
28247
28488
|
const v = [];
|
|
28248
28489
|
const push = (code, message, nodeId) => {
|
|
28249
28490
|
v.push(nodeId === void 0 ? {
|
|
@@ -28321,7 +28562,7 @@ function verifyWorkflowIR(ir, opts = {}) {
|
|
|
28321
28562
|
const g = n.gate;
|
|
28322
28563
|
if (g.kind === "executable") {
|
|
28323
28564
|
if (typeof g.gateId !== "string" || g.gateId.length === 0) push("BAD_GATE", `executable gate on node "${n.id}" must reference a sealed gateId (gate-immutability)`, n.id);
|
|
28324
|
-
else if (
|
|
28565
|
+
else if (!knownGateIds.has(g.gateId)) push("UNKNOWN_GATE_ID", `executable gate on node "${n.id}" references gateId "${g.gateId}" not in the kernel's sealed-gate registry`, n.id);
|
|
28325
28566
|
}
|
|
28326
28567
|
if (g.kind === "cross_lab") {
|
|
28327
28568
|
if (typeof g.checkerLab !== "string" || g.checkerLab.length === 0) push("BAD_GATE", `cross_lab gate on node "${n.id}" must name a checkerLab`, n.id);
|
|
@@ -28428,53 +28669,6 @@ function hasCycle(nodes, byId) {
|
|
|
28428
28669
|
return false;
|
|
28429
28670
|
}
|
|
28430
28671
|
|
|
28431
|
-
//#endregion
|
|
28432
|
-
//#region src/lib/orchestration/select.ts
|
|
28433
|
-
const subsetOf = (a, b) => {
|
|
28434
|
-
for (const x of a) if (!b.has(x)) return false;
|
|
28435
|
-
return true;
|
|
28436
|
-
};
|
|
28437
|
-
function selectChampion(orchestrated, baseline, canonicalGateIds, tiePolicy) {
|
|
28438
|
-
if (!subsetOf(orchestrated.passed, orchestrated.ran)) return {
|
|
28439
|
-
winner: "baseline",
|
|
28440
|
-
reason: "orchestrated outcome malformed (passed not a subset of ran)"
|
|
28441
|
-
};
|
|
28442
|
-
if (!subsetOf(baseline.passed, baseline.ran)) return {
|
|
28443
|
-
winner: "baseline",
|
|
28444
|
-
reason: "baseline outcome malformed (passed not a subset of ran)"
|
|
28445
|
-
};
|
|
28446
|
-
if (canonicalGateIds.size === 0) return {
|
|
28447
|
-
winner: "baseline",
|
|
28448
|
-
reason: "no executable gate for this ask — ship the baseline (judgment-only)"
|
|
28449
|
-
};
|
|
28450
|
-
for (const id of canonicalGateIds) if (!orchestrated.ran.has(id)) return {
|
|
28451
|
-
winner: "baseline",
|
|
28452
|
-
reason: `orchestrated did not run canonical gate "${id}"`
|
|
28453
|
-
};
|
|
28454
|
-
let baselinePass = 0;
|
|
28455
|
-
let orchestratedPass = 0;
|
|
28456
|
-
for (const id of canonicalGateIds) {
|
|
28457
|
-
if (baseline.passed.has(id)) baselinePass += 1;
|
|
28458
|
-
if (orchestrated.passed.has(id)) orchestratedPass += 1;
|
|
28459
|
-
else if (baseline.passed.has(id)) return {
|
|
28460
|
-
winner: "baseline",
|
|
28461
|
-
reason: `orchestrated regresses on canonical check "${id}" the baseline passed`
|
|
28462
|
-
};
|
|
28463
|
-
}
|
|
28464
|
-
if (orchestratedPass > baselinePass) return {
|
|
28465
|
-
winner: "orchestrated",
|
|
28466
|
-
reason: "orchestrated passes strictly more canonical executable checks"
|
|
28467
|
-
};
|
|
28468
|
-
if (tiePolicy === "superset") return {
|
|
28469
|
-
winner: "orchestrated",
|
|
28470
|
-
reason: "orchestrated matches the baseline on the canonical checks (superset policy)"
|
|
28471
|
-
};
|
|
28472
|
-
return {
|
|
28473
|
-
winner: "baseline",
|
|
28474
|
-
reason: "orchestrated does not pass strictly more canonical checks than the baseline (strict policy)"
|
|
28475
|
-
};
|
|
28476
|
-
}
|
|
28477
|
-
|
|
28478
28672
|
//#endregion
|
|
28479
28673
|
//#region src/lib/orchestration/kernel.ts
|
|
28480
28674
|
const DEFAULT_MAX_RETRIES = 2;
|
|
@@ -28594,6 +28788,7 @@ const clone = (v) => typeof structuredClone === "function" ? structuredClone(v)
|
|
|
28594
28788
|
async function decomposeWorkflow(ask, deps, opts = {}) {
|
|
28595
28789
|
const maxRounds = Math.max(1, opts.maxRounds ?? DEFAULT_MAX_ROUNDS);
|
|
28596
28790
|
const verifyOpts = opts.verify ?? {};
|
|
28791
|
+
const context = typeof opts.context === "string" && opts.context.trim().length > 0 ? opts.context.trim() : void 0;
|
|
28597
28792
|
let feedback;
|
|
28598
28793
|
let lastViolations = [{
|
|
28599
28794
|
code: "NO_DRAFT",
|
|
@@ -28603,6 +28798,7 @@ async function decomposeWorkflow(ask, deps, opts = {}) {
|
|
|
28603
28798
|
for (let round = 1; round <= maxRounds; round += 1) {
|
|
28604
28799
|
const drafted = await safeDraft(deps, {
|
|
28605
28800
|
ask,
|
|
28801
|
+
context,
|
|
28606
28802
|
feedback
|
|
28607
28803
|
});
|
|
28608
28804
|
attempts += 1;
|
|
@@ -28627,6 +28823,7 @@ async function decomposeWorkflow(ask, deps, opts = {}) {
|
|
|
28627
28823
|
if (round < maxRounds) {
|
|
28628
28824
|
const next = await safeDraft(deps, {
|
|
28629
28825
|
ask,
|
|
28826
|
+
context,
|
|
28630
28827
|
feedback: concerns
|
|
28631
28828
|
});
|
|
28632
28829
|
attempts += 1;
|
|
@@ -28852,38 +29049,6 @@ function detectGateWeakening(diff) {
|
|
|
28852
29049
|
};
|
|
28853
29050
|
}
|
|
28854
29051
|
|
|
28855
|
-
//#endregion
|
|
28856
|
-
//#region src/lib/orchestration/gate-runner.ts
|
|
28857
|
-
async function runGateChecks(checks, cwd, exec) {
|
|
28858
|
-
const results = await Promise.all(checks.map(async (c) => {
|
|
28859
|
-
try {
|
|
28860
|
-
const r = await exec({
|
|
28861
|
-
command: c.command,
|
|
28862
|
-
cwd
|
|
28863
|
-
});
|
|
28864
|
-
return {
|
|
28865
|
-
id: c.id,
|
|
28866
|
-
passed: r.exitCode === 0
|
|
28867
|
-
};
|
|
28868
|
-
} catch {
|
|
28869
|
-
return {
|
|
28870
|
-
id: c.id,
|
|
28871
|
-
passed: false
|
|
28872
|
-
};
|
|
28873
|
-
}
|
|
28874
|
-
}));
|
|
28875
|
-
const passed = /* @__PURE__ */ new Set();
|
|
28876
|
-
const ran = /* @__PURE__ */ new Set();
|
|
28877
|
-
for (const r of results) {
|
|
28878
|
-
ran.add(r.id);
|
|
28879
|
-
if (r.passed) passed.add(r.id);
|
|
28880
|
-
}
|
|
28881
|
-
return {
|
|
28882
|
-
passed,
|
|
28883
|
-
ran
|
|
28884
|
-
};
|
|
28885
|
-
}
|
|
28886
|
-
|
|
28887
29052
|
//#endregion
|
|
28888
29053
|
//#region src/lib/orchestration/stop-gate.ts
|
|
28889
29054
|
async function evaluateStopGate(input) {
|
|
@@ -28929,63 +29094,6 @@ const liveExec = async ({ command, cwd }) => {
|
|
|
28929
29094
|
}
|
|
28930
29095
|
};
|
|
28931
29096
|
|
|
28932
|
-
//#endregion
|
|
28933
|
-
//#region src/lib/orchestration/gate-registry.ts
|
|
28934
|
-
/**
|
|
28935
|
-
* Built-in sealed gates. Commands follow this repo's TS/Bun conventions (the
|
|
28936
|
-
* `bun run <script>` indirection means a repo without that script simply fails
|
|
28937
|
-
* the check, which the selector treats as not-passed rather than a crash). New
|
|
28938
|
-
* ecosystems get a new sealed id here, never a caller-supplied command.
|
|
28939
|
-
*/
|
|
28940
|
-
const SEALED_GATES = {
|
|
28941
|
-
"default-ci": [
|
|
28942
|
-
{
|
|
28943
|
-
id: "typecheck",
|
|
28944
|
-
command: "bun run typecheck"
|
|
28945
|
-
},
|
|
28946
|
-
{
|
|
28947
|
-
id: "test",
|
|
28948
|
-
command: "bun test"
|
|
28949
|
-
},
|
|
28950
|
-
{
|
|
28951
|
-
id: "lint",
|
|
28952
|
-
command: "bun run lint"
|
|
28953
|
-
}
|
|
28954
|
-
],
|
|
28955
|
-
"typecheck-test": [{
|
|
28956
|
-
id: "typecheck",
|
|
28957
|
-
command: "bun run typecheck"
|
|
28958
|
-
}, {
|
|
28959
|
-
id: "test",
|
|
28960
|
-
command: "bun test"
|
|
28961
|
-
}],
|
|
28962
|
-
"typecheck-only": [{
|
|
28963
|
-
id: "typecheck",
|
|
28964
|
-
command: "bun run typecheck"
|
|
28965
|
-
}]
|
|
28966
|
-
};
|
|
28967
|
-
/** The set of sealed gate ids, used as the kernel's `knownGateIds` so the IR
|
|
28968
|
-
* verifier rejects an executable gate that references an unregistered id. */
|
|
28969
|
-
function sealedGateIds() {
|
|
28970
|
-
return new Set(Object.keys(SEALED_GATES));
|
|
28971
|
-
}
|
|
28972
|
-
/**
|
|
28973
|
-
* Resolve a sealed gate by id. Returns a DEFENSIVE CLONE (fresh objects) so a
|
|
28974
|
-
* caller can never mutate the registry's command set. `undefined` for an
|
|
28975
|
-
* unknown id, which `run_workflow` rejects before executing anything.
|
|
28976
|
-
*/
|
|
28977
|
-
function resolveSealedGate(gateId) {
|
|
28978
|
-
const checks = SEALED_GATES[gateId];
|
|
28979
|
-
if (!checks) return void 0;
|
|
28980
|
-
return {
|
|
28981
|
-
id: gateId,
|
|
28982
|
-
checks: checks.map((c) => ({
|
|
28983
|
-
id: c.id,
|
|
28984
|
-
command: c.command
|
|
28985
|
-
}))
|
|
28986
|
-
};
|
|
28987
|
-
}
|
|
28988
|
-
|
|
28989
29097
|
//#endregion
|
|
28990
29098
|
//#region src/lib/orchestration/runner-live.ts
|
|
28991
29099
|
/** Map a node role to the worker-engine mode. `baseline` is pre-mapped to
|
|
@@ -29476,6 +29584,19 @@ async function decideStopHook(input) {
|
|
|
29476
29584
|
let dynamicBaselineKey;
|
|
29477
29585
|
const planMode = input.planMode === true || payload.plan_mode === true;
|
|
29478
29586
|
const scanDiff = (diff) => planMode ? stripPlanMemoryDiffHunks(diff) : diff;
|
|
29587
|
+
const capturedDiff = async (workdir) => {
|
|
29588
|
+
try {
|
|
29589
|
+
return {
|
|
29590
|
+
diff: await input.captureDiff(workdir),
|
|
29591
|
+
captured: true
|
|
29592
|
+
};
|
|
29593
|
+
} catch {
|
|
29594
|
+
return {
|
|
29595
|
+
diff: "",
|
|
29596
|
+
captured: false
|
|
29597
|
+
};
|
|
29598
|
+
}
|
|
29599
|
+
};
|
|
29479
29600
|
const runGate = async () => {
|
|
29480
29601
|
if (input.resolveChecks) {
|
|
29481
29602
|
const resolved = await input.resolveChecks(cwd).catch(() => null);
|
|
@@ -29483,27 +29604,37 @@ async function decideStopHook(input) {
|
|
|
29483
29604
|
resolvedKey = resolved.descriptorKey;
|
|
29484
29605
|
dynamicBaselineKey = resolved.baselineKey;
|
|
29485
29606
|
const workdir = resolved.workdir || cwd;
|
|
29486
|
-
const diff$1 = await
|
|
29607
|
+
const { diff: diff$1, captured: captured$1 } = await capturedDiff(workdir);
|
|
29608
|
+
if (captured$1 && diff$1.length === 0) return {
|
|
29609
|
+
kind: "no-diff",
|
|
29610
|
+
diff: diff$1
|
|
29611
|
+
};
|
|
29487
29612
|
const result$1 = await evaluateStopGate({
|
|
29488
29613
|
checks: resolved.checks,
|
|
29489
29614
|
cwd: workdir,
|
|
29490
29615
|
exec: input.exec,
|
|
29491
|
-
diff: scanDiff(diff$1)
|
|
29616
|
+
diff: captured$1 ? scanDiff(diff$1) : ""
|
|
29492
29617
|
});
|
|
29493
29618
|
return {
|
|
29619
|
+
kind: "evaluated",
|
|
29494
29620
|
failedChecks: [...result$1.failedChecks],
|
|
29495
29621
|
weakeningPatterns: [...new Set(result$1.weakening.map((w) => w.pattern))],
|
|
29496
29622
|
diff: diff$1
|
|
29497
29623
|
};
|
|
29498
29624
|
}
|
|
29499
|
-
const diff = await
|
|
29625
|
+
const { diff, captured } = await capturedDiff(cwd);
|
|
29626
|
+
if (captured && diff.length === 0) return {
|
|
29627
|
+
kind: "no-diff",
|
|
29628
|
+
diff
|
|
29629
|
+
};
|
|
29500
29630
|
const result = await runStopGateForLaunch({
|
|
29501
29631
|
workspace: cwd,
|
|
29502
29632
|
gateId: input.gateId,
|
|
29503
29633
|
exec: input.exec,
|
|
29504
|
-
diff: scanDiff(diff)
|
|
29634
|
+
diff: captured ? scanDiff(diff) : ""
|
|
29505
29635
|
});
|
|
29506
29636
|
return {
|
|
29637
|
+
kind: "evaluated",
|
|
29507
29638
|
failedChecks: [...result.failedChecks],
|
|
29508
29639
|
weakeningPatterns: [...new Set(result.weakening.map((w) => w.pattern))],
|
|
29509
29640
|
diff
|
|
@@ -29517,6 +29648,7 @@ async function decideStopHook(input) {
|
|
|
29517
29648
|
if (timer) clearTimeout(timer);
|
|
29518
29649
|
if (raced === "timeout") return { exitCode: 0 };
|
|
29519
29650
|
if (raced === null) return { exitCode: 0 };
|
|
29651
|
+
if (raced.kind === "no-diff") return { exitCode: 0 };
|
|
29520
29652
|
const baselineKey = dynamicBaselineKey ?? JSON.stringify([
|
|
29521
29653
|
sessionId,
|
|
29522
29654
|
cwd,
|
|
@@ -29553,7 +29685,7 @@ async function decideStopHook(input) {
|
|
|
29553
29685
|
* `markReviewed` runs BEFORE the spawn so a crashing spawn still records the
|
|
29554
29686
|
* debounce (an identical tree won't re-trigger on the next stop). The review is
|
|
29555
29687
|
* gated on the diff CHANGING since the last review — without it, every stop of
|
|
29556
|
-
* an unchanged tree would re-spend a background gpt-5.
|
|
29688
|
+
* an unchanged tree would re-spend a background gpt-5.6-sol review.
|
|
29557
29689
|
*
|
|
29558
29690
|
* The whole body is bounded by a short timeout (the stores are local temp files
|
|
29559
29691
|
* that complete in well under a millisecond in practice, so the timeout never
|
|
@@ -29804,8 +29936,8 @@ function buildLiveDecomposeDeps(opts) {
|
|
|
29804
29936
|
endpoint: "/v1/messages",
|
|
29805
29937
|
effort: "xhigh"
|
|
29806
29938
|
};
|
|
29807
|
-
const deps = { async draftIR({ ask, feedback }) {
|
|
29808
|
-
const userText = `Ask:\n${ask}` + (feedback && feedback.length > 0 ? `\n\nFix these issues from the previous draft:\n- ${feedback.join("\n- ")}` : "");
|
|
29939
|
+
const deps = { async draftIR({ ask, context, feedback }) {
|
|
29940
|
+
const userText = `Ask:\n${ask}` + (context && context.trim().length > 0 ? `\n\nContext:\n${context.trim()}` : "") + (feedback && feedback.length > 0 ? `\n\nFix these issues from the previous draft:\n- ${feedback.join("\n- ")}` : "");
|
|
29809
29941
|
return extractJson(await dispatchModelCall({
|
|
29810
29942
|
model: driver.model,
|
|
29811
29943
|
endpoint: driver.endpoint,
|
|
@@ -29839,7 +29971,7 @@ const CRITIC_INSTRUCTIONS = "You are a cross-lab code reviewer. Review the diff
|
|
|
29839
29971
|
function labPersona(lab) {
|
|
29840
29972
|
switch (lab.toLowerCase()) {
|
|
29841
29973
|
case "openai": return {
|
|
29842
|
-
model: "gpt-5.
|
|
29974
|
+
model: "gpt-5.6-sol",
|
|
29843
29975
|
endpoint: "/v1/responses",
|
|
29844
29976
|
effort: "high"
|
|
29845
29977
|
};
|
|
@@ -30066,7 +30198,7 @@ Cold-start contract for the lead orchestrator (Opus):
|
|
|
30066
30198
|
(c) any prior decisions I should not relitigate.
|
|
30067
30199
|
If your brief lacks (a), I will reply with a one-line request for the artifact instead of speculating.
|
|
30068
30200
|
`.trim();
|
|
30069
|
-
const CRITIC_BASE = `You are codex-critic, an adversarial reviewer running on gpt-5.
|
|
30201
|
+
const CRITIC_BASE = `You are codex-critic, an adversarial reviewer running on gpt-5.6-sol. Your single job is to overcome the lead orchestrator's blind spots — assumptions it didn't notice it was making, failure modes it didn't enumerate, alternatives it didn't consider.
|
|
30070
30202
|
|
|
30071
30203
|
You are NOT a helpful assistant. You are NOT a coach. Sycophancy is the failure mode you exist to fight. Manufactured contrarianism is a different failure of the same shape — silence on good work is a valid and welcome answer.
|
|
30072
30204
|
|
|
@@ -30154,9 +30286,9 @@ Reply format (markdown):
|
|
|
30154
30286
|
|
|
30155
30287
|
Resilience reminder:
|
|
30156
30288
|
If your session terminates abnormally before "Status: complete", the lead will retry once. On recovery, ask the lead to confirm what's already been done before re-applying changes — duplicate edits are worse than a slow restart.`;
|
|
30157
|
-
const OPUS_CRITIC_BASE = `You are opus-critic, a fresh-context
|
|
30289
|
+
const OPUS_CRITIC_BASE = `You are opus-critic, a fresh-context same-lab adversarial reviewer running on Opus 4.6. The lead orchestrator that just delegated to you runs newer Opus-family context, but you are NOT the lead. You did not see the lead's reasoning trace. You only see the brief.
|
|
30158
30290
|
|
|
30159
|
-
Your job is to spot what the lead missed because of cognitive momentum, sunk-cost on a plan, or motivated reasoning toward a particular fix. Your blind-spot diversification is LIMITED compared to codex-critic (gpt-5.
|
|
30291
|
+
Your job is to spot what the lead missed because of cognitive momentum, sunk-cost on a plan, or motivated reasoning toward a particular fix. Your blind-spot diversification is LIMITED compared to codex-critic (gpt-5.6-sol) and gemini-critic (gemini-3.1-pro), same lab, adjacent model family, related priors. Use that honestly: don't pretend to find a different perspective when the obvious read is "the lead got it right." Silence on good work is a valid and welcome answer.
|
|
30160
30292
|
|
|
30161
30293
|
Sycophancy is the failure mode you exist to fight. Manufactured contrarianism is a different failure of the same shape — do neither.
|
|
30162
30294
|
|
|
@@ -30167,9 +30299,9 @@ const PERSONAS_READ = Object.freeze([
|
|
|
30167
30299
|
{
|
|
30168
30300
|
agentName: "codex-critic",
|
|
30169
30301
|
toolNameHttp: "codex_critic",
|
|
30170
|
-
model: "gpt-5.
|
|
30302
|
+
model: "gpt-5.6-sol",
|
|
30171
30303
|
endpoint: "/v1/responses",
|
|
30172
|
-
description: "Adversarial
|
|
30304
|
+
description: "Adversarial architecture and design critic backed by gpt-5.6-sol (OpenAI, ~1M-token input window), the strongest cross-lab reasoning critic in this surface. It reviews plans, designs, tradeoffs, and large code-change proposals for unsound assumptions, missing failure modes, and overlooked alternatives, then returns a calibrated objection or `no material objection`. Use when a decision or design needs a different-lab strategic challenge before implementation or merge. Not for line-level bug finding in a concrete diff or file, use codex_reviewer or gemini_reviewer; pass the artifact and constraints verbatim.",
|
|
30173
30305
|
baseInstructions: CRITIC_BASE,
|
|
30174
30306
|
agentPrompt: "",
|
|
30175
30307
|
writeCapable: false,
|
|
@@ -30187,7 +30319,7 @@ const PERSONAS_READ = Object.freeze([
|
|
|
30187
30319
|
toolNameHttp: "gemini_critic",
|
|
30188
30320
|
model: "gemini-3.1-pro-preview",
|
|
30189
30321
|
endpoint: "/v1/chat/completions",
|
|
30190
|
-
description: "Adversarial
|
|
30322
|
+
description: "Adversarial third-lab critic backed by gemini-3.1-pro-preview (Google), strong on formal reasoning, invariants, proofs, and cross-checking another critic's conclusion. It reviews plans, designs, mathematical arguments, and large artifacts for assumption gaps or invariant failures, then returns a focused critique or no-material-objection style verdict. Use when codex_critic's result needs an independent lab check or when the artifact hinges on formal correctness. Not for line-level diff review, use gemini_reviewer or codex_reviewer; pass the artifact and constraints verbatim.",
|
|
30191
30323
|
baseInstructions: GEMINI_CRITIC_BASE,
|
|
30192
30324
|
agentPrompt: "",
|
|
30193
30325
|
writeCapable: false,
|
|
@@ -30205,7 +30337,7 @@ const PERSONAS_READ = Object.freeze([
|
|
|
30205
30337
|
toolNameHttp: "codex_reviewer",
|
|
30206
30338
|
model: "gpt-5.3-codex",
|
|
30207
30339
|
endpoint: "/v1/responses",
|
|
30208
|
-
description: "Line-level
|
|
30340
|
+
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.",
|
|
30209
30341
|
baseInstructions: REVIEWER_BASE,
|
|
30210
30342
|
agentPrompt: "",
|
|
30211
30343
|
writeCapable: false,
|
|
@@ -30223,7 +30355,7 @@ const PERSONAS_READ = Object.freeze([
|
|
|
30223
30355
|
toolNameHttp: "gemini_reviewer",
|
|
30224
30356
|
model: "gemini-3.1-pro-preview",
|
|
30225
30357
|
endpoint: "/v1/chat/completions",
|
|
30226
|
-
description: "Line-level
|
|
30358
|
+
description: "Line-level code reviewer backed by gemini-3.1-pro-preview (Google), providing second-lab coverage that catches a different slice of concrete-code defects than codex_reviewer. It reviews diffs, files, or function bodies and returns severity-ranked findings with file:line citations and suggested fixes. Use alongside codex_reviewer when a non-trivial diff benefits from cross-lab code-review coverage, especially around invariants or edge cases. Not for architecture or product-design review, use codex_critic or gemini_critic; pass the code artifact verbatim.",
|
|
30227
30359
|
baseInstructions: GEMINI_REVIEWER_BASE,
|
|
30228
30360
|
agentPrompt: "",
|
|
30229
30361
|
writeCapable: false,
|
|
@@ -30241,7 +30373,7 @@ const PERSONAS_READ = Object.freeze([
|
|
|
30241
30373
|
toolNameHttp: "opus_critic",
|
|
30242
30374
|
model: "claude-opus-4-6",
|
|
30243
30375
|
endpoint: "/v1/messages",
|
|
30244
|
-
description: "Adversarial
|
|
30376
|
+
description: "Adversarial same-lab critic backed by fresh-context Opus 4.6, with limited blind-spot diversity compared with cross-lab critics. It reviews plans, designs, or code tradeoffs for cognitive momentum, sunk-cost reasoning, and confabulated assumptions, then returns a calibrated objection or no material objection. Use when a same-family sanity check can catch lead-context drift or when comparing against codex_critic / gemini_critic findings. Not a substitute for cross-lab review on security-sensitive or high-risk changes; use codex_critic or gemini_critic for stronger diversity. On enterprise catalogs that carry Opus-4.6-1M it runs with ≈936K input tokens; otherwise ≈168K. Pinned two minors behind the default Opus so the panel spans more of the version curve. Pass artifact verbatim.",
|
|
30245
30377
|
baseInstructions: OPUS_CRITIC_BASE,
|
|
30246
30378
|
agentPrompt: "",
|
|
30247
30379
|
writeCapable: false,
|
|
@@ -30259,7 +30391,7 @@ const PERSONAS_WRITE = Object.freeze([{
|
|
|
30259
30391
|
toolNameHttp: "codex_implementer",
|
|
30260
30392
|
model: "gpt-5.3-codex",
|
|
30261
30393
|
endpoint: "/v1/responses",
|
|
30262
|
-
description: "Targeted implementation
|
|
30394
|
+
description: "Targeted implementation persona backed by gpt-5.3-codex with workspace-write access. It executes self-contained coding tasks from a pasted spec, reads the relevant files, edits the workspace, verifies the result, and returns changed files plus verification output. Use when the task is bounded enough for direct implementation and the caller can provide acceptance criteria and file context up front. Not for open-ended planning or broad repo exploration, use plan or explore first; not for read-only review, use codex_reviewer or gemini_reviewer. Because it can mutate the workspace, scope files and allowed changes explicitly and pass the spec verbatim.",
|
|
30263
30395
|
baseInstructions: IMPLEMENTER_BASE,
|
|
30264
30396
|
agentPrompt: "",
|
|
30265
30397
|
writeCapable: true,
|
|
@@ -30354,8 +30486,8 @@ function buildAgentPrompt(persona, opts) {
|
|
|
30354
30486
|
* - Conditionally lists gemini_critic only when `geminiAvailable`.
|
|
30355
30487
|
* - Conditionally lists the `worker-*` background dispatcher subagents
|
|
30356
30488
|
* (worker-explore / worker-review / worker-plan / worker-implement /
|
|
30357
|
-
* worker-test), the non-blocking-guard fact, and
|
|
30358
|
-
*
|
|
30489
|
+
* worker-test), the non-blocking-guard fact, and the worker code-search
|
|
30490
|
+
* affordance only when `workerToolsAvailable` (mirrors
|
|
30359
30491
|
* `workerToolsEnabled()` so the snippet never names a surface gated out
|
|
30360
30492
|
* of the live catalog). The raw `mcp__<workers>__*` tools are named only
|
|
30361
30493
|
* as the guarded plumbing the dispatchers call, never as a main-agent
|
|
@@ -30379,15 +30511,19 @@ function buildPeerAwarenessSnippet(opts) {
|
|
|
30379
30511
|
const orchestrateKey = key("orchestrate");
|
|
30380
30512
|
const browserKey = key("browser");
|
|
30381
30513
|
const decideKey = key("decide");
|
|
30382
|
-
const
|
|
30514
|
+
const fleetKey = key("fleet");
|
|
30515
|
+
const compoundBrowseAvailable = opts.browseAvailable && opts.compoundBrowseAvailable;
|
|
30516
|
+
const powerBrowseAvailable = opts.browseAvailable && opts.powerBrowseAvailable === true;
|
|
30517
|
+
const criticList = ["`codex_critic` (gpt-5.6-sol)", "`codex_reviewer` (gpt-5.3-codex)"];
|
|
30383
30518
|
if (opts.geminiAvailable) {
|
|
30384
30519
|
criticList.push("`gemini_reviewer` (gemini-3.1-pro, line-level code review)");
|
|
30385
30520
|
criticList.push("`gemini_critic` (gemini-3.1-pro)");
|
|
30386
30521
|
}
|
|
30387
|
-
criticList.push("`opus_critic` (Opus 4.
|
|
30522
|
+
criticList.push("`opus_critic` (Opus 4.6)");
|
|
30388
30523
|
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." : "";
|
|
30389
30524
|
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.`];
|
|
30390
30525
|
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; \`worktree: true\` isolates in a git worktree and returns the diff), \`worker-test\` (independent test author). 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\`.`);
|
|
30526
|
+
if (opts.workerToolsAvailable && opts.implementerAvailable) para2Parts.push(`For a bounded, well-scoped implementation, prefer the \`implementer\` subagent (Task, runs on gpt-5.6-sol) over \`worker-implement\`; reach for \`worker-implement\` only when you specifically need git-worktree isolation, parallel variants, or a throwaway experiment.`);
|
|
30391
30527
|
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.`);
|
|
30392
30528
|
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).`);
|
|
30393
30529
|
if (opts.workerToolsAvailable) {
|
|
@@ -30396,10 +30532,10 @@ function buildPeerAwarenessSnippet(opts) {
|
|
|
30396
30532
|
}
|
|
30397
30533
|
para2Parts.push(`\`mcp__${searchKey}__web\` surfaces citable sources for docs, errors, and upstream issues.`);
|
|
30398
30534
|
if (opts.standInAvailable) para2Parts.push(`\`mcp__${decideKey}__stand_in\` provides three-lab consensus for decision tiebreak when the user is unavailable.`);
|
|
30399
|
-
if (opts.browseAvailable) {
|
|
30400
|
-
|
|
30401
|
-
|
|
30402
|
-
}
|
|
30535
|
+
if (opts.browseAvailable) para2Parts.push(`\`mcp__${browserKey}__*\` tools drive a real Chrome / Edge browser via a local extension. Lead browse surface includes \`__navigate\` / \`__open_tab\` / \`__screenshot\` for state, visuals, and navigation.`);
|
|
30536
|
+
if (compoundBrowseAvailable) para2Parts.push(`Compound browse surface includes \`mcp__${browserKey}__act(intent, value?)\` / \`__observe(intent?)\` / \`__extract(schema, instruction)\` / \`__find\`; an inner fast model resolves intent, find/observe yield element refs act consumes, and the lead never sees raw DOM.`);
|
|
30537
|
+
if (powerBrowseAvailable) para2Parts.push(`Power browse surface adds \`mcp__${browserKey}__mouse\`, \`__drag\`, \`__type\`, \`__keyboard\`, \`__scroll\`, \`__eval_js\`, \`__read_page\`, \`__diagnostics\`, \`__list_tabs\`, \`__close_tab\`, \`__wait\`, and \`__download\` for direct DOM and coordinate control.`);
|
|
30538
|
+
if (opts.fleetAvailable) para2Parts.push(`\`mcp__${fleetKey}__*\` tools drive remote ai-or-die coding sessions (list / read / create / stop / await / drive, plus remote read_file / list_dir / search / git_show); they act on a REMOTE fleet instance, not the local repo.`);
|
|
30403
30539
|
return [
|
|
30404
30540
|
"## Peer review and advisor",
|
|
30405
30541
|
"",
|
|
@@ -30408,6 +30544,31 @@ function buildPeerAwarenessSnippet(opts) {
|
|
|
30408
30544
|
para2Parts.join(" ")
|
|
30409
30545
|
].join("\n");
|
|
30410
30546
|
}
|
|
30547
|
+
/**
|
|
30548
|
+
* Compact, gated capability SUMMARY for the spawned session's system prompt
|
|
30549
|
+
* (`--append-system-prompt`). The FULL per-tool inventory lives once in the
|
|
30550
|
+
* mirrored CLAUDE.md (buildPeerAwarenessSnippet); this ~300-token summary gives
|
|
30551
|
+
* the main agent high-salience awareness of what is available without
|
|
30552
|
+
* duplicating the full snippet in the context window every turn. Gated
|
|
30553
|
+
* identically to the full snippet so it never names a surface the live
|
|
30554
|
+
* tools/list dropped. Factual present tense, no imperatives.
|
|
30555
|
+
*/
|
|
30556
|
+
function buildPeerAwarenessSummary(opts) {
|
|
30557
|
+
const key = (g) => opts.groupKeys?.[g] ?? GROUP_META[g].preferredKey;
|
|
30558
|
+
const lines = [
|
|
30559
|
+
"## Injected capabilities (summary)",
|
|
30560
|
+
"",
|
|
30561
|
+
`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.`
|
|
30562
|
+
];
|
|
30563
|
+
if (opts.workerToolsAvailable) lines.push(`Background \`worker-*\` agents (explore, review, plan, implement, test) run delegated work in their own context without blocking your turn, and \`mcp__${key("orchestrate")}__*\` composes, verifies, and runs floor-raising workflows.`);
|
|
30564
|
+
if (opts.standInAvailable) lines.push(`\`mcp__${key("decide")}__stand_in\` returns a three-lab consensus for a decision when the user is unavailable.`);
|
|
30565
|
+
if (opts.browseAvailable) lines.push(`\`mcp__${key("browser")}__*\` drives a real Chrome or Edge browser.`);
|
|
30566
|
+
if (opts.fleetAvailable) lines.push(`\`mcp__${key("fleet")}__*\` drives remote ai-or-die coding sessions.`);
|
|
30567
|
+
if (opts.agentToolsAvailable === true) lines.push("The `/gh-first-mate` skill drives a durable GitHub cloud-agent loop.");
|
|
30568
|
+
lines.push("");
|
|
30569
|
+
lines.push(`Each tool's own description carries when to use it and when not. The full per-tool inventory (models, gating, workers, skills) is in the "Peer review and advisor" section of your CLAUDE.md project instructions.`);
|
|
30570
|
+
return lines.join("\n");
|
|
30571
|
+
}
|
|
30411
30572
|
/** Convenience: every persona that should be registered for the given mode. */
|
|
30412
30573
|
function personasFor(opts) {
|
|
30413
30574
|
const result = [];
|
|
@@ -30418,7 +30579,7 @@ function personasFor(opts) {
|
|
|
30418
30579
|
if (opts.codexCli) for (const p of PERSONAS_WRITE) result.push(p);
|
|
30419
30580
|
return result;
|
|
30420
30581
|
}
|
|
30421
|
-
const WEB_SEARCH_DESCRIPTION = "Web search via GitHub Copilot's MCP
|
|
30582
|
+
const WEB_SEARCH_DESCRIPTION = "Web search via GitHub Copilot's MCP that returns answer text plus source URLs the caller can cite. It accepts a natural-language `query`; the upstream provider rewrites for the search index and the handler formats any references as markdown links. Use for current external information such as API documentation, error-message diagnosis, upstream issue searches, and claims that need web sources. Not for local repository discovery or code navigation, use code, Read, Grep, or Glob for workspace content. Prefer it over the built-in WebSearch when source URLs are needed or the built-in surface is geographically constrained.";
|
|
30422
30583
|
/**
|
|
30423
30584
|
* Format a `searchWeb()` result as an MCP-friendly text block. Mirrors
|
|
30424
30585
|
* the legacy inject format that `injectWebSearchIfNeeded` produces and
|
|
@@ -30453,7 +30614,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30453
30614
|
if (!query) return {
|
|
30454
30615
|
content: [{
|
|
30455
30616
|
type: "text",
|
|
30456
|
-
text: "
|
|
30617
|
+
text: "web: arguments.query is required (must be a non-empty string)"
|
|
30457
30618
|
}],
|
|
30458
30619
|
isError: true
|
|
30459
30620
|
};
|
|
@@ -30466,7 +30627,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30466
30627
|
return {
|
|
30467
30628
|
content: [{
|
|
30468
30629
|
type: "text",
|
|
30469
|
-
text: `
|
|
30630
|
+
text: `web failed: ${err instanceof Error ? err.message : String(err)}`
|
|
30470
30631
|
}],
|
|
30471
30632
|
isError: true
|
|
30472
30633
|
};
|
|
@@ -30625,7 +30786,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30625
30786
|
toolNameHttp: "explore",
|
|
30626
30787
|
group: "workers",
|
|
30627
30788
|
capability: "worker",
|
|
30628
|
-
description: "Runs as the background `worker-explore` agent. Dispatch via the Agent tool (subagent_type: worker-explore) so
|
|
30789
|
+
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 `claude-sonnet-5` at xhigh 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.",
|
|
30629
30790
|
inputSchema: {
|
|
30630
30791
|
type: "object",
|
|
30631
30792
|
required: ["prompt"],
|
|
@@ -30637,7 +30798,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30637
30798
|
},
|
|
30638
30799
|
model: {
|
|
30639
30800
|
type: "string",
|
|
30640
|
-
description: "Optional Copilot catalog model id (defaults to
|
|
30801
|
+
description: "Optional Copilot catalog model id (defaults to claude-sonnet-5). Must advertise tool_calls support; the engine emits an isError envelope listing the eligible catalog models on mismatch."
|
|
30641
30802
|
},
|
|
30642
30803
|
thinking: {
|
|
30643
30804
|
type: "string",
|
|
@@ -30649,7 +30810,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30649
30810
|
"high",
|
|
30650
30811
|
"xhigh"
|
|
30651
30812
|
],
|
|
30652
|
-
description: "Optional reasoning depth (default
|
|
30813
|
+
description: "Optional reasoning depth (default xhigh). Silently clamped to the model's allowed range; \"off\" drops the parameter entirely."
|
|
30653
30814
|
},
|
|
30654
30815
|
workspace: {
|
|
30655
30816
|
type: "string",
|
|
@@ -30673,7 +30834,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30673
30834
|
toolNameHttp: "implement",
|
|
30674
30835
|
group: "workers",
|
|
30675
30836
|
capability: "worker",
|
|
30676
|
-
description: "Runs as the background `worker-implement` agent. Dispatch via the Agent tool (subagent_type: worker-implement) so
|
|
30837
|
+
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. With `worktree: false` (default) edits happen in place, so concurrent implement calls and lead edits to the same files can race. With `worktree: true` it runs in an isolated git worktree and returns the diff; this errors if the workspace is not a git repository.",
|
|
30677
30838
|
inputSchema: {
|
|
30678
30839
|
type: "object",
|
|
30679
30840
|
required: ["prompt"],
|
|
@@ -30685,11 +30846,11 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30685
30846
|
},
|
|
30686
30847
|
worktree: {
|
|
30687
30848
|
type: "boolean",
|
|
30688
|
-
description: "When true, run inside a fresh git worktree and return Pi's final text followed by the unified diff (so the lead can review before merging). When false/omitted, edits the workspace in place
|
|
30849
|
+
description: "When true, run inside a fresh git worktree and return Pi's final text followed by the unified diff (so the lead can review before merging). When false/omitted, edits the workspace in place, so concurrent worker calls and lead edits can race. Errors if true and the workspace is not a git repository."
|
|
30689
30850
|
},
|
|
30690
30851
|
model: {
|
|
30691
30852
|
type: "string",
|
|
30692
|
-
description: "Optional Copilot catalog model id (defaults to gpt-5.
|
|
30853
|
+
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."
|
|
30693
30854
|
},
|
|
30694
30855
|
thinking: {
|
|
30695
30856
|
type: "string",
|
|
@@ -30725,7 +30886,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30725
30886
|
toolNameHttp: "review",
|
|
30726
30887
|
group: "workers",
|
|
30727
30888
|
capability: "worker",
|
|
30728
|
-
description: "Runs as the background `worker-review` agent. Dispatch via the Agent tool (subagent_type: worker-review) so
|
|
30889
|
+
description: "Runs as the background `worker-review` agent. Dispatch via the Agent tool (subagent_type: worker-review) so the turn is never blocked; the result arrives as a completion notification. Read-only code review by an autonomous worker (Pi runtime; default model `gemini-3.1-pro-preview`, default thinking xhigh clamped to high for that model, override via `model` with any Copilot-catalog model that advertises `tool_calls`). It has the same read-only toolset as explore and verifies claims against surrounding repository context before returning severity-ranked findings with `file:line` citations. Use for reviewing a change, diff, or correctness claim when the reviewer should read the code itself rather than trusting a pasted artifact. Not for architecture critique, implementation, or test authoring; use codex_critic or gemini_critic for design review, implement for edits, and test for independent test creation.",
|
|
30729
30890
|
inputSchema: {
|
|
30730
30891
|
type: "object",
|
|
30731
30892
|
required: ["prompt"],
|
|
@@ -30737,7 +30898,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30737
30898
|
},
|
|
30738
30899
|
model: {
|
|
30739
30900
|
type: "string",
|
|
30740
|
-
description: "Optional Copilot catalog model id (defaults to
|
|
30901
|
+
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."
|
|
30741
30902
|
},
|
|
30742
30903
|
thinking: {
|
|
30743
30904
|
type: "string",
|
|
@@ -30749,7 +30910,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30749
30910
|
"high",
|
|
30750
30911
|
"xhigh"
|
|
30751
30912
|
],
|
|
30752
|
-
description: "Optional reasoning depth (default
|
|
30913
|
+
description: "Optional reasoning depth (defaults to xhigh, clamped to high for the default review model). Silently clamped to the model's allowed range; \"off\" drops the parameter entirely."
|
|
30753
30914
|
},
|
|
30754
30915
|
workspace: {
|
|
30755
30916
|
type: "string",
|
|
@@ -30773,7 +30934,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30773
30934
|
toolNameHttp: "plan",
|
|
30774
30935
|
group: "workers",
|
|
30775
30936
|
capability: "worker",
|
|
30776
|
-
description: "Runs as the background `worker-plan` agent. Dispatch via the Agent tool (subagent_type: worker-plan) so
|
|
30937
|
+
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-4.8` 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.",
|
|
30777
30938
|
inputSchema: {
|
|
30778
30939
|
type: "object",
|
|
30779
30940
|
required: ["prompt"],
|
|
@@ -30797,7 +30958,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30797
30958
|
"high",
|
|
30798
30959
|
"xhigh"
|
|
30799
30960
|
],
|
|
30800
|
-
description: "Optional reasoning depth (default
|
|
30961
|
+
description: "Optional reasoning depth (default xhigh). Silently clamped to the model's allowed range; \"off\" drops the parameter entirely."
|
|
30801
30962
|
},
|
|
30802
30963
|
workspace: {
|
|
30803
30964
|
type: "string",
|
|
@@ -30821,7 +30982,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30821
30982
|
toolNameHttp: "test",
|
|
30822
30983
|
group: "workers",
|
|
30823
30984
|
capability: "worker",
|
|
30824
|
-
description: "Runs as the background `worker-test` agent. Dispatch via the Agent tool (subagent_type: worker-test) so
|
|
30985
|
+
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. With `worktree: true` it runs in an isolated git worktree and returns the test diff; this errors if the workspace is not a git repository.",
|
|
30825
30986
|
inputSchema: {
|
|
30826
30987
|
type: "object",
|
|
30827
30988
|
required: ["prompt"],
|
|
@@ -30833,11 +30994,11 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30833
30994
|
},
|
|
30834
30995
|
worktree: {
|
|
30835
30996
|
type: "boolean",
|
|
30836
|
-
description: "When true, run inside a fresh git worktree and return Pi's final text followed by the unified diff (so the lead can review the authored tests before merging). When false/omitted, writes tests in place
|
|
30997
|
+
description: "When true, run inside a fresh git worktree and return Pi's final text followed by the unified diff (so the lead can review the authored tests before merging). When false/omitted, writes tests in place, so concurrent worker calls and lead edits can race. Errors if true and the workspace is not a git repository."
|
|
30837
30998
|
},
|
|
30838
30999
|
model: {
|
|
30839
31000
|
type: "string",
|
|
30840
|
-
description: "Optional Copilot catalog model id (defaults to gpt-5.
|
|
31001
|
+
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."
|
|
30841
31002
|
},
|
|
30842
31003
|
thinking: {
|
|
30843
31004
|
type: "string",
|
|
@@ -30872,7 +31033,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30872
31033
|
{
|
|
30873
31034
|
toolNameHttp: "verify_workflow",
|
|
30874
31035
|
group: "orchestrate",
|
|
30875
|
-
description: "Statically
|
|
31036
|
+
description: "Statically verifies a workflow IR against the orchestration floor invariants before the kernel runs it. It accepts the typed WorkflowIR as `ir` and an optional `knownGateIds` allowlist, then returns {ok, violations:[{code, message, nodeId?}]} with stable violation codes such as NO_BASELINE, SELECTOR_NOT_RAW_ASK, SAME_LAB_CHECK, ORPHAN_NODE, or MISSING_INTEGRATION_GATE. Use immediately after composing or receiving a workflow IR, especially before paying for run_workflow, so structural floor failures can be fixed while still in data form. Not a runner, model reviewer, or proof that the user's spec is correct; use run_workflow to execute sealed gates and use critic/review tools for advisory review.",
|
|
30876
31037
|
inputSchema: {
|
|
30877
31038
|
type: "object",
|
|
30878
31039
|
required: ["ir"],
|
|
@@ -30902,7 +31063,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30902
31063
|
toolNameHttp: "decompose",
|
|
30903
31064
|
group: "orchestrate",
|
|
30904
31065
|
capability: "worker",
|
|
30905
|
-
description: "
|
|
31066
|
+
description: "Composes a verified, tool-routed WorkflowIR from an open-ended software ask. A strong driver model drafts the IR, the static verifier checks floor invariants, the driver re-drafts on violations, and a cross-lab critic reviews a clean draft; optional `context` supplies repo facts, constraints, or research findings to the driver. It returns {ok, ir, rounds, concerns?} on success, or {ok:false, violations, rounds} when it cannot converge. Use for non-trivial, role-separated asks where blind-spot reduction and sealed-gate structure justify orchestration. Not for trivial edits, direct implementation, or execution; use implement for a scoped code change and run_workflow only after the IR is verified.",
|
|
30906
31067
|
inputSchema: {
|
|
30907
31068
|
type: "object",
|
|
30908
31069
|
required: ["ask"],
|
|
@@ -30935,7 +31096,10 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30935
31096
|
effort: "high"
|
|
30936
31097
|
},
|
|
30937
31098
|
signal
|
|
30938
|
-
}), {
|
|
31099
|
+
}), {
|
|
31100
|
+
maxRounds: 3,
|
|
31101
|
+
context: typeof args.context === "string" ? args.context : void 0
|
|
31102
|
+
});
|
|
30939
31103
|
return {
|
|
30940
31104
|
content: [{
|
|
30941
31105
|
type: "text",
|
|
@@ -30949,7 +31113,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
30949
31113
|
toolNameHttp: "run_workflow",
|
|
30950
31114
|
group: "orchestrate",
|
|
30951
31115
|
capability: "worker",
|
|
30952
|
-
description: "
|
|
31116
|
+
description: "Executes a verified WorkflowIR through the frozen orchestration kernel. The kernel runs a single-model baseline beside the orchestrated DAG, gates producers over the sealed executable `gateId` selected by the caller, and returns {ok, outcome:{status, winner?, artifact?, reason, gatesPassed?}}. It uses champion retention: the orchestrated candidate wins only when it does not regress the baseline's executable checks; otherwise the baseline ships. Use after decompose and verify_workflow for non-trivial asks in a git workspace with a meaningful sealed gate. Not for composing an IR, performing advisory review, or running arbitrary model-authored shell commands; use decompose or verify_workflow before this tool, and use ordinary tests or review tools outside the workflow kernel.",
|
|
30953
31117
|
inputSchema: {
|
|
30954
31118
|
type: "object",
|
|
30955
31119
|
required: [
|
|
@@ -31014,7 +31178,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
31014
31178
|
{
|
|
31015
31179
|
toolNameHttp: "attest_step",
|
|
31016
31180
|
group: "orchestrate",
|
|
31017
|
-
description: "
|
|
31181
|
+
description: "Audits self-reported producer lineage for bias-isolation structure. It accepts `nodes` with each producer lab, final artifact hash, and checker hashes, then returns {attested, recommendation:'accept'|'ship_baseline', nodes:[{id, attested, reason}]}. The check passes only when every producer has a different-lab check over the same final artifact hash, so missing, same-lab, or stale checks fail closed to a baseline recommendation. Use for workflows composed outside run_workflow, where lineage is self-reported and needs a deterministic completeness gate. Not a security boundary, hash authenticator, or executor; run_workflow is the kernel-owned path when the router must control artifacts, gates, and hashes.",
|
|
31018
31182
|
inputSchema: {
|
|
31019
31183
|
type: "object",
|
|
31020
31184
|
required: ["nodes"],
|
|
@@ -31072,7 +31236,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
31072
31236
|
toolNameHttp: "browse",
|
|
31073
31237
|
group: "workers",
|
|
31074
31238
|
capability: "browse_agent",
|
|
31075
|
-
description: "Runs as the background `worker-browse` agent. Dispatch via the Agent tool (subagent_type: worker-browse) so
|
|
31239
|
+
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.",
|
|
31076
31240
|
inputSchema: {
|
|
31077
31241
|
type: "object",
|
|
31078
31242
|
required: ["task"],
|
|
@@ -31100,7 +31264,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
31100
31264
|
toolNameHttp: "stand_in",
|
|
31101
31265
|
group: "decide",
|
|
31102
31266
|
capability: "stand_in",
|
|
31103
|
-
description: "
|
|
31267
|
+
description: "Three-lab away-mode decision tiebreak advisor for moments when the user is unavailable and the agent is stuck between two or more concrete options. It polls gpt-5.6-sol, Opus 4.7, and gemini-3.1-pro-preview across blind and informed voting rounds, then returns a ranked-choice verdict such as consensus, majority, no_consensus, or need_more_info. Use when work would otherwise halt on a bounded choice the user would normally make. Not for code review, open-ended exploration, single-model second opinions, or bypassing confirmation on irreversible actions such as push, delete, drop, or deploy; use peer-review-coordinator or the individual critics for review and still ask the user for destructive actions.",
|
|
31104
31268
|
inputSchema: {
|
|
31105
31269
|
type: "object",
|
|
31106
31270
|
required: ["decision", "options"],
|
|
@@ -31189,7 +31353,7 @@ function assertMcpToolSurfaceConsistent() {
|
|
|
31189
31353
|
* accessibility) and never throws — its `{text, isError?}` envelope
|
|
31190
31354
|
* is forwarded verbatim into the MCP `tool result` shape.
|
|
31191
31355
|
*
|
|
31192
|
-
* Arg-validation policy mirrors `
|
|
31356
|
+
* Arg-validation policy mirrors `web`'s pattern: shape errors
|
|
31193
31357
|
* surface as `isError: true` tool-result envelopes (NOT JSON-RPC -32602
|
|
31194
31358
|
* errors). The MCP `tools/list` JSON schema already documents the
|
|
31195
31359
|
* required/optional fields; this runtime check is defense against a
|
|
@@ -31396,7 +31560,7 @@ async function runBrowseToolCall(args, signal) {
|
|
|
31396
31560
|
* failures, abstains) all surface inside the structured `StandInResult`
|
|
31397
31561
|
* envelope, which we JSON-stringify into the single MCP text block.
|
|
31398
31562
|
*
|
|
31399
|
-
* Arg-validation policy mirrors `runWorkerToolCall` and `
|
|
31563
|
+
* Arg-validation policy mirrors `runWorkerToolCall` and `web`:
|
|
31400
31564
|
* shape errors surface as `isError: true` tool-result envelopes (NOT
|
|
31401
31565
|
* JSON-RPC -32602). The `tools/list` JSON schema documents required
|
|
31402
31566
|
* fields; this runtime check is defense against a schema-ignoring
|
|
@@ -31494,5 +31658,5 @@ async function runStandInToolCall(args, signal) {
|
|
|
31494
31658
|
}
|
|
31495
31659
|
|
|
31496
31660
|
//#endregion
|
|
31497
|
-
export {
|
|
31498
|
-
//# sourceMappingURL=peer-mcp-personas-
|
|
31661
|
+
export { isAdvisorRequested as $, cacheModels as $t, liveExec as A, hasSupportedBrowserInstalled as At, withNoOutputRetry as B, DEFAULT_CODEX_MODEL_FALLBACKS as Bt, fileReviewDebounce as C, pickEndpoint as Ct, stopGateEnabledForRepo as D, readResponseBodyCapped as Dt, repoRoot as E, MAX_RESPONSE_BODY_BYTES as Et, IMPLEMENT_DEFAULT_MODEL as F, ArtifactClient as Ft, vscodeRipgrepPath as G, pickClaudeDefault as Gt, buildToolbeltAwareness as H, UPSTREAM_FETCH_TIMEOUT_MS as Ht, PLAN_DEFAULT_MODEL as I, collapsePathKeys as It, searchWeb as J, setupCopilotToken as Jt, TOOLBELT_TOOLS$1 as K, getPackageVersion as Kt, REVIEW_DEFAULT_MODEL as L, toolbeltPathOverride as Lt, BROWSE_DEFAULT_MODEL as M, extractTarGzMember as Mt, DEFAULT_MODEL as N, extractZipMember as Nt, stopReviewStateDir as O, parseJsonOrDiagnose as Ot, EXPLORE_DEFAULT_MODEL as P, shouldUseInsecureTls as Pt, injectAdvisorTool as Q, cacheCopilotVersion as Qt, appendPlanReminder as R, DEFAULT_CLAUDE_MODEL_FALLBACKS as Rt, fileLastPromptStore as S, resolveMcpToolTimeoutMs as St, repoFingerprint as T, createChatCompletions as Tt, toolbeltEnabled as U, UPSTREAM_INACTIVITY_TIMEOUT_MS as Ut, availableToolCommands as V, DEFAULT_PORT as Vt, toolbeltSkipSet as W, generateRandomPort as Wt, ADVISOR_TOOL_INSTRUCTIONS as X, setupGitHubToken as Xt, ADVISOR_INTERNAL_TOOL_NAME as Y, setupGitHubAgentToken as Yt, buildAdvisorStream as Z, tryRefreshAndRetry as Zt, stopGateId as _, workerToolsEnabled as _t, buildPeerAwarenessSnippet as a, sleep as an, relayAnthropicStream as at, fileBaselineStore as b, getTokenCount as bt, buildArtifactOpenHookCommand as c, HTTPError as cn, agentToolsEnabled as ct, captureLaunchBaseline as d, copilotBaseUrl as dn, browserCompoundToolsEnabled as dt, cacheVSCodeVersion as en, buildAnthropicErrorEvent as et, decideStopHook as f, copilotHeaders as fn, browserToolsEnabled as ft, stopGateDisabled as g, standInToolEnabled as gt, launchBaselineKey as h, implementerSubagentModel as ht, buildAgentPrompt as i, resolveModel as in, readIteratorWithTimeout as it, resolveSealedGate as j, provisionAndIndexColbert as jt, trustRepo as k, provisionBrowserAssets as kt, buildSessionBindHookCommand as l, forwardError as ln, artifactToolsEnabled as lt, injectStopHookIntoSettingsFile as m, state as mn, geminiAvailable as mt, MCP_GROUPS as n, isNullish as nn, isControllerClosedError as nt, buildPeerAwarenessSummary as o, getModels as on, handleMcpDelete as ot, fileBlockBudget as p, githubHeaders as pn, fleetToolsEnabled as pt, assetFor as q, withInstallLock as qt, assertMcpToolSurfaceConsistent as r, resolveCodexModel as rn, logStreamError as rt, personasFor as s, fetchWithTransientRetry as sn, handleMcpPost as st, GROUP_META as t, filterBetaHeader as tn, buildOpenAIErrorEvent as tt, buildStopHookCommand as u, GITHUB_API_BASE_URL as un, browseAgentEnabled as ut, stopGatePlanMode as v, countTokens as vt, isSubagentContext as w, createResponses as wt, fileFindingsStore as x, assembleResponsesPayload as xt, stopReviewEnabled as y, createMessages as yt, runWorkerAgent as z, DEFAULT_CODEX_MODEL as zt };
|
|
31662
|
+
//# sourceMappingURL=peer-mcp-personas-BKkdfOyK.js.map
|