@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
@@ -4,385 +4,163 @@ import { dirname as __adfDirname } from 'node:path';
4
4
  const require = __adfCreateRequire(import.meta.url);
5
5
  const __filename = __adfFileURLToPath(import.meta.url);
6
6
  const __dirname = __adfDirname(__filename);
7
- import {
8
- require_jsx_runtime
9
- } from "./chunk-7CV2SA3H.mjs";
10
- import {
11
- WELCOME_OVERLAY
12
- } from "./chunk-I3UYSITV.mjs";
13
- import {
14
- cjs
15
- } from "./chunk-SGUTYISF.mjs";
16
- import {
17
- mcp_config_exports
18
- } from "./chunk-VMHTYDH4.mjs";
19
- import {
20
- Box_default,
21
- Text
22
- } from "./chunk-3AT7IIP7.mjs";
23
- import {
24
- useTheme
25
- } from "./chunk-PRMGZZM5.mjs";
26
- import {
27
- require_react
28
- } from "./chunk-6GJ4QHRI.mjs";
29
- import {
30
- adapter_registry_exports
31
- } from "./chunk-UYY5M2PB.mjs";
32
7
  import {
33
8
  external_exports
34
9
  } from "./chunk-ZJKXHM4Q.mjs";
35
10
  import {
36
- __export,
37
- __toESM
11
+ __export
38
12
  } from "./chunk-M2RX3S2T.mjs";
39
13
 
