@agentdocumentformat/cli 0.7.7 → 0.8.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.
Files changed (102) 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-5KXVPMBV.mjs → App-A5GUFCFJ.mjs} +279 -291
  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-YJSGLMA4.mjs} +2 -2
  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-3UGZFWIF.mjs +26 -0
  21. package/dist/chunks/{chunk-5PO5PKRV.mjs → chunk-4OGZFUKA.mjs} +126 -67
  22. package/dist/chunks/{chunk-VN7UH7I5.mjs → chunk-6XQZGYMK.mjs} +246 -67
  23. package/dist/chunks/{chunk-XNPZBLYL.mjs → chunk-75DC5EWN.mjs} +13 -2
  24. package/dist/chunks/chunk-AZYOXXVL.mjs +865 -0
  25. package/dist/chunks/{chunk-6VQEXLE2.mjs → chunk-BHY7QDCM.mjs} +41 -3
  26. package/dist/chunks/chunk-C2S64Y6F.mjs +203 -0
  27. package/dist/chunks/chunk-C4GA5SI4.mjs +12799 -0
  28. package/dist/chunks/chunk-DDTTSKGG.mjs +2443 -0
  29. package/dist/chunks/{chunk-VAUOM3IN.mjs → chunk-DLWCKKIO.mjs} +1 -1
  30. package/dist/chunks/{chunk-HPVFJYXR.mjs → chunk-ESP3VNMX.mjs} +1 -1
  31. package/dist/chunks/{chunk-QPLEAE6V.mjs → chunk-G6NBFYG5.mjs} +152 -824
  32. package/dist/chunks/{chunk-KXEF4F4E.mjs → chunk-GAZO6UMI.mjs} +1 -1
  33. package/dist/chunks/{chunk-XYTWGHFS.mjs → chunk-H3XLRWVE.mjs} +1 -1
  34. package/dist/chunks/{chunk-7T2YMTWL.mjs → chunk-H4C65MTP.mjs} +4 -4
  35. package/dist/chunks/chunk-HBOFZRUS.mjs +738 -0
  36. package/dist/chunks/chunk-JVPZIMXW.mjs +976 -0
  37. package/dist/chunks/{chunk-XYV3VCIX.mjs → chunk-JZFONJSL.mjs} +79 -20
  38. package/dist/chunks/chunk-KDDVQKCG.mjs +65 -0
  39. package/dist/chunks/chunk-KRPKWOMB.mjs +290 -0
  40. package/dist/chunks/{chunk-4N4ASPH6.mjs → chunk-LCMANRYY.mjs} +4 -254
  41. package/dist/chunks/{chunk-TPRZQ7Z4.mjs → chunk-LGL6ML37.mjs} +4 -4
  42. package/dist/chunks/chunk-LKFHERRV.mjs +145 -0
  43. package/dist/chunks/chunk-LTX74NU6.mjs +29 -0
  44. package/dist/chunks/chunk-M2F7C2UJ.mjs +425 -0
  45. package/dist/chunks/{chunk-62NE4LG4.mjs → chunk-MQAMI5BF.mjs} +5 -5
  46. package/dist/chunks/chunk-MZRXFWPQ.mjs +278 -0
  47. package/dist/chunks/{chunk-PRMGZZM5.mjs → chunk-NZLEPJ5M.mjs} +2 -0
  48. package/dist/chunks/{chunk-CD3ATSXE.mjs → chunk-NZO5O4VN.mjs} +1 -1
  49. package/dist/chunks/{chunk-I3UYSITV.mjs → chunk-O7XKQ6CH.mjs} +1 -1
  50. package/dist/chunks/chunk-P3RG5LQA.mjs +244 -0
  51. package/dist/chunks/chunk-PAK5JCO2.mjs +48 -0
  52. package/dist/chunks/chunk-PC63YFB7.mjs +34 -0
  53. package/dist/chunks/{daemon-control-HKFVSQTQ.mjs → chunk-PRPTKMQW.mjs} +67 -26
  54. package/dist/chunks/{chunk-LFMB4PAA.mjs → chunk-TKXIH27X.mjs} +974 -113
  55. package/dist/chunks/{chunk-5W7KES6P.mjs → chunk-UZPDETEU.mjs} +1 -1
  56. package/dist/chunks/chunk-V2T6NZX2.mjs +517 -0
  57. package/dist/chunks/chunk-V3MM6PCH.mjs +366 -0
  58. package/dist/chunks/chunk-WJGPNHGX.mjs +67 -0
  59. package/dist/chunks/chunk-WVTPPOKK.mjs +290 -0
  60. package/dist/chunks/{chunk-J74STFKE.mjs → chunk-WX6QCUWI.mjs} +272 -51
  61. package/dist/chunks/{chunk-Y5ZLKFLE.mjs → chunk-XNNJQCZP.mjs} +196 -165
  62. package/dist/chunks/{chunk-HDBPBORT.mjs → chunk-XT2BJUFC.mjs} +15 -6
  63. package/dist/chunks/chunk-YRMKSHW3.mjs +9076 -0
  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-33BMZB6I.mjs +29 -0
  67. package/dist/chunks/{cli-AFHQ2XTN.mjs → cli-I47IFDHJ.mjs} +797 -56
  68. package/dist/chunks/{commands-XNJMCD5L.mjs → commands-E4EQUHE5.mjs} +5 -2
  69. package/dist/chunks/{daemon-CHZHTLGR.mjs → daemon-FQ5BV3AP.mjs} +84550 -70518
  70. package/dist/chunks/daemon-control-L3CLG63P.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/{environment-NX277MQG.mjs → environment-R47X44GM.mjs} +1 -1
  75. package/dist/chunks/{grok-subscription-4PYX7TBF.mjs → grok-subscription-E74FS5EG.mjs} +5 -2
  76. package/dist/chunks/{lib-N7FCZWKH.mjs → lib-L27L5PXM.mjs} +22 -22
  77. package/dist/chunks/{open-VAU7PXT6.mjs → open-TLGS2Z3Q.mjs} +4 -4
  78. package/dist/chunks/{parser-JVY2PWSM.mjs → parser-7GARNT5L.mjs} +1 -1
  79. package/dist/chunks/{pipeline-executor-U6IMCCP3.mjs → pipeline-executor-FD4FBWQA.mjs} +8 -5
  80. package/dist/chunks/prompt-RRHZX4YT.mjs +13 -0
  81. package/dist/chunks/remote-access-cli-XXAPQWH6.mjs +268 -0
  82. package/dist/chunks/remote-hello-UFWUBDQI.mjs +37 -0
  83. package/dist/chunks/sdk-5FD2ZP7N.mjs +28422 -0
  84. package/dist/chunks/{slack-OCNNF4DX.mjs → slack-IYC5RAB5.mjs} +3 -4
  85. package/dist/chunks/{store-HUVDJPYN.mjs → store-ZRN2WCFB.mjs} +6 -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-4ZWZKD4C.mjs → tui-SPSPDADM.mjs} +17 -14
  92. package/dist/chunks/{welcome-XHXFV7SH.mjs → welcome-J5JZZAM5.mjs} +1 -1
  93. package/dist/chunks/{whatsapp-AVKT3CTJ.mjs → whatsapp-YJFFVN4Q.mjs} +8 -8
  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-ZROSGV65.mjs +0 -3112
  101. package/dist/chunks/{chunk-NBTUWMGP.mjs → chunk-2MTE22CR.mjs} +3 -3
  102. package/dist/chunks/{telegram-YI2OHNTD.mjs → telegram-JYY2VDTI.mjs} +4 -4
