@agentdocumentformat/cli 0.7.8 → 0.8.1

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.
Files changed (103) hide show
  1. package/README.md +1 -1
  2. package/dist/adf.mjs +59 -8
  3. package/dist/chunks/{APEv2Parser-2CNNHMXV.mjs → APEv2Parser-WIXRJLHB.mjs} +2 -2
  4. package/dist/chunks/{AiffParser-7BR4RL6G.mjs → AiffParser-ZC4QFOVJ.mjs} +5 -5
  5. package/dist/chunks/{App-7RIIOHJJ.mjs → App-4AZZJNN2.mjs} +917 -826
  6. package/dist/chunks/{DsdiffParser-CMD4AX7A.mjs → DsdiffParser-UAPAJHFX.mjs} +5 -5
  7. package/dist/chunks/{DsfParser-UOGZDS2M.mjs → DsfParser-NNYZK2QX.mjs} +6 -6
  8. package/dist/chunks/{FlacParser-HB3T3CD4.mjs → FlacParser-MW2W4LO3.mjs} +6 -6
  9. package/dist/chunks/{MP4Parser-66HBRUSX.mjs → MP4Parser-Z57SYOOQ.mjs} +4 -4
  10. package/dist/chunks/{MpegParser-YW6LIUEW.mjs → MpegParser-XIIPAZVM.mjs} +7 -7
  11. package/dist/chunks/{MusepackParser-PAUSXP7D.mjs → MusepackParser-QWNDEYHJ.mjs} +6 -6
  12. package/dist/chunks/{OggParser-NUBV3GWC.mjs → OggParser-WRX53F77.mjs} +9 -9
  13. package/dist/chunks/{WavPackParser-WQAGT7TC.mjs → WavPackParser-MJ7WCSJ5.mjs} +2 -2
  14. package/dist/chunks/{WaveParser-EWLQVDX4.mjs → WaveParser-RAVLHZ5S.mjs} +7 -7
  15. package/dist/chunks/{adf-schema-US4NFHMR.mjs → adf-schema-AIPBQTR2.mjs} +9 -3
  16. package/dist/chunks/auth-manager-AJ32FZWS.mjs +19 -0
  17. package/dist/chunks/auth-manager-C5OBEQK2.mjs +18 -0
  18. package/dist/chunks/auth-manager-TBNKCJ45.mjs +17 -0
  19. package/dist/chunks/{chatgpt-subscription-E4MXTIAT.mjs → chatgpt-subscription-MMGNW5KJ.mjs} +5 -2
  20. package/dist/chunks/chunk-2Z7X3UUR.mjs +678 -0
  21. package/dist/chunks/chunk-3UGZFWIF.mjs +26 -0
  22. package/dist/chunks/{chunk-XNPZBLYL.mjs → chunk-75DC5EWN.mjs} +13 -2
  23. package/dist/chunks/{chunk-5PO5PKRV.mjs → chunk-7JZXMDDF.mjs} +158 -67
  24. package/dist/chunks/chunk-AEAJDCVK.mjs +517 -0
  25. package/dist/chunks/{chunk-6VQEXLE2.mjs → chunk-BHY7QDCM.mjs} +41 -3
  26. package/dist/chunks/{chunk-CD3ATSXE.mjs → chunk-BR3AD5QZ.mjs} +8 -2
  27. package/dist/chunks/chunk-BS3USVEA.mjs +301 -0
  28. package/dist/chunks/chunk-C2S64Y6F.mjs +203 -0
  29. package/dist/chunks/chunk-D7A77SNL.mjs +976 -0
  30. package/dist/chunks/chunk-DDTTSKGG.mjs +2443 -0
  31. package/dist/chunks/{chunk-VAUOM3IN.mjs → chunk-DLWCKKIO.mjs} +1 -1
  32. package/dist/chunks/{chunk-G6PH7RPW.mjs → chunk-E7LC6SHP.mjs} +3 -3
  33. package/dist/chunks/{chunk-ZESQMP66.mjs → chunk-F3WSCAJD.mjs} +3 -3
  34. package/dist/chunks/{chunk-KXEF4F4E.mjs → chunk-GAZO6UMI.mjs} +1 -1
  35. package/dist/chunks/{chunk-XYTWGHFS.mjs → chunk-H3XLRWVE.mjs} +1 -1
  36. package/dist/chunks/{chunk-7T2YMTWL.mjs → chunk-H4C65MTP.mjs} +4 -4
  37. package/dist/chunks/chunk-HBOFZRUS.mjs +738 -0
  38. package/dist/chunks/{chunk-VN7UH7I5.mjs → chunk-IMVMSU3A.mjs} +251 -68
  39. package/dist/chunks/{chunk-XYV3VCIX.mjs → chunk-JZFONJSL.mjs} +79 -20
  40. package/dist/chunks/chunk-KCIRFUZH.mjs +12799 -0
  41. package/dist/chunks/chunk-KDDVQKCG.mjs +65 -0
  42. package/dist/chunks/chunk-KRPKWOMB.mjs +290 -0
  43. package/dist/chunks/chunk-LKFHERRV.mjs +145 -0
  44. package/dist/chunks/chunk-LTX74NU6.mjs +29 -0
  45. package/dist/chunks/{chunk-HSBV6YFU.mjs → chunk-LVF2DRBR.mjs} +634 -99
  46. package/dist/chunks/chunk-M2F7C2UJ.mjs +425 -0
  47. package/dist/chunks/{chunk-62NE4LG4.mjs → chunk-MQAMI5BF.mjs} +5 -5
  48. package/dist/chunks/chunk-MZRXFWPQ.mjs +278 -0
  49. package/dist/chunks/{chunk-PRMGZZM5.mjs → chunk-NZLEPJ5M.mjs} +2 -0
  50. package/dist/chunks/{chunk-I3UYSITV.mjs → chunk-O7XKQ6CH.mjs} +1 -1
  51. package/dist/chunks/chunk-P3RG5LQA.mjs +244 -0
  52. package/dist/chunks/chunk-PAK5JCO2.mjs +48 -0
  53. package/dist/chunks/chunk-PC63YFB7.mjs +34 -0
  54. package/dist/chunks/{daemon-control-HKFVSQTQ.mjs → chunk-RHBGCOS3.mjs} +67 -26
  55. package/dist/chunks/{chunk-J74STFKE.mjs → chunk-RJDOVMM4.mjs} +362 -58
  56. package/dist/chunks/{chunk-QPLEAE6V.mjs → chunk-SOSPQPEN.mjs} +167 -650
  57. package/dist/chunks/{chunk-LFMB4PAA.mjs → chunk-TKXIH27X.mjs} +974 -113
  58. package/dist/chunks/{chunk-5W7KES6P.mjs → chunk-UZPDETEU.mjs} +1 -1
  59. package/dist/chunks/chunk-V3MM6PCH.mjs +366 -0
  60. package/dist/chunks/chunk-VENQBMOA.mjs +62 -0
  61. package/dist/chunks/chunk-WJGPNHGX.mjs +67 -0
  62. package/dist/chunks/{chunk-Y5ZLKFLE.mjs → chunk-XNNJQCZP.mjs} +196 -165
  63. package/dist/chunks/{chunk-HDBPBORT.mjs → chunk-YRBFIDLB.mjs} +46 -10
  64. package/dist/chunks/{chunk-BNXUAOO4.mjs → chunk-ZGXUOAWZ.mjs} +3186 -959
  65. package/dist/chunks/chunk-ZPB3HYM7.mjs +45 -0
  66. package/dist/chunks/claude-subscription-EB4LAAVV.mjs +29 -0
  67. package/dist/chunks/{cli-NMFIAR7Z.mjs → cli-PCVFB6B4.mjs} +797 -56
  68. package/dist/chunks/{commands-KPJWFRUE.mjs → commands-KOMPXJZS.mjs} +4 -3
  69. package/dist/chunks/{daemon-YDIK3AAM.mjs → daemon-BVDB565V.mjs} +83142 -64424
  70. package/dist/chunks/daemon-control-MKN7G5M3.mjs +59 -0
  71. package/dist/chunks/{daemon-token-WRSULP7G.mjs → daemon-token-L5QKTHU5.mjs} +3 -1
  72. package/dist/chunks/{discord-DSP4HUWI.mjs → discord-IR62565M.mjs} +3 -52
  73. package/dist/chunks/{email-BRG7KUO2.mjs → email-KHHTJBDW.mjs} +4 -2
  74. package/dist/chunks/{grok-subscription-4PYX7TBF.mjs → grok-subscription-E74FS5EG.mjs} +5 -2
  75. package/dist/chunks/{layout-EPJQNFAI.mjs → layout-ECWGJF6M.mjs} +2 -2
  76. package/dist/chunks/{lib-N7FCZWKH.mjs → lib-L27L5PXM.mjs} +22 -22
  77. package/dist/chunks/{open-VAU7PXT6.mjs → open-3OR6WT4T.mjs} +6 -6
  78. package/dist/chunks/{parser-JVY2PWSM.mjs → parser-7GARNT5L.mjs} +1 -1
  79. package/dist/chunks/{pipeline-executor-O77NTGLP.mjs → pipeline-executor-DRYEEFDR.mjs} +6 -5
  80. package/dist/chunks/prompt-RRHZX4YT.mjs +13 -0
  81. package/dist/chunks/remote-access-cli-GLEEP7DI.mjs +268 -0
  82. package/dist/chunks/remote-hello-UFWUBDQI.mjs +37 -0
  83. package/dist/chunks/sdk-OJOAF4DP.mjs +30014 -0
  84. package/dist/chunks/{slack-OCNNF4DX.mjs → slack-IYC5RAB5.mjs} +3 -4
  85. package/dist/chunks/{store-HUVDJPYN.mjs → store-55CQSAOX.mjs} +7 -3
  86. package/dist/chunks/tailscale-WLJATFMB.mjs +25 -0
  87. package/dist/chunks/{theme-SFE3JMA2.mjs → theme-HLBDTF6F.mjs} +1 -1
  88. package/dist/chunks/{themes-YLXLOIJF.mjs → themes-BQ72P446.mjs} +2 -2
  89. package/dist/chunks/{token-6G3HCMNX.mjs → token-6D22WECM.mjs} +20 -16
  90. package/dist/chunks/{token-util-UXYSDQIW.mjs → token-util-YF3ZWBZ4.mjs} +1 -2
  91. package/dist/chunks/{tui-UQJLK7XI.mjs → tui-RAUVFOYY.mjs} +21 -18
  92. package/dist/chunks/{welcome-XHXFV7SH.mjs → welcome-J5JZZAM5.mjs} +1 -1
  93. package/dist/chunks/{whatsapp-AJMRQBT7.mjs → whatsapp-YJFFVN4Q.mjs} +9 -9
  94. package/package.json +1 -1
  95. package/dist/chunks/chunk-GKKCMXIZ.mjs +0 -94
  96. package/dist/chunks/chunk-IHDDCZBS.mjs +0 -112
  97. package/dist/chunks/chunk-KWFOS5WC.mjs +0 -41
  98. package/dist/chunks/chunk-UEZR2CNS.mjs +0 -65
  99. package/dist/chunks/chunk-VMHTYDH4.mjs +0 -172
  100. package/dist/chunks/chunk-Y2QA53AN.mjs +0 -259
  101. package/dist/chunks/{chunk-NBTUWMGP.mjs → chunk-2MTE22CR.mjs} +3 -3
  102. package/dist/chunks/{chunk-APRU6PHC.mjs → chunk-JZ7AQNPM.mjs} +3 -3
  103. package/dist/chunks/{telegram-2EFGKIVK.mjs → telegram-JYY2VDTI.mjs} +5 -5
