@springbrand/cli 0.1.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 (222) hide show
  1. package/README.md +167 -0
  2. package/dist/commands/auth.d.ts +4 -0
  3. package/dist/commands/auth.d.ts.map +1 -0
  4. package/dist/commands/auth.js +241 -0
  5. package/dist/commands/auth.js.map +1 -0
  6. package/dist/commands/check-version.d.ts +3 -0
  7. package/dist/commands/check-version.d.ts.map +1 -0
  8. package/dist/commands/check-version.js +112 -0
  9. package/dist/commands/check-version.js.map +1 -0
  10. package/dist/commands/config-claude.d.ts +4 -0
  11. package/dist/commands/config-claude.d.ts.map +1 -0
  12. package/dist/commands/config-claude.js +78 -0
  13. package/dist/commands/config-claude.js.map +1 -0
  14. package/dist/commands/connect.d.ts +41 -0
  15. package/dist/commands/connect.d.ts.map +1 -0
  16. package/dist/commands/connect.js +901 -0
  17. package/dist/commands/connect.js.map +1 -0
  18. package/dist/commands/doctor.d.ts +6 -0
  19. package/dist/commands/doctor.d.ts.map +1 -0
  20. package/dist/commands/doctor.js +124 -0
  21. package/dist/commands/doctor.js.map +1 -0
  22. package/dist/commands/upgrade.d.ts +9 -0
  23. package/dist/commands/upgrade.d.ts.map +1 -0
  24. package/dist/commands/upgrade.js +133 -0
  25. package/dist/commands/upgrade.js.map +1 -0
  26. package/dist/index.d.ts +4 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +15 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/lib/agent-detect.d.ts +33 -0
  31. package/dist/lib/agent-detect.d.ts.map +1 -0
  32. package/dist/lib/agent-detect.js +81 -0
  33. package/dist/lib/agent-detect.js.map +1 -0
  34. package/dist/lib/agent-launcher.d.ts +22 -0
  35. package/dist/lib/agent-launcher.d.ts.map +1 -0
  36. package/dist/lib/agent-launcher.js +67 -0
  37. package/dist/lib/agent-launcher.js.map +1 -0
  38. package/dist/lib/auth.d.ts +90 -0
  39. package/dist/lib/auth.d.ts.map +1 -0
  40. package/dist/lib/auth.js +327 -0
  41. package/dist/lib/auth.js.map +1 -0
  42. package/dist/lib/bundled-skill.d.ts +5 -0
  43. package/dist/lib/bundled-skill.d.ts.map +1 -0
  44. package/dist/lib/bundled-skill.js +13 -0
  45. package/dist/lib/bundled-skill.js.map +1 -0
  46. package/dist/lib/claude-config.d.ts +19 -0
  47. package/dist/lib/claude-config.d.ts.map +1 -0
  48. package/dist/lib/claude-config.js +202 -0
  49. package/dist/lib/claude-config.js.map +1 -0
  50. package/dist/lib/cli-install.d.ts +40 -0
  51. package/dist/lib/cli-install.d.ts.map +1 -0
  52. package/dist/lib/cli-install.js +42 -0
  53. package/dist/lib/cli-install.js.map +1 -0
  54. package/dist/lib/command-code-config.d.ts +5 -0
  55. package/dist/lib/command-code-config.d.ts.map +1 -0
  56. package/dist/lib/command-code-config.js +16 -0
  57. package/dist/lib/command-code-config.js.map +1 -0
  58. package/dist/lib/connect-all-auth.d.ts +21 -0
  59. package/dist/lib/connect-all-auth.d.ts.map +1 -0
  60. package/dist/lib/connect-all-auth.js +113 -0
  61. package/dist/lib/connect-all-auth.js.map +1 -0
  62. package/dist/lib/connect-all-summary.d.ts +10 -0
  63. package/dist/lib/connect-all-summary.d.ts.map +1 -0
  64. package/dist/lib/connect-all-summary.js +153 -0
  65. package/dist/lib/connect-all-summary.js.map +1 -0
  66. package/dist/lib/connect-all-uninstall.d.ts +7 -0
  67. package/dist/lib/connect-all-uninstall.d.ts.map +1 -0
  68. package/dist/lib/connect-all-uninstall.js +249 -0
  69. package/dist/lib/connect-all-uninstall.js.map +1 -0
  70. package/dist/lib/connect-all.d.ts +42 -0
  71. package/dist/lib/connect-all.d.ts.map +1 -0
  72. package/dist/lib/connect-all.js +438 -0
  73. package/dist/lib/connect-all.js.map +1 -0
  74. package/dist/lib/connect-auth.d.ts +7 -0
  75. package/dist/lib/connect-auth.d.ts.map +1 -0
  76. package/dist/lib/connect-auth.js +50 -0
  77. package/dist/lib/connect-auth.js.map +1 -0
  78. package/dist/lib/connect-clients.d.ts +108 -0
  79. package/dist/lib/connect-clients.d.ts.map +1 -0
  80. package/dist/lib/connect-clients.js +358 -0
  81. package/dist/lib/connect-clients.js.map +1 -0
  82. package/dist/lib/connect-fallback.d.ts +27 -0
  83. package/dist/lib/connect-fallback.d.ts.map +1 -0
  84. package/dist/lib/connect-fallback.js +166 -0
  85. package/dist/lib/connect-fallback.js.map +1 -0
  86. package/dist/lib/connect-picker.d.ts +19 -0
  87. package/dist/lib/connect-picker.d.ts.map +1 -0
  88. package/dist/lib/connect-picker.js +155 -0
  89. package/dist/lib/connect-picker.js.map +1 -0
  90. package/dist/lib/connect-preflight.d.ts +17 -0
  91. package/dist/lib/connect-preflight.d.ts.map +1 -0
  92. package/dist/lib/connect-preflight.js +81 -0
  93. package/dist/lib/connect-preflight.js.map +1 -0
  94. package/dist/lib/connect-runtime.d.ts +109 -0
  95. package/dist/lib/connect-runtime.d.ts.map +1 -0
  96. package/dist/lib/connect-runtime.js +360 -0
  97. package/dist/lib/connect-runtime.js.map +1 -0
  98. package/dist/lib/constants.d.ts +23 -0
  99. package/dist/lib/constants.d.ts.map +1 -0
  100. package/dist/lib/constants.js +87 -0
  101. package/dist/lib/constants.js.map +1 -0
  102. package/dist/lib/cursor-config.d.ts +16 -0
  103. package/dist/lib/cursor-config.d.ts.map +1 -0
  104. package/dist/lib/cursor-config.js +34 -0
  105. package/dist/lib/cursor-config.js.map +1 -0
  106. package/dist/lib/doctor-checks.d.ts +21 -0
  107. package/dist/lib/doctor-checks.d.ts.map +1 -0
  108. package/dist/lib/doctor-checks.js +312 -0
  109. package/dist/lib/doctor-checks.js.map +1 -0
  110. package/dist/lib/doctor-repairs.d.ts +11 -0
  111. package/dist/lib/doctor-repairs.d.ts.map +1 -0
  112. package/dist/lib/doctor-repairs.js +130 -0
  113. package/dist/lib/doctor-repairs.js.map +1 -0
  114. package/dist/lib/doctor-report.d.ts +195 -0
  115. package/dist/lib/doctor-report.d.ts.map +1 -0
  116. package/dist/lib/doctor-report.js +102 -0
  117. package/dist/lib/doctor-report.js.map +1 -0
  118. package/dist/lib/doctor-telemetry.d.ts +9 -0
  119. package/dist/lib/doctor-telemetry.d.ts.map +1 -0
  120. package/dist/lib/doctor-telemetry.js +63 -0
  121. package/dist/lib/doctor-telemetry.js.map +1 -0
  122. package/dist/lib/harness-detect.d.ts +33 -0
  123. package/dist/lib/harness-detect.d.ts.map +1 -0
  124. package/dist/lib/harness-detect.js +70 -0
  125. package/dist/lib/harness-detect.js.map +1 -0
  126. package/dist/lib/harness-spec.d.ts +285 -0
  127. package/dist/lib/harness-spec.d.ts.map +1 -0
  128. package/dist/lib/harness-spec.js +268 -0
  129. package/dist/lib/harness-spec.js.map +1 -0
  130. package/dist/lib/harness.d.ts +27 -0
  131. package/dist/lib/harness.d.ts.map +1 -0
  132. package/dist/lib/harness.js +125 -0
  133. package/dist/lib/harness.js.map +1 -0
  134. package/dist/lib/hermes-config.d.ts +22 -0
  135. package/dist/lib/hermes-config.d.ts.map +1 -0
  136. package/dist/lib/hermes-config.js +76 -0
  137. package/dist/lib/hermes-config.js.map +1 -0
  138. package/dist/lib/hermes-env.d.ts +19 -0
  139. package/dist/lib/hermes-env.d.ts.map +1 -0
  140. package/dist/lib/hermes-env.js +169 -0
  141. package/dist/lib/hermes-env.js.map +1 -0
  142. package/dist/lib/hermes-plugin.d.ts +40 -0
  143. package/dist/lib/hermes-plugin.d.ts.map +1 -0
  144. package/dist/lib/hermes-plugin.js +168 -0
  145. package/dist/lib/hermes-plugin.js.map +1 -0
  146. package/dist/lib/install-root.d.ts +18 -0
  147. package/dist/lib/install-root.d.ts.map +1 -0
  148. package/dist/lib/install-root.js +55 -0
  149. package/dist/lib/install-root.js.map +1 -0
  150. package/dist/lib/mcp-config.d.ts +36 -0
  151. package/dist/lib/mcp-config.d.ts.map +1 -0
  152. package/dist/lib/mcp-config.js +90 -0
  153. package/dist/lib/mcp-config.js.map +1 -0
  154. package/dist/lib/mcp-endpoint.d.ts +16 -0
  155. package/dist/lib/mcp-endpoint.d.ts.map +1 -0
  156. package/dist/lib/mcp-endpoint.js +41 -0
  157. package/dist/lib/mcp-endpoint.js.map +1 -0
  158. package/dist/lib/mcp-json-config.d.ts +43 -0
  159. package/dist/lib/mcp-json-config.d.ts.map +1 -0
  160. package/dist/lib/mcp-json-config.js +164 -0
  161. package/dist/lib/mcp-json-config.js.map +1 -0
  162. package/dist/lib/notice.d.ts +13 -0
  163. package/dist/lib/notice.d.ts.map +1 -0
  164. package/dist/lib/notice.js +73 -0
  165. package/dist/lib/notice.js.map +1 -0
  166. package/dist/lib/omp-config.d.ts +18 -0
  167. package/dist/lib/omp-config.d.ts.map +1 -0
  168. package/dist/lib/omp-config.js +73 -0
  169. package/dist/lib/omp-config.js.map +1 -0
  170. package/dist/lib/output.d.ts +22 -0
  171. package/dist/lib/output.d.ts.map +1 -0
  172. package/dist/lib/output.js +92 -0
  173. package/dist/lib/output.js.map +1 -0
  174. package/dist/lib/pi-config.d.ts +27 -0
  175. package/dist/lib/pi-config.d.ts.map +1 -0
  176. package/dist/lib/pi-config.js +113 -0
  177. package/dist/lib/pi-config.js.map +1 -0
  178. package/dist/lib/registration-detect.d.ts +28 -0
  179. package/dist/lib/registration-detect.d.ts.map +1 -0
  180. package/dist/lib/registration-detect.js +563 -0
  181. package/dist/lib/registration-detect.js.map +1 -0
  182. package/dist/lib/setup-telemetry.d.ts +273 -0
  183. package/dist/lib/setup-telemetry.d.ts.map +1 -0
  184. package/dist/lib/setup-telemetry.js +309 -0
  185. package/dist/lib/setup-telemetry.js.map +1 -0
  186. package/dist/lib/signals.d.ts +14 -0
  187. package/dist/lib/signals.d.ts.map +1 -0
  188. package/dist/lib/signals.js +29 -0
  189. package/dist/lib/signals.js.map +1 -0
  190. package/dist/lib/skill-install.d.ts +10 -0
  191. package/dist/lib/skill-install.d.ts.map +1 -0
  192. package/dist/lib/skill-install.js +94 -0
  193. package/dist/lib/skill-install.js.map +1 -0
  194. package/dist/lib/skill-paths.d.ts +7 -0
  195. package/dist/lib/skill-paths.d.ts.map +1 -0
  196. package/dist/lib/skill-paths.js +37 -0
  197. package/dist/lib/skill-paths.js.map +1 -0
  198. package/dist/lib/skill-vendor.d.ts +20 -0
  199. package/dist/lib/skill-vendor.d.ts.map +1 -0
  200. package/dist/lib/skill-vendor.js +215 -0
  201. package/dist/lib/skill-vendor.js.map +1 -0
  202. package/dist/lib/skill.d.ts +14 -0
  203. package/dist/lib/skill.d.ts.map +1 -0
  204. package/dist/lib/skill.js +87 -0
  205. package/dist/lib/skill.js.map +1 -0
  206. package/dist/lib/verify.d.ts +35 -0
  207. package/dist/lib/verify.d.ts.map +1 -0
  208. package/dist/lib/verify.js +169 -0
  209. package/dist/lib/verify.js.map +1 -0
  210. package/dist/program.d.ts +8 -0
  211. package/dist/program.d.ts.map +1 -0
  212. package/dist/program.js +54 -0
  213. package/dist/program.js.map +1 -0
  214. package/package.json +55 -0
  215. package/skill/springbrand-action-api/SKILL.md +49 -0
  216. package/skill/springbrand-action-api/references/action-aliases.md +156 -0
  217. package/skill/springbrand-action-api/references/action-discovery.md +95 -0
  218. package/skill/springbrand-connector/SKILL.md +49 -0
  219. package/skill/springbrand-gtm/SKILL.md +34 -0
  220. package/skill/springbrand-platform/SKILL.md +55 -0
  221. package/skill/springbrand-platform/references/plugin-discovery.md +94 -0
  222. package/skill/use-springbrand/SKILL.md +70 -0