@@ -0,0 +1,865 @@
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
+ require_jsx_runtime
9
+ } from "./chunk-7CV2SA3H.mjs";
10
+ import {
11
+ cjs
12
+ } from "./chunk-SGUTYISF.mjs";
13
+ import {
14
+ WELCOME_OVERLAY
15
+ } from "./chunk-O7XKQ6CH.mjs";
16
+ import {
17
+ mcp_config_exports,
18
+ mcp_registry_exports
19
+ } from "./chunk-G6NBFYG5.mjs";
20
+ import {
21
+ Box_default,
22
+ Text
23
+ } from "./chunk-3AT7IIP7.mjs";
24
+ import {
25
+ useTheme
26
+ } from "./chunk-NZLEPJ5M.mjs";
27
+ import {
28
+ require_react
29
+ } from "./chunk-6GJ4QHRI.mjs";
30
+ import {
31
+ adapter_registry_exports
32
+ } from "./chunk-UYY5M2PB.mjs";
33
+ import {
34
+ __export,
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/shared/constants/provider-catalog.ts
387
+ var provider_catalog_exports = {};
388
+ __export(provider_catalog_exports, {
389
+ PROVIDER_CATALOG: () => PROVIDER_CATALOG,
390
+ PROVIDER_CATALOG_GROUPS: () => PROVIDER_CATALOG_GROUPS,
391
+ catalogEntryForProvider: () => catalogEntryForProvider,
392
+ findCatalogEntry: () => findCatalogEntry,
393
+ isSubscriptionType: () => isSubscriptionType,
394
+ nextProviderName: () => nextProviderName,
395
+ providerTypeHint: () => providerTypeHint
396
+ });
397
+ var PROVIDER_CATALOG_GROUPS = [
398
+ { id: "subscription", label: "Subscriptions", hint: "Sign in with an existing consumer plan. No API key." },
399
+ { id: "api", label: "APIs", hint: "Pay-as-you-go endpoints. Paste an API key." },
400
+ { id: "local", label: "Local", hint: "Servers running on this machine. Usually no key." },
401
+ { id: "other", label: "Other", hint: "Anything that speaks the OpenAI API." }
402
+ ], oc = (key, label, baseUrl, description, extra = {}) => ({
403
+ key,
404
+ label,
405
+ type: "openai-compatible",
406
+ group: "api",
407
+ baseUrl,
408
+ description,
409
+ keyPlaceholder: "API key",
410
+ modelPlaceholder: "model id",
411
+ ...extra
412
+ }), local = (key, label, baseUrl, description, extra = {}) => ({
413
+ key,
414
+ label,
415
+ type: "openai-compatible",
416
+ group: "local",
417
+ baseUrl,
418
+ description,
419
+ keyPlaceholder: "Usually not needed",
420
+ modelPlaceholder: "loaded model id",
421
+ keyOptional: !0,
422
+ ...extra
423
+ }), PROVIDER_CATALOG = [
424
+ // ---- Subscriptions --------------------------------------------------------
425
+ {
426
+ key: "chatgpt-subscription",
427
+ label: "ChatGPT",
428
+ type: "chatgpt-subscription",
429
+ group: "subscription",
430
+ description: "Use your ChatGPT Plus / Pro plan. Sign in with your OpenAI account.",
431
+ modelPlaceholder: "e.g. gpt-5.6-sol",
432
+ iconKey: "openai"
433
+ },
434
+ {
435
+ key: "grok-subscription",
436
+ label: "Grok",
437
+ type: "grok-subscription",
438
+ group: "subscription",
439
+ description: "Use your SuperGrok or X Premium plan. Sign in with xAI.",
440
+ modelPlaceholder: "e.g. grok-4.5",
441
+ iconKey: "x"
442
+ },
443
+ {
444
+ key: "claude-subscription",
445
+ label: "Claude",
446
+ type: "claude-subscription",
447
+ group: "subscription",
448
+ description: "Use your Claude Pro or Max plan, via Claude Code.",
449
+ modelPlaceholder: "e.g. claude-sonnet-5-5",
450
+ iconKey: "anthropic"
451
+ },
452
+ // ---- First-party APIs -----------------------------------------------------
453
+ {
454
+ key: "anthropic",
455
+ label: "Anthropic",
456
+ type: "anthropic",
457
+ group: "api",
458
+ description: "Claude models via the Anthropic API.",
459
+ keyPlaceholder: "sk-ant-...",
460
+ modelPlaceholder: "e.g. claude-sonnet-4-5",
461
+ iconKey: "anthropic",
462
+ keysUrl: "https://console.anthropic.com/settings/keys"
463
+ },
464
+ {
465
+ key: "openai",
466
+ label: "OpenAI",
467
+ type: "openai",
468
+ group: "api",
469
+ description: "GPT and o-series models via the OpenAI API.",
470
+ keyPlaceholder: "sk-...",
471
+ modelPlaceholder: "e.g. gpt-4o, o3-mini",
472
+ iconKey: "openai",
473
+ keysUrl: "https://platform.openai.com/api-keys"
474
+ },
475
+ {
476
+ key: "openrouter",
477
+ label: "OpenRouter",
478
+ type: "openrouter",
479
+ group: "api",
480
+ description: "One key for hundreds of models across providers.",
481
+ keyPlaceholder: "sk-or-...",
482
+ modelPlaceholder: "e.g. anthropic/claude-sonnet-4",
483
+ iconKey: "openrouter",
484
+ keysUrl: "https://openrouter.ai/keys"
485
+ },
486
+ // ---- OpenAI-compatible hosted APIs ---------------------------------------
487
+ oc("gemini", "Google Gemini", "https://generativelanguage.googleapis.com/v1beta/openai", "Gemini models through the OpenAI-compatible endpoint.", { iconKey: "gemini", keysUrl: "https://aistudio.google.com/apikey", modelPlaceholder: "e.g. gemini-2.5-pro" }),
488
+ oc("xai", "xAI", "https://api.x.ai/v1", "Grok models via the xAI API.", { iconKey: "x", keysUrl: "https://console.x.ai", modelPlaceholder: "e.g. grok-4" }),
489
+ oc("mistral", "Mistral", "https://api.mistral.ai/v1", "Mistral and Codestral models.", { iconKey: "mistral", keysUrl: "https://console.mistral.ai/api-keys", modelPlaceholder: "e.g. mistral-large-latest" }),
490
+ oc("deepseek", "DeepSeek", "https://api.deepseek.com/v1", "DeepSeek chat and reasoner models.", { iconKey: "deepseek", keysUrl: "https://platform.deepseek.com/api_keys", modelPlaceholder: "e.g. deepseek-chat" }),
491
+ oc("groq", "Groq", "https://api.groq.com/openai/v1", "Fast inference for open models on LPUs.", { keysUrl: "https://console.groq.com/keys", modelPlaceholder: "e.g. llama-3.3-70b-versatile" }),
492
+ oc("cerebras", "Cerebras", "https://api.cerebras.ai/v1", "Very fast inference for open models.", { keysUrl: "https://cloud.cerebras.ai", modelPlaceholder: "e.g. llama-3.3-70b" }),
493
+ oc("together", "Together AI", "https://api.together.xyz/v1", "Open models, fine-tunes, and dedicated endpoints.", { keysUrl: "https://api.together.ai/settings/api-keys", modelPlaceholder: "e.g. meta-llama/Llama-3.3-70B-Instruct-Turbo" }),
494
+ oc("fireworks", "Fireworks AI", "https://api.fireworks.ai/inference/v1", "Fast serverless inference for open models.", { keysUrl: "https://fireworks.ai/account/api-keys", modelPlaceholder: "e.g. accounts/fireworks/models/llama-v3p3-70b-instruct" }),
495
+ oc("perplexity", "Perplexity", "https://api.perplexity.ai", "Sonar models with built-in web search.", { iconKey: "perplexity", keysUrl: "https://www.perplexity.ai/settings/api", modelPlaceholder: "e.g. sonar-pro" }),
496
+ oc("cohere", "Cohere", "https://api.cohere.ai/compatibility/v1", "Command models through the compatibility API.", { keysUrl: "https://dashboard.cohere.com/api-keys", modelPlaceholder: "e.g. command-a-03-2025" }),
497
+ oc("huggingface", "Hugging Face", "https://router.huggingface.co/v1", "Inference Providers router. Uses your HF token.", { iconKey: "huggingface", keysUrl: "https://huggingface.co/settings/tokens", keyPlaceholder: "hf_...", modelPlaceholder: "e.g. meta-llama/Llama-3.3-70B-Instruct" }),
498
+ oc("nvidia", "NVIDIA NIM", "https://integrate.api.nvidia.com/v1", "Hosted NIM endpoints on build.nvidia.com.", { iconKey: "nvidia", keysUrl: "https://build.nvidia.com", keyPlaceholder: "nvapi-...", modelPlaceholder: "e.g. meta/llama-3.3-70b-instruct" }),
499
+ oc("vercel-ai-gateway", "Vercel AI Gateway", "https://ai-gateway.vercel.sh/v1", "Route to many providers through one Vercel key.", { iconKey: "vercel", keysUrl: "https://vercel.com/dashboard/ai-gateway", modelPlaceholder: "e.g. anthropic/claude-sonnet-4" }),
500
+ oc("cloudflare", "Cloudflare Workers AI", "https://api.cloudflare.com/client/v4/accounts/YOUR_ACCOUNT_ID/ai/v1", "Open models at the edge. Replace YOUR_ACCOUNT_ID in the base URL.", { iconKey: "cloudflare", keysUrl: "https://dash.cloudflare.com/profile/api-tokens", modelPlaceholder: "e.g. @cf/meta/llama-3.3-70b-instruct-fp8-fast" }),
501
+ oc("azure-openai", "Azure OpenAI", "https://YOUR_RESOURCE.openai.azure.com/openai/v1", "Azure-hosted OpenAI models. Replace YOUR_RESOURCE in the base URL.", { keysUrl: "https://portal.azure.com", modelPlaceholder: "your deployment name" }),
502
+ oc("deepinfra", "DeepInfra", "https://api.deepinfra.com/v1/openai", "Low-cost hosting for open models.", { keysUrl: "https://deepinfra.com/dash/api_keys", modelPlaceholder: "e.g. meta-llama/Llama-3.3-70B-Instruct" }),
503
+ oc("sambanova", "SambaNova", "https://api.sambanova.ai/v1", "Fast inference on SambaNova RDUs.", { keysUrl: "https://cloud.sambanova.ai/apis", modelPlaceholder: "e.g. Meta-Llama-3.3-70B-Instruct" }),
504
+ oc("nebius", "Nebius", "https://api.studio.nebius.com/v1", "Nebius AI Studio open-model endpoints.", { keysUrl: "https://studio.nebius.com/settings/api-keys", modelPlaceholder: "e.g. meta-llama/Llama-3.3-70B-Instruct" }),
505
+ oc("hyperbolic", "Hyperbolic", "https://api.hyperbolic.xyz/v1", "Open models on decentralized GPU capacity.", { keysUrl: "https://app.hyperbolic.xyz/settings", modelPlaceholder: "e.g. meta-llama/Llama-3.3-70B-Instruct" }),
506
+ oc("novita", "Novita AI", "https://api.novita.ai/v3/openai", "Serverless open-model inference.", { keysUrl: "https://novita.ai/settings/key-management", modelPlaceholder: "e.g. meta-llama/llama-3.3-70b-instruct" }),
507
+ oc("baseten", "Baseten", "https://inference.baseten.co/v1", "Model APIs and dedicated deployments.", { keysUrl: "https://app.baseten.co/settings/api_keys", modelPlaceholder: "e.g. deepseek-ai/DeepSeek-V3-0324" }),
508
+ oc("scaleway", "Scaleway", "https://api.scaleway.ai/v1", "EU-hosted generative APIs.", { iconKey: "scaleway", keysUrl: "https://console.scaleway.com/iam/api-keys", modelPlaceholder: "e.g. llama-3.3-70b-instruct" }),
509
+ oc("venice", "Venice", "https://api.venice.ai/api/v1", "Private, uncensored open-model inference.", { keysUrl: "https://venice.ai/settings/api", modelPlaceholder: "e.g. llama-3.3-70b" }),
510
+ oc("kluster", "kluster.ai", "https://api.kluster.ai/v1", "Open-model inference with batch pricing.", { keysUrl: "https://platform.kluster.ai/apikeys", modelPlaceholder: "e.g. deepseek-ai/DeepSeek-V3-0324" }),
511
+ oc("moonshot", "Moonshot (Kimi)", "https://api.moonshot.ai/v1", "Kimi models from Moonshot AI.", { iconKey: "kimi", keysUrl: "https://platform.moonshot.ai/console/api-keys", modelPlaceholder: "e.g. kimi-k2-0711-preview" }),
512
+ oc("zai", "Z.ai (GLM)", "https://api.z.ai/api/paas/v4", "GLM models from Zhipu / Z.ai.", { keysUrl: "https://z.ai/manage-apikey/apikey-list", modelPlaceholder: "e.g. glm-4.5" }),
513
+ oc("qwen", "Qwen (Alibaba)", "https://dashscope-intl.aliyuncs.com/compatible-mode/v1", "Qwen models via Model Studio (international).", { iconKey: "qwen", keysUrl: "https://modelstudio.console.alibabacloud.com/?tab=playground#/api-key", modelPlaceholder: "e.g. qwen-plus" }),
514
+ oc("minimax", "MiniMax", "https://api.minimax.io/v1", "MiniMax text models.", { iconKey: "minimax", keysUrl: "https://platform.minimax.io/user-center/basic-information/interface-key", modelPlaceholder: "e.g. MiniMax-M1" }),
515
+ oc("inception", "Inception", "https://api.inceptionlabs.ai/v1", "Mercury diffusion language models.", { keysUrl: "https://platform.inceptionlabs.ai", modelPlaceholder: "e.g. mercury-coder" }),
516
+ // ---- Local servers ---------------------------------------------------------
517
+ local("lmstudio", "LM Studio", "http://localhost:1234/v1", "Local server from the LM Studio app.", { iconKey: "lmstudio" }),
518
+ local("ollama", "Ollama", "http://localhost:11434/v1", "Local models served by Ollama.", { iconKey: "ollama", modelPlaceholder: "e.g. llama3.3" }),
519
+ local("vllm", "vLLM", "http://localhost:8000/v1", "vLLM OpenAI-compatible server.", { iconKey: "vllm" }),
520
+ local("llamacpp", "llama.cpp", "http://localhost:8080/v1", "llama-server from llama.cpp."),
521
+ local("litellm", "LiteLLM", "http://localhost:4000/v1", "LiteLLM proxy in front of any provider.", { keyOptional: !1, keyPlaceholder: "Proxy key, if set" }),
522
+ local("jan", "Jan", "http://localhost:1337/v1", "Local server from the Jan app."),
523
+ local("localai", "LocalAI", "http://localhost:8080/v1", "LocalAI drop-in OpenAI server."),
524
+ local("tgwui", "text-generation-webui", "http://localhost:5000/v1", "oobabooga OpenAI extension."),
525
+ // ---- Other -----------------------------------------------------------------
526
+ {
527
+ key: "openai-compatible",
528
+ label: "OpenAI-compatible",
529
+ type: "openai-compatible",
530
+ group: "other",
531
+ description: "Any endpoint that speaks the OpenAI chat API. Enter the base URL.",
532
+ keyPlaceholder: "Optional",
533
+ modelPlaceholder: "model id"
534
+ }
535
+ ], BY_KEY = new Map(PROVIDER_CATALOG.map((e) => [e.key, e]));
536
+ function findCatalogEntry(key) {
537
+ return key ? BY_KEY.get(key) : void 0;
538
+ }
539
+ function catalogEntryForProvider(p) {
540
+ return findCatalogEntry(p.preset) ?? findCatalogEntry(p.type);
541
+ }
542
+ function nextProviderName(label, existing) {
543
+ let taken = new Set(existing.map((p) => p.name.trim().toLowerCase()));
544
+ if (!taken.has(label.toLowerCase())) return label;
545
+ for (let n = 2; n < 1e3; n++) {
546
+ let candidate = `${label} ${n}`;
547
+ if (!taken.has(candidate.toLowerCase())) return candidate;
548
+ }
549
+ return `${label} ${Date.now()}`;
550
+ }
551
+ function providerTypeHint(type) {
552
+ switch (type) {
553
+ case "anthropic":
554
+ return "Anthropic API";
555
+ case "openai":
556
+ return "OpenAI API";
557
+ case "openrouter":
558
+ return "OpenRouter API";
559
+ case "openai-compatible":
560
+ return "OpenAI-compatible API";
561
+ case "chatgpt-subscription":
562
+ return "ChatGPT subscription (OAuth)";
563
+ case "grok-subscription":
564
+ return "Grok subscription (OAuth)";
565
+ case "claude-subscription":
566
+ return "Claude subscription (via Claude Code)";
567
+ }
568
+ }
569
+ function isSubscriptionType(type) {
570
+ return type === "chatgpt-subscription" || type === "grok-subscription" || type === "claude-subscription";
571
+ }
572
+
573
+ // src/main/tui/setup/provider.ts
574
+ var { PROVIDER_CATALOG: PROVIDER_CATALOG2 } = cjs(provider_catalog_exports), PROVIDER_OVERLAY = "provider.add", API_TYPES = /* @__PURE__ */ new Set(["anthropic", "openai", "openrouter", "openai-compatible"]), SIGN_IN = {
575
+ "chatgpt-subscription": "chatgpt",
576
+ "grok-subscription": "grok",
577
+ "claude-subscription": "claude"
578
+ };
579
+ function providerRows() {
580
+ let order = { subscription: 0, api: 1, local: 2, other: 3 };
581
+ return [...PROVIDER_CATALOG2].filter((e) => e.group === "subscription" || API_TYPES.has(e.type)).sort((a, b) => (order[a.group] ?? 9) - (order[b.group] ?? 9)).map((entry) => ({
582
+ entry,
583
+ ...SIGN_IN[entry.type] ? { signIn: SIGN_IN[entry.type] } : {}
584
+ }));
585
+ }
586
+ function findProviderRow(key) {
587
+ if (!key) return;
588
+ let wanted = key.trim().toLowerCase();
589
+ return providerRows().find((r) => r.entry.key === wanted || r.entry.label.toLowerCase() === wanted || r.entry.type === wanted);
590
+ }
591
+ function keyOptional(entry) {
592
+ return entry.keyOptional === !0 || entry.group === "other";
593
+ }
594
+ function needsBaseUrl(entry) {
595
+ return entry.type === "openai-compatible";
596
+ }
597
+ function validateProvider(entry, v) {
598
+ let errors = {};
599
+ if (needsBaseUrl(entry)) {
600
+ let url = v.baseUrl.trim();
601
+ if (!url) errors.baseUrl = "The server\u2019s base URL, e.g. http://localhost:11434/v1.";
602
+ else if (/YOUR_[A-Z_]+/.test(url)) errors.baseUrl = "Replace the YOUR_\u2026 part of the URL with your own value.";
603
+ else
604
+ try {
605
+ let parsed = new URL(url);
606
+ parsed.protocol !== "http:" && parsed.protocol !== "https:" && (errors.baseUrl = "Use an http(s) URL.");
607
+ } catch {
608
+ errors.baseUrl = "Not a URL.";
609
+ }
610
+ }
611
+ let key = v.apiKey.trim();
612
+ return !key && !keyOptional(entry) ? errors.apiKey = "Paste the API key." : /\s/.test(key) && (errors.apiKey = "No spaces: paste the key exactly."), errors;
613
+ }
614
+ function providerInput(entry, v) {
615
+ let key = v.apiKey.trim();
616
+ return {
617
+ type: entry.type,
618
+ name: v.name.trim() || entry.label,
619
+ ...needsBaseUrl(entry) ? { baseUrl: v.baseUrl.trim() } : {},
620
+ ...v.defaultModel.trim() ? { defaultModel: v.defaultModel.trim() } : {},
621
+ preset: entry.key,
622
+ ...key ? { apiKey: key } : {}
623
+ };
624
+ }
625
+ function keyStorageText(storage) {
626
+ return storage === "file" ? "the daemon\u2019s passphrase-protected secret file" : "the OS keychain";
627
+ }
628
+
629
+ // src/main/tui/setup/mcp.ts
630
+ var { MCP_REGISTRY, registrationFromRegistryEntry, hasUnresolvedPlaceholderArgs, REGISTRY_ARG_PLACEHOLDER_RE } = cjs(mcp_registry_exports), { buildMcpServerConfigFromRegistration, mcpCredentialNamespace } = cjs(mcp_config_exports), MCP_OVERLAY = "mcp";
631
+ function mcpSourceRows() {
632
+ let custom = [
633
+ { kind: "npm", label: "npm package", detail: "Any MCP server published to npm (e.g. @modelcontextprotocol/server-everything)" },
634
+ { kind: "python", label: "Python package (uvx)", detail: "Any MCP server on PyPI, run with uvx (e.g. mcp-server-fetch)" },
635
+ { kind: "http", label: "Remote server (URL)", detail: "A Streamable HTTP MCP endpoint; token from an env var" }
636
+ ], catalog = MCP_REGISTRY.filter((e) => !e.deprecated).map((entry) => ({ kind: "catalog", entry, label: entry.displayName, detail: entry.description }));
637
+ return [...custom, ...catalog];
638
+ }
639
+ function parseAddTarget(arg) {
640
+ let raw = (arg ?? "").trim();
641
+ if (!raw) return {};
642
+ let rows = mcpSourceRows();
643
+ if (/^https?:\/\//i.test(raw)) {
644
+ let known = rows.find((r) => r.entry?.url === raw);
645
+ return known ? { row: known } : { row: rows.find((r) => r.kind === "http"), value: raw };
646
+ }
647
+ let prefixed = raw.match(/^(npm|python|uvx|pip):(.+)$/i);
648
+ if (prefixed) {
649
+ let kind = prefixed[1].toLowerCase() === "npm" ? "npm" : "python";
650
+ return { row: rows.find((r) => r.kind === kind), value: prefixed[2].trim() };
651
+ }
652
+ 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));
653
+ return entry ? { row: entry } : { row: rows.find((r) => r.kind === "npm"), value: raw };
654
+ }
655
+ function sanitizeServerName(value) {
656
+ return value.toLowerCase().replace(/^@[^/]+\//, "").replace(/^mcp-server-|-mcp-server$|^server-|-mcp$|^mcp-/g, "").replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
657
+ }
658
+ function defaultServerName(row, value = "") {
659
+ if (row.entry) return row.entry.name;
660
+ if (row.kind === "http")
661
+ try {
662
+ return sanitizeServerName(new URL(value).hostname.split(".").slice(-2, -1)[0] ?? "");
663
+ } catch {
664
+ return "";
665
+ }
666
+ return sanitizeServerName(value.split("/").pop() ?? value);
667
+ }
668
+ function envKeysOf(row) {
669
+ let e = row.entry;
670
+ if (!e) return row.kind === "http" ? [{ key: "MCP_TOKEN", required: !1 }] : [];
671
+ let keys = [
672
+ ...e.requiredEnvKeys.map((key) => ({ key, required: !0 })),
673
+ ...(e.optionalEnvKeys ?? []).map((key) => ({ key, required: !1 })),
674
+ ...e.bearerTokenEnvVar ? [{ key: e.bearerTokenEnvVar, required: !!e.url && !e.oauth }] : [],
675
+ ...(e.headerEnv ?? []).map((h) => ({ key: h.env, required: !0 }))
676
+ ];
677
+ return keys.filter((k, i) => keys.findIndex((x) => x.key === k.key) === i);
678
+ }
679
+ function studioOnlyReason(row) {
680
+ let e = row.entry;
681
+ 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;
682
+ }
683
+ function validateMcpForm(row, form, taken) {
684
+ let errors = {};
685
+ 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) {
686
+ let source = form.source.trim();
687
+ if (!source) errors.source = row.kind === "http" ? "The server URL." : "The package name.";
688
+ else if (row.kind === "http")
689
+ try {
690
+ /^https?:$/.test(new URL(source).protocol) || (errors.source = "Use an http(s) URL.");
691
+ } catch {
692
+ errors.source = "Not a URL.";
693
+ }
694
+ else /\s/.test(source) && (errors.source = "One package name, no spaces.");
695
+ }
696
+ hasUnresolvedPlaceholderArgs(splitArgs(form.args)) && (errors.args = "Fill in the {placeholders}.");
697
+ for (let { key, required } of envKeysOf(row))
698
+ required && !(form.env[key] ?? "").trim() && (errors[`env:${key}`] = `${key} is required.`);
699
+ return errors;
700
+ }
701
+ function splitArgs(text) {
702
+ let out = [], pattern = /"((?:[^"\\]|\\.)*)"|'([^']*)'|(\S+)/g, m;
703
+ for (; m = pattern.exec(text); ) out.push(m[1] !== void 0 ? m[1].replace(/\\(.)/g, "$1") : m[2] ?? m[3]);
704
+ return out;
705
+ }
706
+ function joinArgs(args) {
707
+ return (args ?? []).map((a) => /\s/.test(a) ? `"${a.replace(/"/g, '\\"')}"` : a).join(" ");
708
+ }
709
+ function registrationFor(row, form) {
710
+ 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());
711
+ return {
712
+ ...base,
713
+ name: form.name,
714
+ credentialStorage: "agent",
715
+ // Keys only: values go to the agent's identity store.
716
+ env: (row.entry ? envKeys : keysWithValues).map((key) => ({ key, value: "" })),
717
+ // Remote catalog entries that also take a token: the token path (OAuth runs in Studio only).
718
+ ...isHttp && base.oauth && base.bearerTokenEnvVar ? { oauth: !1 } : {},
719
+ ...isHttp ? {} : { args: args.length ? args : void 0 },
720
+ // Container unless the user picked the host (a catalog entry's host default is only a preselection).
721
+ runLocation: !isHttp && form.runOn === "host" ? "host" : void 0
722
+ };
723
+ }
724
+ function serverConfigFor(row, form) {
725
+ return buildMcpServerConfigFromRegistration(registrationFor(row, form));
726
+ }
727
+ function credentialNamespace(server) {
728
+ return mcpCredentialNamespace(server);
729
+ }
730
+ function packageToInstall(server) {
731
+ return server.transport === "http" ? null : server.npm_package ? { kind: "npm", name: server.npm_package } : server.pypi_package ? { kind: "python", name: server.pypi_package } : null;
732
+ }
733
+ function serverEnvKeys(server) {
734
+ return [.../* @__PURE__ */ new Set([
735
+ ...server.env_keys ?? [],
736
+ ...(server.env_schema ?? []).map((e) => e.key),
737
+ ...server.bearer_token_env_var ? [server.bearer_token_env_var] : [],
738
+ ...(server.header_env ?? []).map((h) => h.env)
739
+ ])];
740
+ }
741
+ function runsOnText(server, location) {
742
+ return location || (server ? server.transport === "http" ? "remote" : server.run_location === "host" ? "host" : server.run_location === "shared" ? "shared container" : "container" : "");
743
+ }
744
+ function serverToolDecls(tools, server) {
745
+ let prefix = `mcp_${server}_`;
746
+ return (tools ?? []).filter((t) => t.name.startsWith(prefix)).map((t) => ({ name: t.name, tool: t.name.slice(prefix.length), enabled: t.enabled !== !1 }));
747
+ }
748
+
749
+ // src/main/tui/setup/open.ts
750
+ function channelsIdentityReady(store) {
751
+ let identity = store.getState().identity;
752
+ return !identity || identity.status === "ready";
753
+ }
754
+ function secretStoreReady(store) {
755
+ let identity = store.getState().identity;
756
+ return identity ? identity.storage === "keychain" ? identity.status !== "locked" : identity.status === "ready" : !0;
757
+ }
758
+ function openChannels(store, props = {}) {
759
+ let state = store.getState(), agentId = props.agentId ?? state.selectedAgentId;
760
+ if (!agentId || !state.agents[agentId]) {
761
+ store.actions.toast("Select an agent first (sidebar or /agent), or create one with /new", "warn");
762
+ return;
763
+ }
764
+ let next = { agentId, ...props.channel ? { channel: props.channel } : {} };
765
+ if (props.channel && !channelsIdentityReady(store)) {
766
+ identityFirst(store, CHANNELS_OVERLAY, next, "Channel credentials are sealed under your owner identity: set it up first, then the channel setup follows.");
767
+ return;
768
+ }
769
+ store.actions.pushOverlay({ kind: CHANNELS_OVERLAY, props: { ...next } });
770
+ }
771
+ function openProviderAdd(store, props = {}) {
772
+ if (!secretStoreReady(store)) {
773
+ 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.");
774
+ return;
775
+ }
776
+ store.actions.pushOverlay({ kind: PROVIDER_OVERLAY, props: { ...props } });
777
+ }
778
+ function openMcp(store, props = {}) {
779
+ let state = store.getState(), agentId = props.agentId ?? state.selectedAgentId;
780
+ if (!agentId || !state.agents[agentId]) {
781
+ store.actions.toast("Select an agent first (sidebar or /agent), or create one with /new", "warn");
782
+ return;
783
+ }
784
+ store.actions.pushOverlay({ kind: MCP_OVERLAY, props: { ...props, agentId } });
785
+ }
786
+ function openWelcome(store) {
787
+ store.actions.pushOverlay({ id: WELCOME_OVERLAY, kind: WELCOME_OVERLAY });
788
+ }
789
+ function identityFirst(store, then, thenProps, reason) {
790
+ openIdentity(store, { mode: "status", then, thenProps, reason });
791
+ }
792
+
793
+ export {
794
+ elementRect,
795
+ rectContains,
796
+ createKeyRouter,
797
+ KeyRouterProvider,
798
+ useKeyRouter,
799
+ useKeys,
800
+ WHEEL_STEP,
801
+ useWheel,
802
+ useClick,
803
+ keyLabel,
804
+ IDENTITY_OVERLAY,
805
+ NEW_AGENT_OVERLAY,
806
+ IDENTITY_BANNER_KEY,
807
+ SAVED_WORD,
808
+ shortDid,
809
+ normalizePhrase,
810
+ phraseWords,
811
+ isLoopbackUrl,
812
+ LOOPBACK_ONLY_TEXT,
813
+ IDENTITY_EXPLAINER,
814
+ identityErrorText,
815
+ identityBadge,
816
+ onboardingLines,
817
+ onboardingChoices,
818
+ passphraseProblem,
819
+ KeyHints,
820
+ openIdentity,
821
+ openNewAgent,
822
+ bannerKeyOf,
823
+ needsAttention,
824
+ identityKey,
825
+ IdentityOnboarding,
826
+ IdentityBanner,
827
+ CHANNELS_OVERLAY,
828
+ CHANNEL_ORDER,
829
+ channelEntries,
830
+ findChannel,
831
+ credentialFields,
832
+ DEFAULT_ADAPTER_CONFIG,
833
+ validateCredentials,
834
+ adapterLiveState,
835
+ configuredChannels,
836
+ PROVIDER_OVERLAY,
837
+ providerRows,
838
+ findProviderRow,
839
+ keyOptional,
840
+ needsBaseUrl,
841
+ validateProvider,
842
+ providerInput,
843
+ keyStorageText,
844
+ MCP_OVERLAY,
845
+ mcpSourceRows,
846
+ parseAddTarget,
847
+ defaultServerName,
848
+ envKeysOf,
849
+ studioOnlyReason,
850
+ validateMcpForm,
851
+ joinArgs,
852
+ serverConfigFor,
853
+ credentialNamespace,
854
+ packageToInstall,
855
+ serverEnvKeys,
856
+ runsOnText,
857
+ serverToolDecls,
858
+ channelsIdentityReady,
859
+ secretStoreReady,
860
+ openChannels,
861
+ openProviderAdd,
862
+ openMcp,
863
+ openWelcome,
864
+ identityFirst
865
+ };