@charzhu/openjaw-agent 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +345 -29
- package/dist/main.js.map +3 -3
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -3540,6 +3540,13 @@ var init_tool_exposure = __esm({
|
|
|
3540
3540
|
|
|
3541
3541
|
// src/copilot-auth.ts
|
|
3542
3542
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
3543
|
+
function isOAuthAbortError(err) {
|
|
3544
|
+
if (!err || typeof err !== "object") return false;
|
|
3545
|
+
const anyErr = err;
|
|
3546
|
+
if (anyErr.name === "AbortError") return true;
|
|
3547
|
+
if (anyErr.code === "ABORT_ERR") return true;
|
|
3548
|
+
return false;
|
|
3549
|
+
}
|
|
3543
3550
|
function oauthDomain(enterpriseUrl) {
|
|
3544
3551
|
return enterpriseUrl ? normalizeCopilotEnterpriseDomain(enterpriseUrl) : "github.com";
|
|
3545
3552
|
}
|
|
@@ -3578,11 +3585,14 @@ async function startCopilotDeviceFlow(clientId, enterpriseUrl) {
|
|
|
3578
3585
|
enterpriseUrl: normalizedEnterpriseUrl
|
|
3579
3586
|
};
|
|
3580
3587
|
}
|
|
3581
|
-
async function completeCopilotDeviceFlow(flow) {
|
|
3588
|
+
async function completeCopilotDeviceFlow(flow, signal) {
|
|
3582
3589
|
const domain = oauthDomain(flow.enterpriseUrl);
|
|
3583
3590
|
let intervalMs = flow.intervalSeconds * 1e3;
|
|
3584
3591
|
while (true) {
|
|
3585
|
-
|
|
3592
|
+
if (signal?.aborted) {
|
|
3593
|
+
throw signal.reason instanceof Error ? signal.reason : new DOMException("Aborted", "AbortError");
|
|
3594
|
+
}
|
|
3595
|
+
await sleep(intervalMs + OAUTH_POLLING_SAFETY_MARGIN_MS, void 0, { signal });
|
|
3586
3596
|
const res = await fetch(`https://${domain}/login/oauth/access_token`, {
|
|
3587
3597
|
method: "POST",
|
|
3588
3598
|
headers: {
|
|
@@ -3594,7 +3604,8 @@ async function completeCopilotDeviceFlow(flow) {
|
|
|
3594
3604
|
client_id: flow.clientId,
|
|
3595
3605
|
device_code: flow.deviceCode,
|
|
3596
3606
|
grant_type: "urn:ietf:params:oauth:grant-type:device_code"
|
|
3597
|
-
})
|
|
3607
|
+
}),
|
|
3608
|
+
signal
|
|
3598
3609
|
});
|
|
3599
3610
|
if (!res.ok) {
|
|
3600
3611
|
throw new Error(`GitHub device login failed: ${res.status}`);
|
|
@@ -3633,6 +3644,7 @@ var init_copilot_auth = __esm({
|
|
|
3633
3644
|
init_provider_auth();
|
|
3634
3645
|
init_copilot();
|
|
3635
3646
|
OAUTH_POLLING_SAFETY_MARGIN_MS = 3e3;
|
|
3647
|
+
__name(isOAuthAbortError, "isOAuthAbortError");
|
|
3636
3648
|
__name(oauthDomain, "oauthDomain");
|
|
3637
3649
|
__name(startCopilotDeviceFlow, "startCopilotDeviceFlow");
|
|
3638
3650
|
__name(completeCopilotDeviceFlow, "completeCopilotDeviceFlow");
|
|
@@ -3648,7 +3660,8 @@ __export(connect_exports, {
|
|
|
3648
3660
|
disconnectContext: () => disconnectContext,
|
|
3649
3661
|
handleConnectCommand: () => handleConnectCommand,
|
|
3650
3662
|
listDisconnectChoices: () => listDisconnectChoices,
|
|
3651
|
-
maestroConfig: () => maestroConfig
|
|
3663
|
+
maestroConfig: () => maestroConfig,
|
|
3664
|
+
resolveCopilotClientId: () => resolveCopilotClientId
|
|
3652
3665
|
});
|
|
3653
3666
|
function maestroConfig(flavor = "anthropic") {
|
|
3654
3667
|
return {
|
|
@@ -19276,6 +19289,16 @@ var init_registry = __esm({
|
|
|
19276
19289
|
this.registerTool(tool);
|
|
19277
19290
|
}
|
|
19278
19291
|
}
|
|
19292
|
+
/**
|
|
19293
|
+
* Remove a tool by name. Returns true if a tool was removed.
|
|
19294
|
+
*
|
|
19295
|
+
* Used to drop stale MCP tools when a server reconnects, is denied,
|
|
19296
|
+
* or is removed so the LLM does not try to call a tool whose backing
|
|
19297
|
+
* connection no longer exists.
|
|
19298
|
+
*/
|
|
19299
|
+
unregisterTool(name) {
|
|
19300
|
+
return this.tools.delete(name);
|
|
19301
|
+
}
|
|
19279
19302
|
getTool(name) {
|
|
19280
19303
|
return this.tools.get(name);
|
|
19281
19304
|
}
|
|
@@ -47309,6 +47332,19 @@ function registerRpcHandlers(options) {
|
|
|
47309
47332
|
let currentRun = null;
|
|
47310
47333
|
const pendingResponders = /* @__PURE__ */ new Map();
|
|
47311
47334
|
const promptCollector = createPromptCollector(bus, () => agentLoop.sessionId);
|
|
47335
|
+
const OAUTH_FLOW_TTL_MS = 15 * 60 * 1e3;
|
|
47336
|
+
const oauthFlows = /* @__PURE__ */ new Map();
|
|
47337
|
+
const cleanupOAuthFlow = /* @__PURE__ */ __name((flowId, abort) => {
|
|
47338
|
+
const entry = oauthFlows.get(flowId);
|
|
47339
|
+
if (!entry) {
|
|
47340
|
+
return;
|
|
47341
|
+
}
|
|
47342
|
+
clearTimeout(entry.timer);
|
|
47343
|
+
if (abort && !entry.controller.signal.aborted) {
|
|
47344
|
+
entry.controller.abort();
|
|
47345
|
+
}
|
|
47346
|
+
oauthFlows.delete(flowId);
|
|
47347
|
+
}, "cleanupOAuthFlow");
|
|
47312
47348
|
const onBridgeEvent = /* @__PURE__ */ __name((rawEvent) => {
|
|
47313
47349
|
const source = inferBridgeSource(rawEvent);
|
|
47314
47350
|
const user = bridgeUser(rawEvent, source);
|
|
@@ -47855,6 +47891,77 @@ ${helpMessage}` : field.label;
|
|
|
47855
47891
|
}
|
|
47856
47892
|
return { disconnected: true, slug };
|
|
47857
47893
|
});
|
|
47894
|
+
bus.registerRpc("model.oauth_start", async (params) => {
|
|
47895
|
+
const slug = String(params.slug ?? "").trim();
|
|
47896
|
+
if (!PROVIDERS2.includes(slug)) {
|
|
47897
|
+
throw new Error(`unknown provider: ${slug}`);
|
|
47898
|
+
}
|
|
47899
|
+
const auth = PROVIDER_AUTH[slug];
|
|
47900
|
+
if (auth.auth_type !== "oauth") {
|
|
47901
|
+
throw new Error(`${PROVIDER_LABELS[slug]} does not use OAuth (auth_type=${auth.auth_type})`);
|
|
47902
|
+
}
|
|
47903
|
+
const clientId = resolveCopilotClientId();
|
|
47904
|
+
if (!clientId) {
|
|
47905
|
+
throw new Error(
|
|
47906
|
+
"GitHub Copilot login needs a GitHub OAuth App client ID. Set GITHUB_COPILOT_CLIENT_ID or llm.copilot_oauth_client_id in ~/.openjaw-agent/config.yaml."
|
|
47907
|
+
);
|
|
47908
|
+
}
|
|
47909
|
+
const enterpriseUrl = (() => {
|
|
47910
|
+
const raw = params["enterprise_url"];
|
|
47911
|
+
if (typeof raw === "string" && raw.trim()) {
|
|
47912
|
+
return raw.trim();
|
|
47913
|
+
}
|
|
47914
|
+
return agentConfig.llm.copilot_enterprise_url;
|
|
47915
|
+
})();
|
|
47916
|
+
const flow = await startCopilotDeviceFlow(clientId, enterpriseUrl);
|
|
47917
|
+
const flowId = randomUUID13();
|
|
47918
|
+
const controller = new AbortController();
|
|
47919
|
+
const timer = setTimeout(() => {
|
|
47920
|
+
cleanupOAuthFlow(flowId, true);
|
|
47921
|
+
}, OAUTH_FLOW_TTL_MS);
|
|
47922
|
+
if (typeof timer.unref === "function") {
|
|
47923
|
+
timer.unref();
|
|
47924
|
+
}
|
|
47925
|
+
oauthFlows.set(flowId, { controller, flow, slug, timer });
|
|
47926
|
+
return {
|
|
47927
|
+
flow_id: flowId,
|
|
47928
|
+
interval_seconds: flow.intervalSeconds,
|
|
47929
|
+
user_code: flow.userCode,
|
|
47930
|
+
verification_uri: flow.verificationUri
|
|
47931
|
+
};
|
|
47932
|
+
});
|
|
47933
|
+
bus.registerRpc("model.oauth_complete", async (params) => {
|
|
47934
|
+
const flowId = String(params["flow_id"] ?? "").trim();
|
|
47935
|
+
const entry = oauthFlows.get(flowId);
|
|
47936
|
+
if (!entry) {
|
|
47937
|
+
throw new Error("OAuth flow not found or already completed/expired");
|
|
47938
|
+
}
|
|
47939
|
+
try {
|
|
47940
|
+
await completeCopilotDeviceFlow(entry.flow, entry.controller.signal);
|
|
47941
|
+
} catch (err) {
|
|
47942
|
+
cleanupOAuthFlow(flowId, false);
|
|
47943
|
+
if (isOAuthAbortError(err) || entry.controller.signal.aborted) {
|
|
47944
|
+
return { aborted: true, slug: entry.slug };
|
|
47945
|
+
}
|
|
47946
|
+
throw err;
|
|
47947
|
+
}
|
|
47948
|
+
cleanupOAuthFlow(flowId, false);
|
|
47949
|
+
reconnectProviderContext(entry.slug);
|
|
47950
|
+
const live = await fetchLiveModels(entry.slug, agentConfig, agentLoop.model);
|
|
47951
|
+
return {
|
|
47952
|
+
provider: buildProviderOption(entry.slug, agentLoop.providerName, agentLoop.model, live.models, live.error),
|
|
47953
|
+
slug: entry.slug
|
|
47954
|
+
};
|
|
47955
|
+
});
|
|
47956
|
+
bus.registerRpc("model.oauth_cancel", (params) => {
|
|
47957
|
+
const flowId = String(params["flow_id"] ?? "").trim();
|
|
47958
|
+
const entry = oauthFlows.get(flowId);
|
|
47959
|
+
if (!entry) {
|
|
47960
|
+
return { cancelled: false, reason: "flow not found" };
|
|
47961
|
+
}
|
|
47962
|
+
cleanupOAuthFlow(flowId, true);
|
|
47963
|
+
return { cancelled: true, slug: entry.slug };
|
|
47964
|
+
});
|
|
47858
47965
|
bus.registerRpc("commands.catalog", () => {
|
|
47859
47966
|
const skillCount = toolRegistry.listTools().filter((t) => /^skill[:_-]/i.test(t.name)).length;
|
|
47860
47967
|
return buildCommandsCatalog({ skillCount });
|
|
@@ -48461,12 +48568,14 @@ ${helpMessage}` : field.label;
|
|
|
48461
48568
|
bus.registerRpc("delegation.status", () => ({ delegated: [], paused: false }));
|
|
48462
48569
|
bus.registerRpc("delegation.pause", (params) => ({ paused: Boolean(params.paused) }));
|
|
48463
48570
|
bus.registerRpc("subagent.interrupt", () => ({ ok: true }));
|
|
48571
|
+
syncMcpTools(mcpManager, toolRegistry);
|
|
48464
48572
|
bus.emitEvent({
|
|
48465
48573
|
payload: sessionInfoSnapshot(agentLoop, toolRegistry),
|
|
48466
48574
|
session_id: agentLoop.sessionId,
|
|
48467
48575
|
type: "session.info"
|
|
48468
48576
|
});
|
|
48469
48577
|
const onToolsChanged = /* @__PURE__ */ __name(() => {
|
|
48578
|
+
syncMcpTools(mcpManager, toolRegistry);
|
|
48470
48579
|
bus.emitEvent({
|
|
48471
48580
|
payload: sessionInfoSnapshot(agentLoop, toolRegistry),
|
|
48472
48581
|
session_id: agentLoop.sessionId,
|
|
@@ -48478,14 +48587,18 @@ ${helpMessage}` : field.label;
|
|
|
48478
48587
|
bridgeEmitter?.off("bridgeEvent", onBridgeEvent);
|
|
48479
48588
|
mcpManager.off("tools-changed", onToolsChanged);
|
|
48480
48589
|
pendingResponders.clear();
|
|
48590
|
+
for (const id of Array.from(oauthFlows.keys())) {
|
|
48591
|
+
cleanupOAuthFlow(id, true);
|
|
48592
|
+
}
|
|
48481
48593
|
};
|
|
48482
48594
|
}
|
|
48483
|
-
var PROVIDERS2, PROVIDER_LABELS, PROVIDER_AUTH, isProviderAuthenticated, buildProviderOption, fetchLiveModels, BRIDGE_SOURCES, isBridgeSource, inferBridgeSource, bridgeLabels, bridgeEventLabels, stripBridgeGlyph, firstLogLine, bridgeUser, formatBridgeText, runProcess, contentToText, sessionMessageToMarkdown, usageSnapshot, sessionInfoSnapshot;
|
|
48595
|
+
var PROVIDERS2, PROVIDER_LABELS, PROVIDER_AUTH, isProviderAuthenticated, buildProviderOption, fetchLiveModels, BRIDGE_SOURCES, isBridgeSource, inferBridgeSource, bridgeLabels, bridgeEventLabels, stripBridgeGlyph, firstLogLine, bridgeUser, formatBridgeText, runProcess, contentToText, sessionMessageToMarkdown, usageSnapshot, sessionInfoSnapshot, MCP_TOOL_PREFIX, MAX_TOTAL_TOOLS, syncMcpTools;
|
|
48484
48596
|
var init_rpcHandlers = __esm({
|
|
48485
48597
|
"src/rpcHandlers.ts"() {
|
|
48486
48598
|
"use strict";
|
|
48487
48599
|
init_connect();
|
|
48488
48600
|
init_config();
|
|
48601
|
+
init_copilot_auth();
|
|
48489
48602
|
init_context_manager();
|
|
48490
48603
|
init_eventBridge();
|
|
48491
48604
|
init_fork();
|
|
@@ -48708,6 +48821,23 @@ ${raw}`;
|
|
|
48708
48821
|
tools: { [agentLoop.providerName]: toolRegistry.listTools().map((t) => t.name) },
|
|
48709
48822
|
usage: usageSnapshot(agentLoop)
|
|
48710
48823
|
}), "sessionInfoSnapshot");
|
|
48824
|
+
MCP_TOOL_PREFIX = "mcp__";
|
|
48825
|
+
MAX_TOTAL_TOOLS = 200;
|
|
48826
|
+
syncMcpTools = /* @__PURE__ */ __name((mcpManager, toolRegistry) => {
|
|
48827
|
+
let removed = 0;
|
|
48828
|
+
for (const tool of toolRegistry.listTools()) {
|
|
48829
|
+
if (tool.name.startsWith(MCP_TOOL_PREFIX)) {
|
|
48830
|
+
if (toolRegistry.unregisterTool(tool.name)) removed++;
|
|
48831
|
+
}
|
|
48832
|
+
}
|
|
48833
|
+
const nonMcpCount = toolRegistry.listTools().length;
|
|
48834
|
+
const budget = Math.max(0, MAX_TOTAL_TOOLS - nonMcpCount);
|
|
48835
|
+
const mcpTools = mcpManager.getTools(budget);
|
|
48836
|
+
for (const tool of mcpTools) {
|
|
48837
|
+
toolRegistry.registerTool(tool);
|
|
48838
|
+
}
|
|
48839
|
+
return { added: mcpTools.length, removed };
|
|
48840
|
+
}, "syncMcpTools");
|
|
48711
48841
|
__name(registerRpcHandlers, "registerRpcHandlers");
|
|
48712
48842
|
}
|
|
48713
48843
|
});
|
|
@@ -56345,8 +56475,8 @@ var init_providers2 = __esm({
|
|
|
56345
56475
|
});
|
|
56346
56476
|
|
|
56347
56477
|
// src/components/modelPicker.tsx
|
|
56348
|
-
import { useEffect as useEffect17, useMemo as useMemo12, useState as useState19 } from "react";
|
|
56349
|
-
import { jsx as jsx25, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
56478
|
+
import { useEffect as useEffect17, useMemo as useMemo12, useRef as useRef17, useState as useState19 } from "react";
|
|
56479
|
+
import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
56350
56480
|
function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t }) {
|
|
56351
56481
|
const [providers, setProviders] = useState19([]);
|
|
56352
56482
|
const [currentModel, setCurrentModel] = useState19("");
|
|
@@ -56359,10 +56489,19 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56359
56489
|
const [keyInput, setKeyInput] = useState19("");
|
|
56360
56490
|
const [keySaving, setKeySaving] = useState19(false);
|
|
56361
56491
|
const [keyError, setKeyError] = useState19("");
|
|
56492
|
+
const [oauthStatus, setOauthStatus] = useState19("starting");
|
|
56493
|
+
const [oauthVerificationUri, setOauthVerificationUri] = useState19("");
|
|
56494
|
+
const [oauthUserCode, setOauthUserCode] = useState19("");
|
|
56495
|
+
const [oauthError, setOauthError] = useState19("");
|
|
56496
|
+
const oauthFlowIdRef = useRef17(null);
|
|
56497
|
+
const oauthProviderSlugRef = useRef17(null);
|
|
56498
|
+
const oauthAttemptRef = useRef17(0);
|
|
56499
|
+
const mountedRef = useRef17(true);
|
|
56362
56500
|
const { stdout } = useStdout();
|
|
56363
56501
|
const width = Math.max(MIN_WIDTH2, Math.min(MAX_WIDTH2, (stdout?.columns ?? 80) - 6));
|
|
56364
56502
|
useEffect17(() => {
|
|
56365
56503
|
gw.request("model.options", sessionId ? { session_id: sessionId } : {}).then((raw) => {
|
|
56504
|
+
if (!mountedRef.current) return;
|
|
56366
56505
|
const r = asRpcResult(raw);
|
|
56367
56506
|
if (!r) {
|
|
56368
56507
|
setErr("invalid response: model.options");
|
|
@@ -56383,6 +56522,7 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56383
56522
|
setErr("");
|
|
56384
56523
|
setLoading(false);
|
|
56385
56524
|
}).catch((e) => {
|
|
56525
|
+
if (!mountedRef.current) return;
|
|
56386
56526
|
setErr(rpcErrorMessage(e));
|
|
56387
56527
|
setLoading(false);
|
|
56388
56528
|
});
|
|
@@ -56390,7 +56530,121 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56390
56530
|
const provider = providers[providerIdx];
|
|
56391
56531
|
const models = provider?.models ?? [];
|
|
56392
56532
|
const names = useMemo12(() => providerDisplayNames(providers), [providers]);
|
|
56533
|
+
useEffect17(() => {
|
|
56534
|
+
mountedRef.current = true;
|
|
56535
|
+
return () => {
|
|
56536
|
+
mountedRef.current = false;
|
|
56537
|
+
const flowId = oauthFlowIdRef.current;
|
|
56538
|
+
if (flowId) {
|
|
56539
|
+
gw.request("model.oauth_cancel", { flow_id: flowId }).catch(() => {
|
|
56540
|
+
});
|
|
56541
|
+
oauthFlowIdRef.current = null;
|
|
56542
|
+
}
|
|
56543
|
+
};
|
|
56544
|
+
}, [gw]);
|
|
56545
|
+
const refreshProviders = /* @__PURE__ */ __name(() => gw.request("model.options", sessionId ? { session_id: sessionId } : {}).then((raw) => {
|
|
56546
|
+
if (!mountedRef.current) return;
|
|
56547
|
+
const r = asRpcResult(raw);
|
|
56548
|
+
if (!r) {
|
|
56549
|
+
return;
|
|
56550
|
+
}
|
|
56551
|
+
setProviders(r.providers ?? []);
|
|
56552
|
+
setCurrentModel(String(r.model ?? ""));
|
|
56553
|
+
}).catch(() => {
|
|
56554
|
+
}), "refreshProviders");
|
|
56555
|
+
const cancelActiveOAuth = /* @__PURE__ */ __name(() => {
|
|
56556
|
+
oauthAttemptRef.current += 1;
|
|
56557
|
+
const flowId = oauthFlowIdRef.current;
|
|
56558
|
+
if (!flowId) {
|
|
56559
|
+
return;
|
|
56560
|
+
}
|
|
56561
|
+
oauthFlowIdRef.current = null;
|
|
56562
|
+
gw.request("model.oauth_cancel", { flow_id: flowId }).catch(() => {
|
|
56563
|
+
});
|
|
56564
|
+
}, "cancelActiveOAuth");
|
|
56565
|
+
const startOAuthFlow = /* @__PURE__ */ __name((slug) => {
|
|
56566
|
+
cancelActiveOAuth();
|
|
56567
|
+
const attempt = ++oauthAttemptRef.current;
|
|
56568
|
+
oauthProviderSlugRef.current = slug;
|
|
56569
|
+
setStage("oauth");
|
|
56570
|
+
setOauthStatus("starting");
|
|
56571
|
+
setOauthVerificationUri("");
|
|
56572
|
+
setOauthUserCode("");
|
|
56573
|
+
setOauthError("");
|
|
56574
|
+
const isCurrent = /* @__PURE__ */ __name(() => mountedRef.current && oauthAttemptRef.current === attempt, "isCurrent");
|
|
56575
|
+
gw.request("model.oauth_start", {
|
|
56576
|
+
slug,
|
|
56577
|
+
...sessionId ? { session_id: sessionId } : {}
|
|
56578
|
+
}).then((raw) => {
|
|
56579
|
+
const r = asRpcResult(raw);
|
|
56580
|
+
if (!isCurrent()) {
|
|
56581
|
+
if (r?.flow_id) {
|
|
56582
|
+
gw.request("model.oauth_cancel", { flow_id: r.flow_id }).catch(() => {
|
|
56583
|
+
});
|
|
56584
|
+
}
|
|
56585
|
+
return;
|
|
56586
|
+
}
|
|
56587
|
+
if (!r?.flow_id) {
|
|
56588
|
+
setOauthStatus("error");
|
|
56589
|
+
setOauthError("invalid response from model.oauth_start");
|
|
56590
|
+
return;
|
|
56591
|
+
}
|
|
56592
|
+
oauthFlowIdRef.current = r.flow_id;
|
|
56593
|
+
setOauthVerificationUri(r.verification_uri);
|
|
56594
|
+
setOauthUserCode(r.user_code);
|
|
56595
|
+
setOauthStatus("waiting");
|
|
56596
|
+
gw.request("model.oauth_complete", {
|
|
56597
|
+
flow_id: r.flow_id,
|
|
56598
|
+
...sessionId ? { session_id: sessionId } : {}
|
|
56599
|
+
}).then((rawComplete) => {
|
|
56600
|
+
if (!isCurrent()) return;
|
|
56601
|
+
if (oauthFlowIdRef.current !== r.flow_id) return;
|
|
56602
|
+
oauthFlowIdRef.current = null;
|
|
56603
|
+
const rc = asRpcResult(rawComplete);
|
|
56604
|
+
if (!rc) {
|
|
56605
|
+
setOauthStatus("error");
|
|
56606
|
+
setOauthError("invalid response from model.oauth_complete");
|
|
56607
|
+
return;
|
|
56608
|
+
}
|
|
56609
|
+
if (rc.aborted) {
|
|
56610
|
+
setStage("provider");
|
|
56611
|
+
return;
|
|
56612
|
+
}
|
|
56613
|
+
if (rc.provider) {
|
|
56614
|
+
setProviders(
|
|
56615
|
+
(prev) => prev.map((p) => p.slug === rc.provider.slug ? rc.provider : p)
|
|
56616
|
+
);
|
|
56617
|
+
} else {
|
|
56618
|
+
refreshProviders();
|
|
56619
|
+
}
|
|
56620
|
+
if (mode === "connect") {
|
|
56621
|
+
onCancel();
|
|
56622
|
+
return;
|
|
56623
|
+
}
|
|
56624
|
+
setStage("model");
|
|
56625
|
+
setModelIdx(0);
|
|
56626
|
+
}).catch((e) => {
|
|
56627
|
+
if (!isCurrent()) return;
|
|
56628
|
+
if (oauthFlowIdRef.current !== r.flow_id) return;
|
|
56629
|
+
oauthFlowIdRef.current = null;
|
|
56630
|
+
setOauthStatus("error");
|
|
56631
|
+
setOauthError(rpcErrorMessage(e));
|
|
56632
|
+
});
|
|
56633
|
+
}).catch((e) => {
|
|
56634
|
+
if (!isCurrent()) return;
|
|
56635
|
+
setOauthStatus("error");
|
|
56636
|
+
setOauthError(rpcErrorMessage(e));
|
|
56637
|
+
});
|
|
56638
|
+
}, "startOAuthFlow");
|
|
56393
56639
|
const back = /* @__PURE__ */ __name(() => {
|
|
56640
|
+
if (stage === "oauth") {
|
|
56641
|
+
cancelActiveOAuth();
|
|
56642
|
+
setStage("provider");
|
|
56643
|
+
setOauthVerificationUri("");
|
|
56644
|
+
setOauthUserCode("");
|
|
56645
|
+
setOauthError("");
|
|
56646
|
+
return;
|
|
56647
|
+
}
|
|
56394
56648
|
if (stage === "model" || stage === "key" || stage === "disconnect") {
|
|
56395
56649
|
setStage("provider");
|
|
56396
56650
|
setModelIdx(0);
|
|
@@ -56401,8 +56655,30 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56401
56655
|
}
|
|
56402
56656
|
onCancel();
|
|
56403
56657
|
}, "back");
|
|
56404
|
-
|
|
56658
|
+
const close = /* @__PURE__ */ __name(() => {
|
|
56659
|
+
if (stage === "oauth") {
|
|
56660
|
+
cancelActiveOAuth();
|
|
56661
|
+
}
|
|
56662
|
+
onCancel();
|
|
56663
|
+
}, "close");
|
|
56664
|
+
useOverlayKeys({ onBack: back, onClose: close });
|
|
56405
56665
|
use_input_default((ch, key) => {
|
|
56666
|
+
if (stage === "oauth") {
|
|
56667
|
+
if (key.escape) {
|
|
56668
|
+
back();
|
|
56669
|
+
return;
|
|
56670
|
+
}
|
|
56671
|
+
if (key.return && oauthStatus === "error") {
|
|
56672
|
+
const slug = oauthProviderSlugRef.current;
|
|
56673
|
+
if (slug) {
|
|
56674
|
+
startOAuthFlow(slug);
|
|
56675
|
+
} else {
|
|
56676
|
+
back();
|
|
56677
|
+
}
|
|
56678
|
+
return;
|
|
56679
|
+
}
|
|
56680
|
+
return;
|
|
56681
|
+
}
|
|
56406
56682
|
if (stage === "key") {
|
|
56407
56683
|
if (keySaving) {
|
|
56408
56684
|
return;
|
|
@@ -56508,6 +56784,11 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56508
56784
|
setStage("key");
|
|
56509
56785
|
setKeyInput("");
|
|
56510
56786
|
setKeyError("");
|
|
56787
|
+
return;
|
|
56788
|
+
}
|
|
56789
|
+
if (provider.auth_type === "oauth") {
|
|
56790
|
+
startOAuthFlow(provider.slug);
|
|
56791
|
+
return;
|
|
56511
56792
|
}
|
|
56512
56793
|
return;
|
|
56513
56794
|
}
|
|
@@ -56554,6 +56835,41 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56554
56835
|
/* @__PURE__ */ jsx25(OverlayHint, { t, children: "Esc/q cancel" })
|
|
56555
56836
|
] });
|
|
56556
56837
|
}
|
|
56838
|
+
if (stage === "oauth") {
|
|
56839
|
+
const slug = oauthProviderSlugRef.current;
|
|
56840
|
+
const providerName = providers.find((p) => p.slug === slug)?.name ?? "GitHub Copilot";
|
|
56841
|
+
return /* @__PURE__ */ jsxs13(Box_default, { flexDirection: "column", width, children: [
|
|
56842
|
+
/* @__PURE__ */ jsxs13(Text9, { bold: true, color: t.color.accent, wrap: "truncate-end", children: [
|
|
56843
|
+
"Sign in to ",
|
|
56844
|
+
providerName
|
|
56845
|
+
] }),
|
|
56846
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56847
|
+
oauthStatus === "starting" ? /* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: "requesting device code\u2026" }) : oauthStatus === "error" ? /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
56848
|
+
/* @__PURE__ */ jsxs13(Text9, { color: t.color.label, wrap: "truncate-end", children: [
|
|
56849
|
+
"error: ",
|
|
56850
|
+
oauthError || "failed to start GitHub sign-in"
|
|
56851
|
+
] }),
|
|
56852
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56853
|
+
/* @__PURE__ */ jsx25(OverlayHint, { t, children: "Enter retry \xB7 Esc back" })
|
|
56854
|
+
] }) : /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
56855
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: "1. Open this URL in your browser:" }),
|
|
56856
|
+
/* @__PURE__ */ jsxs13(Text9, { bold: true, color: t.color.accent, wrap: "truncate-end", children: [
|
|
56857
|
+
" ",
|
|
56858
|
+
oauthVerificationUri
|
|
56859
|
+
] }),
|
|
56860
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56861
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: "2. Enter this code on the GitHub page:" }),
|
|
56862
|
+
/* @__PURE__ */ jsxs13(Text9, { bold: true, color: t.color.accent, wrap: "truncate-end", children: [
|
|
56863
|
+
" ",
|
|
56864
|
+
oauthUserCode
|
|
56865
|
+
] }),
|
|
56866
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56867
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: "waiting for authorization\u2026" }),
|
|
56868
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56869
|
+
/* @__PURE__ */ jsx25(OverlayHint, { t, children: "Esc cancel" })
|
|
56870
|
+
] })
|
|
56871
|
+
] });
|
|
56872
|
+
}
|
|
56557
56873
|
if (stage === "key" && provider) {
|
|
56558
56874
|
const masked = keyInput ? "\u2022".repeat(Math.min(keyInput.length, 40)) : "";
|
|
56559
56875
|
return /* @__PURE__ */ jsxs13(Box_default, { flexDirection: "column", width, children: [
|
|
@@ -57507,7 +57823,7 @@ var init_appOverlays = __esm({
|
|
|
57507
57823
|
|
|
57508
57824
|
// src/components/branding.tsx
|
|
57509
57825
|
import { useEffect as useEffect20, useState as useState24 } from "react";
|
|
57510
|
-
import { Fragment as
|
|
57826
|
+
import { Fragment as Fragment6, jsx as jsx30, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
57511
57827
|
function useColumns() {
|
|
57512
57828
|
const { stdout } = useStdout();
|
|
57513
57829
|
const [cols, setCols] = useState24(stdout?.columns ?? 80);
|
|
@@ -58948,7 +59264,7 @@ var init_syntax = __esm({
|
|
|
58948
59264
|
});
|
|
58949
59265
|
|
|
58950
59266
|
// src/components/markdown.tsx
|
|
58951
|
-
import { Fragment as
|
|
59267
|
+
import { Fragment as Fragment7, memo, useMemo as useMemo14 } from "react";
|
|
58952
59268
|
import { jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
58953
59269
|
function ResolvedLink({ fallbackLabel, t, url }) {
|
|
58954
59270
|
const fetched = useLinkTitle(url);
|
|
@@ -59480,7 +59796,7 @@ var init_markdown = __esm({
|
|
|
59480
59796
|
const cellWidth = /* @__PURE__ */ __name((raw) => stringWidth(stripInlineMarkup(raw)), "cellWidth");
|
|
59481
59797
|
const widths = rows[0].map((_, ci) => Math.max(...rows.map((r) => cellWidth(r[ci] ?? ""))));
|
|
59482
59798
|
const sep2 = widths.map((w) => "\u2500".repeat(Math.max(1, w))).join(" ");
|
|
59483
|
-
return /* @__PURE__ */ jsx34(Box_default, { flexDirection: "column", paddingLeft: 2, children: rows.map((row, ri) => /* @__PURE__ */ jsxs21(
|
|
59799
|
+
return /* @__PURE__ */ jsx34(Box_default, { flexDirection: "column", paddingLeft: 2, children: rows.map((row, ri) => /* @__PURE__ */ jsxs21(Fragment7, { children: [
|
|
59484
59800
|
/* @__PURE__ */ jsx34(Box_default, { children: widths.map((w, ci) => /* @__PURE__ */ jsxs21(Text9, { bold: ri === 0, color: ri === 0 ? t.color.accent : void 0, children: [
|
|
59485
59801
|
/* @__PURE__ */ jsx34(MdInline, { t, text: row[ci] ?? "" }),
|
|
59486
59802
|
" ".repeat(Math.max(0, w - cellWidth(row[ci] ?? ""))),
|
|
@@ -59521,7 +59837,7 @@ var init_markdown = __esm({
|
|
|
59521
59837
|
});
|
|
59522
59838
|
|
|
59523
59839
|
// src/components/streamingMarkdown.tsx
|
|
59524
|
-
import { memo as memo2, useRef as
|
|
59840
|
+
import { memo as memo2, useRef as useRef18 } from "react";
|
|
59525
59841
|
import { jsx as jsx35, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
59526
59842
|
var fenceOpenAt, findStableBoundary, StreamingMd;
|
|
59527
59843
|
var init_streamingMarkdown = __esm({
|
|
@@ -59584,7 +59900,7 @@ var init_streamingMarkdown = __esm({
|
|
|
59584
59900
|
return -1;
|
|
59585
59901
|
}, "findStableBoundary");
|
|
59586
59902
|
StreamingMd = memo2(/* @__PURE__ */ __name(function StreamingMd2({ compact, t, text }) {
|
|
59587
|
-
const stablePrefixRef =
|
|
59903
|
+
const stablePrefixRef = useRef18("");
|
|
59588
59904
|
if (!text.startsWith(stablePrefixRef.current)) {
|
|
59589
59905
|
stablePrefixRef.current = "";
|
|
59590
59906
|
}
|
|
@@ -59611,7 +59927,7 @@ var init_streamingMarkdown = __esm({
|
|
|
59611
59927
|
// src/components/thinking.tsx
|
|
59612
59928
|
import { memo as memo3, useEffect as useEffect23, useMemo as useMemo15, useState as useState26 } from "react";
|
|
59613
59929
|
import spinners from "unicode-animations";
|
|
59614
|
-
import { Fragment as
|
|
59930
|
+
import { Fragment as Fragment8, jsx as jsx36, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
59615
59931
|
import { createElement } from "react";
|
|
59616
59932
|
function TreeRow({
|
|
59617
59933
|
branch,
|
|
@@ -59870,7 +60186,7 @@ function SubagentAccordion({
|
|
|
59870
60186
|
{
|
|
59871
60187
|
branch: index === item.tools.length - 1 ? "last" : "mid",
|
|
59872
60188
|
color: t.color.text,
|
|
59873
|
-
content: /* @__PURE__ */ jsxs23(
|
|
60189
|
+
content: /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
59874
60190
|
/* @__PURE__ */ jsx36(Text9, { color: t.color.accent, children: "\u25CF " }),
|
|
59875
60191
|
line
|
|
59876
60192
|
] }),
|
|
@@ -60143,7 +60459,7 @@ var init_thinking = __esm({
|
|
|
60143
60459
|
color: t.color.muted,
|
|
60144
60460
|
dimColor: true,
|
|
60145
60461
|
key: `tr-${i}`,
|
|
60146
|
-
content: groups.length ? /* @__PURE__ */ jsxs23(
|
|
60462
|
+
content: groups.length ? /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60147
60463
|
/* @__PURE__ */ jsx36(Spinner3, { color: t.color.accent, variant: "think" }),
|
|
60148
60464
|
" ",
|
|
60149
60465
|
line
|
|
@@ -60160,7 +60476,7 @@ var init_thinking = __esm({
|
|
|
60160
60476
|
key: tool.id,
|
|
60161
60477
|
label,
|
|
60162
60478
|
details: [],
|
|
60163
|
-
content: /* @__PURE__ */ jsxs23(
|
|
60479
|
+
content: /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60164
60480
|
/* @__PURE__ */ jsx36(Spinner3, { color: t.color.accent, variant: "tool" }),
|
|
60165
60481
|
" ",
|
|
60166
60482
|
label,
|
|
@@ -60188,7 +60504,7 @@ var init_thinking = __esm({
|
|
|
60188
60504
|
const inlineDelegateKey = hasSubagents && delegateGroups.length === 1 ? delegateGroups[0].key : null;
|
|
60189
60505
|
const toolLabel = /* @__PURE__ */ __name((group) => {
|
|
60190
60506
|
const { duration, label } = splitToolDuration(String(group.content));
|
|
60191
|
-
return duration ? /* @__PURE__ */ jsxs23(
|
|
60507
|
+
return duration ? /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60192
60508
|
label,
|
|
60193
60509
|
/* @__PURE__ */ jsx36(Text9, { color: t.color.statusFg, dim: true, children: duration })
|
|
60194
60510
|
] }) : group.content;
|
|
@@ -60300,7 +60616,7 @@ var init_thinking = __esm({
|
|
|
60300
60616
|
{
|
|
60301
60617
|
branch,
|
|
60302
60618
|
color: group.color,
|
|
60303
|
-
content: /* @__PURE__ */ jsxs23(
|
|
60619
|
+
content: /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60304
60620
|
/* @__PURE__ */ jsx36(Text9, { color: t.color.accent, children: "\u25CF " }),
|
|
60305
60621
|
toolLabel(group)
|
|
60306
60622
|
] }),
|
|
@@ -60403,7 +60719,7 @@ var init_thinking = __esm({
|
|
|
60403
60719
|
{
|
|
60404
60720
|
branch: "last",
|
|
60405
60721
|
color: t.color.statusFg,
|
|
60406
|
-
content: /* @__PURE__ */ jsxs23(
|
|
60722
|
+
content: /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60407
60723
|
/* @__PURE__ */ jsx36(Text9, { color: t.color.accent, children: "\u03A3 " }),
|
|
60408
60724
|
totalTokensLabel
|
|
60409
60725
|
] }),
|
|
@@ -60706,7 +61022,7 @@ var init_queuedMessages = __esm({
|
|
|
60706
61022
|
// src/components/streamingAssistant.tsx
|
|
60707
61023
|
import { useStore as useStore8 } from "@nanostores/react";
|
|
60708
61024
|
import { memo as memo6 } from "react";
|
|
60709
|
-
import { Fragment as
|
|
61025
|
+
import { Fragment as Fragment9, jsx as jsx40, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
60710
61026
|
var groupedSegments, StreamingAssistant, LiveTodoPanel;
|
|
60711
61027
|
var init_streamingAssistant = __esm({
|
|
60712
61028
|
"src/components/streamingAssistant.tsx"() {
|
|
@@ -60734,7 +61050,7 @@ var init_streamingAssistant = __esm({
|
|
|
60734
61050
|
if (!progress.showProgressArea && !showStreamingArea && !activeTools.length) {
|
|
60735
61051
|
return null;
|
|
60736
61052
|
}
|
|
60737
|
-
return /* @__PURE__ */ jsxs27(
|
|
61053
|
+
return /* @__PURE__ */ jsxs27(Fragment9, { children: [
|
|
60738
61054
|
groupedSegments(streamSegments).map((msg, i) => /* @__PURE__ */ jsx40(
|
|
60739
61055
|
MessageLine,
|
|
60740
61056
|
{
|
|
@@ -60803,8 +61119,8 @@ var init_streamingAssistant = __esm({
|
|
|
60803
61119
|
|
|
60804
61120
|
// src/components/appLayout.tsx
|
|
60805
61121
|
import { useStore as useStore9 } from "@nanostores/react";
|
|
60806
|
-
import { Fragment as
|
|
60807
|
-
import { Fragment as
|
|
61122
|
+
import { Fragment as Fragment10, memo as memo7, useMemo as useMemo16, useRef as useRef19 } from "react";
|
|
61123
|
+
import { Fragment as Fragment11, jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
60808
61124
|
var PromptPrefix, TranscriptPane, ComposerPane, AgentsOverlayPane, StatusRulePane, AppLayout;
|
|
60809
61125
|
var init_appLayout = __esm({
|
|
60810
61126
|
"src/components/appLayout.tsx"() {
|
|
@@ -60860,7 +61176,7 @@ var init_appLayout = __esm({
|
|
|
60860
61176
|
() => transcript.historyItems.findIndex((m) => m.role === "user"),
|
|
60861
61177
|
[transcript.historyItems]
|
|
60862
61178
|
);
|
|
60863
|
-
return /* @__PURE__ */ jsxs28(
|
|
61179
|
+
return /* @__PURE__ */ jsxs28(Fragment11, { children: [
|
|
60864
61180
|
/* @__PURE__ */ jsx41(
|
|
60865
61181
|
ScrollBox_default,
|
|
60866
61182
|
{
|
|
@@ -60934,7 +61250,7 @@ var init_appLayout = __esm({
|
|
|
60934
61250
|
const promptBlank = " ".repeat(promptWidth);
|
|
60935
61251
|
const inputColumns = stableComposerColumns(composer.cols, promptWidth);
|
|
60936
61252
|
const inputHeight = inputVisualHeight(composer.input, inputColumns);
|
|
60937
|
-
const inputMouseRef =
|
|
61253
|
+
const inputMouseRef = useRef19(null);
|
|
60938
61254
|
const captureInputDrag = /* @__PURE__ */ __name((e) => {
|
|
60939
61255
|
if (e.button !== 0) {
|
|
60940
61256
|
return;
|
|
@@ -61004,7 +61320,7 @@ var init_appLayout = __esm({
|
|
|
61004
61320
|
}
|
|
61005
61321
|
),
|
|
61006
61322
|
composer.input === "?" && !composer.inputBuf.length && /* @__PURE__ */ jsx41(HelpHint, { t: ui.theme }),
|
|
61007
|
-
!isBlocked && /* @__PURE__ */ jsxs28(
|
|
61323
|
+
!isBlocked && /* @__PURE__ */ jsxs28(Fragment11, { children: [
|
|
61008
61324
|
composer.inputBuf.map((line, i) => /* @__PURE__ */ jsxs28(Box_default, { children: [
|
|
61009
61325
|
/* @__PURE__ */ jsx41(Box_default, { width: promptWidth, children: i === 0 ? /* @__PURE__ */ jsx41(PromptPrefix, { color: ui.theme.color.muted, promptText, width: promptWidth }) : /* @__PURE__ */ jsx41(Text9, { color: ui.theme.color.muted, children: promptBlank }) }),
|
|
61010
61326
|
/* @__PURE__ */ jsx41(Text9, { color: ui.theme.color.composeText, children: line || " " })
|
|
@@ -61110,11 +61426,11 @@ var init_appLayout = __esm({
|
|
|
61110
61426
|
}) {
|
|
61111
61427
|
const overlay = useStore9($overlayState);
|
|
61112
61428
|
const ui = useStore9($uiState);
|
|
61113
|
-
const Shell = INLINE_MODE ?
|
|
61429
|
+
const Shell = INLINE_MODE ? Fragment10 : AlternateScreen;
|
|
61114
61430
|
const shellProps = INLINE_MODE ? {} : { mouseTracking };
|
|
61115
61431
|
return /* @__PURE__ */ jsx41(Shell, { ...shellProps, children: /* @__PURE__ */ jsxs28(Box_default, { flexDirection: "column", flexGrow: 1, children: [
|
|
61116
61432
|
/* @__PURE__ */ jsx41(Box_default, { flexDirection: "row", flexGrow: 1, children: overlay.agents ? /* @__PURE__ */ jsx41(PerfPane, { id: "agents", children: /* @__PURE__ */ jsx41(AgentsOverlayPane, {}) }) : /* @__PURE__ */ jsx41(PerfPane, { id: "transcript", children: /* @__PURE__ */ jsx41(TranscriptPane, { actions, composer, progress, transcript }) }) }),
|
|
61117
|
-
!overlay.agents && /* @__PURE__ */ jsxs28(
|
|
61433
|
+
!overlay.agents && /* @__PURE__ */ jsxs28(Fragment11, { children: [
|
|
61118
61434
|
/* @__PURE__ */ jsx41(PerfPane, { id: "prompt", children: /* @__PURE__ */ jsx41(
|
|
61119
61435
|
PromptZone,
|
|
61120
61436
|
{
|