zidane 5.5.4 → 5.6.0
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 +7 -1
- package/dist/{agent-CMAklak7.d.ts → agent-B26FuGew.d.ts} +90 -2
- package/dist/agent-B26FuGew.d.ts.map +1 -0
- package/dist/chat.d.ts +133 -22
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +3 -3
- package/dist/{errors-C5VSakmT.js → errors-DdZXnyXE.js} +38 -2
- package/dist/errors-DdZXnyXE.js.map +1 -0
- package/dist/{index-CF5QwBiz.d.ts → index-CE7z_11T.d.ts} +2 -2
- package/dist/{index-CF5QwBiz.d.ts.map → index-CE7z_11T.d.ts.map} +1 -1
- package/dist/{index-kroGomhj.d.ts → index-CROWxXo9.d.ts} +23 -2
- package/dist/index-CROWxXo9.d.ts.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +10 -10
- package/dist/{interpolate-Cvjy8gpk.js → interpolate-j5V-wcAQ.js} +2 -2
- package/dist/{interpolate-Cvjy8gpk.js.map → interpolate-j5V-wcAQ.js.map} +1 -1
- package/dist/{login-B_kfoGMP.js → login-D5lQWoFx.js} +3 -3
- package/dist/{login-B_kfoGMP.js.map → login-D5lQWoFx.js.map} +1 -1
- package/dist/{mcp-BE43Viwi.js → mcp-ngMS0S6N.js} +2 -2
- package/dist/{mcp-BE43Viwi.js.map → mcp-ngMS0S6N.js.map} +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/{messages-BBWakTN6.js → messages-B5k4DAXy.js} +2 -2
- package/dist/{messages-BBWakTN6.js.map → messages-B5k4DAXy.js.map} +1 -1
- package/dist/{presets-BDvBZuYI.js → presets-BDCthpyD.js} +2 -2
- package/dist/{presets-BDvBZuYI.js.map → presets-BDCthpyD.js.map} +1 -1
- package/dist/presets.d.ts +2 -2
- package/dist/presets.js +1 -1
- package/dist/{providers-CsUyN_FJ.js → providers-CaJE2ToS.js} +3 -3
- package/dist/{providers-CsUyN_FJ.js.map → providers-CaJE2ToS.js.map} +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +2 -2
- package/dist/restate.d.ts +1 -1
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session/sqlite.d.ts.map +1 -1
- package/dist/session/sqlite.js +226 -51
- package/dist/session/sqlite.js.map +1 -1
- package/dist/{session-DzfRacU_.js → session-BoEW_wCR.js} +2 -2
- package/dist/{session-DzfRacU_.js.map → session-BoEW_wCR.js.map} +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/session.js +2 -2
- package/dist/skills.d.ts +2 -2
- package/dist/skills.js +1 -1
- package/dist/{tools-Bbd0Ivwn.js → tools-Co3VYhgM.js} +154 -15
- package/dist/tools-Co3VYhgM.js.map +1 -0
- package/dist/tools.d.ts +2 -2
- package/dist/tools.js +1 -1
- package/dist/{transcript-anchors-C79AszkC.d.ts → transcript-anchors-CTTeQJzy.d.ts} +12 -4
- package/dist/{transcript-anchors-C79AszkC.d.ts.map → transcript-anchors-CTTeQJzy.d.ts.map} +1 -1
- package/dist/tui.d.ts +2 -2
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +432 -83
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-CGf7wWF0.js → turn-operations-fhinWY4m.js} +134 -18
- package/dist/turn-operations-fhinWY4m.js.map +1 -0
- package/dist/types-oKPBdCmL.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.js +2 -2
- package/docs/ARCHITECTURE.md +5 -2
- package/docs/CHAT.md +10 -3
- package/docs/RESTATE.md +190 -0
- package/docs/SKILL.md +27 -2
- package/docs/TUI.md +3 -3
- package/package.json +1 -1
- package/dist/agent-CMAklak7.d.ts.map +0 -1
- package/dist/errors-C5VSakmT.js.map +0 -1
- package/dist/index-kroGomhj.d.ts.map +0 -1
- package/dist/tools-Bbd0Ivwn.js.map +0 -1
- package/dist/turn-operations-CGf7wWF0.js.map +0 -1
package/dist/tui.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
import { A as resolvePersistDir, B as formatTaskStatus, H as previewLine, I as ageString, L as compactPath, O as cleanupPersistedSession, R as fmtTokens, U as shortId, V as formatTaskSummary, j as resolveTasksDir, p as createAgent, z as formatDuration } from "./tools-
|
|
3
|
-
import {
|
|
4
|
-
import { s as McpOAuthProvider, t as connectMcpServers } from "./mcp-
|
|
5
|
-
import { C as summaryToTurn, a as selectFilesFromSession, r as buildPostCompactAttachments, s as compactConversation, t as loginMcpServer } from "./login-
|
|
1
|
+
import { $n as blendHsl, $t as lastContextSizeFromTurns, A as getSafelist, An as summarizeOutcomes, Ar as getContextWindow, B as oauthUsesManualCodePaste, Bt as DiscoveryProvider, Cn as buildEditOutcomesAnnotation, Ct as useEnabledToggleSet, D as useSafeModeQueue, Dn as resolveApprovalForPayload, Dt as SettingsProvider, E as useSafeModeActions, En as parseEditOutcomesFromResult, Et as SETTINGS_TOGGLES, F as suggestSafelistEntry, Fn as ensureKeybindingsFile, G as indexOfEntry, Gt as resolveConfig, H as supportsOAuth, Ht as useDiscoveryOptional, Ir as piIdOf, J as discoverProjectMcps, Jt as deriveSessionTitle, K as buildMcpServers, Kn as createFilesCompletionProvider, Kt as EDIT_TOOL_NAMES, L as splitPromptSegments, Ln as matchesBinding, Mr as modelSupportsReasoning, Mt as resolveChipColor, Nt as resolveTheme, On as rewriteMultiEditHeader, Ot as clampFps, Qn as useCompletion, Qt as isVisible, R as formatPathForCwd, Sr as setProviderCredential, St as listProjectFiles, T as SafeModeProvider, Tn as mergeApprovalAndBodyOutcomes, Tt as SETTINGS_CHOICES, U as buildModelCatalog, Un as createSkillsCompletionProvider, Ur as accentColor, Ut as ConfigProvider, V as runOAuthLogin, Vt as useDiscovery, W as filterModelCatalog, Wn as uniqueSkillNamesFromReferences, Wt as useConfig, Xt as isEditErrorResult, Yr as TODO_STATUS_GLYPHS, Yt as eventsFromTurns, Z as createFileMcpCredentialStore, Zt as isTurnHighlighted, _ as turnContextSize, _i as buildPlanSystem, _n as extractEditPayload, _t as clipHintsToWidth, a as computeTurnAnchors, ai as useActiveTodos, an as stripSpawnTokensLine, ar as useUpdateCheck, at as splitMarkdownCodeBlocks, b as defaultSkillScanPaths, c as formatToolCall, cn as toolCallPreview, d as useSelectStyle, dn as updateToolEventOutcomes, en as listSessionMeta, er as buildLinearRamp, et as McpAuthProvider, f as useSurfaces, ft as makeRequestInteraction, g as finalizeStreamingMarkdownForOwner, gi as buildBuildSystem, gr as detectAuth, gt as useInteractionsQueue, h as finalizeStreamingMarkdown, hr as shouldAutoCompact, ht as useInteractionsActions, i as turnAsText, in as selectableTurnIds, ir as buildUpdateHint, j as isOnSafelist, jn as findGitRoot, k as addToSafelist, kn as stripEditOutcomesAnnotation, kt as useSettings, l as ThemeProvider, ln as toolResultText, lt as buildResumedToolResultsTurn, m as useTheme, mn as buildUnifiedDiff, mr as AUTO_COMPACT_MIN_GROWTH_FRACTION, n as deleteTurnSafely, nn as marginTopFor, nt as useMcpAuthState, o as TOOL_DISPLAY, on as sumRunCosts, pn as buildContextualDiff, pt as pendingInteractionsFromTurns, r as truncateTurnsAt, rr as bootTick, rt as getMcpAuthStatus, s as displayNameFor, st as InteractionsProvider, tr as tryOpenBrowser, tt as useMcpAuthDispatch, u as useColors, un as turnSelectionOwnership, ut as createInteractionTools, v as useStreamBuffer, vn as filetypeFromPath, vt as hintsLength, w as writeSessionExport, wt as DEFAULT_SETTINGS, x as discoverProjectSkills, xn as summarizeEditPayload, xt as generateSessionTitle, y as buildSkillsConfig, yn as previewEditPayload, yt as truncateTrailing, z as fetchOAuthRedirect, zt as createDiscoverySlot } from "./turn-operations-fhinWY4m.js";
|
|
2
|
+
import { A as resolvePersistDir, B as formatTaskStatus, H as previewLine, I as ageString, L as compactPath, O as cleanupPersistedSession, R as fmtTokens, U as shortId, V as formatTaskSummary, j as resolveTasksDir, p as createAgent, z as formatDuration } from "./tools-Co3VYhgM.js";
|
|
3
|
+
import { c as errorMessage } from "./errors-DdZXnyXE.js";
|
|
4
|
+
import { s as McpOAuthProvider, t as connectMcpServers } from "./mcp-ngMS0S6N.js";
|
|
5
|
+
import { C as summaryToTurn, a as selectFilesFromSession, r as buildPostCompactAttachments, s as compactConversation, t as loginMcpServer } from "./login-D5lQWoFx.js";
|
|
6
6
|
import { n as formatTokenUsage } from "./stats-Lc3zL3RM.js";
|
|
7
|
-
import { n as loadSession, t as createSession } from "./session-
|
|
7
|
+
import { n as loadSession, t as createSession } from "./session-BoEW_wCR.js";
|
|
8
8
|
import { createTuiStore } from "./session/sqlite.js";
|
|
9
9
|
import { homedir } from "node:os";
|
|
10
10
|
import { spawn } from "node:child_process";
|
|
@@ -4637,6 +4637,282 @@ function OptionList({ items, initialCursor, onPick }) {
|
|
|
4637
4637
|
});
|
|
4638
4638
|
}
|
|
4639
4639
|
//#endregion
|
|
4640
|
+
//#region src/tui/oauth-url-block.tsx
|
|
4641
|
+
/** @jsxImportSource @opentui/react */
|
|
4642
|
+
/**
|
|
4643
|
+
* Long URL rendered as N single-row OSC 8 hyperlinks instead of one
|
|
4644
|
+
* wrapped hyperlink.
|
|
4645
|
+
*
|
|
4646
|
+
* Why split: OpenTUI packs a `linkId` per cell into the attribute
|
|
4647
|
+
* bitfield, but its renderer emits an OSC 8 open/close pair per visual
|
|
4648
|
+
* row without the spec's `id=` parameter. Terminals (notably iTerm2)
|
|
4649
|
+
* need a matching `id=` to stitch hyperlink fragments across rows —
|
|
4650
|
+
* without it, only one row of a wrapped link ends up clickable. We
|
|
4651
|
+
* pre-chunk the URL into rows that fit on one line and render each as
|
|
4652
|
+
* its own intact `<a href>` with `wrapMode="none"`, so the terminal
|
|
4653
|
+
* never sees a wrapped hyperlink and clicking any row opens the full
|
|
4654
|
+
* URL.
|
|
4655
|
+
*
|
|
4656
|
+
* Width: caller passes a hard cap (its container's content-area width).
|
|
4657
|
+
* We further clamp by the live terminal width minus `chromeWidth` so a
|
|
4658
|
+
* narrow terminal still chunks short enough to avoid forced wrap by
|
|
4659
|
+
* the layout engine. `chromeWidth` is the container's border + padding
|
|
4660
|
+
* budget — default 14 fits a typical modal; pass a smaller value for
|
|
4661
|
+
* less-padded containers (e.g. 6 for the auth wizard panel).
|
|
4662
|
+
*/
|
|
4663
|
+
function OAuthUrlBlock({ url, fg, maxLineWidth, chromeWidth = 14 }) {
|
|
4664
|
+
const { width: termWidth } = useTerminalDimensions();
|
|
4665
|
+
return /* @__PURE__ */ jsx(Fragment, { children: chunkString(url, Math.max(20, Math.min(maxLineWidth, termWidth - chromeWidth))).map((line, i) => /* @__PURE__ */ jsx("text", {
|
|
4666
|
+
wrapMode: "none",
|
|
4667
|
+
fg,
|
|
4668
|
+
children: /* @__PURE__ */ jsx("a", {
|
|
4669
|
+
href: url,
|
|
4670
|
+
children: line
|
|
4671
|
+
})
|
|
4672
|
+
}, i)) });
|
|
4673
|
+
}
|
|
4674
|
+
function chunkString(s, n) {
|
|
4675
|
+
if (s.length <= n) return [s];
|
|
4676
|
+
const out = [];
|
|
4677
|
+
for (let i = 0; i < s.length; i += n) out.push(s.slice(i, i + n));
|
|
4678
|
+
return out;
|
|
4679
|
+
}
|
|
4680
|
+
//#endregion
|
|
4681
|
+
//#region src/tui/oauth-auth-block.tsx
|
|
4682
|
+
/** Keystroke shown next to the open-browser button. */
|
|
4683
|
+
const OPEN_BROWSER_KEY = "ctrl+b";
|
|
4684
|
+
/**
|
|
4685
|
+
* Unified affordance for surfacing an OAuth authorization URL in the TUI:
|
|
4686
|
+
*
|
|
4687
|
+
* 1. A prominent OSC 8 hyperlink button — "Click here to open auth URL in
|
|
4688
|
+
* browser". Honored by every terminal that supports clickable links
|
|
4689
|
+
* (iTerm2, Kitty, WezTerm, Ghostty, Alacritty, …). Lands on the user's
|
|
4690
|
+
* LOCAL terminal even over SSH because OSC 8 is interpreted client-side.
|
|
4691
|
+
* 2. The full URL rendered greyed below, chunked into per-row hyperlinks
|
|
4692
|
+
* via {@link OAuthUrlBlock}. Backup channel for terminals without OSC 8,
|
|
4693
|
+
* and for users who'd rather copy via drag-select than click.
|
|
4694
|
+
* 3. Optional paste-back input. When `paste` is provided, an `<input>`
|
|
4695
|
+
* renders below the URL so the user can paste the FULL redirect URL
|
|
4696
|
+
* their browser ended up at after authorizing — useful when zidane runs
|
|
4697
|
+
* over SSH and the browser-side redirect to loopback can't reach the
|
|
4698
|
+
* remote callback server. The caller's `onSubmit` typically pipes the
|
|
4699
|
+
* pasted value through {@link fetchOAuthRedirect} so the in-process
|
|
4700
|
+
* server receives the request and the OAuth promise resolves through
|
|
4701
|
+
* the same happy path a real browser would have taken.
|
|
4702
|
+
*
|
|
4703
|
+
* The component owns presentation only — keyboard focus, input ref, and
|
|
4704
|
+
* the submit handler stay with the caller so the affordance composes
|
|
4705
|
+
* cleanly with whatever picker / wizard / modal it lives in.
|
|
4706
|
+
*/
|
|
4707
|
+
function OAuthAuthBlock({ authUrl, maxLineWidth, chromeWidth = 14, paste }) {
|
|
4708
|
+
const COLOR = useColors();
|
|
4709
|
+
return /* @__PURE__ */ jsxs("box", {
|
|
4710
|
+
style: {
|
|
4711
|
+
flexDirection: "column",
|
|
4712
|
+
gap: 1
|
|
4713
|
+
},
|
|
4714
|
+
children: [
|
|
4715
|
+
/* @__PURE__ */ jsx(OpenBrowserButton, { authUrl }),
|
|
4716
|
+
/* @__PURE__ */ jsxs("box", {
|
|
4717
|
+
style: { flexDirection: "column" },
|
|
4718
|
+
children: [/* @__PURE__ */ jsx("text", {
|
|
4719
|
+
fg: COLOR.mute,
|
|
4720
|
+
children: "or copy the URL manually:"
|
|
4721
|
+
}), /* @__PURE__ */ jsx(OAuthUrlBlock, {
|
|
4722
|
+
url: authUrl,
|
|
4723
|
+
fg: COLOR.dim,
|
|
4724
|
+
maxLineWidth,
|
|
4725
|
+
chromeWidth
|
|
4726
|
+
})]
|
|
4727
|
+
}),
|
|
4728
|
+
paste && /* @__PURE__ */ jsxs("box", {
|
|
4729
|
+
style: { flexDirection: "column" },
|
|
4730
|
+
children: [
|
|
4731
|
+
/* @__PURE__ */ jsx("text", {
|
|
4732
|
+
fg: COLOR.mute,
|
|
4733
|
+
children: "or — if the browser couldn't reach this machine (SSH, firewall) — paste the URL it tried to redirect to:"
|
|
4734
|
+
}),
|
|
4735
|
+
paste.hint && /* @__PURE__ */ jsx("text", {
|
|
4736
|
+
fg: toneColor(paste.hint.tone, COLOR),
|
|
4737
|
+
children: paste.hint.text
|
|
4738
|
+
}),
|
|
4739
|
+
/* @__PURE__ */ jsx("box", {
|
|
4740
|
+
style: {
|
|
4741
|
+
border: true,
|
|
4742
|
+
borderColor: paste.focused ? COLOR.borderActive : COLOR.border,
|
|
4743
|
+
paddingLeft: 1,
|
|
4744
|
+
paddingRight: 1,
|
|
4745
|
+
height: 3
|
|
4746
|
+
},
|
|
4747
|
+
children: /* @__PURE__ */ jsx("input", {
|
|
4748
|
+
ref: paste.inputRef,
|
|
4749
|
+
focused: paste.focused,
|
|
4750
|
+
placeholder: paste.placeholder ?? "paste redirect URL and press enter…",
|
|
4751
|
+
onSubmit: paste.onSubmit,
|
|
4752
|
+
style: { flexGrow: 1 }
|
|
4753
|
+
})
|
|
4754
|
+
})
|
|
4755
|
+
]
|
|
4756
|
+
})
|
|
4757
|
+
]
|
|
4758
|
+
});
|
|
4759
|
+
}
|
|
4760
|
+
/**
|
|
4761
|
+
* Real button: a bordered, brand-colored box hosting a labeled keystroke
|
|
4762
|
+
* hint. Pressing `ctrl+b` (anywhere this block is mounted) calls
|
|
4763
|
+
* {@link tryOpenBrowser} to launch the URL via the OS handler AND
|
|
4764
|
+
* {@link writeToClipboard} so the URL also lands in the user's clipboard
|
|
4765
|
+
* (OSC 52 → works over SSH, native helper → works locally). Both fire
|
|
4766
|
+
* because either alone can fail silently — `open`/`xdg-open` are no-ops
|
|
4767
|
+
* on a headless box, and OSC 52 is disabled on some terminals — and the
|
|
4768
|
+
* combination covers both failure modes without prompting again.
|
|
4769
|
+
*
|
|
4770
|
+
* The visible label is also wrapped in an OSC 8 hyperlink so a mouse
|
|
4771
|
+
* click in a supporting terminal (iTerm2, Kitty, WezTerm, …) reaches the
|
|
4772
|
+
* same browser. The keybind is the authoritative path — it doesn't
|
|
4773
|
+
* depend on terminal capability — and the hyperlink is the bonus.
|
|
4774
|
+
*/
|
|
4775
|
+
function OpenBrowserButton({ authUrl }) {
|
|
4776
|
+
const COLOR = useColors();
|
|
4777
|
+
const [feedback, setFeedback] = useState(null);
|
|
4778
|
+
const feedbackTimer = useRef(null);
|
|
4779
|
+
const trigger = useCallback(() => {
|
|
4780
|
+
tryOpenBrowser(authUrl);
|
|
4781
|
+
setFeedback(writeToClipboard(authUrl) ? "opened in browser · URL copied to clipboard" : "opened in browser");
|
|
4782
|
+
if (feedbackTimer.current) clearTimeout(feedbackTimer.current);
|
|
4783
|
+
feedbackTimer.current = setTimeout(setFeedback, 4e3, null);
|
|
4784
|
+
}, [authUrl]);
|
|
4785
|
+
useKeyboard((key) => {
|
|
4786
|
+
if (key.ctrl && key.name === "b") {
|
|
4787
|
+
key.preventDefault();
|
|
4788
|
+
trigger();
|
|
4789
|
+
}
|
|
4790
|
+
});
|
|
4791
|
+
useEffect(() => () => {
|
|
4792
|
+
if (feedbackTimer.current) clearTimeout(feedbackTimer.current);
|
|
4793
|
+
}, []);
|
|
4794
|
+
return /* @__PURE__ */ jsxs("box", {
|
|
4795
|
+
style: { flexDirection: "column" },
|
|
4796
|
+
children: [/* @__PURE__ */ jsx("box", {
|
|
4797
|
+
style: {
|
|
4798
|
+
border: true,
|
|
4799
|
+
borderColor: COLOR.brand,
|
|
4800
|
+
paddingLeft: 1,
|
|
4801
|
+
paddingRight: 1,
|
|
4802
|
+
alignSelf: "flex-start"
|
|
4803
|
+
},
|
|
4804
|
+
children: /* @__PURE__ */ jsxs("text", {
|
|
4805
|
+
wrapMode: "none",
|
|
4806
|
+
children: [
|
|
4807
|
+
/* @__PURE__ */ jsx("a", {
|
|
4808
|
+
href: authUrl,
|
|
4809
|
+
fg: COLOR.brand,
|
|
4810
|
+
children: "↗ Open auth URL in browser"
|
|
4811
|
+
}),
|
|
4812
|
+
/* @__PURE__ */ jsx("span", {
|
|
4813
|
+
fg: COLOR.mute,
|
|
4814
|
+
children: " "
|
|
4815
|
+
}),
|
|
4816
|
+
/* @__PURE__ */ jsx("span", {
|
|
4817
|
+
fg: COLOR.warn,
|
|
4818
|
+
children: OPEN_BROWSER_KEY
|
|
4819
|
+
}),
|
|
4820
|
+
/* @__PURE__ */ jsx("span", {
|
|
4821
|
+
fg: COLOR.mute,
|
|
4822
|
+
children: " open · click also works"
|
|
4823
|
+
})
|
|
4824
|
+
]
|
|
4825
|
+
})
|
|
4826
|
+
}), feedback && /* @__PURE__ */ jsx("text", {
|
|
4827
|
+
fg: COLOR.accent,
|
|
4828
|
+
children: `✓ ${feedback}`
|
|
4829
|
+
})]
|
|
4830
|
+
});
|
|
4831
|
+
}
|
|
4832
|
+
function toneColor(tone, COLOR) {
|
|
4833
|
+
switch (tone) {
|
|
4834
|
+
case "error": return COLOR.error;
|
|
4835
|
+
case "accent": return COLOR.accent;
|
|
4836
|
+
case "dim": return COLOR.dim;
|
|
4837
|
+
}
|
|
4838
|
+
}
|
|
4839
|
+
/**
|
|
4840
|
+
* Self-contained MCP authorizing panel:
|
|
4841
|
+
*
|
|
4842
|
+
* - Renders the {@link OAuthAuthBlock} for the URL + paste input.
|
|
4843
|
+
* - Owns the input ref, the submit handler, and the hint state.
|
|
4844
|
+
* - Auto-fetches the pasted URL via {@link fetchOAuthRedirect} so the
|
|
4845
|
+
* MCP SDK's loopback callback server resolves the OAuth promise
|
|
4846
|
+
* through the same code path a real browser-redirect would have
|
|
4847
|
+
* taken — works over SSH where the browser can't reach the remote
|
|
4848
|
+
* callback server directly.
|
|
4849
|
+
*
|
|
4850
|
+
* `inputFocused` is forwarded as the input's `focused` prop AND read by
|
|
4851
|
+
* the parent picker's `useKeyboard` (via a ref) to suppress single-key
|
|
4852
|
+
* shortcuts (`l` / `o` / `r`) while the user is typing into the input.
|
|
4853
|
+
*/
|
|
4854
|
+
function McpAuthorizingPanel({ serverName, authUrl, maxLineWidth, chromeWidth, inputFocused }) {
|
|
4855
|
+
const COLOR = useColors();
|
|
4856
|
+
const inputRef = useRef(null);
|
|
4857
|
+
const [hint, setHint] = useState(null);
|
|
4858
|
+
const onSubmit = useCallback(() => {
|
|
4859
|
+
const value = inputRef.current?.value?.trim() ?? "";
|
|
4860
|
+
if (!value) return;
|
|
4861
|
+
setHint({
|
|
4862
|
+
text: "submitting redirect URL…",
|
|
4863
|
+
tone: "dim"
|
|
4864
|
+
});
|
|
4865
|
+
(async () => {
|
|
4866
|
+
try {
|
|
4867
|
+
const result = await fetchOAuthRedirect(value);
|
|
4868
|
+
if (result.status >= 200 && result.status < 300) setHint({
|
|
4869
|
+
text: "redirect accepted — finalizing…",
|
|
4870
|
+
tone: "accent"
|
|
4871
|
+
});
|
|
4872
|
+
else setHint({
|
|
4873
|
+
text: `callback server rejected the URL (${result.status}${result.message ? `: ${result.message}` : ""}). Cancel and retry.`,
|
|
4874
|
+
tone: "error"
|
|
4875
|
+
});
|
|
4876
|
+
} catch (err) {
|
|
4877
|
+
setHint({
|
|
4878
|
+
text: errorMessage(err),
|
|
4879
|
+
tone: "error"
|
|
4880
|
+
});
|
|
4881
|
+
}
|
|
4882
|
+
})();
|
|
4883
|
+
}, []);
|
|
4884
|
+
return /* @__PURE__ */ jsxs("box", {
|
|
4885
|
+
style: {
|
|
4886
|
+
flexDirection: "column",
|
|
4887
|
+
border: ["top"],
|
|
4888
|
+
borderColor: COLOR.border,
|
|
4889
|
+
paddingTop: 1
|
|
4890
|
+
},
|
|
4891
|
+
children: [
|
|
4892
|
+
/* @__PURE__ */ jsx("text", {
|
|
4893
|
+
fg: COLOR.brand,
|
|
4894
|
+
children: `Authorizing ${serverName}`
|
|
4895
|
+
}),
|
|
4896
|
+
/* @__PURE__ */ jsx("text", {
|
|
4897
|
+
fg: COLOR.dim,
|
|
4898
|
+
children: "Your browser should have opened — complete the login, then return here."
|
|
4899
|
+
}),
|
|
4900
|
+
/* @__PURE__ */ jsx(OAuthAuthBlock, {
|
|
4901
|
+
authUrl,
|
|
4902
|
+
maxLineWidth,
|
|
4903
|
+
chromeWidth,
|
|
4904
|
+
paste: {
|
|
4905
|
+
inputRef,
|
|
4906
|
+
focused: inputFocused,
|
|
4907
|
+
onSubmit,
|
|
4908
|
+
placeholder: "paste redirect URL and press enter…",
|
|
4909
|
+
hint: hint ?? void 0
|
|
4910
|
+
}
|
|
4911
|
+
})
|
|
4912
|
+
]
|
|
4913
|
+
});
|
|
4914
|
+
}
|
|
4915
|
+
//#endregion
|
|
4640
4916
|
//#region src/tui/todo-indicator.tsx
|
|
4641
4917
|
/**
|
|
4642
4918
|
* Layout budget when truncating the content. The bar never wraps —
|
|
@@ -5085,9 +5361,15 @@ function EnterApiKeyStep({ descriptor, error, onSubmit }) {
|
|
|
5085
5361
|
});
|
|
5086
5362
|
}
|
|
5087
5363
|
function OAuthRunningStep({ descriptor, dataDir, onSuccess, onError }) {
|
|
5364
|
+
const usesManualPaste = oauthUsesManualCodePaste(descriptor);
|
|
5088
5365
|
const [url, setUrl] = useState(null);
|
|
5089
|
-
const [status, setStatus] = useState("starting browser…");
|
|
5090
|
-
const
|
|
5366
|
+
const [status, setStatus] = useState(usesManualPaste ? "opening browser…" : "starting browser…");
|
|
5367
|
+
const [pending, setPending] = useState(null);
|
|
5368
|
+
const [pasteHint, setPasteHint] = useState(null);
|
|
5369
|
+
const focused = useModalAwareFocus();
|
|
5370
|
+
const inputRef = useRef(null);
|
|
5371
|
+
const pendingRef = useRef(null);
|
|
5372
|
+
pendingRef.current = pending;
|
|
5091
5373
|
useEffect(() => {
|
|
5092
5374
|
const ac = new AbortController();
|
|
5093
5375
|
let cancelled = false;
|
|
@@ -5097,8 +5379,22 @@ function OAuthRunningStep({ descriptor, dataDir, onSuccess, onError }) {
|
|
|
5097
5379
|
onUrl: (loginUrl) => {
|
|
5098
5380
|
if (cancelled) return;
|
|
5099
5381
|
setUrl(loginUrl);
|
|
5100
|
-
setStatus("waiting for browser callback…");
|
|
5382
|
+
setStatus(usesManualPaste ? "complete the login in your browser, then paste the code below" : "waiting for browser callback…");
|
|
5101
5383
|
},
|
|
5384
|
+
onPrompt: (prompt) => new Promise((resolve, reject) => {
|
|
5385
|
+
if (cancelled) {
|
|
5386
|
+
reject(/* @__PURE__ */ new Error("OAuth flow cancelled"));
|
|
5387
|
+
return;
|
|
5388
|
+
}
|
|
5389
|
+
pendingRef.current?.reject(/* @__PURE__ */ new Error("superseded by a newer OAuth prompt"));
|
|
5390
|
+
setPending({
|
|
5391
|
+
message: prompt.message,
|
|
5392
|
+
placeholder: prompt.placeholder,
|
|
5393
|
+
allowEmpty: prompt.allowEmpty,
|
|
5394
|
+
resolve,
|
|
5395
|
+
reject
|
|
5396
|
+
});
|
|
5397
|
+
}),
|
|
5102
5398
|
onProgress: (message) => {
|
|
5103
5399
|
if (!cancelled) setStatus(message);
|
|
5104
5400
|
},
|
|
@@ -5117,31 +5413,70 @@ function OAuthRunningStep({ descriptor, dataDir, onSuccess, onError }) {
|
|
|
5117
5413
|
})();
|
|
5118
5414
|
return () => {
|
|
5119
5415
|
cancelled = true;
|
|
5416
|
+
pendingRef.current?.reject(/* @__PURE__ */ new Error("OAuth flow cancelled"));
|
|
5417
|
+
pendingRef.current = null;
|
|
5120
5418
|
ac.abort();
|
|
5121
5419
|
};
|
|
5122
5420
|
}, [
|
|
5123
5421
|
descriptor,
|
|
5124
5422
|
dataDir,
|
|
5125
5423
|
onSuccess,
|
|
5126
|
-
onError
|
|
5424
|
+
onError,
|
|
5425
|
+
usesManualPaste
|
|
5127
5426
|
]);
|
|
5427
|
+
const submitInput = useCallback(() => {
|
|
5428
|
+
const value = inputRef.current?.value?.trim() ?? "";
|
|
5429
|
+
const current = pendingRef.current;
|
|
5430
|
+
if (current) {
|
|
5431
|
+
if (!value && !current.allowEmpty) return;
|
|
5432
|
+
pendingRef.current = null;
|
|
5433
|
+
setPending(null);
|
|
5434
|
+
setStatus("exchanging code…");
|
|
5435
|
+
current.resolve(value);
|
|
5436
|
+
return;
|
|
5437
|
+
}
|
|
5438
|
+
if (!value) return;
|
|
5439
|
+
setPasteHint({
|
|
5440
|
+
text: "submitting redirect URL…",
|
|
5441
|
+
tone: "dim"
|
|
5442
|
+
});
|
|
5443
|
+
(async () => {
|
|
5444
|
+
try {
|
|
5445
|
+
const result = await fetchOAuthRedirect(value);
|
|
5446
|
+
if (result.status >= 200 && result.status < 300) {
|
|
5447
|
+
setPasteHint({
|
|
5448
|
+
text: "redirect accepted — exchanging code…",
|
|
5449
|
+
tone: "accent"
|
|
5450
|
+
});
|
|
5451
|
+
setStatus("exchanging code…");
|
|
5452
|
+
} else setPasteHint({
|
|
5453
|
+
text: `callback server rejected the URL (${result.status}${result.message ? `: ${result.message}` : ""}). Try again or restart the flow.`,
|
|
5454
|
+
tone: "error"
|
|
5455
|
+
});
|
|
5456
|
+
} catch (err) {
|
|
5457
|
+
setPasteHint({
|
|
5458
|
+
text: errorMessage(err),
|
|
5459
|
+
tone: "error"
|
|
5460
|
+
});
|
|
5461
|
+
}
|
|
5462
|
+
})();
|
|
5463
|
+
}, []);
|
|
5128
5464
|
return /* @__PURE__ */ jsxs(WizardPanel, {
|
|
5129
5465
|
title: `configure ${descriptor.label} — OAuth`,
|
|
5130
5466
|
children: [
|
|
5131
5467
|
/* @__PURE__ */ jsx(WizardEscHint, {}),
|
|
5132
|
-
/* @__PURE__ */ jsx(Spinner, { label: status }),
|
|
5133
|
-
url && /* @__PURE__ */
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
})]
|
|
5468
|
+
pending ? /* @__PURE__ */ jsx(Spinner, { label: pending.message }) : /* @__PURE__ */ jsx(Spinner, { label: status }),
|
|
5469
|
+
url && /* @__PURE__ */ jsx(OAuthAuthBlock, {
|
|
5470
|
+
authUrl: url,
|
|
5471
|
+
maxLineWidth: 200,
|
|
5472
|
+
chromeWidth: 6,
|
|
5473
|
+
paste: {
|
|
5474
|
+
inputRef,
|
|
5475
|
+
focused,
|
|
5476
|
+
onSubmit: submitInput,
|
|
5477
|
+
placeholder: pending?.placeholder ?? "paste redirect URL (or code) and press enter…",
|
|
5478
|
+
hint: pasteHint ?? void 0
|
|
5479
|
+
}
|
|
5145
5480
|
})
|
|
5146
5481
|
]
|
|
5147
5482
|
});
|
|
@@ -7106,7 +7441,13 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
7106
7441
|
]);
|
|
7107
7442
|
const focusedMcp = filteredMcps[cursor];
|
|
7108
7443
|
const focusedMcpStatus = focusedMcp ? getMcpAuthStatus(authState, focusedMcp.config.name) : void 0;
|
|
7444
|
+
const oauthPasteActive = activeTab === "mcps" && focusedMcpStatus?.kind === "authorizing" && !!focusedMcpStatus.url;
|
|
7109
7445
|
useKeyboard((key) => {
|
|
7446
|
+
if (key.name === "escape" && oauthPasteActive && focusedMcp) {
|
|
7447
|
+
actions?.onCancelLoginMcp?.(focusedMcp.config.name);
|
|
7448
|
+
return;
|
|
7449
|
+
}
|
|
7450
|
+
if (oauthPasteActive) return;
|
|
7110
7451
|
if (!key.ctrl && !key.meta && !key.shift && (key.name === "left" || key.name === "right")) {
|
|
7111
7452
|
key.preventDefault();
|
|
7112
7453
|
const idx = TAB_ORDER.indexOf(activeTab);
|
|
@@ -7203,7 +7544,7 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
7203
7544
|
},
|
|
7204
7545
|
children: /* @__PURE__ */ jsx("input", {
|
|
7205
7546
|
ref: inputRef,
|
|
7206
|
-
focused:
|
|
7547
|
+
focused: !oauthPasteActive,
|
|
7207
7548
|
placeholder: searchPlaceholder(activeTab),
|
|
7208
7549
|
onInput: handleQueryChange,
|
|
7209
7550
|
onSubmit: () => {},
|
|
@@ -7623,35 +7964,29 @@ function EmptyRow({ label }) {
|
|
|
7623
7964
|
});
|
|
7624
7965
|
}
|
|
7625
7966
|
function renderMcpDetailPanel(entry, status, COLOR) {
|
|
7626
|
-
if (status.kind === "authorizing")
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
/* @__PURE__ */ jsx("text", {
|
|
7967
|
+
if (status.kind === "authorizing") {
|
|
7968
|
+
if (!status.url) return /* @__PURE__ */ jsxs("box", {
|
|
7969
|
+
style: {
|
|
7970
|
+
flexDirection: "column",
|
|
7971
|
+
border: ["top"],
|
|
7972
|
+
borderColor: COLOR.border,
|
|
7973
|
+
paddingTop: 1
|
|
7974
|
+
},
|
|
7975
|
+
children: [/* @__PURE__ */ jsx("text", {
|
|
7635
7976
|
fg: COLOR.brand,
|
|
7636
7977
|
children: `Authorizing ${entry.config.name}`
|
|
7637
|
-
}),
|
|
7638
|
-
/* @__PURE__ */ jsx("text", {
|
|
7639
|
-
fg: COLOR.dim,
|
|
7640
|
-
children: "Your browser should have opened — complete the login, then return here."
|
|
7641
|
-
}),
|
|
7642
|
-
status.url && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("text", {
|
|
7643
|
-
fg: COLOR.mute,
|
|
7644
|
-
children: "If it didn't, click the URL below (or copy it):"
|
|
7645
7978
|
}), /* @__PURE__ */ jsx("text", {
|
|
7646
|
-
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7979
|
+
fg: COLOR.dim,
|
|
7980
|
+
children: "Starting login flow…"
|
|
7981
|
+
})]
|
|
7982
|
+
});
|
|
7983
|
+
return /* @__PURE__ */ jsx(McpAuthorizingPanel, {
|
|
7984
|
+
serverName: entry.config.name,
|
|
7985
|
+
authUrl: status.url,
|
|
7986
|
+
maxLineWidth: 134,
|
|
7987
|
+
inputFocused: true
|
|
7988
|
+
});
|
|
7989
|
+
}
|
|
7655
7990
|
if (status.kind === "error") return /* @__PURE__ */ jsxs("box", {
|
|
7656
7991
|
style: {
|
|
7657
7992
|
flexDirection: "column",
|
|
@@ -8591,6 +8926,15 @@ function AppShell() {
|
|
|
8591
8926
|
useEffect(() => {
|
|
8592
8927
|
autoCompactThresholdRef.current = settings.autoCompactThreshold;
|
|
8593
8928
|
}, [settings.autoCompactThreshold]);
|
|
8929
|
+
/**
|
|
8930
|
+
* Post-compaction baseline for the hysteresis check in
|
|
8931
|
+
* {@link shouldAutoCompact}. Latched to the effective post-compact token
|
|
8932
|
+
* count whenever a compaction lands (see {@link onCompactSession}), reset
|
|
8933
|
+
* to `undefined` on session change so the first compaction in a fresh
|
|
8934
|
+
* session fires off the absolute threshold without any growth gating.
|
|
8935
|
+
* Pairs with {@link AUTO_COMPACT_MIN_GROWTH_FRACTION} in the predicate.
|
|
8936
|
+
*/
|
|
8937
|
+
const lastCompactedInputTokensRef = useRef(void 0);
|
|
8594
8938
|
const smoothStreamingRef = useRef(settings.smoothStreaming);
|
|
8595
8939
|
useEffect(() => {
|
|
8596
8940
|
smoothStreamingRef.current = settings.smoothStreaming;
|
|
@@ -9470,6 +9814,7 @@ function AppShell() {
|
|
|
9470
9814
|
const replayedTokens = lastContextSizeFromTurns(session.turns, session.runs);
|
|
9471
9815
|
setLastInputTokens(replayedTokens);
|
|
9472
9816
|
lastInputTokensRef.current = replayedTokens;
|
|
9817
|
+
lastCompactedInputTokensRef.current = void 0;
|
|
9473
9818
|
setSessionCost(sumRunCosts(session.runs));
|
|
9474
9819
|
setCurrentSession({
|
|
9475
9820
|
id: session.id,
|
|
@@ -10048,6 +10393,7 @@ function AppShell() {
|
|
|
10048
10393
|
const replayedTokens = lastContextSizeFromTurns(session.turns, session.runs);
|
|
10049
10394
|
setLastInputTokens(replayedTokens);
|
|
10050
10395
|
lastInputTokensRef.current = replayedTokens;
|
|
10396
|
+
lastCompactedInputTokensRef.current = void 0;
|
|
10051
10397
|
setSessionCost(sumRunCosts(session.runs));
|
|
10052
10398
|
setCurrentSession((prev) => prev ? {
|
|
10053
10399
|
...prev,
|
|
@@ -10085,6 +10431,7 @@ function AppShell() {
|
|
|
10085
10431
|
const replayedTokens = lastContextSizeFromTurns(session.turns, session.runs);
|
|
10086
10432
|
setLastInputTokens(replayedTokens);
|
|
10087
10433
|
lastInputTokensRef.current = replayedTokens;
|
|
10434
|
+
lastCompactedInputTokensRef.current = void 0;
|
|
10088
10435
|
setCurrentSession((prev) => prev ? {
|
|
10089
10436
|
...prev,
|
|
10090
10437
|
updatedAt: Date.now()
|
|
@@ -10241,6 +10588,7 @@ function AppShell() {
|
|
|
10241
10588
|
setEvents(eventsFromTurns(liveSession.turns, liveSession.runs));
|
|
10242
10589
|
setLastInputTokens(effectiveTokens);
|
|
10243
10590
|
lastInputTokensRef.current = effectiveTokens;
|
|
10591
|
+
lastCompactedInputTokensRef.current = effectiveTokens;
|
|
10244
10592
|
}
|
|
10245
10593
|
setCurrentSession((prev) => prev && prev.id === sessionId ? {
|
|
10246
10594
|
...prev,
|
|
@@ -10283,7 +10631,9 @@ function AppShell() {
|
|
|
10283
10631
|
threshold: autoCompactThresholdRef.current,
|
|
10284
10632
|
inputTokens: lastInputTokensRef.current,
|
|
10285
10633
|
rawContextWindow: rawWindow,
|
|
10286
|
-
alreadyCompacting: !!autoCompactInFlightRef.current
|
|
10634
|
+
alreadyCompacting: !!autoCompactInFlightRef.current,
|
|
10635
|
+
...lastCompactedInputTokensRef.current !== void 0 ? { lastCompactedInputTokens: lastCompactedInputTokensRef.current } : {},
|
|
10636
|
+
minGrowthFraction: AUTO_COMPACT_MIN_GROWTH_FRACTION
|
|
10287
10637
|
});
|
|
10288
10638
|
if (decision.kind !== "fire") return;
|
|
10289
10639
|
const pct = Math.round(decision.usedFraction * 100);
|
|
@@ -11104,7 +11454,18 @@ function McpsSettingsModal({ catalog, errors, onLogin, onLogout, onCancelLogin,
|
|
|
11104
11454
|
return ((prev + delta) % catalog.length + catalog.length) % catalog.length;
|
|
11105
11455
|
}), [catalog.length]);
|
|
11106
11456
|
const safeCursor = Math.min(cursor, Math.max(0, catalog.length - 1));
|
|
11457
|
+
const focusedEntry = catalog[safeCursor];
|
|
11458
|
+
const focusedStatus = focusedEntry ? getMcpAuthStatus(authState, focusedEntry.config.name) : void 0;
|
|
11459
|
+
const inputActive = focusedStatus?.kind === "authorizing" && !!focusedStatus.url;
|
|
11107
11460
|
useKeyboard((key) => {
|
|
11461
|
+
if (key.name === "escape" && focusedEntry) {
|
|
11462
|
+
const name = focusedEntry.config.name;
|
|
11463
|
+
if (getMcpAuthStatus(authState, name).kind === "authorizing") {
|
|
11464
|
+
onCancelLogin(name);
|
|
11465
|
+
return;
|
|
11466
|
+
}
|
|
11467
|
+
}
|
|
11468
|
+
if (inputActive) return;
|
|
11108
11469
|
if (key.name === "up" || key.name === "k" || key.ctrl && key.name === "p") {
|
|
11109
11470
|
moveCursor(-1);
|
|
11110
11471
|
return;
|
|
@@ -11118,10 +11479,6 @@ function McpsSettingsModal({ catalog, errors, onLogin, onLogout, onCancelLogin,
|
|
|
11118
11479
|
if (!entry) return;
|
|
11119
11480
|
const name = entry.config.name;
|
|
11120
11481
|
const status = getMcpAuthStatus(authState, name);
|
|
11121
|
-
if (key.name === "escape" && status.kind === "authorizing") {
|
|
11122
|
-
onCancelLogin(name);
|
|
11123
|
-
return;
|
|
11124
|
-
}
|
|
11125
11482
|
if (key.name === "return" || key.name === "space") {
|
|
11126
11483
|
toggle(name);
|
|
11127
11484
|
return;
|
|
@@ -11209,8 +11566,6 @@ function McpsSettingsModal({ catalog, errors, onLogin, onLogout, onCancelLogin,
|
|
|
11209
11566
|
})
|
|
11210
11567
|
]
|
|
11211
11568
|
});
|
|
11212
|
-
const focusedEntry = catalog[safeCursor];
|
|
11213
|
-
const focusedStatus = focusedEntry ? getMcpAuthStatus(authState, focusedEntry.config.name) : void 0;
|
|
11214
11569
|
return /* @__PURE__ */ jsxs(Modal, {
|
|
11215
11570
|
title: ` mcp servers · ${enabledSet.size} / ${catalog.length} enabled `,
|
|
11216
11571
|
children: [
|
|
@@ -11300,35 +11655,29 @@ function renderInlineBadge(status, COLOR) {
|
|
|
11300
11655
|
* itself to the content automatically).
|
|
11301
11656
|
*/
|
|
11302
11657
|
function renderDetailPanel(entry, status, COLOR) {
|
|
11303
|
-
if (status.kind === "authorizing")
|
|
11304
|
-
|
|
11305
|
-
|
|
11306
|
-
|
|
11307
|
-
|
|
11308
|
-
|
|
11309
|
-
|
|
11310
|
-
|
|
11311
|
-
/* @__PURE__ */ jsx("text", {
|
|
11658
|
+
if (status.kind === "authorizing") {
|
|
11659
|
+
if (!status.url) return /* @__PURE__ */ jsxs("box", {
|
|
11660
|
+
style: {
|
|
11661
|
+
flexDirection: "column",
|
|
11662
|
+
border: ["top"],
|
|
11663
|
+
borderColor: COLOR.border,
|
|
11664
|
+
paddingTop: 1
|
|
11665
|
+
},
|
|
11666
|
+
children: [/* @__PURE__ */ jsx("text", {
|
|
11312
11667
|
fg: COLOR.brand,
|
|
11313
11668
|
children: `Authorizing ${entry.config.name}`
|
|
11314
|
-
}),
|
|
11315
|
-
/* @__PURE__ */ jsx("text", {
|
|
11316
|
-
fg: COLOR.dim,
|
|
11317
|
-
children: "Your browser should have opened — complete the login, then return here."
|
|
11318
|
-
}),
|
|
11319
|
-
status.url && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("text", {
|
|
11320
|
-
fg: COLOR.mute,
|
|
11321
|
-
children: "If it didn't, click the URL below (or copy it):"
|
|
11322
11669
|
}), /* @__PURE__ */ jsx("text", {
|
|
11323
|
-
|
|
11324
|
-
|
|
11325
|
-
|
|
11326
|
-
|
|
11327
|
-
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
|
|
11331
|
-
|
|
11670
|
+
fg: COLOR.dim,
|
|
11671
|
+
children: "Starting login flow…"
|
|
11672
|
+
})]
|
|
11673
|
+
});
|
|
11674
|
+
return /* @__PURE__ */ jsx(McpAuthorizingPanel, {
|
|
11675
|
+
serverName: entry.config.name,
|
|
11676
|
+
authUrl: status.url,
|
|
11677
|
+
maxLineWidth: 86,
|
|
11678
|
+
inputFocused: true
|
|
11679
|
+
});
|
|
11680
|
+
}
|
|
11332
11681
|
if (status.kind === "error") return /* @__PURE__ */ jsxs("box", {
|
|
11333
11682
|
style: {
|
|
11334
11683
|
flexDirection: "column",
|