40
- // src/main/tui/ui/KeyHint.tsx
41
- var import_react2 = __toESM(require_react(), 1);
42
-
43
- // src/main/tui/app/keys.tsx
44
- var import_react = __toESM(require_react(), 1), import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
45
- function elementRect(element) {
46
- if (!element?.yogaNode) return null;
47
- let x = 0, y = 0;
48
- for (let node = element; node; node = node.parentNode)
49
- node.yogaNode && (x += node.yogaNode.getComputedLeft(), y += node.yogaNode.getComputedTop());
50
- return { x, y, width: element.yogaNode.getComputedWidth(), height: element.yogaNode.getComputedHeight() };
51
- }
52
- function rectContains(rect, x, y) {
53
- return !!rect && x >= rect.x && x < rect.x + rect.width && y >= rect.y && y < rect.y + rect.height;
54
- }
55
- function createKeyRouter() {
56
- let bindings = [], wheels = [], clicks = [], nextId = 1;
57
- return {
58
- registerClick(binding) {
59
- return clicks.push(binding), () => {
60
- let index = clicks.indexOf(binding);
61
- index >= 0 && clicks.splice(index, 1);
62
- };
63
- },
64
- click(event) {
65
- let best = null;
66
- for (let binding of clicks) {
67
- if (!binding.active.current) continue;
68
- let rect = elementRect(binding.ref.current);
69
- if (!rect || !rectContains(rect, event.x, event.y)) continue;
70
- let area = rect.width * rect.height;
71
- (!best || area <= best.area) && (best = { binding, area });
72
- }
73
- return best ? best.binding.handler.current(event) === !0 : !1;
74
- },
75
- registerWheel(binding) {
76
- return wheels.push(binding), () => {
77
- let index = wheels.indexOf(binding);
78
- index >= 0 && wheels.splice(index, 1);
79
- };
80
- },
81
- wheel(event, context) {
82
- let best = null;
83
- for (let binding of wheels) {
84
- if (!binding.active.current || binding.layer === "overlay" !== context.overlayOpen) continue;
85
- let rect = elementRect(binding.ref.current);
86
- if (!rect || !rectContains(rect, event.x, event.y)) continue;
87
- let area = rect.width * rect.height;
88
- (!best || area <= best.area) && (best = { binding, area });
89
- }
90
- return !best || event.delta === 0 ? !!best : (best.binding.handler.current(event.delta, event), !0);
91
- },
92
- register(layer, handler, active) {
93
- let binding = { id: nextId++, layer, handler, active };
94
- return bindings.push(binding), () => {
95
- let index = bindings.indexOf(binding);
96
- index >= 0 && bindings.splice(index, 1);
97
- };
98
- },
99
- dispatch(input, key, context) {
100
- let order = context.overlayOpen ? ["overlay", "global"] : context.focus === "input" || context.focus === "tabs" ? [context.focus, "global"] : [context.focus, "view", "global"];
101
- for (let layer of order) {
102
- let candidates = bindings.filter((b) => b.layer === layer && b.active.current);
103
- for (let i = candidates.length - 1; i >= 0; i--)
104
- if (candidates[i].handler.current(input, key) === !0) return !0;
105
- }
106
- return !1;
107
- }
108
- };
109
- }
110
- var KeyRouterContext = (0, import_react.createContext)(null);
111
- function KeyRouterProvider({ router, children }) {
112
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(KeyRouterContext.Provider, { value: router, children });
113
- }
114
- function useKeyRouter() {
115
- let router = (0, import_react.useContext)(KeyRouterContext);
116
- if (!router) throw new Error("useKeys must be used inside the TUI shell");
117
- return router;
118
- }
119
- function useKeys(handler, options) {
120
- let router = useKeyRouter(), handlerRef = (0, import_react.useRef)(handler), activeRef = (0, import_react.useRef)(options.active !== !1);
121
- handlerRef.current = handler, activeRef.current = options.active !== !1, (0, import_react.useEffect)(() => router.register(options.layer, handlerRef, activeRef), [router, options.layer]);
122
- }
123
- var WHEEL_STEP = 3;
124
- function useWheel(ref, onWheel, options = {}) {
125
- let router = useKeyRouter(), handler = (0, import_react.useRef)(onWheel), active = (0, import_react.useRef)(options.active !== !1);
126
- handler.current = onWheel, active.current = options.active !== !1;
127
- let layer = options.layer ?? "main";
128
- (0, import_react.useEffect)(() => router.registerWheel({ layer, ref, handler, active }), [router, layer, ref]);
129
- }
130
- function useClick(ref, onClick, options = {}) {
131
- let router = useKeyRouter(), handler = (0, import_react.useRef)(onClick), active = (0, import_react.useRef)(options.active !== !1);
132
- handler.current = onClick, active.current = options.active !== !1, (0, import_react.useEffect)(() => router.registerClick({ ref, handler, active }), [router, ref]);
133
- }
134
- function keyLabel(spec) {
135
- let parts = spec.split("+"), ctrl = parts.some((p) => p.toLowerCase() === "ctrl");
136
- return parts.map((part) => {
137
- let p = part.toLowerCase();
138
- 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;
139
- }).join("");
140
- }
141
-
142
- // src/main/tui/ui/KeyHint.tsx
143
- var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
144
- function KeyHint({ keys, label }) {
145
- let theme = useTheme();
146
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { children: [
147
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { bold: !0, color: theme.color.accent, children: keys.split(" ").map(keyLabel).join("/") }),
148
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { color: theme.color.muted, children: [
149
- " ",
150
- label
151
- ] })
152
- ] });
153
- }
154
- function KeyHints({ hints }) {
155
- let theme = useTheme();
156
- 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: [
157
- index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { color: theme.color.dim, children: [
158
- " ",
159
- theme.glyph.sep,
160
- " "
161
- ] }) : null,
162
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(KeyHint, { ...hint })
163
- ] }, `${hint.keys}:${hint.label}`)) });
164
- }
165
-
166
- // src/main/tui/identity/model.ts
167
- var IDENTITY_OVERLAY = "identity", NEW_AGENT_OVERLAY = "new-agent", IDENTITY_BANNER_KEY = "shell.identity.banner";
168
- var SAVED_WORD = "saved";
169
- function shortDid(did, keep = 6) {
170
- if (!did) return "";
171
- let m = did.match(/^(did:[a-z0-9]+:)(.*)$/i);
172
- if (!m) return did.length > 16 ? `${did.slice(0, 10)}\u2026${did.slice(-4)}` : did;
173
- let id = m[2];
174
- return id.length > keep + 5 ? `${m[1]}${id.slice(0, keep)}\u2026${id.slice(-4)}` : did;
175
- }
176
- function normalizePhrase(text) {
177
- return phraseWords(text).join(" ");
178
- }
179
- function phraseWords(text) {
180
- return text.toLowerCase().split(/[\s,;]+/).map((w) => w.replace(/^\d+[.):-]?$/, "").replace(/^\d+[.):-]/, "").replace(/[^a-z]/g, "")).filter(Boolean);
181
- }
182
- function isLoopbackUrl(url) {
183
- try {
184
- let host = new URL(url).hostname.replace(/^\[|\]$/g, "").toLowerCase();
185
- return host === "localhost" || host === "::1" || /^127\./.test(host) || host.startsWith("::ffff:127.");
186
- } catch {
187
- return !1;
188
- }
14
+ // src/shared/utils/mcp-config.ts
15
+ var mcp_config_exports = {};
16
+ __export(mcp_config_exports, {
17
+ MCP_EXECUTABLE_IDENTITY_FIELDS: () => MCP_EXECUTABLE_IDENTITY_FIELDS,
18
+ buildEnvSchemaFromKeys: () => buildEnvSchemaFromKeys,
19
+ buildHeaderEnvSchemaFromEntries: () => buildHeaderEnvSchemaFromEntries,
20
+ buildMcpServerConfigFromRegistration: () => buildMcpServerConfigFromRegistration,
21
+ deriveRegistrationTestPlan: () => deriveRegistrationTestPlan,
22
+ getMcpRegistrationEnvKeys: () => getMcpRegistrationEnvKeys,
23
+ isRegistrationAgentVisible: () => isRegistrationAgentVisible,
24
+ isSensitiveMcpHeader: () => isSensitiveMcpHeader,
25
+ mcpCredentialNamespace: () => mcpCredentialNamespace,
26
+ mcpCredentialRef: () => mcpCredentialRef,
27
+ pinServerConfigToRegistration: () => pinServerConfigToRegistration,
28
+ reconcileHostApprovedRegistrations: () => reconcileHostApprovedRegistrations,
29
+ registrationSourceIdentity: () => registrationSourceIdentity,
30
+ sameExecutableIdentity: () => sameExecutableIdentity,
31
+ suggestedAgentVisible: () => suggestedAgentVisible
32
+ });
33
+ function sourcePackage(source) {
34
+ let s = source;
35
+ return s.npm_package ?? s.npmPackage ?? s.pypi_package ?? s.pypiPackage;
36
+ }
37
+ function mcpCredentialNamespace(source) {
38
+ return sourcePackage(source) ?? source.name;
39
+ }
40
+ function mcpCredentialRef(source, key) {
41
+ return `mcp:${mcpCredentialNamespace(source)}:${key}`;
42
+ }
43
+ function isSensitiveMcpHeader(header) {
44
+ let normalized = header.trim().toLowerCase();
45
+ return normalized === "authorization" || normalized === "proxy-authorization" || normalized === "x-api-key" || normalized === "api-key" || normalized === "apikey" || normalized === "x-auth-token" || normalized === "x-access-token" || normalized.includes("token") || normalized.includes("secret") || normalized.includes("credential");
46
+ }
47
+ function buildEnvSchemaFromKeys(source, keys, scope, requiredKeys = keys) {
48
+ let required = new Set(requiredKeys);
49
+ return [...new Set(keys.filter(Boolean))].map((key) => ({
50
+ key,
51
+ scope,
52
+ required: required.has(key) || void 0,
53
+ credential_ref: scope === "app" ? mcpCredentialRef(source, key) : void 0
54
+ }));
189
55
  }
190
- 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.";
191
- function identityErrorText(code, fallback, identity) {
192
- switch (code) {
193
- case "invalid_mnemonic":
194
- return "Those are not 12 valid seed words. Check each word and the order.";
195
- case "owner_mismatch":
196
- 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.";
197
- case "wrong_passphrase":
198
- return "Wrong passphrase.";
199
- case "weak_passphrase":
200
- return "Choose a passphrase of at least 8 characters.";
201
- case "passphrase_required":
202
- return "This machine keeps the identity in a passphrase-protected file: enter the passphrase.";
203
- case "loopback_only":
204
- return LOOPBACK_ONLY_TEXT;
205
- case "identity_exists":
206
- return "An owner identity already exists here; nothing was created.";
207
- case "nothing_to_unlock":
208
- return "There is nothing to unlock yet: create or restore an identity.";
209
- default:
210
- return fallback;
211
- }
56
+ function buildHeaderEnvSchemaFromEntries(source, entries, appScoped = !0) {
57
+ return entries.filter((entry) => entry.header && entry.env).map((entry) => ({
58
+ header: entry.header,
59
+ env: entry.env,
60
+ required: !0,
61
+ credential_ref: appScoped ? mcpCredentialRef(source, entry.env) : void 0
62
+ }));
212
63
  }
213
- function identityBadge(identity) {
214
- if (!identity) return null;
215
- switch (identity.status) {
216
- case "ready":
217
- 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" };
218
- case "locked":
219
- return { text: "owner locked", tone: "warn" };
220
- case "restore-needed":
221
- return { text: "owner: restore", tone: "warn" };
222
- default:
223
- return { text: "no owner", tone: "warn" };
224
- }
64
+ function getMcpRegistrationEnvKeys(registration) {
65
+ return [.../* @__PURE__ */ new Set([
66
+ ...(registration.env ?? []).map((entry) => entry.key).filter(Boolean),
67
+ ...registration.bearerTokenEnvVar ? [registration.bearerTokenEnvVar] : [],
68
+ ...(registration.headerEnv ?? []).map((entry) => entry.value).filter(Boolean)
69
+ ])];
225
70
  }
226
- function onboardingLines(identity) {
227
- switch (identity.status) {
228
- case "locked":
229
- return { title: "Your owner identity is locked", next: "Unlock it with its passphrase to create and seal agents." };
230
- case "restore-needed":
231
- return {
232
- title: "Restore your owner identity",
233
- next: `This machine already belongs to ${shortDid(identity.ownerDid)}: enter the 12-word phrase for this owner.`
234
- };
235
- case "ready":
236
- return { title: "Owner identity ready", next: "" };
237
- default:
238
- return { title: "Set up your owner identity", next: "Create a new one, or restore yours from its 12-word seed phrase." };
71
+ function buildMcpServerConfigFromRegistration(registration) {
72
+ let isHttp = registration.type === "http" || !!registration.url, serverCfg = {
73
+ name: registration.name,
74
+ transport: isHttp ? "http" : "stdio"
75
+ };
76
+ if (isHttp) {
77
+ serverCfg.url = registration.url, serverCfg.source = registration.url ? `http:${registration.url}` : "http";
78
+ let staticHeaders = {};
79
+ for (let { key, value } of registration.headers ?? [])
80
+ key && value && !isSensitiveMcpHeader(key) && (staticHeaders[key] = value);
81
+ Object.keys(staticHeaders).length && (serverCfg.headers = staticHeaders), registration.headerEnv?.length && (serverCfg.header_env = buildHeaderEnvSchemaFromEntries(
82
+ registration,
83
+ registration.headerEnv.map(({ key, value }) => ({ header: key, env: value })),
84
+ (registration.credentialStorage ?? "app") !== "agent"
85
+ )), registration.oauth ? serverCfg.oauth = !0 : registration.bearerTokenEnvVar && (serverCfg.bearer_token_env_var = registration.bearerTokenEnvVar);
86
+ } else registration.npmPackage ? (serverCfg.source = `npm:${registration.npmPackage}`, serverCfg.npm_package = registration.npmPackage) : registration.pypiPackage ? (serverCfg.source = `uvx:${registration.pypiPackage}`, serverCfg.pypi_package = registration.pypiPackage) : (serverCfg.source = "custom", serverCfg.command = registration.command, serverCfg.args = registration.args);
87
+ isHttp || (registration.command && (serverCfg.command = registration.command), registration.args?.length && (serverCfg.args = registration.args));
88
+ let envKeys = getMcpRegistrationEnvKeys(registration);
89
+ if (envKeys.length) {
90
+ let scope = (registration.credentialStorage ?? "app") === "agent" ? "agent" : "app";
91
+ scope === "agent" && (serverCfg.env_keys = envKeys), serverCfg.env_schema = buildEnvSchemaFromKeys(registration, envKeys, scope);
239
92
  }
93
+ return registration.toolCallTimeout && (serverCfg.tool_call_timeout_ms = registration.toolCallTimeout * 1e3), !isHttp && registration.runLocation && (serverCfg.run_location = registration.runLocation), registration.credentialFiles?.length && (serverCfg.credential_files = registration.credentialFiles.map((f) => ({
94
+ path: f.path,
95
+ ...f.required !== void 0 ? { required: f.required } : {},
96
+ ...f.writeBack !== void 0 ? { write_back: f.writeBack } : {}
97
+ }))), serverCfg;
98
+ }
99
+ function pinServerConfigToRegistration(connCfg, registration) {
100
+ let canonical = buildMcpServerConfigFromRegistration(registration), agentEnvSchema = (connCfg.env_schema ?? []).filter((e) => e.scope === "agent"), mergedEnvSchema = [
101
+ ...canonical.env_schema ?? [],
102
+ ...agentEnvSchema.filter(
103
+ (a) => !(canonical.env_schema ?? []).some((c) => c.key === a.key && c.scope === a.scope)
104
+ )
105
+ ];
106
+ return {
107
+ ...canonical,
108
+ // Agent-owned state kept from the .adf copy:
109
+ env: connCfg.env,
110
+ env_keys: connCfg.env_keys,
111
+ available_tools: connCfg.available_tools,
112
+ restricted: connCfg.restricted,
113
+ ...mergedEnvSchema.length ? { env_schema: mergedEnvSchema } : {}
114
+ };
240
115
  }
241
- function onboardingChoices(identity) {
242
- switch (identity.status) {
243
- case "none":
244
- return [
245
- { key: "c", label: "Create new", mode: "create" },
246
- { key: "r", label: "Restore from seed phrase", mode: "restore" }
247
- ];
248
- case "restore-needed":
249
- return [{ key: "r", label: "Restore from seed phrase", mode: "restore" }];
250
- case "locked":
251
- return identity.storage === "file" && identity.passphraseRequired ? [{ key: "u", label: "Unlock with passphrase", mode: "unlock" }] : [];
252
- default:
253
- return [];
254
- }
116
+ function suggestedAgentVisible(reg) {
117
+ return reg.type === "http" || !!reg.url ? !0 : reg.runLocation !== "host";
255
118
  }
256
- function passphraseProblem(first, second, isNew) {
257
- 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.";
119
+ function isRegistrationAgentVisible(reg) {
120
+ return reg.agentVisible ?? suggestedAgentVisible(reg);
258
121
  }
259
-
260
- // src/main/tui/identity/Onboarding.tsx
261
- var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
262
- function openIdentity(store, props = {}) {
263
- store.actions.pushOverlay({ kind: IDENTITY_OVERLAY, props: { ...props } });
122
+ var MCP_EXECUTABLE_IDENTITY_FIELDS = ["type", "url", "command", "args", "npmPackage", "pypiPackage"];
123
+ function sameExecutableIdentity(a, b) {
124
+ let argsA = a.args ?? [], argsB = b.args ?? [];
125
+ return a.type === b.type && a.url === b.url && a.command === b.command && a.npmPackage === b.npmPackage && a.pypiPackage === b.pypiPackage && argsA.length === argsB.length && argsA.every((arg, i) => arg === argsB[i]);
264
126
  }
265
- function openNewAgent(store, name) {
266
- let identity = store.getState().identity;
267
- if (identity && identity.status !== "ready") {
268
- 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." });
269
- return;
127
+ function deriveRegistrationTestPlan(reg, opts) {
128
+ if (reg.type === "http" || !!reg.url) {
129
+ let notes2 = reg.oauth ? ["Interactive OAuth sign-in runs in a browser during this test."] : [];
130
+ return { location: "remote http", authMode: reg.oauth ? "run" : "none", materializeFiles: !1, notes: notes2 };
270
131
  }
271
- store.actions.pushOverlay({ kind: NEW_AGENT_OVERLAY, props: name ? { name } : {} });
272
- }
273
- function bannerKeyOf(identity) {
274
- return `${identity.status}:${identity.backupConfirmed ? 1 : 0}`;
275
- }
276
- function needsAttention(identity) {
277
- return !!identity && (identity.status !== "ready" || !identity.backupConfirmed);
278
- }
279
- function identityKey(store, identity, input, panel) {
280
- if (!identity) return !1;
281
- if (input === "i")
282
- return openIdentity(store), !0;
283
- if (input === "I" && !panel && needsAttention(identity))
284
- return store.actions.setViewState(IDENTITY_BANNER_KEY, bannerKeyOf(identity)), !0;
285
- if (!panel) return !1;
286
- let choice = onboardingChoices(identity).find((c) => c.key === input);
287
- return choice ? (openIdentity(store, { mode: choice.mode }), !0) : !1;
288
- }
289
- function IdentityOnboarding({ identity, width, focused }) {
290
- let theme = useTheme(), { title, next } = onboardingLines(identity), choices = onboardingChoices(identity), inner = Math.max(30, Math.min(width - 2, 72));
291
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", width: inner, marginTop: 1, children: [
292
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { bold: !0, color: theme.color.accent, children: [
293
- theme.glyph.wordmark,
294
- " ",
295
- title
296
- ] }),
297
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: " " }),
298
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { wrap: "wrap", color: theme.color.text, children: IDENTITY_EXPLAINER }),
299
- next ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { wrap: "wrap", color: theme.color.muted, children: next }) : null,
300
- identity.status === "locked" && choices.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { wrap: "wrap", color: theme.color.warn, children: identity.message }) : null,
301
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: " " }),
302
- choices.map((c) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { children: [
303
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { bold: !0, color: theme.color.accent, children: [
304
- " [",
305
- c.key,
306
- "]"
307
- ] }),
308
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: theme.color.text, children: [
309
- " ",
310
- c.label
311
- ] })
312
- ] }, c.key)),
313
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: " " }),
314
- /* @__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" }] })
315
- ] });
316
- }
317
- function IdentityBanner({ identity, width }) {
318
- 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.";
319
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { wrap: "truncate-end", children: [
320
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: theme.color.warn, children: [
321
- theme.glyph.warn,
322
- " ",
323
- text.slice(0, Math.max(10, width - 24))
324
- ] }),
325
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: theme.color.dim, children: " " }),
326
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { bold: !0, color: theme.color.accent, children: "i" }),
327
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: theme.color.muted, children: " open" }),
328
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: theme.color.dim, children: [
329
- " ",
330
- theme.glyph.sep,
331
- " "
332
- ] }),
333
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { bold: !0, color: theme.color.accent, children: "I" }),
334
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: theme.color.muted, children: " hide" })
335
- ] });
336
- }
337
-
338
- // src/main/tui/setup/channels.ts
339
- var { ADAPTER_REGISTRY } = cjs(adapter_registry_exports), CHANNELS_OVERLAY = "channels", CHANNEL_ORDER = ["telegram", "discord", "slack", "email", "whatsapp"];
340
- function channelEntries() {
341
- let byType = new Map(ADAPTER_REGISTRY.map((e) => [e.type, e]));
342
- return CHANNEL_ORDER.map((t) => byType.get(t)).filter((e) => !!e);
343
- }
344
- function findChannel(type) {
345
- if (!type) return;
346
- let wanted = type.trim().toLowerCase();
347
- return channelEntries().find((e) => e.type === wanted || e.displayName.toLowerCase() === wanted);
348
- }
349
- function credentialFields(entry) {
350
- return entry.credentials ?? [
351
- ...entry.requiredEnvKeys.map((key) => ({ key, label: key, required: !0 })),
352
- ...(entry.optionalEnvKeys ?? []).map((key) => ({ key, label: key, required: !1 }))
353
- ];
354
- }
355
- var DEFAULT_ADAPTER_CONFIG = { enabled: !0, policy: { dm: "all", groups: "mention" } }, SHAPES = {
356
- 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)." },
357
- 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)." },
358
- DISCORD_APPLICATION_ID: { test: /^\d{15,22}$/, message: "The application ID is a long number (General Information page)." },
359
- SLACK_APP_TOKEN: { test: /^xapp-/, message: "The app-level token starts with xapp- (Socket Mode page)." },
360
- SLACK_BOT_TOKEN: { test: /^xoxb-/, message: "The bot token starts with xoxb- (Install App page)." },
361
- EMAIL_USERNAME: { test: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: "Enter the full email address." }
362
- };
363
- function validateCredentials(entry, values) {
364
- let errors = {};
365
- for (let field of credentialFields(entry)) {
366
- let value = (values[field.key] ?? "").trim();
367
- if (!value) {
368
- field.required && (errors[field.key] = `${field.label} is required.`);
369
- continue;
132
+ if (reg.runLocation === "host") {
133
+ if (!opts?.hostAccessEnabled) {
134
+ let notes2 = ["Host access is disabled app-wide \u2014 this test ran in the shared container. Turn on Host access in Settings \u2192 Compute to test on the host."];
135
+ return reg.auth && notes2.push("Authorization for containerized servers happens per-agent when an agent attaches this server."), { location: "shared container", authMode: reg.auth ? "skip" : "none", materializeFiles: !1, notes: notes2 };
370
136
  }
371
- if (/\s/.test(value)) {
372
- errors[field.key] = "No spaces: paste the value exactly.";
373
- continue;
374
- }
375
- let shape = SHAPES[field.key];
376
- shape && !shape.test.test(value) && (errors[field.key] = shape.message);
137
+ return {
138
+ location: "host",
139
+ authMode: reg.auth ? "run" : "none",
140
+ materializeFiles: !0,
141
+ notes: []
142
+ };
377
143
  }
378
- return errors;
379
- }
380
- function adapterLiveState(diag, type) {
381
- let state = diag?.states?.find((s) => s.type === type);
382
- 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" };
383
- }
384
- function configuredChannels(config) {
385
- return Object.keys(config?.adapters ?? {});
144
+ let notes = [];
145
+ return reg.auth && notes.push("Authorization for containerized servers happens per-agent when an agent attaches this server."), reg.credentialFiles?.length && notes.push("Credential files for containerized servers are captured per-agent at attach; this test verifies the package launches and lists tools."), { location: "shared container", authMode: reg.auth ? "skip" : "none", materializeFiles: !1, notes };
146
+ }
147
+ function registrationSourceIdentity(reg) {
148
+ return reg.type === "http" || reg.url ? reg.url ? `http:${reg.url}` : "http" : reg.npmPackage ? `npm:${reg.npmPackage}` : reg.pypiPackage ? `uvx:${reg.pypiPackage}` : "custom";
149
+ }
150
+ function reconcileHostApprovedRegistrations(prev, next, approved, approvedSources) {
151
+ let result = [...approved], sources = { ...approvedSources ?? {} }, prevByName = new Map(prev.filter((r) => r.name).map((r) => [r.name, r])), nextByName = new Map(next.filter((r) => r.name).map((r) => [r.name, r])), add = (name, reg) => {
152
+ result.includes(name) || result.push(name), sources[name] = registrationSourceIdentity(reg);
153
+ }, remove = (name) => {
154
+ let i = result.indexOf(name);
155
+ i >= 0 && result.splice(i, 1), delete sources[name];
156
+ };
157
+ for (let [name, reg] of nextByName) {
158
+ let wasHost = prevByName.get(name)?.runLocation === "host", isHost = reg.runLocation === "host" && reg.type !== "http";
159
+ isHost && !wasHost ? add(name, reg) : !isHost && wasHost ? remove(name) : isHost && wasHost && result.includes(name) && (sources[name] = registrationSourceIdentity(reg));
160
+ }
161
+ for (let [name, reg] of prevByName)
162
+ !nextByName.has(name) && reg.runLocation === "host" && remove(name);
163
+ return { approved: result, sources };
386
164
  }
387
165
 
388
166
  // src/shared/constants/provider-catalog.ts
@@ -442,6 +220,15 @@ var PROVIDER_CATALOG_GROUPS = [
442
220
  modelPlaceholder: "e.g. grok-4.5",
443
221
  iconKey: "x"
444
222
  },
223
+ {
224
+ key: "claude-subscription",
225
+ label: "Claude",
226
+ type: "claude-subscription",
227
+ group: "subscription",
228
+ description: "Use your Claude Pro or Max plan, via Claude Code.",
229
+ modelPlaceholder: "e.g. claude-sonnet-5-5",
230
+ iconKey: "anthropic"
231
+ },
445
232
  // ---- First-party APIs -----------------------------------------------------
446
233
  {
447
234
  key: "anthropic",
@@ -555,62 +342,12 @@ function providerTypeHint(type) {
555
342
  return "ChatGPT subscription (OAuth)";
556
343
  case "grok-subscription":
557
344
  return "Grok subscription (OAuth)";
345
+ case "claude-subscription":
346
+ return "Claude subscription (via Claude Code)";
558
347
  }
559
348
  }
560
349
  function isSubscriptionType(type) {
561
- return type === "chatgpt-subscription" || type === "grok-subscription";
562
- }
563
-
564
- // src/main/tui/setup/provider.ts
565
- var { PROVIDER_CATALOG: PROVIDER_CATALOG2 } = cjs(provider_catalog_exports), PROVIDER_OVERLAY = "provider.add", API_TYPES = /* @__PURE__ */ new Set(["anthropic", "openai", "openrouter", "openai-compatible"]);
566
- function providerRows() {
567
- let order = { subscription: 0, api: 1, local: 2, other: 3 };
568
- 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) => ({
569
- entry,
570
- ...entry.type === "chatgpt-subscription" ? { signIn: "chatgpt" } : entry.type === "grok-subscription" ? { signIn: "grok" } : {}
571
- }));
572
- }
573
- function findProviderRow(key) {
574
- if (!key) return;
575
- let wanted = key.trim().toLowerCase();
576
- return providerRows().find((r) => r.entry.key === wanted || r.entry.label.toLowerCase() === wanted || r.entry.type === wanted);
577
- }
578
- function keyOptional(entry) {
579
- return entry.keyOptional === !0 || entry.group === "other";
580
- }
581
- function needsBaseUrl(entry) {
582
- return entry.type === "openai-compatible";
583
- }
584
- function validateProvider(entry, v) {
585
- let errors = {};
586
- if (needsBaseUrl(entry)) {
587
- let url = v.baseUrl.trim();
588
- if (!url) errors.baseUrl = "The server\u2019s base URL, e.g. http://localhost:11434/v1.";
589
- else if (/YOUR_[A-Z_]+/.test(url)) errors.baseUrl = "Replace the YOUR_\u2026 part of the URL with your own value.";
590
- else
591
- try {
592
- let parsed = new URL(url);
593
- parsed.protocol !== "http:" && parsed.protocol !== "https:" && (errors.baseUrl = "Use an http(s) URL.");
594
- } catch {
595
- errors.baseUrl = "Not a URL.";
596
- }
597
- }
598
- let key = v.apiKey.trim();
599
- return !key && !keyOptional(entry) ? errors.apiKey = "Paste the API key." : /\s/.test(key) && (errors.apiKey = "No spaces: paste the key exactly."), errors;
600
- }
601
- function providerInput(entry, v) {
602
- let key = v.apiKey.trim();
603
- return {
604
- type: entry.type,
605
- name: v.name.trim() || entry.label,
606
- ...needsBaseUrl(entry) ? { baseUrl: v.baseUrl.trim() } : {},
607
- ...v.defaultModel.trim() ? { defaultModel: v.defaultModel.trim() } : {},
608
- preset: entry.key,
609
- ...key ? { apiKey: key } : {}
610
- };
611
- }
612
- function keyStorageText(storage) {
613
- return storage === "file" ? "the daemon\u2019s passphrase-protected secret file" : "the OS keychain";
350
+ return type === "chatgpt-subscription" || type === "grok-subscription" || type === "claude-subscription";
614
351
  }