@@ -0,0 +1,358 @@
1
+ /** 复刻自 tiny-fish CLI 编译产物:connect-clients.d.ts + connect-clients.impl.js */
2
+ import spawn from 'cross-spawn';
3
+ import { SKILL_INSTALL_TIMEOUT_MS } from './cli-install.js';
4
+ import { detectHumanInitiated } from './harness.js';
5
+ import { harnessConfigPath } from './harness-detect.js';
6
+ import { errLine, sanitizeLine, warnLine } from './output.js';
7
+ import { ConnectInterruptedError, ConnectStepError, spawnStepError, } from './connect-runtime.js';
8
+ import { SPRINGBRAND_API_KEY_VAR } from './constants.js';
9
+ import { HARNESS_SPECS, NATIVE_HARNESSES, harnessSpec, } from './harness-spec.js';
10
+ import { HERMES_KEY_VAR, captureHermesKeyRestore, hermesEnvPath, resolveHermesHome, writeHermesKey, } from './hermes-env.js';
11
+ import { hermesConfigPath, readHermesEntry } from './hermes-config.js';
12
+ import { HERMES_PLUGIN_VERSION, installHermesPlugin, removeHermesMcpEntry, setHermesWebBackends, writeHermesMcpEntry, } from './hermes-plugin.js';
13
+ const HERMES_SEED_TIMEOUT_MS = 120_000;
14
+ const OPENCLAW_SKILL = '@springbrand/springbrand';
15
+ // --force makes this an unconditional overwrite, so the same call installs and refreshes.
16
+ export function openclawSkillInstallArgs(ackFlag) {
17
+ const ack = ackFlag === undefined ? [] : [ackFlag];
18
+ return ['skills', 'install', OPENCLAW_SKILL, '--global', '--force', ...ack];
19
+ }
20
+ /** `openclaw skills` has no uninstall; ClawHub removes from the global dir. */
21
+ export function openclawSkillUninstall() {
22
+ return {
23
+ command: 'npx',
24
+ args: [
25
+ '-y',
26
+ // Pinned: npx would otherwise execute whatever is newest at run time.
27
+ 'clawhub@0.23.3',
28
+ '--workdir',
29
+ harnessConfigPath('openclaw'),
30
+ 'uninstall',
31
+ OPENCLAW_SKILL,
32
+ '--yes',
33
+ ],
34
+ timeoutMs: SKILL_INSTALL_TIMEOUT_MS,
35
+ };
36
+ }
37
+ export const DEFAULT_ONBOARDING_PROMPT = 'I just connected SpringBrand. Use the MCP server named `springbrand` for every SpringBrand tool call; ' +
38
+ 'if another SpringBrand server is also registered, still use `springbrand` and do not ask me which. ' +
39
+ 'Start by asking me which service and operation I want to try — sending a Gmail message or pulling ' +
40
+ 'Search Console data, for example — and wait for my reply. Then call `search_tools` with an English ' +
41
+ 'query, show me what came back, and let me pick one before calling `get_tool_schemas` for its ' +
42
+ 'contract. Confirm the arguments with me before `execute_tools`. If the operation needs an account ' +
43
+ 'I have not linked yet, use `manage_connections` first and show me the authorization link unchanged. ' +
44
+ 'Ask for my input and wait for my reply before each SpringBrand tool call. If a tool call comes back ' +
45
+ 'blocked or not approved, tell me which tool needs approval and how to grant it, then wait for ' +
46
+ 'me instead of ending the walkthrough.';
47
+ export const OPENCLAW_ONBOARDING_PROMPT = 'I just installed the SpringBrand skill. Guide me through it interactively: first ask which service ' +
48
+ 'and operation I want to try and wait for my reply, then call `search_tools` with an English query. ' +
49
+ 'Show me the results, ask which one I want, and wait before calling `get_tool_schemas` for its ' +
50
+ 'contract. Confirm the arguments with me before `execute_tools`, and use `manage_connections` first ' +
51
+ 'if the operation needs an account I have not linked. Never skip ahead or choose for me.';
52
+ /** Cursor writes its own MCP config, so it has no descriptor to carry this. */
53
+ export const CURSOR_SKILL_TARGET = {
54
+ skillAgent: HARNESS_SPECS.cursor.skillAgent,
55
+ displayName: HARNESS_SPECS.cursor.displayName,
56
+ };
57
+ /**
58
+ * `cmd` re-parses its command line after `/c`, so an unquoted `&` in the query string ends the
59
+ * command and truncates the URL. Quoting needs windowsVerbatimArguments, or Node escapes the
60
+ * quotes back out. Untested on Windows.
61
+ */
62
+ export function openExternalUrl(url) {
63
+ if (process.platform === 'darwin')
64
+ return spawn.sync('open', [url], { stdio: 'ignore' });
65
+ if (process.platform === 'win32') {
66
+ return spawn.sync('cmd', ['/c', 'start', '""', `"${url}"`], {
67
+ stdio: 'ignore',
68
+ windowsVerbatimArguments: true,
69
+ });
70
+ }
71
+ return spawn.sync('xdg-open', [url], { stdio: 'ignore' });
72
+ }
73
+ function launchCodexWalkthrough() {
74
+ const deepLink = new URL('codex://new');
75
+ deepLink.searchParams.set('prompt', DEFAULT_ONBOARDING_PROMPT);
76
+ deepLink.searchParams.set('path', process.cwd());
77
+ const result = openExternalUrl(deepLink.toString());
78
+ if (result.error || result.status !== 0) {
79
+ // Headless box: nothing can open a window; recover like the gated clients.
80
+ printPromptForHandoff('Codex', 'codex', DEFAULT_ONBOARDING_PROMPT, 'Codex could not be opened here (no `codex://` handler)');
81
+ return 'printed';
82
+ }
83
+ errLine('Codex opened with the SpringBrand walkthrough ready. Send the prompt to start.');
84
+ return 'launched';
85
+ }
86
+ // Handover: spawn errors are ours; the exit is the user's.
87
+ function handOverTerminal(command, args, displayName) {
88
+ const result = spawn.sync(command, args, { stdio: 'inherit' });
89
+ if (result.error) {
90
+ throw spawnStepError(`Could not launch ${displayName}`, result);
91
+ }
92
+ }
93
+ function launchHermesWalkthrough() {
94
+ const seedResult = spawn.sync('hermes', ['chat', '-Q', '-q', DEFAULT_ONBOARDING_PROMPT], {
95
+ encoding: 'utf8',
96
+ timeout: HERMES_SEED_TIMEOUT_MS,
97
+ });
98
+ if (seedResult.error || seedResult.status !== 0) {
99
+ throw spawnStepError('Could not start the SpringBrand walkthrough in Hermes', seedResult);
100
+ }
101
+ // A colourised id would carry its trailing escape sequence into `--resume` (PF-3452).
102
+ const sessionId = sanitizeLine(seedResult.stderr ?? '').match(/session_id:\s*([^\s]+)/i)?.[1];
103
+ if (!sessionId) {
104
+ throw new Error('Hermes did not return a walkthrough session ID');
105
+ }
106
+ handOverTerminal('hermes', ['--resume', sessionId], 'Hermes');
107
+ }
108
+ /** Writes exit 0 having saved nothing, a disabled entry, or a keyless one. */
109
+ export function hermesRegistrationEnabled(home) {
110
+ const entry = readHermesEntry(home);
111
+ if (entry.state === 'enabled') {
112
+ if (entry.usesKeyHeader)
113
+ return { ok: true };
114
+ // Exit codes carry no signal, so a corrupt entry can only be caught here.
115
+ return {
116
+ ok: false,
117
+ detail: 'the entry does not read the seeded key',
118
+ tag: 'hermes_entry_no_key_header',
119
+ };
120
+ }
121
+ // Each of these is a different repair, so none of them share wording.
122
+ const detail = {
123
+ disabled: 'the entry was saved disabled',
124
+ absent: 'no springbrand entry was saved',
125
+ unreadable: `${hermesConfigPath(home)} could not be read`,
126
+ unparseable: `${hermesConfigPath(home)} could not be parsed`,
127
+ }[entry.state];
128
+ // The tag keeps the path-bearing prose out of telemetry.
129
+ return { ok: false, detail, tag: `hermes_entry_${entry.state}` };
130
+ }
131
+ // A plain Error settles unexpected_error; cli_connect_stage is load-bearing.
132
+ function requireHermesHome() {
133
+ const resolved = resolveHermesHome();
134
+ if (typeof resolved === 'string')
135
+ return resolved;
136
+ throw new ConnectStepError("Could not determine Hermes' home directory from `hermes dump`", 'invalid_config', { failureDetail: `hermes_home_undetermined_${resolved.reason}` });
137
+ }
138
+ /** Our own write, so `mcp add`'s install-time probe never disables the entry. */
139
+ function registerHermesEntry(home, mcpUrl) {
140
+ try {
141
+ writeHermesMcpEntry(home, mcpUrl);
142
+ }
143
+ catch (error) {
144
+ // A Ctrl+C must abandon the attempt, not fall through to `mcp add`.
145
+ if (error instanceof ConnectInterruptedError)
146
+ throw error;
147
+ return false;
148
+ }
149
+ return hermesRegistrationEnabled(home).ok;
150
+ }
151
+ function seedHermesKey(apiKey) {
152
+ const home = requireHermesHome();
153
+ const restore = captureHermesKeyRestore(home);
154
+ writeHermesKey(home, apiKey);
155
+ // Set before the write, which can land even when it later throws.
156
+ let wroteEntry = false;
157
+ return {
158
+ home,
159
+ // Pins HERMES_HOME so a sticky profile can't shadow this key.
160
+ env: { ...process.env, HERMES_HOME: home },
161
+ // Three: a failed `mcp remove` adds an extra Overwrite prompt.
162
+ stdinInput: 'y\ny\ny\n',
163
+ note: `Wrote ${HERMES_KEY_VAR} to ${hermesEnvPath(home)} — Hermes reads the key from there.`,
164
+ rollback: () => rollbackHermesKey(home, restore, wroteEntry),
165
+ register: (mcpUrl) => {
166
+ wroteEntry = true;
167
+ return registerHermesEntry(home, mcpUrl);
168
+ },
169
+ confirmRegistered: () => hermesRegistrationEnabled(home),
170
+ };
171
+ }
172
+ // A failed re-run must not cost a working key.
173
+ function rollbackHermesKey(home, restore, wroteEntry) {
174
+ try {
175
+ // The next `hermes mcp add` silently reuses whatever value survives here.
176
+ restore();
177
+ }
178
+ catch {
179
+ warnLine(`Could not restore ${HERMES_KEY_VAR} in ${hermesEnvPath(home)}; check it by hand.`);
180
+ }
181
+ if (!wroteEntry)
182
+ return;
183
+ try {
184
+ // Left behind, the row stays enabled with no key behind it.
185
+ removeHermesMcpEntry(home);
186
+ }
187
+ catch {
188
+ warnLine(`Could not remove the springbrand entry in ${hermesConfigPath(home)}; check it by hand.`);
189
+ }
190
+ }
191
+ // Hermes is keyRequired; a missing key here is a resolution bug.
192
+ function installHermesWebPlugin({ apiKey, verbose, seededHome, }) {
193
+ if (!apiKey) {
194
+ throw new ConnectStepError('No SpringBrand API key was available to install the Hermes web plugin', 'invalid_config');
195
+ }
196
+ // Reuses the seed's home: a second `hermes dump` can disagree with the first.
197
+ const home = seededHome ?? requireHermesHome();
198
+ installHermesPlugin(home, apiKey, { verbose });
199
+ setHermesWebBackends(home);
200
+ }
201
+ // OpenCode's TUI takes a positional as a project directory, so a bare `opencode "<prompt>"`
202
+ // would be read as a folder. The `--prompt` flag seeds the interactive TUI with a first message
203
+ // (opencode.ai/docs/cli), so the onboarding guide fires just like the other agents.
204
+ function launchOpencode() {
205
+ handOverTerminal('opencode', ['--prompt', DEFAULT_ONBOARDING_PROMPT], 'OpenCode');
206
+ }
207
+ /** "positional": flags before `springbrand <url>`. "flag": flags after `--url`. */
208
+ function specAddArgs(spec, mcpUrl) {
209
+ const flags = spec.addFlags ?? [];
210
+ return spec.urlStyle === 'positional'
211
+ ? ['mcp', 'add', ...flags, 'springbrand', mcpUrl]
212
+ : ['mcp', 'add', 'springbrand', '--url', mcpUrl, ...flags];
213
+ }
214
+ /** `mcp add` probes the server and runs OAuth; add-json only writes config. */
215
+ function jsonAddArgs(spec, mcpUrl, apiKey) {
216
+ const { header } = spec;
217
+ const body = {
218
+ transport: 'http',
219
+ url: mcpUrl,
220
+ ...(header ? { headers: { [header.name]: `${header.valuePrefix ?? ''}${apiKey}` } } : {}),
221
+ };
222
+ return ['mcp', 'add-json', ...(spec.keyedAddJsonFlags ?? []), 'springbrand', JSON.stringify(body)];
223
+ }
224
+ function specKeyAuth(spec) {
225
+ const { header, keyEnvFlag, keyAddFlags } = spec;
226
+ if (spec.keyedAddJsonFlags) {
227
+ return { addArgs: (mcpUrl, apiKey) => jsonAddArgs(spec, mcpUrl, apiKey) };
228
+ }
229
+ if (keyEnvFlag) {
230
+ return {
231
+ envVar: SPRINGBRAND_API_KEY_VAR,
232
+ addArgs: (mcpUrl) => [...specAddArgs(spec, mcpUrl), keyEnvFlag, SPRINGBRAND_API_KEY_VAR],
233
+ };
234
+ }
235
+ if (keyAddFlags) {
236
+ return { addArgs: (mcpUrl) => [...specAddArgs(spec, mcpUrl), ...keyAddFlags] };
237
+ }
238
+ if (!header)
239
+ return undefined;
240
+ const value = (apiKey) => `${header.name}${header.sep}${header.valuePrefix ?? ''}${apiKey}`;
241
+ if (header.viaEnv) {
242
+ return {
243
+ envVar: SPRINGBRAND_API_KEY_VAR,
244
+ addArgs: (mcpUrl) => [
245
+ ...specAddArgs(spec, mcpUrl),
246
+ '--header',
247
+ value(`\${${SPRINGBRAND_API_KEY_VAR}}`),
248
+ ],
249
+ };
250
+ }
251
+ return {
252
+ addArgs: (mcpUrl, apiKey) => [...specAddArgs(spec, mcpUrl), '--header', value(apiKey)],
253
+ };
254
+ }
255
+ const HARNESS_OVERRIDES = {
256
+ codex: { detachedLaunch: launchCodexWalkthrough },
257
+ hermes: {
258
+ launchWalkthrough: launchHermesWalkthrough,
259
+ extraPostInstall: installHermesWebPlugin,
260
+ pluginVersion: HERMES_PLUGIN_VERSION,
261
+ seedKey: seedHermesKey,
262
+ },
263
+ opencode: { launchWalkthrough: launchOpencode },
264
+ };
265
+ function toNativeClient(harness) {
266
+ const spec = harnessSpec(harness);
267
+ if (!spec.supportCheck)
268
+ throw new Error(`${harness} has no supportCheck to probe`);
269
+ const overrides = HARNESS_OVERRIDES[harness] ?? {};
270
+ const keyed = specKeyAuth(spec);
271
+ const keyAuth = keyed && { ...keyed, seedKey: overrides.seedKey };
272
+ const base = {
273
+ command: spec.command,
274
+ connectClient: harness,
275
+ displayName: spec.displayName,
276
+ supportCheck: spec.supportCheck,
277
+ skillAgent: spec.skillAgent,
278
+ nonInteractiveAdd: spec.nonInteractiveAdd,
279
+ keyAuth,
280
+ signInHint: spec.signInHint,
281
+ degradedAuthNotes: spec.degradedAuthNotes,
282
+ removals: spec.removals ?? [
283
+ {
284
+ args: ['mcp', 'remove', 'springbrand'],
285
+ label: `SpringBrand registration from ${spec.displayName}`,
286
+ },
287
+ ],
288
+ launchWalkthrough: overrides.launchWalkthrough,
289
+ detachedLaunch: overrides.detachedLaunch,
290
+ postConnectNote: spec.postConnectNote,
291
+ extraPostInstall: overrides.extraPostInstall,
292
+ pluginVersion: overrides.pluginVersion,
293
+ uninstallExtra: spec.uninstallExtra,
294
+ };
295
+ if (spec.keyRequired) {
296
+ if (!keyAuth)
297
+ throw new Error(`${harness} takes only a key but has no keyed add`);
298
+ return { ...base, keyRequired: true, keyAuth };
299
+ }
300
+ return {
301
+ ...base,
302
+ loginArgs: spec.loginArgs,
303
+ addArgs: (mcpUrl) => specAddArgs(spec, mcpUrl),
304
+ };
305
+ }
306
+ export const NATIVE_MCP_CLIENTS = NATIVE_HARNESSES.map(toNativeClient);
307
+ /** Native descriptor by harness id; Cursor and OpenClaw have none. */
308
+ export const NATIVE_BY_HARNESS = new Map(NATIVE_MCP_CLIENTS.map((client) => [client.connectClient, client]));
309
+ export const OPENCLAW = {
310
+ command: HARNESS_SPECS.openclaw.command,
311
+ displayName: HARNESS_SPECS.openclaw.displayName,
312
+ supportCheck: HARNESS_SPECS.openclaw.supportCheck,
313
+ };
314
+ function printPromptForHandoff(displayName, command, prompt, reason) {
315
+ // "set up", not "connected": sign-in can still be deferred here.
316
+ errLine(`SpringBrand is set up in ${displayName}.`);
317
+ errLine(`${reason}, so SpringBrand did not launch it. Start ${displayName} (\`${command}\`) yourself ` +
318
+ `and paste this first message:`);
319
+ errLine('');
320
+ errLine(prompt);
321
+ }
322
+ /** One gate + one decide-before-block path for every terminal handover. */
323
+ async function deliverWalkthrough(displayName, command, prompt, handover, onDecided) {
324
+ // Inherited-stdio handover: a non-TTY parent cannot approve tool calls.
325
+ if (!detectHumanInitiated()) {
326
+ await onDecided?.('printed');
327
+ printPromptForHandoff(displayName, command, prompt, `This terminal cannot answer ${displayName}'s tool-approval prompts`);
328
+ return 'printed';
329
+ }
330
+ // Decided and delivered first: the handover blocks for the whole session.
331
+ await onDecided?.('launched');
332
+ errLine(`Starting the SpringBrand walkthrough in ${displayName}...`);
333
+ handover();
334
+ return 'launched';
335
+ }
336
+ export async function launchNativeMcpClient(client, onDecided) {
337
+ if (client.detachedLaunch) {
338
+ // Detached: the open attempt never blocks, so decide after it.
339
+ errLine(`Starting the SpringBrand walkthrough in ${client.displayName}...`);
340
+ const outcome = client.detachedLaunch();
341
+ await onDecided?.(outcome);
342
+ return outcome;
343
+ }
344
+ return deliverWalkthrough(client.displayName, client.command, DEFAULT_ONBOARDING_PROMPT, () => client.launchWalkthrough
345
+ ? client.launchWalkthrough()
346
+ : handOverTerminal(client.command, [DEFAULT_ONBOARDING_PROMPT], client.displayName), onDecided);
347
+ }
348
+ // Via deliverWalkthrough: handOverTerminal alone would wedge a headless --launch.
349
+ export function launchOmpWalkthrough(onDecided) {
350
+ return deliverWalkthrough('omp', 'omp', DEFAULT_ONBOARDING_PROMPT, () => handOverTerminal('omp', [DEFAULT_ONBOARDING_PROMPT], 'omp'), onDecided);
351
+ }
352
+ export function launchPiWalkthrough(onDecided) {
353
+ return deliverWalkthrough('Pi', 'pi', DEFAULT_ONBOARDING_PROMPT, () => handOverTerminal('pi', [DEFAULT_ONBOARDING_PROMPT], 'Pi'), onDecided);
354
+ }
355
+ export function launchOpenClawWalkthrough(onDecided) {
356
+ return deliverWalkthrough('OpenClaw', 'openclaw', OPENCLAW_ONBOARDING_PROMPT, () => handOverTerminal('openclaw', ['chat', '--message', OPENCLAW_ONBOARDING_PROMPT], 'OpenClaw'), onDecided);
357
+ }
358
+ //# sourceMappingURL=connect-clients.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect-clients.js","sourceRoot":"","sources":["../../src/lib/connect-clients.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /** 复刻自 tiny-fish CLI 编译产物:connect-fallback.d.ts + connect-fallback.impl.js */
2
+ import type { CliFallbackOutcome, ConnectCheckpoint, ConnectFailureStage } from './connect-runtime.js';
3
+ export declare const SEARCH_RETRY = "springbrand search query --pretty -- \"<your query>\"";
4
+ export declare const DEFAULT_VERIFICATION_QUERY = "today's top Hacker News story";
5
+ export declare const MALFORMED_ENV_KEY_MESSAGE = "SPRINGBRAND_API_KEY is set but malformed; it will override any stored key. Fix or unset it, then re-run.";
6
+ export declare const MALFORMED_STORED_KEY_MESSAGE = "The stored SpringBrand API key is malformed. Run: sp auth login";
7
+ export type Prompt = (question: string) => Promise<string>;
8
+ interface CliFallbackHooks {
9
+ onStepStart?: (stage: ConnectFailureStage) => void;
10
+ onStepDone?: (phase: ConnectCheckpoint) => void;
11
+ }
12
+ export interface CliFallbackOptions {
13
+ apiKey?: string;
14
+ verbose: boolean;
15
+ /** Absent means headless: no interactive login, no query prompt. */
16
+ prompt?: Prompt;
17
+ /** Whole-command retry line, per entry point. */
18
+ retryCommand: string;
19
+ /** Absent under --all's zero-harness path, which has no telemetry object. */
20
+ hooks?: CliFallbackHooks;
21
+ }
22
+ /** One readline per question; a held-open interface wedges raw-stdin children. */
23
+ export declare function createStdinPrompt(): Prompt;
24
+ /** Steps print retry lines and return outcomes; only interrupts throw. */
25
+ export declare function runCliFallback(opts: CliFallbackOptions): Promise<CliFallbackOutcome>;
26
+ export {};
27
+ //# sourceMappingURL=connect-fallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect-fallback.d.ts","sourceRoot":"","sources":["../../src/lib/connect-fallback.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAE9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AASvG,eAAO,MAAM,YAAY,0DAAwD,CAAC;AAElF,eAAO,MAAM,0BAA0B,kCAAkC,CAAC;AAI1E,eAAO,MAAM,yBAAyB,6GAA6G,CAAC;AACpJ,eAAO,MAAM,4BAA4B,oEAAoE,CAAC;AAE9G,MAAM,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAE3D,UAAU,gBAAgB;IACtB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACnD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACnD;AAED,MAAM,WAAW,kBAAkB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,YAAY,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAOD,kFAAkF;AAClF,wBAAgB,iBAAiB,IAAI,MAAM,CA4B1C;AAkFD,0EAA0E;AAC1E,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA8B1F"}
@@ -0,0 +1,166 @@
1
+ /** 复刻自 tiny-fish CLI 编译产物:connect-fallback.d.ts + connect-fallback.impl.js */
2
+ import * as readline from 'node:readline/promises';
3
+ import spawn from 'cross-spawn';
4
+ import { resolvedApiKey, validateKeyFormat } from './auth.js';
5
+ import { installSpringBrandCli } from './cli-install.js';
6
+ import { ensureCliAuthenticated, SPRINGBRAND_CLI_NOT_FOUND_MESSAGE } from './connect-auth.js';
7
+ import { SPRINGBRAND_API_KEY_VAR } from './constants.js';
8
+ import { commandNotFound, ConnectInterruptedError, ConnectStepError, throwIfInterrupted, } from './connect-runtime.js';
9
+ import { errLine, outLine } from './output.js';
10
+ export const SEARCH_RETRY = 'springbrand search query --pretty -- "<your query>"';
11
+ // Echoes the finale suggestion, so headless rescues rehearse the same task.
12
+ export const DEFAULT_VERIFICATION_QUERY = "today's top Hacker News story";
13
+ // Must undercut agent tool-call budgets (Claude Code Bash defaults to 120s).
14
+ const HEADLESS_VERIFY_TIMEOUT_MS = 90_000;
15
+ // An exported var must be unset, not re-logged-in.
16
+ export const MALFORMED_ENV_KEY_MESSAGE = 'SPRINGBRAND_API_KEY is set but malformed; it will override any stored key. Fix or unset it, then re-run.';
17
+ export const MALFORMED_STORED_KEY_MESSAGE = 'The stored SpringBrand API key is malformed. Run: sp auth login';
18
+ function searchRetry(query) {
19
+ if (process.platform === 'win32')
20
+ return SEARCH_RETRY;
21
+ return `springbrand search query --pretty -- '${query.replaceAll("'", "'\\''")}'`;
22
+ }
23
+ /** One readline per question; a held-open interface wedges raw-stdin children. */
24
+ export function createStdinPrompt() {
25
+ let stdinClosed = false;
26
+ return async (question) => {
27
+ if (stdinClosed)
28
+ throw new Error('stdin is closed');
29
+ const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
30
+ // Without a close-linked signal, question() never settles on Ctrl+D.
31
+ const closed = new AbortController();
32
+ rl.on('close', () => closed.abort());
33
+ // Raw mode swallows Ctrl+C here; resurface it as the interrupt.
34
+ let interrupted = false;
35
+ rl.on('SIGINT', () => {
36
+ interrupted = true;
37
+ rl.close();
38
+ });
39
+ try {
40
+ return await rl.question(question, { signal: closed.signal });
41
+ }
42
+ catch (error) {
43
+ if (interrupted)
44
+ throw new ConnectInterruptedError('Setup interrupted');
45
+ stdinClosed = true;
46
+ throw error;
47
+ }
48
+ finally {
49
+ rl.close();
50
+ }
51
+ };
52
+ }
53
+ function installStep(opts) {
54
+ try {
55
+ installSpringBrandCli({ verbose: opts.verbose, announce: true });
56
+ return null;
57
+ }
58
+ catch (error) {
59
+ if (error instanceof ConnectInterruptedError)
60
+ throw error;
61
+ errLine(error instanceof Error ? error.message : String(error));
62
+ outLine(`Retry: ${opts.retryCommand}`);
63
+ return 'cli_install_failed';
64
+ }
65
+ }
66
+ function authStep(opts) {
67
+ // Resolved raw: validatedApiKey collapses a malformed key into "no key".
68
+ const rawKey = resolvedApiKey(opts.apiKey);
69
+ if (rawKey && !validateKeyFormat(rawKey)) {
70
+ // Terminal even in a TTY: login writes config; env shadows it.
71
+ errLine(process.env[SPRINGBRAND_API_KEY_VAR] ? MALFORMED_ENV_KEY_MESSAGE : MALFORMED_STORED_KEY_MESSAGE);
72
+ outLine(`Retry: ${opts.retryCommand}`);
73
+ return 'invalid_credentials';
74
+ }
75
+ if (!opts.prompt && !rawKey) {
76
+ outLine(`Retry in a terminal: ${opts.retryCommand}`);
77
+ return 'no_credentials';
78
+ }
79
+ try {
80
+ // Gate-only widening: a config-only key must not re-persist anywhere.
81
+ // Headless has no one to answer a login prompt; never inherit stdio there.
82
+ ensureCliAuthenticated('cli', opts.apiKey ?? process.env[SPRINGBRAND_API_KEY_VAR], {
83
+ interactiveLogin: !!opts.prompt,
84
+ });
85
+ return null;
86
+ }
87
+ catch (error) {
88
+ if (error instanceof ConnectInterruptedError)
89
+ throw error;
90
+ errLine(error instanceof Error ? error.message : String(error));
91
+ outLine(error instanceof ConnectStepError && error.failureReason === 'command_not_found'
92
+ ? 'Retry in a new terminal: sp auth login'
93
+ : 'Retry: sp auth login');
94
+ return 'authentication_failed';
95
+ }
96
+ }
97
+ /** null = abandoned; the retry line is already printed. */
98
+ async function promptQuery(prompt) {
99
+ let query;
100
+ try {
101
+ query = (await prompt('What would you like to search? ')).trim();
102
+ }
103
+ catch (error) {
104
+ if (error instanceof ConnectInterruptedError)
105
+ throw error;
106
+ outLine(`Retry: ${SEARCH_RETRY}`);
107
+ return null;
108
+ }
109
+ if (!query) {
110
+ outLine(`Retry: ${SEARCH_RETRY}`);
111
+ return null;
112
+ }
113
+ return query;
114
+ }
115
+ function verifyStep(query, interactive) {
116
+ const search = spawn.sync('sp', ['search', 'query', '--pretty', '--', query], {
117
+ stdio: 'inherit',
118
+ env: { ...process.env, TF_SETUP_VERIFICATION: '1' },
119
+ // A user-driven search must never be cut off.
120
+ timeout: interactive ? undefined : HEADLESS_VERIFY_TIMEOUT_MS,
121
+ });
122
+ if (commandNotFound(search.error)) {
123
+ errLine(SPRINGBRAND_CLI_NOT_FOUND_MESSAGE);
124
+ outLine(`Retry in a new terminal: ${searchRetry(query)}`);
125
+ return 'verification_failed';
126
+ }
127
+ throwIfInterrupted(search);
128
+ if (search.error || search.status !== 0) {
129
+ outLine(`Retry: ${searchRetry(query)}`);
130
+ return 'verification_failed';
131
+ }
132
+ return 'cli_verified';
133
+ }
134
+ /** Steps print retry lines and return outcomes; only interrupts throw. */
135
+ export async function runCliFallback(opts) {
136
+ const { hooks, prompt } = opts;
137
+ const stepStart = hooks?.onStepStart ?? (() => { });
138
+ const stepDone = hooks?.onStepDone ?? (() => { });
139
+ stepStart('cli_install');
140
+ const installFailure = installStep(opts);
141
+ if (installFailure)
142
+ return installFailure;
143
+ stepDone('cli_installed');
144
+ stepStart('authentication');
145
+ const authFailure = authStep(opts);
146
+ if (authFailure)
147
+ return authFailure;
148
+ stepDone('authenticated');
149
+ stepStart('cli_verification');
150
+ let query;
151
+ if (prompt) {
152
+ const answered = await promptQuery(prompt);
153
+ if (answered === null)
154
+ return 'abandoned';
155
+ query = answered;
156
+ }
157
+ else {
158
+ // Headless with a key: a canned query still proves the pipe.
159
+ query = DEFAULT_VERIFICATION_QUERY;
160
+ }
161
+ const outcome = verifyStep(query, !!prompt);
162
+ if (outcome === 'cli_verified')
163
+ stepDone('cli_verified');
164
+ return outcome;
165
+ }
166
+ //# sourceMappingURL=connect-fallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect-fallback.js","sourceRoot":"","sources":["../../src/lib/connect-fallback.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAG9E,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,MAAM,aAAa,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,iCAAiC,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,kBAAkB,GAAG,MAAM,sBAAsB,CAAC;AACvH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC/C,MAAM,CAAC,MAAM,YAAY,GAAG,qDAAqD,CAAC;AAClF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,0BAA0B,GAAG,+BAA+B,CAAC;AAC1E,6EAA6E;AAC7E,MAAM,0BAA0B,GAAG,MAAM,CAAC;AAC1C,mDAAmD;AACnD,MAAM,CAAC,MAAM,yBAAyB,GAAG,0GAA0G,CAAC;AACpJ,MAAM,CAAC,MAAM,4BAA4B,GAAG,iEAAiE,CAAC;AAoB9G,SAAS,WAAW,CAAC,KAAa;IAC9B,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAC5B,OAAO,YAAY,CAAC;IACxB,OAAO,yCAAyC,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC;AACtF,CAAC;AACD,kFAAkF;AAClF,MAAM,UAAU,iBAAiB;IAC7B,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,EAAE;QACtB,IAAI,WAAW;YACX,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACvC,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACtF,qEAAqE;QACrE,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACrC,gEAAgE;QAChE,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YACjB,WAAW,GAAG,IAAI,CAAC;YACnB,EAAE,CAAC,KAAK,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;QACH,IAAI,CAAC;YACD,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YACX,IAAI,WAAW;gBACX,MAAM,IAAI,uBAAuB,CAAC,mBAAmB,CAAC,CAAC;YAC3D,WAAW,GAAG,IAAI,CAAC;YACnB,MAAM,KAAK,CAAC;QAChB,CAAC;gBACO,CAAC;YACL,EAAE,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;IACL,CAAC,CAAC;AACN,CAAC;AACD,SAAS,WAAW,CAAC,IAAwB;IACzC,IAAI,CAAC;QACD,qBAAqB,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,EAAE,CAAC;QACX,IAAI,KAAK,YAAY,uBAAuB;YACxC,MAAM,KAAK,CAAC;QAChB,OAAO,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,UAAU,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QACvC,OAAO,oBAAoB,CAAC;IAChC,CAAC;AACL,CAAC;AACD,SAAS,QAAQ,CAAC,IAAwB;IACtC,yEAAyE;IACzE,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,MAAM,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;QACvC,+DAA+D;QAC/D,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC;QACzG,OAAO,CAAC,UAAU,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QACvC,OAAO,qBAAqB,CAAC;IACjC,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QAC1B,OAAO,CAAC,wBAAwB,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QACrD,OAAO,gBAAgB,CAAC;IAC5B,CAAC;IACD,IAAI,CAAC;QACD,sEAAsE;QACtE,2EAA2E;QAC3E,sBAAsB,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,EAAE;YAC/E,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;SAClC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,EAAE,CAAC;QACX,IAAI,KAAK,YAAY,uBAAuB;YACxC,MAAM,KAAK,CAAC;QAChB,OAAO,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,KAAK,YAAY,gBAAgB,IAAI,KAAK,CAAC,aAAa,KAAK,mBAAmB;YACpF,CAAC,CAAC,wCAAwC;YAC1C,CAAC,CAAC,sBAAsB,CAAC,CAAC;QAC9B,OAAO,uBAAuB,CAAC;IACnC,CAAC;AACL,CAAC;AACD,2DAA2D;AAC3D,KAAK,UAAU,WAAW,CAAC,MAAc;IACrC,IAAI,KAAK,CAAC;IACV,IAAI,CAAC;QACD,KAAK,GAAG,CAAC,MAAM,MAAM,CAAC,iCAAiC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACrE,CAAC;IACD,OAAO,KAAK,EAAE,CAAC;QACX,IAAI,KAAK,YAAY,uBAAuB;YACxC,MAAM,KAAK,CAAC;QAChB,OAAO,CAAC,UAAU,YAAY,EAAE,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO,CAAC,UAAU,YAAY,EAAE,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AACD,SAAS,UAAU,CAAC,KAAa,EAAE,WAAoB;IACnD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE;QAC1E,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,qBAAqB,EAAE,GAAG,EAAE;QACnD,8CAA8C;QAC9C,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,0BAA0B;KAChE,CAAC,CAAC;IACH,IAAI,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,iCAAiC,CAAC,CAAC;QAC3C,OAAO,CAAC,4BAA4B,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1D,OAAO,qBAAqB,CAAC;IACjC,CAAC;IACD,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,UAAU,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACxC,OAAO,qBAAqB,CAAC;IACjC,CAAC;IACD,OAAO,cAAc,CAAC;AAC1B,CAAC;AACD,0EAA0E;AAC1E,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAwB;IACzD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC/B,MAAM,SAAS,GAAG,KAAK,EAAE,WAAW,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,KAAK,EAAE,UAAU,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IAClD,SAAS,CAAC,aAAa,CAAC,CAAC;IACzB,MAAM,cAAc,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,cAAc;QACd,OAAO,cAAc,CAAC;IAC1B,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC1B,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC5B,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,WAAW;QACX,OAAO,WAAW,CAAC;IACvB,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC1B,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAC9B,IAAI,KAAK,CAAC;IACV,IAAI,MAAM,EAAE,CAAC;QACT,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;QAC3C,IAAI,QAAQ,KAAK,IAAI;YACjB,OAAO,WAAW,CAAC;QACvB,KAAK,GAAG,QAAQ,CAAC;IACrB,CAAC;SACI,CAAC;QACF,6DAA6D;QAC7D,KAAK,GAAG,0BAA0B,CAAC;IACvC,CAAC;IACD,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,OAAO,KAAK,cAAc;QAC1B,QAAQ,CAAC,cAAc,CAAC,CAAC;IAC7B,OAAO,OAAO,CAAC;AACnB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /** 复刻自 tiny-fish CLI 编译产物:connect-picker.d.ts + connect-picker.impl.js */
2
+ import type { Readable } from 'node:stream';
3
+ import type { Harness, HarnessDetection } from './harness-detect.js';
4
+ export declare function pickHarnesses(detections: HarnessDetection[], connectedBefore: ReadonlySet<string>, io?: PickerIo): Promise<PickResult>;
5
+ type PickSelection = Harness[] | 'cancel';
6
+ export interface PickResult {
7
+ selection: PickSelection;
8
+ mode: 'pick' | 'pick_numeric';
9
+ }
10
+ type PickerStdin = Readable & {
11
+ setRawMode?: (raw: boolean) => unknown;
12
+ };
13
+ export interface PickerIo {
14
+ stdin?: PickerStdin;
15
+ write?: (text: string) => void;
16
+ prompt?: (question: string) => Promise<string>;
17
+ }
18
+ export {};
19
+ //# sourceMappingURL=connect-picker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect-picker.d.ts","sourceRoot":"","sources":["../../src/lib/connect-picker.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AA+IrE,wBAAsB,aAAa,CAAC,UAAU,EAAE,gBAAgB,EAAE,EAAE,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAkB5I;AAGD,KAAK,aAAa,GAAG,OAAO,EAAE,GAAG,QAAQ,CAAC;AAE1C,MAAM,WAAW,UAAU;IACvB,SAAS,EAAE,aAAa,CAAC;IACzB,IAAI,EAAE,MAAM,GAAG,cAAc,CAAC;CACjC;AAED,KAAK,WAAW,GAAG,QAAQ,GAAG;IAC1B,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;CAC1C,CAAC;AAEF,MAAM,WAAW,QAAQ;IACrB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAClD"}