@@ -0,0 +1,678 @@
1
+ import { createRequire as __adfCreateRequire } from 'node:module';
2
+ import { fileURLToPath as __adfFileURLToPath } from 'node:url';
3
+ import { dirname as __adfDirname } from 'node:path';
4
+ const require = __adfCreateRequire(import.meta.url);
5
+ const __filename = __adfFileURLToPath(import.meta.url);
6
+ const __dirname = __adfDirname(__filename);
7
+ import {
8
+ WELCOME_OVERLAY
9
+ } from "./chunk-O7XKQ6CH.mjs";
10
+ import {
11
+ mcp_config_exports,
12
+ mcp_registry_exports,
13
+ provider_catalog_exports
14
+ } from "./chunk-SOSPQPEN.mjs";
15
+ import {
16
+ Box_default,
17
+ Text
18
+ } from "./chunk-3AT7IIP7.mjs";
19
+ import {
20
+ useTheme
21
+ } from "./chunk-NZLEPJ5M.mjs";
22
+ import {
23
+ require_jsx_runtime
24
+ } from "./chunk-7CV2SA3H.mjs";
25
+ import {
26
+ cjs
27
+ } from "./chunk-SGUTYISF.mjs";
28
+ import {
29
+ require_react
30
+ } from "./chunk-6GJ4QHRI.mjs";
31
+ import {
32
+ adapter_registry_exports
33
+ } from "./chunk-UYY5M2PB.mjs";
34
+ import {
35
+ __toESM
36
+ } from "./chunk-M2RX3S2T.mjs";
37
+
38
+ // src/main/tui/ui/KeyHint.tsx
39
+ var import_react2 = __toESM(require_react(), 1);
40
+
41
+ // src/main/tui/app/keys.tsx
42
+ var import_react = __toESM(require_react(), 1), import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
43
+ function elementRect(element) {
44
+ if (!element?.yogaNode) return null;
45
+ let x = 0, y = 0;
46
+ for (let node = element; node; node = node.parentNode)
47
+ node.yogaNode && (x += node.yogaNode.getComputedLeft(), y += node.yogaNode.getComputedTop());
48
+ return { x, y, width: element.yogaNode.getComputedWidth(), height: element.yogaNode.getComputedHeight() };
49
+ }
50
+ function rectContains(rect, x, y) {
51
+ return !!rect && x >= rect.x && x < rect.x + rect.width && y >= rect.y && y < rect.y + rect.height;
52
+ }
53
+ function createKeyRouter() {
54
+ let bindings = [], wheels = [], clicks = [], nextId = 1;
55
+ return {
56
+ registerClick(binding) {
57
+ return clicks.push(binding), () => {
58
+ let index = clicks.indexOf(binding);
59
+ index >= 0 && clicks.splice(index, 1);
60
+ };
61
+ },
62
+ click(event) {
63
+ let best = null;
64
+ for (let binding of clicks) {
65
+ if (!binding.active.current) continue;
66
+ let rect = elementRect(binding.ref.current);
67
+ if (!rect || !rectContains(rect, event.x, event.y)) continue;
68
+ let area = rect.width * rect.height;
69
+ (!best || area <= best.area) && (best = { binding, area });
70
+ }
71
+ return best ? best.binding.handler.current(event) === !0 : !1;
72
+ },
73
+ registerWheel(binding) {
74
+ return wheels.push(binding), () => {
75
+ let index = wheels.indexOf(binding);
76
+ index >= 0 && wheels.splice(index, 1);
77
+ };
78
+ },
79
+ wheel(event, context) {
80
+ let best = null;
81
+ for (let binding of wheels) {
82
+ if (!binding.active.current || binding.layer === "overlay" !== context.overlayOpen) continue;
83
+ let rect = elementRect(binding.ref.current);
84
+ if (!rect || !rectContains(rect, event.x, event.y)) continue;
85
+ let area = rect.width * rect.height;
86
+ (!best || area <= best.area) && (best = { binding, area });
87
+ }
88
+ return !best || event.delta === 0 ? !!best : (best.binding.handler.current(event.delta, event), !0);
89
+ },
90
+ register(layer, handler, active) {
91
+ let binding = { id: nextId++, layer, handler, active };
92
+ return bindings.push(binding), () => {
93
+ let index = bindings.indexOf(binding);
94
+ index >= 0 && bindings.splice(index, 1);
95
+ };
96
+ },
97
+ dispatch(input, key, context) {
98
+ let order = context.overlayOpen ? ["overlay", "global"] : context.focus === "input" || context.focus === "tabs" ? [context.focus, "global"] : [context.focus, "view", "global"];
99
+ for (let layer of order) {
100
+ let candidates = bindings.filter((b) => b.layer === layer && b.active.current);
101
+ for (let i = candidates.length - 1; i >= 0; i--)
102
+ if (candidates[i].handler.current(input, key) === !0) return !0;
103
+ }
104
+ return !1;
105
+ }
106
+ };
107
+ }
108
+ var KeyRouterContext = (0, import_react.createContext)(null);
109
+ function KeyRouterProvider({ router, children }) {
110
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(KeyRouterContext.Provider, { value: router, children });
111
+ }
112
+ function useKeyRouter() {
113
+ let router = (0, import_react.useContext)(KeyRouterContext);
114
+ if (!router) throw new Error("useKeys must be used inside the TUI shell");
115
+ return router;
116
+ }
117
+ function useKeys(handler, options) {
118
+ let router = useKeyRouter(), handlerRef = (0, import_react.useRef)(handler), activeRef = (0, import_react.useRef)(options.active !== !1);
119
+ handlerRef.current = handler, activeRef.current = options.active !== !1, (0, import_react.useEffect)(() => router.register(options.layer, handlerRef, activeRef), [router, options.layer]);
120
+ }
121
+ var WHEEL_STEP = 3;
122
+ function useWheel(ref, onWheel, options = {}) {
123
+ let router = useKeyRouter(), handler = (0, import_react.useRef)(onWheel), active = (0, import_react.useRef)(options.active !== !1);
124
+ handler.current = onWheel, active.current = options.active !== !1;
125
+ let layer = options.layer ?? "main";
126
+ (0, import_react.useEffect)(() => router.registerWheel({ layer, ref, handler, active }), [router, layer, ref]);
127
+ }
128
+ function useClick(ref, onClick, options = {}) {
129
+ let router = useKeyRouter(), handler = (0, import_react.useRef)(onClick), active = (0, import_react.useRef)(options.active !== !1);
130
+ handler.current = onClick, active.current = options.active !== !1, (0, import_react.useEffect)(() => router.registerClick({ ref, handler, active }), [router, ref]);
131
+ }
132
+ function keyLabel(spec) {
133
+ let parts = spec.split("+"), ctrl = parts.some((p) => p.toLowerCase() === "ctrl");
134
+ return parts.map((part) => {
135
+ let p = part.toLowerCase();
136
+ return p === "ctrl" ? "Ctrl+" : p === "alt" || p === "meta" ? "Alt+" : p === "shift" ? "Shift+" : p === "cmd" || p === "super" ? "Cmd+" : p === "backspace" ? "Backspace" : p === "delete" || p === "del" ? "Delete" : p === "home" ? "Home" : p === "end" ? "End" : p === "enter" || p === "return" ? "Enter" : p === "esc" || p === "escape" ? "Esc" : p === "tab" ? "Tab" : p === "up" ? "\u2191" : p === "down" ? "\u2193" : p === "left" ? "\u2190" : p === "right" ? "\u2192" : p === "pgup" || p === "pageup" ? "PgUp" : p === "pgdn" || p === "pagedown" ? "PgDn" : part.length === 1 && ctrl ? part.toUpperCase() : part;
137
+ }).join("");
138
+ }
139
+
140
+ // src/main/tui/ui/KeyHint.tsx
141
+ var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
142
+ function KeyHint({ keys, label }) {
143
+ let theme = useTheme();
144
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { children: [
145
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { bold: !0, color: theme.color.accent, children: keys.split(" ").map(keyLabel).join("/") }),
146
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { color: theme.color.muted, children: [
147
+ " ",
148
+ label
149
+ ] })
150
+ ] });
151
+ }
152
+ function KeyHints({ hints }) {
153
+ let theme = useTheme();
154
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { wrap: "truncate-end", children: hints.map((hint, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react2.Fragment, { children: [
155
+ index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { color: theme.color.dim, children: [
156
+ " ",
157
+ theme.glyph.sep,
158
+ " "
159
+ ] }) : null,
160
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(KeyHint, { ...hint })
161
+ ] }, `${hint.keys}:${hint.label}`)) });
162
+ }
163
+
164
+ // src/main/tui/identity/model.ts
165
+ var IDENTITY_OVERLAY = "identity", NEW_AGENT_OVERLAY = "new-agent", IDENTITY_BANNER_KEY = "shell.identity.banner";
166
+ var SAVED_WORD = "saved";
167
+ function shortDid(did, keep = 6) {
168
+ if (!did) return "";
169
+ let m = did.match(/^(did:[a-z0-9]+:)(.*)$/i);
170
+ if (!m) return did.length > 16 ? `${did.slice(0, 10)}\u2026${did.slice(-4)}` : did;
171
+ let id = m[2];
172
+ return id.length > keep + 5 ? `${m[1]}${id.slice(0, keep)}\u2026${id.slice(-4)}` : did;
173
+ }
174
+ function normalizePhrase(text) {
175
+ return phraseWords(text).join(" ");
176
+ }
177
+ function phraseWords(text) {
178
+ return text.toLowerCase().split(/[\s,;]+/).map((w) => w.replace(/^\d+[.):-]?$/, "").replace(/^\d+[.):-]/, "").replace(/[^a-z]/g, "")).filter(Boolean);
179
+ }
180
+ function isLoopbackUrl(url) {
181
+ try {
182
+ let host = new URL(url).hostname.replace(/^\[|\]$/g, "").toLowerCase();
183
+ return host === "localhost" || host === "::1" || /^127\./.test(host) || host.startsWith("::ffff:127.");
184
+ } catch {
185
+ return !1;
186
+ }
187
+ }
188
+ var LOOPBACK_ONLY_TEXT = "The seed phrase and passphrase never travel over the network: create, restore and unlock only work from the daemon\u2019s own machine. Run the terminal app (`adf`) or `adf identity` there.", IDENTITY_EXPLAINER = "Your owner identity proves these agents are yours. It is 12 words: the same words restore it anywhere, in the terminal or in ADF Studio.";
189
+ function identityErrorText(code, fallback, identity) {
190
+ switch (code) {
191
+ case "invalid_mnemonic":
192
+ return "Those are not 12 valid seed words. Check each word and the order.";
193
+ case "owner_mismatch":
194
+ return identity?.ownerDid ? `That phrase belongs to a different owner. This machine\u2019s owner is ${shortDid(identity.ownerDid)}: enter its phrase. (To switch owners, import the new phrase in ADF Studio.)` : "That phrase belongs to a different owner than this machine\u2019s.";
195
+ case "wrong_passphrase":
196
+ return "Wrong passphrase.";
197
+ case "weak_passphrase":
198
+ return "Choose a passphrase of at least 8 characters.";
199
+ case "passphrase_required":
200
+ return "This machine keeps the identity in a passphrase-protected file: enter the passphrase.";
201
+ case "loopback_only":
202
+ return LOOPBACK_ONLY_TEXT;
203
+ case "identity_exists":
204
+ return "An owner identity already exists here; nothing was created.";
205
+ case "nothing_to_unlock":
206
+ return "There is nothing to unlock yet: create or restore an identity.";
207
+ default:
208
+ return fallback;
209
+ }
210
+ }
211
+ function identityBadge(identity) {
212
+ if (!identity) return null;
213
+ switch (identity.status) {
214
+ case "ready":
215
+ return identity.backupConfirmed ? { text: `owner ${shortDid(identity.ownerDid, 4).replace(/^did:key:/, "")}`, tone: "muted" } : { text: `owner ${shortDid(identity.ownerDid, 4).replace(/^did:key:/, "")} not backed up`, tone: "warn" };
216
+ case "locked":
217
+ return { text: "owner locked", tone: "warn" };
218
+ case "restore-needed":
219
+ return { text: "owner: restore", tone: "warn" };
220
+ default:
221
+ return { text: "no owner", tone: "warn" };
222
+ }
223
+ }
224
+ function onboardingLines(identity) {
225
+ switch (identity.status) {
226
+ case "locked":
227
+ return { title: "Your owner identity is locked", next: "Unlock it with its passphrase to create and seal agents." };
228
+ case "restore-needed":
229
+ return {
230
+ title: "Restore your owner identity",
231
+ next: `This machine already belongs to ${shortDid(identity.ownerDid)}: enter the 12-word phrase for this owner.`
232
+ };
233
+ case "ready":
234
+ return { title: "Owner identity ready", next: "" };
235
+ default:
236
+ return { title: "Set up your owner identity", next: "Create a new one, or restore yours from its 12-word seed phrase." };
237
+ }
238
+ }
239
+ function onboardingChoices(identity) {
240
+ switch (identity.status) {
241
+ case "none":
242
+ return [
243
+ { key: "c", label: "Create new", mode: "create" },
244
+ { key: "r", label: "Restore from seed phrase", mode: "restore" }
245
+ ];
246
+ case "restore-needed":
247
+ return [{ key: "r", label: "Restore from seed phrase", mode: "restore" }];
248
+ case "locked":
249
+ return identity.storage === "file" && identity.passphraseRequired ? [{ key: "u", label: "Unlock with passphrase", mode: "unlock" }] : [];
250
+ default:
251
+ return [];
252
+ }
253
+ }
254
+ function passphraseProblem(first, second, isNew) {
255
+ return first ? isNew ? first.length < 8 ? "At least 8 characters." : second !== null && first !== second ? "The two passphrases differ. Type them again." : null : null : "Enter the passphrase.";
256
+ }
257
+
258
+ // src/main/tui/identity/Onboarding.tsx
259
+ var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
260
+ function openIdentity(store, props = {}) {
261
+ store.actions.pushOverlay({ kind: IDENTITY_OVERLAY, props: { ...props } });
262
+ }
263
+ function openNewAgent(store, name) {
264
+ let identity = store.getState().identity;
265
+ if (identity && identity.status !== "ready") {
266
+ openIdentity(store, { mode: "status", then: NEW_AGENT_OVERLAY, name, reason: "Agents are sealed under your owner identity: set it up first, then the new agent follows." });
267
+ return;
268
+ }
269
+ store.actions.pushOverlay({ kind: NEW_AGENT_OVERLAY, props: name ? { name } : {} });
270
+ }
271
+ function bannerKeyOf(identity) {
272
+ return `${identity.status}:${identity.backupConfirmed ? 1 : 0}`;
273
+ }
274
+ function needsAttention(identity) {
275
+ return !!identity && (identity.status !== "ready" || !identity.backupConfirmed);
276
+ }
277
+ function identityKey(store, identity, input, panel) {
278
+ if (!identity) return !1;
279
+ if (input === "i")
280
+ return openIdentity(store), !0;
281
+ if (input === "I" && !panel && needsAttention(identity))
282
+ return store.actions.setViewState(IDENTITY_BANNER_KEY, bannerKeyOf(identity)), !0;
283
+ if (!panel) return !1;
284
+ let choice = onboardingChoices(identity).find((c) => c.key === input);
285
+ return choice ? (openIdentity(store, { mode: choice.mode }), !0) : !1;
286
+ }
287
+ function IdentityOnboarding({ identity, width, focused }) {
288
+ let theme = useTheme(), { title, next } = onboardingLines(identity), choices = onboardingChoices(identity), inner = Math.max(30, Math.min(width - 2, 72));
289
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", width: inner, marginTop: 1, children: [
290
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { bold: !0, color: theme.color.accent, children: [
291
+ theme.glyph.wordmark,
292
+ " ",
293
+ title
294
+ ] }),
295
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: " " }),
296
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { wrap: "wrap", color: theme.color.text, children: IDENTITY_EXPLAINER }),
297
+ next ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { wrap: "wrap", color: theme.color.muted, children: next }) : null,
298
+ identity.status === "locked" && choices.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { wrap: "wrap", color: theme.color.warn, children: identity.message }) : null,
299
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: " " }),
300
+ choices.map((c) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { children: [
301
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { bold: !0, color: theme.color.accent, children: [
302
+ " [",
303
+ c.key,
304
+ "]"
305
+ ] }),
306
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: theme.color.text, children: [
307
+ " ",
308
+ c.label
309
+ ] })
310
+ ] }, c.key)),
311
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: " " }),
312
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(KeyHints, { hints: focused ? [{ keys: "i", label: "details" }, { keys: "o", label: "load an existing .adf" }] : [{ keys: "shift+tab", label: "focus here to choose" }] })
313
+ ] });
314
+ }
315
+ function IdentityBanner({ identity, width }) {
316
+ let theme = useTheme(), text = identity.status === "ready" ? `Seed phrase backup not confirmed for ${shortDid(identity.ownerDid, 4)}. Make sure the 12 words are written down.` : identity.status === "locked" ? "Owner identity locked: new agents cannot be created until it is unlocked." : identity.status === "restore-needed" ? `Restore owner ${shortDid(identity.ownerDid, 4)} from its 12 words to create agents here.` : "No owner identity yet: set one up to create agents.";
317
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { wrap: "truncate-end", children: [
318
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: theme.color.warn, children: [
319
+ theme.glyph.warn,
320
+ " ",
321
+ text.slice(0, Math.max(10, width - 24))
322
+ ] }),
323
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: theme.color.dim, children: " " }),
324
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { bold: !0, color: theme.color.accent, children: "i" }),
325
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: theme.color.muted, children: " open" }),
326
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: theme.color.dim, children: [
327
+ " ",
328
+ theme.glyph.sep,
329
+ " "
330
+ ] }),
331
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { bold: !0, color: theme.color.accent, children: "I" }),
332
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: theme.color.muted, children: " hide" })
333
+ ] });
334
+ }
335
+
336
+ // src/main/tui/setup/channels.ts
337
+ var { ADAPTER_REGISTRY } = cjs(adapter_registry_exports), CHANNELS_OVERLAY = "channels", CHANNEL_ORDER = ["telegram", "discord", "slack", "email", "whatsapp"];
338
+ function channelEntries() {
339
+ let byType = new Map(ADAPTER_REGISTRY.map((e) => [e.type, e]));
340
+ return CHANNEL_ORDER.map((t) => byType.get(t)).filter((e) => !!e);
341
+ }
342
+ function findChannel(type) {
343
+ if (!type) return;
344
+ let wanted = type.trim().toLowerCase();
345
+ return channelEntries().find((e) => e.type === wanted || e.displayName.toLowerCase() === wanted);
346
+ }
347
+ function credentialFields(entry) {
348
+ return entry.credentials ?? [
349
+ ...entry.requiredEnvKeys.map((key) => ({ key, label: key, required: !0 })),
350
+ ...(entry.optionalEnvKeys ?? []).map((key) => ({ key, label: key, required: !1 }))
351
+ ];
352
+ }
353
+ var DEFAULT_ADAPTER_CONFIG = { enabled: !0, policy: { dm: "all", groups: "mention" } }, SHAPES = {
354
+ TELEGRAM_BOT_TOKEN: { test: /^\d{5,}:[A-Za-z0-9_-]{30,}$/, message: "A bot token looks like 123456789:AA\u2026 (digits, a colon, then 30+ characters)." },
355
+ DISCORD_BOT_TOKEN: { test: /^[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{20,}$/, message: "A Discord bot token has three dot-separated parts (Bot page \u2192 Reset Token)." },
356
+ DISCORD_APPLICATION_ID: { test: /^\d{15,22}$/, message: "The application ID is a long number (General Information page)." },
357
+ SLACK_APP_TOKEN: { test: /^xapp-/, message: "The app-level token starts with xapp- (Socket Mode page)." },
358
+ SLACK_BOT_TOKEN: { test: /^xoxb-/, message: "The bot token starts with xoxb- (Install App page)." },
359
+ EMAIL_USERNAME: { test: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: "Enter the full email address." }
360
+ };
361
+ function validateCredentials(entry, values) {
362
+ let errors = {};
363
+ for (let field of credentialFields(entry)) {
364
+ let value = (values[field.key] ?? "").trim();
365
+ if (!value) {
366
+ field.required && (errors[field.key] = `${field.label} is required.`);
367
+ continue;
368
+ }
369
+ if (/\s/.test(value)) {
370
+ errors[field.key] = "No spaces: paste the value exactly.";
371
+ continue;
372
+ }
373
+ let shape = SHAPES[field.key];
374
+ shape && !shape.test.test(value) && (errors[field.key] = shape.message);
375
+ }
376
+ return errors;
377
+ }
378
+ function adapterLiveState(diag, type) {
379
+ let state = diag?.states?.find((s) => s.type === type);
380
+ return state ? { status: ["connected", "connecting", "disconnected", "error"].includes(state.status) ? state.status : "unknown", ...state.error ? { error: state.error } : {} } : { status: diag?.configured?.some((c) => c.type === type) ? "not running" : "unknown" };
381
+ }
382
+ function configuredChannels(config) {
383
+ return Object.keys(config?.adapters ?? {});
384
+ }
385
+
386
+ // src/main/tui/setup/provider.ts
387
+ var { PROVIDER_CATALOG } = cjs(provider_catalog_exports), PROVIDER_OVERLAY = "provider.add", API_TYPES = /* @__PURE__ */ new Set(["anthropic", "openai", "openrouter", "openai-compatible"]), SIGN_IN = {
388
+ "chatgpt-subscription": "chatgpt",
389
+ "grok-subscription": "grok",
390
+ "claude-subscription": "claude"
391
+ };
392
+ function providerRows() {
393
+ let order = { subscription: 0, api: 1, local: 2, other: 3 };
394
+ return [...PROVIDER_CATALOG].filter((e) => e.group === "subscription" || API_TYPES.has(e.type)).sort((a, b) => (order[a.group] ?? 9) - (order[b.group] ?? 9)).map((entry) => ({
395
+ entry,
396
+ ...SIGN_IN[entry.type] ? { signIn: SIGN_IN[entry.type] } : {}
397
+ }));
398
+ }
399
+ function findProviderRow(key) {
400
+ if (!key) return;
401
+ let wanted = key.trim().toLowerCase();
402
+ return providerRows().find((r) => r.entry.key === wanted || r.entry.label.toLowerCase() === wanted || r.entry.type === wanted);
403
+ }
404
+ function keyOptional(entry) {
405
+ return entry.keyOptional === !0 || entry.group === "other";
406
+ }
407
+ function needsBaseUrl(entry) {
408
+ return entry.type === "openai-compatible";
409
+ }
410
+ function validateProvider(entry, v) {
411
+ let errors = {};
412
+ if (needsBaseUrl(entry)) {
413
+ let url = v.baseUrl.trim();
414
+ if (!url) errors.baseUrl = "The server\u2019s base URL, e.g. http://localhost:11434/v1.";
415
+ else if (/YOUR_[A-Z_]+/.test(url)) errors.baseUrl = "Replace the YOUR_\u2026 part of the URL with your own value.";
416
+ else
417
+ try {
418
+ let parsed = new URL(url);
419
+ parsed.protocol !== "http:" && parsed.protocol !== "https:" && (errors.baseUrl = "Use an http(s) URL.");
420
+ } catch {
421
+ errors.baseUrl = "Not a URL.";
422
+ }
423
+ }
424
+ let key = v.apiKey.trim();
425
+ return !key && !keyOptional(entry) ? errors.apiKey = "Paste the API key." : /\s/.test(key) && (errors.apiKey = "No spaces: paste the key exactly."), errors;
426
+ }
427
+ function providerInput(entry, v) {
428
+ let key = v.apiKey.trim();
429
+ return {
430
+ type: entry.type,
431
+ name: v.name.trim() || entry.label,
432
+ ...needsBaseUrl(entry) ? { baseUrl: v.baseUrl.trim() } : {},
433
+ ...v.defaultModel.trim() ? { defaultModel: v.defaultModel.trim() } : {},
434
+ preset: entry.key,
435
+ ...key ? { apiKey: key } : {}
436
+ };
437
+ }
438
+ function keyStorageText(storage) {
439
+ return storage === "file" ? "the daemon\u2019s passphrase-protected secret file" : "the OS keychain";
440
+ }
441
+
442
+ // src/main/tui/setup/mcp.ts
443
+ var { MCP_REGISTRY, registrationFromRegistryEntry, hasUnresolvedPlaceholderArgs, REGISTRY_ARG_PLACEHOLDER_RE } = cjs(mcp_registry_exports), { buildMcpServerConfigFromRegistration, mcpCredentialNamespace } = cjs(mcp_config_exports), MCP_OVERLAY = "mcp";
444
+ function mcpSourceRows() {
445
+ let custom = [
446
+ { kind: "npm", label: "npm package", detail: "Any MCP server published to npm (e.g. @modelcontextprotocol/server-everything)" },
447
+ { kind: "python", label: "Python package (uvx)", detail: "Any MCP server on PyPI, run with uvx (e.g. mcp-server-fetch)" },
448
+ { kind: "http", label: "Remote server (URL)", detail: "A Streamable HTTP MCP endpoint; token from an env var" }
449
+ ], catalog = MCP_REGISTRY.filter((e) => !e.deprecated).map((entry) => ({ kind: "catalog", entry, label: entry.displayName, detail: entry.description }));
450
+ return [...custom, ...catalog];
451
+ }
452
+ function parseAddTarget(arg) {
453
+ let raw = (arg ?? "").trim();
454
+ if (!raw) return {};
455
+ let rows = mcpSourceRows();
456
+ if (/^https?:\/\//i.test(raw)) {
457
+ let known = rows.find((r) => r.entry?.url === raw);
458
+ return known ? { row: known } : { row: rows.find((r) => r.kind === "http"), value: raw };
459
+ }
460
+ let prefixed = raw.match(/^(npm|python|uvx|pip):(.+)$/i);
461
+ if (prefixed) {
462
+ let kind = prefixed[1].toLowerCase() === "npm" ? "npm" : "python";
463
+ return { row: rows.find((r) => r.kind === kind), value: prefixed[2].trim() };
464
+ }
465
+ let wanted = raw.toLowerCase(), entry = rows.find((r) => r.entry && (r.entry.name === wanted || r.entry.npmPackage === raw || r.entry.pypiPackage === raw || r.entry.displayName.toLowerCase() === wanted));
466
+ return entry ? { row: entry } : { row: rows.find((r) => r.kind === "npm"), value: raw };
467
+ }
468
+ function sanitizeServerName(value) {
469
+ return value.toLowerCase().replace(/^@[^/]+\//, "").replace(/^mcp-server-|-mcp-server$|^server-|-mcp$|^mcp-/g, "").replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
470
+ }
471
+ function defaultServerName(row, value = "") {
472
+ if (row.entry) return row.entry.name;
473
+ if (row.kind === "http")
474
+ try {
475
+ return sanitizeServerName(new URL(value).hostname.split(".").slice(-2, -1)[0] ?? "");
476
+ } catch {
477
+ return "";
478
+ }
479
+ return sanitizeServerName(value.split("/").pop() ?? value);
480
+ }
481
+ function envKeysOf(row) {
482
+ let e = row.entry;
483
+ if (!e) return row.kind === "http" ? [{ key: "MCP_TOKEN", required: !1 }] : [];
484
+ let keys = [
485
+ ...e.requiredEnvKeys.map((key) => ({ key, required: !0 })),
486
+ ...(e.optionalEnvKeys ?? []).map((key) => ({ key, required: !1 })),
487
+ ...e.bearerTokenEnvVar ? [{ key: e.bearerTokenEnvVar, required: !!e.url && !e.oauth }] : [],
488
+ ...(e.headerEnv ?? []).map((h) => ({ key: h.env, required: !0 }))
489
+ ];
490
+ return keys.filter((k, i) => keys.findIndex((x) => x.key === k.key) === i);
491
+ }
492
+ function studioOnlyReason(row) {
493
+ let e = row.entry;
494
+ return e ? e.url && e.oauth && !e.bearerTokenEnvVar && !e.headerEnv?.length ? `${e.displayName} signs in with OAuth in the browser, which only ADF Studio runs today. Add it in Studio (Settings \u2192 MCP \u2192 ${e.displayName}, Connect), then it shows up here.` : e.auth || (e.credentialFiles?.length ?? 0) > 0 ? `${e.displayName} needs a one-time sign-in step (it writes a credential file), which ADF Studio runs. Add it in Studio (Settings \u2192 MCP), then it shows up here.` : null : null;
495
+ }
496
+ function validateMcpForm(row, form, taken) {
497
+ let errors = {};
498
+ if (form.name ? form.name !== sanitizeServerName(form.name) || !/^[a-z0-9][a-z0-9_-]*$/.test(form.name) ? errors.name = "Lowercase letters, digits, - and _ only." : taken.includes(form.name) && (errors.name = `This agent already has a server named ${form.name}.`) : errors.name = "Give it a name (letters, digits, - and _).", !row.entry) {
499
+ let source = form.source.trim();
500
+ if (!source) errors.source = row.kind === "http" ? "The server URL." : "The package name.";
501
+ else if (row.kind === "http")
502
+ try {
503
+ /^https?:$/.test(new URL(source).protocol) || (errors.source = "Use an http(s) URL.");
504
+ } catch {
505
+ errors.source = "Not a URL.";
506
+ }
507
+ else /\s/.test(source) && (errors.source = "One package name, no spaces.");
508
+ }
509
+ hasUnresolvedPlaceholderArgs(splitArgs(form.args)) && (errors.args = "Fill in the {placeholders}.");
510
+ for (let { key, required } of envKeysOf(row))
511
+ required && !(form.env[key] ?? "").trim() && (errors[`env:${key}`] = `${key} is required.`);
512
+ return errors;
513
+ }
514
+ function splitArgs(text) {
515
+ let out = [], pattern = /"((?:[^"\\]|\\.)*)"|'([^']*)'|(\S+)/g, m;
516
+ for (; m = pattern.exec(text); ) out.push(m[1] !== void 0 ? m[1].replace(/\\(.)/g, "$1") : m[2] ?? m[3]);
517
+ return out;
518
+ }
519
+ function joinArgs(args) {
520
+ return (args ?? []).map((a) => /\s/.test(a) ? `"${a.replace(/"/g, '\\"')}"` : a).join(" ");
521
+ }
522
+ function registrationFor(row, form) {
523
+ let envKeys = envKeysOf(row).map((k) => k.key), base = row.entry ? registrationFromRegistryEntry(row.entry, `tui:${form.name}`) : row.kind === "http" ? { id: `tui:${form.name}`, name: form.name, type: "http", url: form.source.trim(), ...form.env.MCP_TOKEN?.trim() ? { bearerTokenEnvVar: "MCP_TOKEN" } : {} } : row.kind === "python" ? { id: `tui:${form.name}`, name: form.name, type: "uvx", pypiPackage: form.source.trim(), managed: !0 } : { id: `tui:${form.name}`, name: form.name, type: "npm", npmPackage: form.source.trim(), managed: !0 }, isHttp = base.type === "http", args = splitArgs(form.args), keysWithValues = envKeys.filter((k) => (form.env[k] ?? "").trim());
524
+ return {
525
+ ...base,
526
+ name: form.name,
527
+ credentialStorage: "agent",
528
+ // Keys only: values go to the agent's identity store.
529
+ env: (row.entry ? envKeys : keysWithValues).map((key) => ({ key, value: "" })),
530
+ // Remote catalog entries that also take a token: the token path (OAuth runs in Studio only).
531
+ ...isHttp && base.oauth && base.bearerTokenEnvVar ? { oauth: !1 } : {},
532
+ ...isHttp ? {} : { args: args.length ? args : void 0 },
533
+ // Container unless the user picked the host (a catalog entry's host default is only a preselection).
534
+ runLocation: !isHttp && form.runOn === "host" ? "host" : void 0
535
+ };
536
+ }
537
+ function serverConfigFor(row, form) {
538
+ return buildMcpServerConfigFromRegistration(registrationFor(row, form));
539
+ }
540
+ function credentialNamespace(server) {
541
+ return mcpCredentialNamespace(server);
542
+ }
543
+ function packageToInstall(server) {
544
+ return server.transport === "http" ? null : server.npm_package ? { kind: "npm", name: server.npm_package } : server.pypi_package ? { kind: "python", name: server.pypi_package } : null;
545
+ }
546
+ function serverEnvKeys(server) {
547
+ return [.../* @__PURE__ */ new Set([
548
+ ...server.env_keys ?? [],
549
+ ...(server.env_schema ?? []).map((e) => e.key),
550
+ ...server.bearer_token_env_var ? [server.bearer_token_env_var] : [],
551
+ ...(server.header_env ?? []).map((h) => h.env)
552
+ ])];
553
+ }
554
+ function runsOnText(server, location) {
555
+ return location || (server ? server.transport === "http" ? "remote" : server.run_location === "host" ? "host" : server.run_location === "shared" ? "shared container" : "container" : "");
556
+ }
557
+ function serverToolDecls(tools, server) {
558
+ let prefix = `mcp_${server}_`;
559
+ return (tools ?? []).filter((t) => t.name.startsWith(prefix)).map((t) => ({ name: t.name, tool: t.name.slice(prefix.length), enabled: t.enabled !== !1 }));
560
+ }
561
+
562
+ // src/main/tui/setup/open.ts
563
+ function channelsIdentityReady(store) {
564
+ let identity = store.getState().identity;
565
+ return !identity || identity.status === "ready";
566
+ }
567
+ function secretStoreReady(store) {
568
+ let identity = store.getState().identity;
569
+ return identity ? identity.storage === "keychain" ? identity.status !== "locked" : identity.status === "ready" : !0;
570
+ }
571
+ function openChannels(store, props = {}) {
572
+ let state = store.getState(), agentId = props.agentId ?? state.selectedAgentId;
573
+ if (!agentId || !state.agents[agentId]) {
574
+ store.actions.toast("Select an agent first (sidebar or /agent), or create one with /new", "warn");
575
+ return;
576
+ }
577
+ let next = { agentId, ...props.channel ? { channel: props.channel } : {} };
578
+ if (props.channel && !channelsIdentityReady(store)) {
579
+ identityFirst(store, CHANNELS_OVERLAY, next, "Channel credentials are sealed under your owner identity: set it up first, then the channel setup follows.");
580
+ return;
581
+ }
582
+ store.actions.pushOverlay({ kind: CHANNELS_OVERLAY, props: { ...next } });
583
+ }
584
+ function openProviderAdd(store, props = {}) {
585
+ if (!secretStoreReady(store)) {
586
+ identityFirst(store, PROVIDER_OVERLAY, { ...props }, "API keys go into the daemon\u2019s secret store, which is protected by your owner identity here: set it up or unlock it first.");
587
+ return;
588
+ }
589
+ store.actions.pushOverlay({ kind: PROVIDER_OVERLAY, props: { ...props } });
590
+ }
591
+ function openMcp(store, props = {}) {
592
+ let state = store.getState(), agentId = props.agentId ?? state.selectedAgentId;
593
+ if (!agentId || !state.agents[agentId]) {
594
+ store.actions.toast("Select an agent first (sidebar or /agent), or create one with /new", "warn");
595
+ return;
596
+ }
597
+ store.actions.pushOverlay({ kind: MCP_OVERLAY, props: { ...props, agentId } });
598
+ }
599
+ function openWelcome(store) {
600
+ store.actions.pushOverlay({ id: WELCOME_OVERLAY, kind: WELCOME_OVERLAY });
601
+ }
602
+ function identityFirst(store, then, thenProps, reason) {
603
+ openIdentity(store, { mode: "status", then, thenProps, reason });
604
+ }
605
+
606
+ export {
607
+ elementRect,
608
+ rectContains,
609
+ createKeyRouter,
610
+ KeyRouterProvider,
611
+ useKeyRouter,
612
+ useKeys,
613
+ WHEEL_STEP,
614
+ useWheel,
615
+ useClick,
616
+ keyLabel,
617
+ IDENTITY_OVERLAY,
618
+ NEW_AGENT_OVERLAY,
619
+ IDENTITY_BANNER_KEY,
620
+ SAVED_WORD,
621
+ shortDid,
622
+ normalizePhrase,
623
+ phraseWords,
624
+ isLoopbackUrl,
625
+ LOOPBACK_ONLY_TEXT,
626
+ IDENTITY_EXPLAINER,
627
+ identityErrorText,
628
+ identityBadge,
629
+ onboardingLines,
630
+ onboardingChoices,
631
+ passphraseProblem,
632
+ KeyHints,
633
+ openIdentity,
634
+ openNewAgent,
635
+ bannerKeyOf,
636
+ needsAttention,
637
+ identityKey,
638
+ IdentityOnboarding,
639
+ IdentityBanner,
640
+ CHANNELS_OVERLAY,
641
+ CHANNEL_ORDER,
642
+ channelEntries,
643
+ findChannel,
644
+ credentialFields,
645
+ DEFAULT_ADAPTER_CONFIG,
646
+ validateCredentials,
647
+ adapterLiveState,
648
+ configuredChannels,
649
+ PROVIDER_OVERLAY,
650
+ providerRows,
651
+ findProviderRow,
652
+ keyOptional,
653
+ needsBaseUrl,
654
+ validateProvider,
655
+ providerInput,
656
+ keyStorageText,
657
+ MCP_OVERLAY,
658
+ mcpSourceRows,
659
+ parseAddTarget,
660
+ defaultServerName,
661
+ envKeysOf,
662
+ studioOnlyReason,
663
+ validateMcpForm,
664
+ joinArgs,
665
+ serverConfigFor,
666
+ credentialNamespace,
667
+ packageToInstall,
668
+ serverEnvKeys,
669
+ runsOnText,
670
+ serverToolDecls,
671
+ channelsIdentityReady,
672
+ secretStoreReady,
673
+ openChannels,
674
+ openProviderAdd,
675
+ openMcp,
676
+ openWelcome,
677
+ identityFirst
678
+ };