615
352
 
616
353
  // src/shared/constants/mcp-registry.ts
@@ -2233,240 +1970,20 @@ function findRegistryEntryByUrl(url) {
2233
1970
  return MCP_REGISTRY.find((e) => e.url === url);
2234
1971
  }
2235
1972
 
2236
- // src/main/tui/setup/mcp.ts
2237
- var { MCP_REGISTRY: MCP_REGISTRY2, registrationFromRegistryEntry: registrationFromRegistryEntry2, hasUnresolvedPlaceholderArgs: hasUnresolvedPlaceholderArgs2, REGISTRY_ARG_PLACEHOLDER_RE: REGISTRY_ARG_PLACEHOLDER_RE2 } = cjs(mcp_registry_exports), { buildMcpServerConfigFromRegistration, mcpCredentialNamespace } = cjs(mcp_config_exports), MCP_OVERLAY = "mcp";
2238
- function mcpSourceRows() {
2239
- let custom = [
2240
- { kind: "npm", label: "npm package", detail: "Any MCP server published to npm (e.g. @modelcontextprotocol/server-everything)" },
2241
- { kind: "python", label: "Python package (uvx)", detail: "Any MCP server on PyPI, run with uvx (e.g. mcp-server-fetch)" },
2242
- { kind: "http", label: "Remote server (URL)", detail: "A Streamable HTTP MCP endpoint; token from an env var" }
2243
- ], catalog = MCP_REGISTRY2.filter((e) => !e.deprecated).map((entry) => ({ kind: "catalog", entry, label: entry.displayName, detail: entry.description }));
2244
- return [...custom, ...catalog];
2245
- }
2246
- function parseAddTarget(arg) {
2247
- let raw = (arg ?? "").trim();
2248
- if (!raw) return {};
2249
- let rows = mcpSourceRows();
2250
- if (/^https?:\/\//i.test(raw)) {
2251
- let known = rows.find((r) => r.entry?.url === raw);
2252
- return known ? { row: known } : { row: rows.find((r) => r.kind === "http"), value: raw };
2253
- }
2254
- let prefixed = raw.match(/^(npm|python|uvx|pip):(.+)$/i);
2255
- if (prefixed) {
2256
- let kind = prefixed[1].toLowerCase() === "npm" ? "npm" : "python";
2257
- return { row: rows.find((r) => r.kind === kind), value: prefixed[2].trim() };
2258
- }
2259
- 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));
2260
- return entry ? { row: entry } : { row: rows.find((r) => r.kind === "npm"), value: raw };
2261
- }
2262
- function sanitizeServerName(value) {
2263
- return value.toLowerCase().replace(/^@[^/]+\//, "").replace(/^mcp-server-|-mcp-server$|^server-|-mcp$|^mcp-/g, "").replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
2264
- }
2265
- function defaultServerName(row, value = "") {
2266
- if (row.entry) return row.entry.name;
2267
- if (row.kind === "http")
2268
- try {
2269
- return sanitizeServerName(new URL(value).hostname.split(".").slice(-2, -1)[0] ?? "");
2270
- } catch {
2271
- return "";
2272
- }
2273
- return sanitizeServerName(value.split("/").pop() ?? value);
2274
- }
2275
- function envKeysOf(row) {
2276
- let e = row.entry;
2277
- if (!e) return row.kind === "http" ? [{ key: "MCP_TOKEN", required: !1 }] : [];
2278
- let keys = [
2279
- ...e.requiredEnvKeys.map((key) => ({ key, required: !0 })),
2280
- ...(e.optionalEnvKeys ?? []).map((key) => ({ key, required: !1 })),
2281
- ...e.bearerTokenEnvVar ? [{ key: e.bearerTokenEnvVar, required: !!e.url && !e.oauth }] : [],
2282
- ...(e.headerEnv ?? []).map((h) => ({ key: h.env, required: !0 }))
2283
- ];
2284
- return keys.filter((k, i) => keys.findIndex((x) => x.key === k.key) === i);
2285
- }
2286
- function studioOnlyReason(row) {
2287
- let e = row.entry;
2288
- 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;
2289
- }
2290
- function validateMcpForm(row, form, taken) {
2291
- let errors = {};
2292
- 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) {
2293
- let source = form.source.trim();
2294
- if (!source) errors.source = row.kind === "http" ? "The server URL." : "The package name.";
2295
- else if (row.kind === "http")
2296
- try {
2297
- /^https?:$/.test(new URL(source).protocol) || (errors.source = "Use an http(s) URL.");
2298
- } catch {
2299
- errors.source = "Not a URL.";
2300
- }
2301
- else /\s/.test(source) && (errors.source = "One package name, no spaces.");
2302
- }
2303
- hasUnresolvedPlaceholderArgs2(splitArgs(form.args)) && (errors.args = "Fill in the {placeholders}.");
2304
- for (let { key, required } of envKeysOf(row))
2305
- required && !(form.env[key] ?? "").trim() && (errors[`env:${key}`] = `${key} is required.`);
2306
- return errors;
2307
- }
2308
- function splitArgs(text) {
2309
- let out = [], pattern = /"((?:[^"\\]|\\.)*)"|'([^']*)'|(\S+)/g, m;
2310
- for (; m = pattern.exec(text); ) out.push(m[1] !== void 0 ? m[1].replace(/\\(.)/g, "$1") : m[2] ?? m[3]);
2311
- return out;
2312
- }
2313
- function joinArgs(args) {
2314
- return (args ?? []).map((a) => /\s/.test(a) ? `"${a.replace(/"/g, '\\"')}"` : a).join(" ");
2315
- }
2316
- function registrationFor(row, form) {
2317
- let envKeys = envKeysOf(row).map((k) => k.key), base = row.entry ? registrationFromRegistryEntry2(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());
2318
- return {
2319
- ...base,
2320
- name: form.name,
2321
- credentialStorage: "agent",
2322
- // Keys only: values go to the agent's identity store.
2323
- env: (row.entry ? envKeys : keysWithValues).map((key) => ({ key, value: "" })),
2324
- // Remote catalog entries that also take a token: the token path (OAuth runs in Studio only).
2325
- ...isHttp && base.oauth && base.bearerTokenEnvVar ? { oauth: !1 } : {},
2326
- ...isHttp ? {} : { args: args.length ? args : void 0 },
2327
- // Container unless the user picked the host (a catalog entry's host default is only a preselection).
2328
- runLocation: !isHttp && form.runOn === "host" ? "host" : void 0
2329
- };
2330
- }
2331
- function serverConfigFor(row, form) {
2332
- return buildMcpServerConfigFromRegistration(registrationFor(row, form));
2333
- }
2334
- function credentialNamespace(server) {
2335
- return mcpCredentialNamespace(server);
2336
- }
2337
- function packageToInstall(server) {
2338
- return server.transport === "http" ? null : server.npm_package ? { kind: "npm", name: server.npm_package } : server.pypi_package ? { kind: "python", name: server.pypi_package } : null;
2339
- }
2340
- function serverEnvKeys(server) {
2341
- return [.../* @__PURE__ */ new Set([
2342
- ...server.env_keys ?? [],
2343
- ...(server.env_schema ?? []).map((e) => e.key),
2344
- ...server.bearer_token_env_var ? [server.bearer_token_env_var] : [],
2345
- ...(server.header_env ?? []).map((h) => h.env)
2346
- ])];
2347
- }
2348
- function runsOnText(server, location) {
2349
- return location || (server ? server.transport === "http" ? "remote" : server.run_location === "host" ? "host" : server.run_location === "shared" ? "shared container" : "container" : "");
2350
- }
2351
- function serverToolDecls(tools, server) {
2352
- let prefix = `mcp_${server}_`;
2353
- return (tools ?? []).filter((t) => t.name.startsWith(prefix)).map((t) => ({ name: t.name, tool: t.name.slice(prefix.length), enabled: t.enabled !== !1 }));
2354
- }
2355
-
2356
- // src/main/tui/setup/open.ts
2357
- function channelsIdentityReady(store) {
2358
- let identity = store.getState().identity;
2359
- return !identity || identity.status === "ready";
2360
- }
2361
- function secretStoreReady(store) {
2362
- let identity = store.getState().identity;
2363
- return identity ? identity.storage === "keychain" ? identity.status !== "locked" : identity.status === "ready" : !0;
2364
- }
2365
- function openChannels(store, props = {}) {
2366
- let state = store.getState(), agentId = props.agentId ?? state.selectedAgentId;
2367
- if (!agentId || !state.agents[agentId]) {
2368
- store.actions.toast("Select an agent first (sidebar or /agent), or create one with /new", "warn");
2369
- return;
2370
- }
2371
- let next = { agentId, ...props.channel ? { channel: props.channel } : {} };
2372
- if (props.channel && !channelsIdentityReady(store)) {
2373
- identityFirst(store, CHANNELS_OVERLAY, next, "Channel credentials are sealed under your owner identity: set it up first, then the channel setup follows.");
2374
- return;
2375
- }
2376
- store.actions.pushOverlay({ kind: CHANNELS_OVERLAY, props: { ...next } });
2377
- }
2378
- function openProviderAdd(store, props = {}) {
2379
- if (!secretStoreReady(store)) {
2380
- 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.");
2381
- return;
2382
- }
2383
- store.actions.pushOverlay({ kind: PROVIDER_OVERLAY, props: { ...props } });
2384
- }
2385
- function openMcp(store, props = {}) {
2386
- let state = store.getState(), agentId = props.agentId ?? state.selectedAgentId;
2387
- if (!agentId || !state.agents[agentId]) {
2388
- store.actions.toast("Select an agent first (sidebar or /agent), or create one with /new", "warn");
2389
- return;
2390
- }
2391
- store.actions.pushOverlay({ kind: MCP_OVERLAY, props: { ...props, agentId } });
2392
- }
2393
- function openWelcome(store) {
2394
- store.actions.pushOverlay({ id: WELCOME_OVERLAY, kind: WELCOME_OVERLAY });
2395
- }
2396
- function identityFirst(store, then, thenProps, reason) {
2397
- openIdentity(store, { mode: "status", then, thenProps, reason });
2398
- }
2399
-
2400
1973
  export {
2401
- elementRect,
2402
- rectContains,
2403
- createKeyRouter,
2404
- KeyRouterProvider,
2405
- useKeyRouter,
2406
- useKeys,
2407
- WHEEL_STEP,
2408
- useWheel,
2409
- useClick,
2410
- keyLabel,
2411
- IDENTITY_OVERLAY,
2412
- NEW_AGENT_OVERLAY,
2413
- IDENTITY_BANNER_KEY,
2414
- SAVED_WORD,
2415
- shortDid,
2416
- normalizePhrase,
2417
- phraseWords,
2418
- isLoopbackUrl,
2419
- LOOPBACK_ONLY_TEXT,
2420
- IDENTITY_EXPLAINER,
2421
- identityErrorText,
2422
- identityBadge,
2423
- onboardingLines,
2424
- onboardingChoices,
2425
- passphraseProblem,
2426
- KeyHints,
2427
- openIdentity,
2428
- openNewAgent,
2429
- bannerKeyOf,
2430
- needsAttention,
2431
- identityKey,
2432
- IdentityOnboarding,
2433
- IdentityBanner,
2434
- CHANNELS_OVERLAY,
2435
- CHANNEL_ORDER,
2436
- channelEntries,
2437
- findChannel,
2438
- credentialFields,
2439
- DEFAULT_ADAPTER_CONFIG,
2440
- validateCredentials,
2441
- adapterLiveState,
2442
- configuredChannels,
2443
- PROVIDER_OVERLAY,
2444
- providerRows,
2445
- findProviderRow,
2446
- keyOptional,
2447
- needsBaseUrl,
2448
- validateProvider,
2449
- providerInput,
2450
- keyStorageText,
2451
- MCP_OVERLAY,
2452
- mcpSourceRows,
2453
- parseAddTarget,
2454
- defaultServerName,
2455
- envKeysOf,
2456
- studioOnlyReason,
2457
- validateMcpForm,
2458
- joinArgs,
2459
- serverConfigFor,
2460
- credentialNamespace,
2461
- packageToInstall,
2462
- serverEnvKeys,
2463
- runsOnText,
2464
- serverToolDecls,
2465
- channelsIdentityReady,
2466
- secretStoreReady,
2467
- openChannels,
2468
- openProviderAdd,
2469
- openMcp,
2470
- openWelcome,
2471
- identityFirst
1974
+ mcpCredentialRef,
1975
+ isSensitiveMcpHeader,
1976
+ buildEnvSchemaFromKeys,
1977
+ buildHeaderEnvSchemaFromEntries,
1978
+ buildMcpServerConfigFromRegistration,
1979
+ pinServerConfigToRegistration,
1980
+ isRegistrationAgentVisible,
1981
+ deriveRegistrationTestPlan,
1982
+ mcp_config_exports,
1983
+ isSubscriptionType,
1984
+ provider_catalog_exports,
1985
+ parseMcpRegistryDocument,
1986
+ MCP_REGISTRY,
1987
+ BUNDLED_REGISTRY_UPDATED_AT,
1988
+ mcp_registry_exports
2472
1989
  };