@charzhu/openjaw-agent 0.2.1 → 0.2.2
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 +315 -28
- 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 {
|
|
@@ -47309,6 +47322,19 @@ function registerRpcHandlers(options) {
|
|
|
47309
47322
|
let currentRun = null;
|
|
47310
47323
|
const pendingResponders = /* @__PURE__ */ new Map();
|
|
47311
47324
|
const promptCollector = createPromptCollector(bus, () => agentLoop.sessionId);
|
|
47325
|
+
const OAUTH_FLOW_TTL_MS = 15 * 60 * 1e3;
|
|
47326
|
+
const oauthFlows = /* @__PURE__ */ new Map();
|
|
47327
|
+
const cleanupOAuthFlow = /* @__PURE__ */ __name((flowId, abort) => {
|
|
47328
|
+
const entry = oauthFlows.get(flowId);
|
|
47329
|
+
if (!entry) {
|
|
47330
|
+
return;
|
|
47331
|
+
}
|
|
47332
|
+
clearTimeout(entry.timer);
|
|
47333
|
+
if (abort && !entry.controller.signal.aborted) {
|
|
47334
|
+
entry.controller.abort();
|
|
47335
|
+
}
|
|
47336
|
+
oauthFlows.delete(flowId);
|
|
47337
|
+
}, "cleanupOAuthFlow");
|
|
47312
47338
|
const onBridgeEvent = /* @__PURE__ */ __name((rawEvent) => {
|
|
47313
47339
|
const source = inferBridgeSource(rawEvent);
|
|
47314
47340
|
const user = bridgeUser(rawEvent, source);
|
|
@@ -47855,6 +47881,77 @@ ${helpMessage}` : field.label;
|
|
|
47855
47881
|
}
|
|
47856
47882
|
return { disconnected: true, slug };
|
|
47857
47883
|
});
|
|
47884
|
+
bus.registerRpc("model.oauth_start", async (params) => {
|
|
47885
|
+
const slug = String(params.slug ?? "").trim();
|
|
47886
|
+
if (!PROVIDERS2.includes(slug)) {
|
|
47887
|
+
throw new Error(`unknown provider: ${slug}`);
|
|
47888
|
+
}
|
|
47889
|
+
const auth = PROVIDER_AUTH[slug];
|
|
47890
|
+
if (auth.auth_type !== "oauth") {
|
|
47891
|
+
throw new Error(`${PROVIDER_LABELS[slug]} does not use OAuth (auth_type=${auth.auth_type})`);
|
|
47892
|
+
}
|
|
47893
|
+
const clientId = resolveCopilotClientId();
|
|
47894
|
+
if (!clientId) {
|
|
47895
|
+
throw new Error(
|
|
47896
|
+
"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."
|
|
47897
|
+
);
|
|
47898
|
+
}
|
|
47899
|
+
const enterpriseUrl = (() => {
|
|
47900
|
+
const raw = params["enterprise_url"];
|
|
47901
|
+
if (typeof raw === "string" && raw.trim()) {
|
|
47902
|
+
return raw.trim();
|
|
47903
|
+
}
|
|
47904
|
+
return agentConfig.llm.copilot_enterprise_url;
|
|
47905
|
+
})();
|
|
47906
|
+
const flow = await startCopilotDeviceFlow(clientId, enterpriseUrl);
|
|
47907
|
+
const flowId = randomUUID13();
|
|
47908
|
+
const controller = new AbortController();
|
|
47909
|
+
const timer = setTimeout(() => {
|
|
47910
|
+
cleanupOAuthFlow(flowId, true);
|
|
47911
|
+
}, OAUTH_FLOW_TTL_MS);
|
|
47912
|
+
if (typeof timer.unref === "function") {
|
|
47913
|
+
timer.unref();
|
|
47914
|
+
}
|
|
47915
|
+
oauthFlows.set(flowId, { controller, flow, slug, timer });
|
|
47916
|
+
return {
|
|
47917
|
+
flow_id: flowId,
|
|
47918
|
+
interval_seconds: flow.intervalSeconds,
|
|
47919
|
+
user_code: flow.userCode,
|
|
47920
|
+
verification_uri: flow.verificationUri
|
|
47921
|
+
};
|
|
47922
|
+
});
|
|
47923
|
+
bus.registerRpc("model.oauth_complete", async (params) => {
|
|
47924
|
+
const flowId = String(params["flow_id"] ?? "").trim();
|
|
47925
|
+
const entry = oauthFlows.get(flowId);
|
|
47926
|
+
if (!entry) {
|
|
47927
|
+
throw new Error("OAuth flow not found or already completed/expired");
|
|
47928
|
+
}
|
|
47929
|
+
try {
|
|
47930
|
+
await completeCopilotDeviceFlow(entry.flow, entry.controller.signal);
|
|
47931
|
+
} catch (err) {
|
|
47932
|
+
cleanupOAuthFlow(flowId, false);
|
|
47933
|
+
if (isOAuthAbortError(err) || entry.controller.signal.aborted) {
|
|
47934
|
+
return { aborted: true, slug: entry.slug };
|
|
47935
|
+
}
|
|
47936
|
+
throw err;
|
|
47937
|
+
}
|
|
47938
|
+
cleanupOAuthFlow(flowId, false);
|
|
47939
|
+
reconnectProviderContext(entry.slug);
|
|
47940
|
+
const live = await fetchLiveModels(entry.slug, agentConfig, agentLoop.model);
|
|
47941
|
+
return {
|
|
47942
|
+
provider: buildProviderOption(entry.slug, agentLoop.providerName, agentLoop.model, live.models, live.error),
|
|
47943
|
+
slug: entry.slug
|
|
47944
|
+
};
|
|
47945
|
+
});
|
|
47946
|
+
bus.registerRpc("model.oauth_cancel", (params) => {
|
|
47947
|
+
const flowId = String(params["flow_id"] ?? "").trim();
|
|
47948
|
+
const entry = oauthFlows.get(flowId);
|
|
47949
|
+
if (!entry) {
|
|
47950
|
+
return { cancelled: false, reason: "flow not found" };
|
|
47951
|
+
}
|
|
47952
|
+
cleanupOAuthFlow(flowId, true);
|
|
47953
|
+
return { cancelled: true, slug: entry.slug };
|
|
47954
|
+
});
|
|
47858
47955
|
bus.registerRpc("commands.catalog", () => {
|
|
47859
47956
|
const skillCount = toolRegistry.listTools().filter((t) => /^skill[:_-]/i.test(t.name)).length;
|
|
47860
47957
|
return buildCommandsCatalog({ skillCount });
|
|
@@ -48478,6 +48575,9 @@ ${helpMessage}` : field.label;
|
|
|
48478
48575
|
bridgeEmitter?.off("bridgeEvent", onBridgeEvent);
|
|
48479
48576
|
mcpManager.off("tools-changed", onToolsChanged);
|
|
48480
48577
|
pendingResponders.clear();
|
|
48578
|
+
for (const id of Array.from(oauthFlows.keys())) {
|
|
48579
|
+
cleanupOAuthFlow(id, true);
|
|
48580
|
+
}
|
|
48481
48581
|
};
|
|
48482
48582
|
}
|
|
48483
48583
|
var PROVIDERS2, PROVIDER_LABELS, PROVIDER_AUTH, isProviderAuthenticated, buildProviderOption, fetchLiveModels, BRIDGE_SOURCES, isBridgeSource, inferBridgeSource, bridgeLabels, bridgeEventLabels, stripBridgeGlyph, firstLogLine, bridgeUser, formatBridgeText, runProcess, contentToText, sessionMessageToMarkdown, usageSnapshot, sessionInfoSnapshot;
|
|
@@ -48486,6 +48586,7 @@ var init_rpcHandlers = __esm({
|
|
|
48486
48586
|
"use strict";
|
|
48487
48587
|
init_connect();
|
|
48488
48588
|
init_config();
|
|
48589
|
+
init_copilot_auth();
|
|
48489
48590
|
init_context_manager();
|
|
48490
48591
|
init_eventBridge();
|
|
48491
48592
|
init_fork();
|
|
@@ -56345,8 +56446,8 @@ var init_providers2 = __esm({
|
|
|
56345
56446
|
});
|
|
56346
56447
|
|
|
56347
56448
|
// 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";
|
|
56449
|
+
import { useEffect as useEffect17, useMemo as useMemo12, useRef as useRef17, useState as useState19 } from "react";
|
|
56450
|
+
import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
56350
56451
|
function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t }) {
|
|
56351
56452
|
const [providers, setProviders] = useState19([]);
|
|
56352
56453
|
const [currentModel, setCurrentModel] = useState19("");
|
|
@@ -56359,10 +56460,19 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56359
56460
|
const [keyInput, setKeyInput] = useState19("");
|
|
56360
56461
|
const [keySaving, setKeySaving] = useState19(false);
|
|
56361
56462
|
const [keyError, setKeyError] = useState19("");
|
|
56463
|
+
const [oauthStatus, setOauthStatus] = useState19("starting");
|
|
56464
|
+
const [oauthVerificationUri, setOauthVerificationUri] = useState19("");
|
|
56465
|
+
const [oauthUserCode, setOauthUserCode] = useState19("");
|
|
56466
|
+
const [oauthError, setOauthError] = useState19("");
|
|
56467
|
+
const oauthFlowIdRef = useRef17(null);
|
|
56468
|
+
const oauthProviderSlugRef = useRef17(null);
|
|
56469
|
+
const oauthAttemptRef = useRef17(0);
|
|
56470
|
+
const mountedRef = useRef17(true);
|
|
56362
56471
|
const { stdout } = useStdout();
|
|
56363
56472
|
const width = Math.max(MIN_WIDTH2, Math.min(MAX_WIDTH2, (stdout?.columns ?? 80) - 6));
|
|
56364
56473
|
useEffect17(() => {
|
|
56365
56474
|
gw.request("model.options", sessionId ? { session_id: sessionId } : {}).then((raw) => {
|
|
56475
|
+
if (!mountedRef.current) return;
|
|
56366
56476
|
const r = asRpcResult(raw);
|
|
56367
56477
|
if (!r) {
|
|
56368
56478
|
setErr("invalid response: model.options");
|
|
@@ -56383,6 +56493,7 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56383
56493
|
setErr("");
|
|
56384
56494
|
setLoading(false);
|
|
56385
56495
|
}).catch((e) => {
|
|
56496
|
+
if (!mountedRef.current) return;
|
|
56386
56497
|
setErr(rpcErrorMessage(e));
|
|
56387
56498
|
setLoading(false);
|
|
56388
56499
|
});
|
|
@@ -56390,7 +56501,121 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56390
56501
|
const provider = providers[providerIdx];
|
|
56391
56502
|
const models = provider?.models ?? [];
|
|
56392
56503
|
const names = useMemo12(() => providerDisplayNames(providers), [providers]);
|
|
56504
|
+
useEffect17(() => {
|
|
56505
|
+
mountedRef.current = true;
|
|
56506
|
+
return () => {
|
|
56507
|
+
mountedRef.current = false;
|
|
56508
|
+
const flowId = oauthFlowIdRef.current;
|
|
56509
|
+
if (flowId) {
|
|
56510
|
+
gw.request("model.oauth_cancel", { flow_id: flowId }).catch(() => {
|
|
56511
|
+
});
|
|
56512
|
+
oauthFlowIdRef.current = null;
|
|
56513
|
+
}
|
|
56514
|
+
};
|
|
56515
|
+
}, [gw]);
|
|
56516
|
+
const refreshProviders = /* @__PURE__ */ __name(() => gw.request("model.options", sessionId ? { session_id: sessionId } : {}).then((raw) => {
|
|
56517
|
+
if (!mountedRef.current) return;
|
|
56518
|
+
const r = asRpcResult(raw);
|
|
56519
|
+
if (!r) {
|
|
56520
|
+
return;
|
|
56521
|
+
}
|
|
56522
|
+
setProviders(r.providers ?? []);
|
|
56523
|
+
setCurrentModel(String(r.model ?? ""));
|
|
56524
|
+
}).catch(() => {
|
|
56525
|
+
}), "refreshProviders");
|
|
56526
|
+
const cancelActiveOAuth = /* @__PURE__ */ __name(() => {
|
|
56527
|
+
oauthAttemptRef.current += 1;
|
|
56528
|
+
const flowId = oauthFlowIdRef.current;
|
|
56529
|
+
if (!flowId) {
|
|
56530
|
+
return;
|
|
56531
|
+
}
|
|
56532
|
+
oauthFlowIdRef.current = null;
|
|
56533
|
+
gw.request("model.oauth_cancel", { flow_id: flowId }).catch(() => {
|
|
56534
|
+
});
|
|
56535
|
+
}, "cancelActiveOAuth");
|
|
56536
|
+
const startOAuthFlow = /* @__PURE__ */ __name((slug) => {
|
|
56537
|
+
cancelActiveOAuth();
|
|
56538
|
+
const attempt = ++oauthAttemptRef.current;
|
|
56539
|
+
oauthProviderSlugRef.current = slug;
|
|
56540
|
+
setStage("oauth");
|
|
56541
|
+
setOauthStatus("starting");
|
|
56542
|
+
setOauthVerificationUri("");
|
|
56543
|
+
setOauthUserCode("");
|
|
56544
|
+
setOauthError("");
|
|
56545
|
+
const isCurrent = /* @__PURE__ */ __name(() => mountedRef.current && oauthAttemptRef.current === attempt, "isCurrent");
|
|
56546
|
+
gw.request("model.oauth_start", {
|
|
56547
|
+
slug,
|
|
56548
|
+
...sessionId ? { session_id: sessionId } : {}
|
|
56549
|
+
}).then((raw) => {
|
|
56550
|
+
const r = asRpcResult(raw);
|
|
56551
|
+
if (!isCurrent()) {
|
|
56552
|
+
if (r?.flow_id) {
|
|
56553
|
+
gw.request("model.oauth_cancel", { flow_id: r.flow_id }).catch(() => {
|
|
56554
|
+
});
|
|
56555
|
+
}
|
|
56556
|
+
return;
|
|
56557
|
+
}
|
|
56558
|
+
if (!r?.flow_id) {
|
|
56559
|
+
setOauthStatus("error");
|
|
56560
|
+
setOauthError("invalid response from model.oauth_start");
|
|
56561
|
+
return;
|
|
56562
|
+
}
|
|
56563
|
+
oauthFlowIdRef.current = r.flow_id;
|
|
56564
|
+
setOauthVerificationUri(r.verification_uri);
|
|
56565
|
+
setOauthUserCode(r.user_code);
|
|
56566
|
+
setOauthStatus("waiting");
|
|
56567
|
+
gw.request("model.oauth_complete", {
|
|
56568
|
+
flow_id: r.flow_id,
|
|
56569
|
+
...sessionId ? { session_id: sessionId } : {}
|
|
56570
|
+
}).then((rawComplete) => {
|
|
56571
|
+
if (!isCurrent()) return;
|
|
56572
|
+
if (oauthFlowIdRef.current !== r.flow_id) return;
|
|
56573
|
+
oauthFlowIdRef.current = null;
|
|
56574
|
+
const rc = asRpcResult(rawComplete);
|
|
56575
|
+
if (!rc) {
|
|
56576
|
+
setOauthStatus("error");
|
|
56577
|
+
setOauthError("invalid response from model.oauth_complete");
|
|
56578
|
+
return;
|
|
56579
|
+
}
|
|
56580
|
+
if (rc.aborted) {
|
|
56581
|
+
setStage("provider");
|
|
56582
|
+
return;
|
|
56583
|
+
}
|
|
56584
|
+
if (rc.provider) {
|
|
56585
|
+
setProviders(
|
|
56586
|
+
(prev) => prev.map((p) => p.slug === rc.provider.slug ? rc.provider : p)
|
|
56587
|
+
);
|
|
56588
|
+
} else {
|
|
56589
|
+
refreshProviders();
|
|
56590
|
+
}
|
|
56591
|
+
if (mode === "connect") {
|
|
56592
|
+
onCancel();
|
|
56593
|
+
return;
|
|
56594
|
+
}
|
|
56595
|
+
setStage("model");
|
|
56596
|
+
setModelIdx(0);
|
|
56597
|
+
}).catch((e) => {
|
|
56598
|
+
if (!isCurrent()) return;
|
|
56599
|
+
if (oauthFlowIdRef.current !== r.flow_id) return;
|
|
56600
|
+
oauthFlowIdRef.current = null;
|
|
56601
|
+
setOauthStatus("error");
|
|
56602
|
+
setOauthError(rpcErrorMessage(e));
|
|
56603
|
+
});
|
|
56604
|
+
}).catch((e) => {
|
|
56605
|
+
if (!isCurrent()) return;
|
|
56606
|
+
setOauthStatus("error");
|
|
56607
|
+
setOauthError(rpcErrorMessage(e));
|
|
56608
|
+
});
|
|
56609
|
+
}, "startOAuthFlow");
|
|
56393
56610
|
const back = /* @__PURE__ */ __name(() => {
|
|
56611
|
+
if (stage === "oauth") {
|
|
56612
|
+
cancelActiveOAuth();
|
|
56613
|
+
setStage("provider");
|
|
56614
|
+
setOauthVerificationUri("");
|
|
56615
|
+
setOauthUserCode("");
|
|
56616
|
+
setOauthError("");
|
|
56617
|
+
return;
|
|
56618
|
+
}
|
|
56394
56619
|
if (stage === "model" || stage === "key" || stage === "disconnect") {
|
|
56395
56620
|
setStage("provider");
|
|
56396
56621
|
setModelIdx(0);
|
|
@@ -56401,8 +56626,30 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56401
56626
|
}
|
|
56402
56627
|
onCancel();
|
|
56403
56628
|
}, "back");
|
|
56404
|
-
|
|
56629
|
+
const close = /* @__PURE__ */ __name(() => {
|
|
56630
|
+
if (stage === "oauth") {
|
|
56631
|
+
cancelActiveOAuth();
|
|
56632
|
+
}
|
|
56633
|
+
onCancel();
|
|
56634
|
+
}, "close");
|
|
56635
|
+
useOverlayKeys({ onBack: back, onClose: close });
|
|
56405
56636
|
use_input_default((ch, key) => {
|
|
56637
|
+
if (stage === "oauth") {
|
|
56638
|
+
if (key.escape) {
|
|
56639
|
+
back();
|
|
56640
|
+
return;
|
|
56641
|
+
}
|
|
56642
|
+
if (key.return && oauthStatus === "error") {
|
|
56643
|
+
const slug = oauthProviderSlugRef.current;
|
|
56644
|
+
if (slug) {
|
|
56645
|
+
startOAuthFlow(slug);
|
|
56646
|
+
} else {
|
|
56647
|
+
back();
|
|
56648
|
+
}
|
|
56649
|
+
return;
|
|
56650
|
+
}
|
|
56651
|
+
return;
|
|
56652
|
+
}
|
|
56406
56653
|
if (stage === "key") {
|
|
56407
56654
|
if (keySaving) {
|
|
56408
56655
|
return;
|
|
@@ -56508,6 +56755,11 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56508
56755
|
setStage("key");
|
|
56509
56756
|
setKeyInput("");
|
|
56510
56757
|
setKeyError("");
|
|
56758
|
+
return;
|
|
56759
|
+
}
|
|
56760
|
+
if (provider.auth_type === "oauth") {
|
|
56761
|
+
startOAuthFlow(provider.slug);
|
|
56762
|
+
return;
|
|
56511
56763
|
}
|
|
56512
56764
|
return;
|
|
56513
56765
|
}
|
|
@@ -56554,6 +56806,41 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56554
56806
|
/* @__PURE__ */ jsx25(OverlayHint, { t, children: "Esc/q cancel" })
|
|
56555
56807
|
] });
|
|
56556
56808
|
}
|
|
56809
|
+
if (stage === "oauth") {
|
|
56810
|
+
const slug = oauthProviderSlugRef.current;
|
|
56811
|
+
const providerName = providers.find((p) => p.slug === slug)?.name ?? "GitHub Copilot";
|
|
56812
|
+
return /* @__PURE__ */ jsxs13(Box_default, { flexDirection: "column", width, children: [
|
|
56813
|
+
/* @__PURE__ */ jsxs13(Text9, { bold: true, color: t.color.accent, wrap: "truncate-end", children: [
|
|
56814
|
+
"Sign in to ",
|
|
56815
|
+
providerName
|
|
56816
|
+
] }),
|
|
56817
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56818
|
+
oauthStatus === "starting" ? /* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: "requesting device code\u2026" }) : oauthStatus === "error" ? /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
56819
|
+
/* @__PURE__ */ jsxs13(Text9, { color: t.color.label, wrap: "truncate-end", children: [
|
|
56820
|
+
"error: ",
|
|
56821
|
+
oauthError || "failed to start GitHub sign-in"
|
|
56822
|
+
] }),
|
|
56823
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56824
|
+
/* @__PURE__ */ jsx25(OverlayHint, { t, children: "Enter retry \xB7 Esc back" })
|
|
56825
|
+
] }) : /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
56826
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: "1. Open this URL in your browser:" }),
|
|
56827
|
+
/* @__PURE__ */ jsxs13(Text9, { bold: true, color: t.color.accent, wrap: "truncate-end", children: [
|
|
56828
|
+
" ",
|
|
56829
|
+
oauthVerificationUri
|
|
56830
|
+
] }),
|
|
56831
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56832
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: "2. Enter this code on the GitHub page:" }),
|
|
56833
|
+
/* @__PURE__ */ jsxs13(Text9, { bold: true, color: t.color.accent, wrap: "truncate-end", children: [
|
|
56834
|
+
" ",
|
|
56835
|
+
oauthUserCode
|
|
56836
|
+
] }),
|
|
56837
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56838
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: "waiting for authorization\u2026" }),
|
|
56839
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56840
|
+
/* @__PURE__ */ jsx25(OverlayHint, { t, children: "Esc cancel" })
|
|
56841
|
+
] })
|
|
56842
|
+
] });
|
|
56843
|
+
}
|
|
56557
56844
|
if (stage === "key" && provider) {
|
|
56558
56845
|
const masked = keyInput ? "\u2022".repeat(Math.min(keyInput.length, 40)) : "";
|
|
56559
56846
|
return /* @__PURE__ */ jsxs13(Box_default, { flexDirection: "column", width, children: [
|
|
@@ -57507,7 +57794,7 @@ var init_appOverlays = __esm({
|
|
|
57507
57794
|
|
|
57508
57795
|
// src/components/branding.tsx
|
|
57509
57796
|
import { useEffect as useEffect20, useState as useState24 } from "react";
|
|
57510
|
-
import { Fragment as
|
|
57797
|
+
import { Fragment as Fragment6, jsx as jsx30, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
57511
57798
|
function useColumns() {
|
|
57512
57799
|
const { stdout } = useStdout();
|
|
57513
57800
|
const [cols, setCols] = useState24(stdout?.columns ?? 80);
|
|
@@ -58948,7 +59235,7 @@ var init_syntax = __esm({
|
|
|
58948
59235
|
});
|
|
58949
59236
|
|
|
58950
59237
|
// src/components/markdown.tsx
|
|
58951
|
-
import { Fragment as
|
|
59238
|
+
import { Fragment as Fragment7, memo, useMemo as useMemo14 } from "react";
|
|
58952
59239
|
import { jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
58953
59240
|
function ResolvedLink({ fallbackLabel, t, url }) {
|
|
58954
59241
|
const fetched = useLinkTitle(url);
|
|
@@ -59480,7 +59767,7 @@ var init_markdown = __esm({
|
|
|
59480
59767
|
const cellWidth = /* @__PURE__ */ __name((raw) => stringWidth(stripInlineMarkup(raw)), "cellWidth");
|
|
59481
59768
|
const widths = rows[0].map((_, ci) => Math.max(...rows.map((r) => cellWidth(r[ci] ?? ""))));
|
|
59482
59769
|
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(
|
|
59770
|
+
return /* @__PURE__ */ jsx34(Box_default, { flexDirection: "column", paddingLeft: 2, children: rows.map((row, ri) => /* @__PURE__ */ jsxs21(Fragment7, { children: [
|
|
59484
59771
|
/* @__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
59772
|
/* @__PURE__ */ jsx34(MdInline, { t, text: row[ci] ?? "" }),
|
|
59486
59773
|
" ".repeat(Math.max(0, w - cellWidth(row[ci] ?? ""))),
|
|
@@ -59521,7 +59808,7 @@ var init_markdown = __esm({
|
|
|
59521
59808
|
});
|
|
59522
59809
|
|
|
59523
59810
|
// src/components/streamingMarkdown.tsx
|
|
59524
|
-
import { memo as memo2, useRef as
|
|
59811
|
+
import { memo as memo2, useRef as useRef18 } from "react";
|
|
59525
59812
|
import { jsx as jsx35, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
59526
59813
|
var fenceOpenAt, findStableBoundary, StreamingMd;
|
|
59527
59814
|
var init_streamingMarkdown = __esm({
|
|
@@ -59584,7 +59871,7 @@ var init_streamingMarkdown = __esm({
|
|
|
59584
59871
|
return -1;
|
|
59585
59872
|
}, "findStableBoundary");
|
|
59586
59873
|
StreamingMd = memo2(/* @__PURE__ */ __name(function StreamingMd2({ compact, t, text }) {
|
|
59587
|
-
const stablePrefixRef =
|
|
59874
|
+
const stablePrefixRef = useRef18("");
|
|
59588
59875
|
if (!text.startsWith(stablePrefixRef.current)) {
|
|
59589
59876
|
stablePrefixRef.current = "";
|
|
59590
59877
|
}
|
|
@@ -59611,7 +59898,7 @@ var init_streamingMarkdown = __esm({
|
|
|
59611
59898
|
// src/components/thinking.tsx
|
|
59612
59899
|
import { memo as memo3, useEffect as useEffect23, useMemo as useMemo15, useState as useState26 } from "react";
|
|
59613
59900
|
import spinners from "unicode-animations";
|
|
59614
|
-
import { Fragment as
|
|
59901
|
+
import { Fragment as Fragment8, jsx as jsx36, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
59615
59902
|
import { createElement } from "react";
|
|
59616
59903
|
function TreeRow({
|
|
59617
59904
|
branch,
|
|
@@ -59870,7 +60157,7 @@ function SubagentAccordion({
|
|
|
59870
60157
|
{
|
|
59871
60158
|
branch: index === item.tools.length - 1 ? "last" : "mid",
|
|
59872
60159
|
color: t.color.text,
|
|
59873
|
-
content: /* @__PURE__ */ jsxs23(
|
|
60160
|
+
content: /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
59874
60161
|
/* @__PURE__ */ jsx36(Text9, { color: t.color.accent, children: "\u25CF " }),
|
|
59875
60162
|
line
|
|
59876
60163
|
] }),
|
|
@@ -60143,7 +60430,7 @@ var init_thinking = __esm({
|
|
|
60143
60430
|
color: t.color.muted,
|
|
60144
60431
|
dimColor: true,
|
|
60145
60432
|
key: `tr-${i}`,
|
|
60146
|
-
content: groups.length ? /* @__PURE__ */ jsxs23(
|
|
60433
|
+
content: groups.length ? /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60147
60434
|
/* @__PURE__ */ jsx36(Spinner3, { color: t.color.accent, variant: "think" }),
|
|
60148
60435
|
" ",
|
|
60149
60436
|
line
|
|
@@ -60160,7 +60447,7 @@ var init_thinking = __esm({
|
|
|
60160
60447
|
key: tool.id,
|
|
60161
60448
|
label,
|
|
60162
60449
|
details: [],
|
|
60163
|
-
content: /* @__PURE__ */ jsxs23(
|
|
60450
|
+
content: /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60164
60451
|
/* @__PURE__ */ jsx36(Spinner3, { color: t.color.accent, variant: "tool" }),
|
|
60165
60452
|
" ",
|
|
60166
60453
|
label,
|
|
@@ -60188,7 +60475,7 @@ var init_thinking = __esm({
|
|
|
60188
60475
|
const inlineDelegateKey = hasSubagents && delegateGroups.length === 1 ? delegateGroups[0].key : null;
|
|
60189
60476
|
const toolLabel = /* @__PURE__ */ __name((group) => {
|
|
60190
60477
|
const { duration, label } = splitToolDuration(String(group.content));
|
|
60191
|
-
return duration ? /* @__PURE__ */ jsxs23(
|
|
60478
|
+
return duration ? /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60192
60479
|
label,
|
|
60193
60480
|
/* @__PURE__ */ jsx36(Text9, { color: t.color.statusFg, dim: true, children: duration })
|
|
60194
60481
|
] }) : group.content;
|
|
@@ -60300,7 +60587,7 @@ var init_thinking = __esm({
|
|
|
60300
60587
|
{
|
|
60301
60588
|
branch,
|
|
60302
60589
|
color: group.color,
|
|
60303
|
-
content: /* @__PURE__ */ jsxs23(
|
|
60590
|
+
content: /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60304
60591
|
/* @__PURE__ */ jsx36(Text9, { color: t.color.accent, children: "\u25CF " }),
|
|
60305
60592
|
toolLabel(group)
|
|
60306
60593
|
] }),
|
|
@@ -60403,7 +60690,7 @@ var init_thinking = __esm({
|
|
|
60403
60690
|
{
|
|
60404
60691
|
branch: "last",
|
|
60405
60692
|
color: t.color.statusFg,
|
|
60406
|
-
content: /* @__PURE__ */ jsxs23(
|
|
60693
|
+
content: /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60407
60694
|
/* @__PURE__ */ jsx36(Text9, { color: t.color.accent, children: "\u03A3 " }),
|
|
60408
60695
|
totalTokensLabel
|
|
60409
60696
|
] }),
|
|
@@ -60706,7 +60993,7 @@ var init_queuedMessages = __esm({
|
|
|
60706
60993
|
// src/components/streamingAssistant.tsx
|
|
60707
60994
|
import { useStore as useStore8 } from "@nanostores/react";
|
|
60708
60995
|
import { memo as memo6 } from "react";
|
|
60709
|
-
import { Fragment as
|
|
60996
|
+
import { Fragment as Fragment9, jsx as jsx40, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
60710
60997
|
var groupedSegments, StreamingAssistant, LiveTodoPanel;
|
|
60711
60998
|
var init_streamingAssistant = __esm({
|
|
60712
60999
|
"src/components/streamingAssistant.tsx"() {
|
|
@@ -60734,7 +61021,7 @@ var init_streamingAssistant = __esm({
|
|
|
60734
61021
|
if (!progress.showProgressArea && !showStreamingArea && !activeTools.length) {
|
|
60735
61022
|
return null;
|
|
60736
61023
|
}
|
|
60737
|
-
return /* @__PURE__ */ jsxs27(
|
|
61024
|
+
return /* @__PURE__ */ jsxs27(Fragment9, { children: [
|
|
60738
61025
|
groupedSegments(streamSegments).map((msg, i) => /* @__PURE__ */ jsx40(
|
|
60739
61026
|
MessageLine,
|
|
60740
61027
|
{
|
|
@@ -60803,8 +61090,8 @@ var init_streamingAssistant = __esm({
|
|
|
60803
61090
|
|
|
60804
61091
|
// src/components/appLayout.tsx
|
|
60805
61092
|
import { useStore as useStore9 } from "@nanostores/react";
|
|
60806
|
-
import { Fragment as
|
|
60807
|
-
import { Fragment as
|
|
61093
|
+
import { Fragment as Fragment10, memo as memo7, useMemo as useMemo16, useRef as useRef19 } from "react";
|
|
61094
|
+
import { Fragment as Fragment11, jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
60808
61095
|
var PromptPrefix, TranscriptPane, ComposerPane, AgentsOverlayPane, StatusRulePane, AppLayout;
|
|
60809
61096
|
var init_appLayout = __esm({
|
|
60810
61097
|
"src/components/appLayout.tsx"() {
|
|
@@ -60860,7 +61147,7 @@ var init_appLayout = __esm({
|
|
|
60860
61147
|
() => transcript.historyItems.findIndex((m) => m.role === "user"),
|
|
60861
61148
|
[transcript.historyItems]
|
|
60862
61149
|
);
|
|
60863
|
-
return /* @__PURE__ */ jsxs28(
|
|
61150
|
+
return /* @__PURE__ */ jsxs28(Fragment11, { children: [
|
|
60864
61151
|
/* @__PURE__ */ jsx41(
|
|
60865
61152
|
ScrollBox_default,
|
|
60866
61153
|
{
|
|
@@ -60934,7 +61221,7 @@ var init_appLayout = __esm({
|
|
|
60934
61221
|
const promptBlank = " ".repeat(promptWidth);
|
|
60935
61222
|
const inputColumns = stableComposerColumns(composer.cols, promptWidth);
|
|
60936
61223
|
const inputHeight = inputVisualHeight(composer.input, inputColumns);
|
|
60937
|
-
const inputMouseRef =
|
|
61224
|
+
const inputMouseRef = useRef19(null);
|
|
60938
61225
|
const captureInputDrag = /* @__PURE__ */ __name((e) => {
|
|
60939
61226
|
if (e.button !== 0) {
|
|
60940
61227
|
return;
|
|
@@ -61004,7 +61291,7 @@ var init_appLayout = __esm({
|
|
|
61004
61291
|
}
|
|
61005
61292
|
),
|
|
61006
61293
|
composer.input === "?" && !composer.inputBuf.length && /* @__PURE__ */ jsx41(HelpHint, { t: ui.theme }),
|
|
61007
|
-
!isBlocked && /* @__PURE__ */ jsxs28(
|
|
61294
|
+
!isBlocked && /* @__PURE__ */ jsxs28(Fragment11, { children: [
|
|
61008
61295
|
composer.inputBuf.map((line, i) => /* @__PURE__ */ jsxs28(Box_default, { children: [
|
|
61009
61296
|
/* @__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
61297
|
/* @__PURE__ */ jsx41(Text9, { color: ui.theme.color.composeText, children: line || " " })
|
|
@@ -61110,11 +61397,11 @@ var init_appLayout = __esm({
|
|
|
61110
61397
|
}) {
|
|
61111
61398
|
const overlay = useStore9($overlayState);
|
|
61112
61399
|
const ui = useStore9($uiState);
|
|
61113
|
-
const Shell = INLINE_MODE ?
|
|
61400
|
+
const Shell = INLINE_MODE ? Fragment10 : AlternateScreen;
|
|
61114
61401
|
const shellProps = INLINE_MODE ? {} : { mouseTracking };
|
|
61115
61402
|
return /* @__PURE__ */ jsx41(Shell, { ...shellProps, children: /* @__PURE__ */ jsxs28(Box_default, { flexDirection: "column", flexGrow: 1, children: [
|
|
61116
61403
|
/* @__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(
|
|
61404
|
+
!overlay.agents && /* @__PURE__ */ jsxs28(Fragment11, { children: [
|
|
61118
61405
|
/* @__PURE__ */ jsx41(PerfPane, { id: "prompt", children: /* @__PURE__ */ jsx41(
|
|
61119
61406
|
PromptZone,
|
|
61120
61407
|
{
|