@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,169 @@
1
+ /** 复刻自 tiny-fish CLI 编译产物:verify.d.ts + verify.impl.js */
2
+ import { BASE_URL, CLI_AGENT_IDENTITY, CLI_VERSION } from './constants.js';
3
+ const VERIFY_TIMEOUT_MS = 5_000;
4
+ // `fetch` collapses every network fault to "fetch failed" and hides the cause on `e.cause`.
5
+ function networkCode(e) {
6
+ const cause = e.cause;
7
+ switch (cause?.code) {
8
+ case 'ECONNREFUSED':
9
+ return 'connection refused';
10
+ case 'ENOTFOUND':
11
+ return 'host not found';
12
+ case 'ETIMEDOUT':
13
+ return 'connection timed out';
14
+ case 'CERT_HAS_EXPIRED':
15
+ case 'UNABLE_TO_VERIFY_LEAF_SIGNATURE':
16
+ case 'DEPTH_ZERO_SELF_SIGNED_CERT':
17
+ return 'TLS verification failed';
18
+ default:
19
+ return e instanceof Error && e.name === 'TimeoutError'
20
+ ? 'request timed out'
21
+ : 'could not reach the endpoint';
22
+ }
23
+ }
24
+ /**
25
+ * The Gateway's authored prose per error code. Its stable codes say more than a status does:
26
+ * 401 alone cannot tell "revoked" from "wrong environment", and both 502 and 503 mean the
27
+ * platform could not answer rather than that the key is bad.
28
+ */
29
+ const CODE_PROSE = {
30
+ AUTH_MCP_KEY_INVALID: 'the API key is invalid, revoked, or expired',
31
+ AUTH_MCP_KEY_ENVIRONMENT_MISMATCH: 'the API key was issued for a different environment',
32
+ AUTH_MCP_ACCOUNT_DISABLED: 'the SpringBrand account is disabled',
33
+ AUTH_MCP_SCOPE_DENIED: 'the API key is missing the mcp:access scope',
34
+ REQUEST_FORBIDDEN: 'SpringBrand refused the key on this endpoint',
35
+ REQUEST_RATE_LIMITED: 'rate limited',
36
+ AUTH_MCP_VERIFICATION_UNAVAILABLE: 'SpringBrand key verification is temporarily unavailable',
37
+ AUTH_MCP_VERIFICATION_INVALID_RESPONSE: 'SpringBrand returned an unexpected verification response',
38
+ };
39
+ function statusProse(status) {
40
+ if (status === 401)
41
+ return 'the API key is invalid or expired';
42
+ if (status === 403)
43
+ return 'the API key is not allowed to do this';
44
+ if (status === 429)
45
+ return 'rate limited';
46
+ return status >= 500 ? 'SpringBrand returned a server error' : `the endpoint returned HTTP ${status}`;
47
+ }
48
+ /** Only 401 and 403 blame the credential; everything else is worth retrying. */
49
+ function failureKind(status) {
50
+ return status === 401 || status === 403 ? 'credential_rejected' : 'retryable';
51
+ }
52
+ /** The `{code, errMsg, requestId}` contract; a non-conforming body is simply no code. */
53
+ async function readErrorCode(response) {
54
+ const body = await response.json().catch(() => undefined);
55
+ const code = body?.code;
56
+ return typeof code === 'string' && code in CODE_PROSE ? code : undefined;
57
+ }
58
+ const IDENTITY_HEADERS = {
59
+ accountId: 'x-springbrand-mcp-account-id',
60
+ keyId: 'x-springbrand-mcp-key-id',
61
+ environment: 'x-springbrand-mcp-environment',
62
+ };
63
+ /** Present on every accepted key request; proves the credential works, not that a host loaded us. */
64
+ function readIdentity(response) {
65
+ const accountId = response.headers.get(IDENTITY_HEADERS.accountId);
66
+ const keyId = response.headers.get(IDENTITY_HEADERS.keyId);
67
+ const environment = response.headers.get(IDENTITY_HEADERS.environment);
68
+ if (!accountId || !keyId || !environment)
69
+ return undefined;
70
+ return { accountId, keyId, environment };
71
+ }
72
+ /** Bounded, so a `Retry-After` of a day cannot be printed as advice. */
73
+ const MAX_RETRY_AFTER_SECONDS = 3600;
74
+ function readRetryAfter(response) {
75
+ const raw = Number(response.headers.get('retry-after'));
76
+ if (!Number.isInteger(raw) || raw <= 0)
77
+ return undefined;
78
+ return Math.min(raw, MAX_RETRY_AFTER_SECONDS);
79
+ }
80
+ /**
81
+ * Cheapest authenticated round-trip the gateway offers: `/mcp` is the only supported
82
+ * endpoint, and `initialize` touches no business state.
83
+ */
84
+ async function probeAuthenticated(apiKey, apiBaseUrl) {
85
+ // Callers omit the base for a default-endpoint install; the SDK used to fill it in.
86
+ return fetch(`${apiBaseUrl ?? BASE_URL}/mcp`, {
87
+ method: 'POST',
88
+ headers: {
89
+ Authorization: `Bearer ${apiKey}`,
90
+ 'Content-Type': 'application/json',
91
+ Accept: 'application/json, text/event-stream',
92
+ },
93
+ body: JSON.stringify({
94
+ jsonrpc: '2.0',
95
+ id: 1,
96
+ method: 'initialize',
97
+ params: {
98
+ protocolVersion: '2025-06-18',
99
+ capabilities: {},
100
+ clientInfo: { name: CLI_AGENT_IDENTITY, version: CLI_VERSION },
101
+ },
102
+ }),
103
+ signal: AbortSignal.timeout(VERIFY_TIMEOUT_MS),
104
+ });
105
+ }
106
+ /** Reachability check. Verify failure is a warning, never install failure. */
107
+ export async function verifyMcpHealth(mcpUrl) {
108
+ try {
109
+ const response = await fetch(mcpUrl, {
110
+ method: 'GET',
111
+ // Redirect (captive portal, typo'd --url) is not healthy.
112
+ redirect: 'error',
113
+ signal: AbortSignal.timeout(VERIFY_TIMEOUT_MS),
114
+ });
115
+ // MCP rejects bare GET with 4xx — still proves endpoint routed.
116
+ if (response.status >= 500) {
117
+ return {
118
+ depth: 'health',
119
+ ok: false,
120
+ reason: `endpoint returned HTTP ${response.status}`,
121
+ code: `the endpoint returned HTTP ${response.status}`,
122
+ };
123
+ }
124
+ return { depth: 'health', ok: true };
125
+ }
126
+ catch (e) {
127
+ return {
128
+ depth: 'health',
129
+ ok: false,
130
+ reason: e instanceof Error ? e.message : 'network error reaching MCP endpoint',
131
+ code: networkCode(e),
132
+ };
133
+ }
134
+ }
135
+ /** Authenticated check — where the CLI holds the key (Cursor, OpenClaw, Hermes). */
136
+ export async function verifyMcpAuth(apiKey, apiBaseUrl) {
137
+ let response;
138
+ try {
139
+ // Bound it: a warning-only check must never hang an install.
140
+ response = await probeAuthenticated(apiKey, apiBaseUrl);
141
+ }
142
+ catch (e) {
143
+ // No answer at all says nothing about the key, so it is never blamed for one.
144
+ return {
145
+ depth: 'health+auth',
146
+ ok: false,
147
+ kind: 'retryable',
148
+ reason: e instanceof Error ? e.message : String(e),
149
+ code: networkCode(e),
150
+ };
151
+ }
152
+ if (response.ok) {
153
+ const identity = readIdentity(response);
154
+ return { depth: 'health+auth', ok: true, ...(identity ? { identity } : {}) };
155
+ }
156
+ const errorCode = await readErrorCode(response);
157
+ const retryAfter = response.status === 429 ? readRetryAfter(response) : undefined;
158
+ return {
159
+ depth: 'health+auth',
160
+ ok: false,
161
+ kind: failureKind(response.status),
162
+ status: response.status,
163
+ reason: `the endpoint returned HTTP ${response.status}`,
164
+ code: errorCode ? CODE_PROSE[errorCode] : statusProse(response.status),
165
+ ...(errorCode ? { errorCode } : {}),
166
+ ...(retryAfter === undefined ? {} : { retryAfter }),
167
+ };
168
+ }
169
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/lib/verify.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAE1D,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC3E,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAChC,4FAA4F;AAC5F,SAAS,WAAW,CAAC,CAAU;IAC3B,MAAM,KAAK,GAAI,CAAmC,CAAC,KAAK,CAAC;IACzD,QAAQ,KAAK,EAAE,IAAI,EAAE,CAAC;QAClB,KAAK,cAAc;YACf,OAAO,oBAAoB,CAAC;QAChC,KAAK,WAAW;YACZ,OAAO,gBAAgB,CAAC;QAC5B,KAAK,WAAW;YACZ,OAAO,sBAAsB,CAAC;QAClC,KAAK,kBAAkB,CAAC;QACxB,KAAK,iCAAiC,CAAC;QACvC,KAAK,6BAA6B;YAC9B,OAAO,yBAAyB,CAAC;QACrC;YACI,OAAO,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc;gBAClD,CAAC,CAAC,mBAAmB;gBACrB,CAAC,CAAC,8BAA8B,CAAC;IAC7C,CAAC;AACL,CAAC;AACD;;;;GAIG;AACH,MAAM,UAAU,GAA2B;IACvC,oBAAoB,EAAE,6CAA6C;IACnE,iCAAiC,EAAE,oDAAoD;IACvF,yBAAyB,EAAE,qCAAqC;IAChE,qBAAqB,EAAE,6CAA6C;IACpE,iBAAiB,EAAE,8CAA8C;IACjE,oBAAoB,EAAE,cAAc;IACpC,iCAAiC,EAAE,yDAAyD;IAC5F,sCAAsC,EAAE,0DAA0D;CACrG,CAAC;AACF,SAAS,WAAW,CAAC,MAAc;IAC/B,IAAI,MAAM,KAAK,GAAG;QACd,OAAO,mCAAmC,CAAC;IAC/C,IAAI,MAAM,KAAK,GAAG;QACd,OAAO,uCAAuC,CAAC;IACnD,IAAI,MAAM,KAAK,GAAG;QACd,OAAO,cAAc,CAAC;IAC1B,OAAO,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,qCAAqC,CAAC,CAAC,CAAC,8BAA8B,MAAM,EAAE,CAAC;AAC1G,CAAC;AACD,gFAAgF;AAChF,SAAS,WAAW,CAAC,MAAc;IAC/B,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,WAAW,CAAC;AAClF,CAAC;AACD,yFAAyF;AACzF,KAAK,UAAU,aAAa,CAAC,QAAkB;IAC3C,MAAM,IAAI,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACnE,MAAM,IAAI,GAAI,IAAuC,EAAE,IAAI,CAAC;IAC5D,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,IAAI,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7E,CAAC;AACD,MAAM,gBAAgB,GAAG;IACrB,SAAS,EAAE,8BAA8B;IACzC,KAAK,EAAE,0BAA0B;IACjC,WAAW,EAAE,+BAA+B;CACtC,CAAC;AACX,qGAAqG;AACrG,SAAS,YAAY,CAAC,QAAkB;IACpC,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;IACnE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACvE,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,IAAI,CAAC,WAAW;QACpC,OAAO,SAAS,CAAC;IACrB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;AAC7C,CAAC;AACD,wEAAwE;AACxE,MAAM,uBAAuB,GAAG,IAAI,CAAC;AACrC,SAAS,cAAc,CAAC,QAAkB;IACtC,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;IACxD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;QAClC,OAAO,SAAS,CAAC;IACrB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC;AAClD,CAAC;AACD;;;GAGG;AACH,KAAK,UAAU,kBAAkB,CAAC,MAAc,EAAE,UAA8B;IAC5E,oFAAoF;IACpF,OAAO,KAAK,CAAC,GAAG,UAAU,IAAI,QAAQ,MAAM,EAAE;QAC1C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACL,aAAa,EAAE,UAAU,MAAM,EAAE;YACjC,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,qCAAqC;SAChD;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACjB,OAAO,EAAE,KAAK;YACd,EAAE,EAAE,CAAC;YACL,MAAM,EAAE,YAAY;YACpB,MAAM,EAAE;gBACJ,eAAe,EAAE,YAAY;gBAC7B,YAAY,EAAE,EAAE;gBAChB,UAAU,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,WAAW,EAAE;aACjE;SACJ,CAAC;QACF,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,iBAAiB,CAAC;KACjD,CAAC,CAAC;AACP,CAAC;AACD,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAc;IAChD,IAAI,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE;YACjC,MAAM,EAAE,KAAK;YACb,0DAA0D;YAC1D,QAAQ,EAAE,OAAO;YACjB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,iBAAiB,CAAC;SACjD,CAAC,CAAC;QACH,gEAAgE;QAChE,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YACzB,OAAO;gBACH,KAAK,EAAE,QAAQ;gBACf,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,0BAA0B,QAAQ,CAAC,MAAM,EAAE;gBACnD,IAAI,EAAE,8BAA8B,QAAQ,CAAC,MAAM,EAAE;aACxD,CAAC;QACN,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACzC,CAAC;IACD,OAAO,CAAC,EAAE,CAAC;QACP,OAAO;YACH,KAAK,EAAE,QAAQ;YACf,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,qCAAqC;YAC9E,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;SACvB,CAAC;IACN,CAAC;AACL,CAAC;AACD,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAc,EAAE,UAAmB;IACnE,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACD,6DAA6D;QAC7D,QAAQ,GAAG,MAAM,kBAAkB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,CAAC,EAAE,CAAC;QACP,8EAA8E;QAC9E,OAAO;YACH,KAAK,EAAE,aAAa;YACpB,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YAClD,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;SACvB,CAAC;IACN,CAAC;IACD,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;QACd,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACxC,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACjF,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAClF,OAAO;QACH,KAAK,EAAE,aAAa;QACpB,EAAE,EAAE,KAAK;QACT,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC;QAClC,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,MAAM,EAAE,8BAA8B,QAAQ,CAAC,MAAM,EAAE;QACvD,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAE,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC;QACvE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnC,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;KACtD,CAAC;AACN,CAAC"}
@@ -0,0 +1,8 @@
1
+ /** 复刻自 tiny-fish CLI 编译产物:program.d.ts + program.impl.js */
2
+ import { Command } from 'commander';
3
+ /** Split from index.ts so tests can drive the real program instead of hand-assembling one. */
4
+ export declare function buildProgram(argv?: string[]): Promise<{
5
+ program: Command;
6
+ uninstallNotice: () => NodeJS.Process;
7
+ }>;
8
+ //# sourceMappingURL=program.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAE5D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+BpC,8FAA8F;AAC9F,wBAAsB,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE;;;GAqBjD"}
@@ -0,0 +1,54 @@
1
+ /** 复刻自 tiny-fish CLI 编译产物:program.d.ts + program.impl.js */
2
+ import { Command } from 'commander';
3
+ import { CLI_VERSION } from './lib/constants.js';
4
+ import { installNoticeEmit } from './lib/notice.js';
5
+ const GROUPS = {
6
+ auth: async (p) => (await import('./commands/auth.js')).registerAuth(p),
7
+ connect: async (p) => (await import('./commands/connect.js')).registerConnect(p),
8
+ doctor: async (p) => (await import('./commands/doctor.js')).registerDoctor(p),
9
+ upgrade: async (p) => (await import('./commands/upgrade.js')).registerUpgrade(p),
10
+ 'check-version': async (p) => (await import('./commands/check-version.js')).registerCheckVersion(p),
11
+ // `config-claude` is deliberately unregistered: it points Claude Code at `sp search`
12
+ // and `sp fetch`, which do not exist yet. commands/config-claude.ts and lib/claude-config.ts
13
+ // are kept so it can be re-registered once those commands land. See README TODO.
14
+ };
15
+ /** Commander answers these before routing, so no command module is needed. */
16
+ const VERSION_FLAGS = ['-V', '--version'];
17
+ // Unknown names need the full list to suggest against.
18
+ /** First bare token is the command. Assumes no global option takes a value. */
19
+ function groupsFor(argv = process.argv) {
20
+ for (const arg of argv.slice(2)) {
21
+ if (arg === '--')
22
+ break;
23
+ if (!arg.startsWith('-')) {
24
+ return Object.hasOwn(GROUPS, arg) ? [arg] : Object.keys(GROUPS);
25
+ }
26
+ if (VERSION_FLAGS.includes(arg))
27
+ return [];
28
+ }
29
+ return Object.keys(GROUPS);
30
+ }
31
+ /** Split from index.ts so tests can drive the real program instead of hand-assembling one. */
32
+ export async function buildProgram(argv) {
33
+ const program = new Command();
34
+ program
35
+ .name('sp')
36
+ .description('SpringBrand CLI — connect your agents to the SpringBrand Gateway.')
37
+ .version(CLI_VERSION, VERSION_FLAGS.join(', '), 'Show version')
38
+ .helpOption('-h, --help', 'Show help')
39
+ .addHelpCommand(false)
40
+ .enablePositionalOptions()
41
+ .option('--debug', 'Print HTTP requests and responses to stderr (or set SPRINGBRAND_DEBUG=1)')
42
+ .hook('preAction', (cmd) => {
43
+ if (cmd.opts().debug) {
44
+ process.env['SPRINGBRAND_DEBUG'] = '1';
45
+ }
46
+ });
47
+ // Order is user-visible: help lists commands as registered.
48
+ for (const name of groupsFor(argv ?? process.argv)) {
49
+ await GROUPS[name](program);
50
+ }
51
+ const uninstallNotice = installNoticeEmit(program);
52
+ return { program, uninstallNotice };
53
+ }
54
+ //# sourceMappingURL=program.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"program.js","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@springbrand/cli",
3
+ "version": "0.1.0",
4
+ "description": "SpringBrand CLI — connect MCP hosts to the SpringBrand Gateway",
5
+ "type": "module",
6
+ "bin": {
7
+ "sp": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "skill",
12
+ "README.md"
13
+ ],
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "prepublishOnly": "npm run build",
20
+ "dev": "tsc --watch",
21
+ "test": "npm run build && vitest run",
22
+ "test:unit": "vitest run test/mcp-json-config.test.ts test/branding.test.ts",
23
+ "test:watch": "vitest",
24
+ "typecheck": "tsc --noEmit"
25
+ },
26
+ "keywords": [
27
+ "mcp",
28
+ "gateway",
29
+ "cli",
30
+ "springbrand"
31
+ ],
32
+ "author": "SpringBrand",
33
+ "license": "MIT",
34
+ "dependencies": {
35
+ "@modelcontextprotocol/sdk": "^1.0.4",
36
+ "chalk": "^5.3.0",
37
+ "commander": "^12.1.0",
38
+ "cross-spawn": "^7.0.6",
39
+ "open": "^10.1.0",
40
+ "tldts": "^6.1.86",
41
+ "which": "^2.0.2",
42
+ "yaml": "^2.9.1",
43
+ "zod": "^4.6.5"
44
+ },
45
+ "devDependencies": {
46
+ "@types/cross-spawn": "^6.0.6",
47
+ "@types/node": "^22.10.2",
48
+ "@types/which": "^3.0.4",
49
+ "typescript": "^5.7.2",
50
+ "vitest": "^2.1.8"
51
+ },
52
+ "engines": {
53
+ "node": ">=18"
54
+ }
55
+ }
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: springbrand-action-api
3
+ description: Use SpringBrand Action APIs for available API services and their operations. Use this guidance for API discovery, current contracts, confirmed execution, and saved results.
4
+ ---
5
+
6
+ # SpringBrand Action API
7
+
8
+ Use the unified SpringBrand MCP for SpringBrand-managed API services. The CLI
9
+ has already configured and authenticated the MCP connection. This Skill does
10
+ not manage third-party connections or install a service.
11
+
12
+ ## Discover and inspect
13
+
14
+ Call `search_tools` once with one concise English query that states the
15
+ intended result, service, important input, and output. Search results are
16
+ bounded; an incomplete result is not proof of absence. Select an Action API
17
+ operation, copy its opaque Tool ID unchanged, and call `get_tool_schemas` for
18
+ its current input and output contract.
19
+
20
+ Do not parse a Tool ID to infer a supplier, model, version, or domain. Do not
21
+ execute a result whose described effect belongs to Platform or Connector; use
22
+ an explicit state-preserving Domain transition instead.
23
+
24
+ ## Confirm and execute
25
+
26
+ Before a write, explain what will happen, the arguments, known fee or credit
27
+ charge, reported risk, and any output limitation. Ask for missing business
28
+ values rather than using placeholders. Execute once with schema-valid
29
+ arguments and a stable idempotency key.
30
+
31
+ Only `succeeded` means complete. If an execution ID is returned, copy it
32
+ exactly and use `get_execution` to read its status or saved result. Running or
33
+ queued remains in progress. A failed or cancelled result is reported with its
34
+ actual safe reason. `outcome_unknown` means the request may have taken effect:
35
+ never retry or re-execute automatically; verify the external effect using the
36
+ same idempotency identity.
37
+
38
+ ## Reusing state
39
+
40
+ An exact execution ID takes precedence over rediscovery. An exact Tool ID with
41
+ its current contract takes precedence over another search. A Tool ID without a
42
+ current contract requires `get_tool_schemas`; never invent a revision or
43
+ reconstruct an identifier.
44
+
45
+ ## Boundaries
46
+
47
+ Action API owns discovery, contract lookup, confirmation, execution, and saved
48
+ result reads for SpringBrand-managed API services. It does not use
49
+ `manage_connections`; connection repair belongs to the Connector Skill.
@@ -0,0 +1,156 @@
1
+ # Action discovery alias map
2
+
3
+ Use this map when a request names an API service, supplier, platform/product,
4
+ model, object, or operation through an abbreviation, alternative spelling, or
5
+ non-English name. It converts that wording into one catalogue-facing English
6
+ form for the unified `search_tools` query; it does not choose or authorize an
7
+ Action.
8
+
9
+ Do not invent a supplier, model version, platform, operation, or modality when
10
+ an alias is ambiguous.
11
+
12
+ ## Inventory provenance and maintenance
13
+
14
+ This snapshot was audited on 2026-09-05 against the then-current Action
15
+ inventory, which contained 52 entries across the ten Supplier ID families
16
+ listed below. It is a terminology aid, not a current availability guarantee.
17
+
18
+ The mappings below were curated from public catalogue text and common,
19
+ unambiguous names; never claim that the service returned them as alias
20
+ metadata. Never copy an ID from this historical snapshot into contract lookup
21
+ or execution: only a current opaque Tool ID returned by unified discovery is
22
+ usable.
23
+
24
+ This is a temporary Agent-side discovery aid. Current unified discovery is
25
+ bounded rather than a complete inventory, so update the map only from an
26
+ authoritative catalogue audit outside a user workflow. A later server-side
27
+ discovery improvement should replace the need for this maintained map.
28
+
29
+ ## Inventory coverage
30
+
31
+ | Supplier ID family | Entries | Public catalogue families reviewed |
32
+ | --- | ---: | --- |
33
+ | `supplier.frank.apify` | 9 | Facebook Ad Library; Reddit scraper and monitor; Google Keyword Volume, Maps Reviews, and Trends; Instagram Profile; TikTok Ads and Data |
34
+ | `supplier.frank.apollo-io` | 2 | Organization Enrichment; People Search |
35
+ | `supplier.frank.elevenlabs` | 1 | Text to Speech |
36
+ | `supplier.frank.exa` | 2 | Web Content Extraction; Web Search |
37
+ | `supplier.frank.firecrawl` | 3 | Structured Data Extraction; Web Scraping; Web Search and Scrape |
38
+ | `supplier.frank.kie-ai-image` | 5 | Seedream 5 Lite image-to-image and text-to-image; Nano Banana 2; GPT Image 2 image-to-image and text-to-image |
39
+ | `supplier.frank.kie-ai-video` | 3 | Seedance 2.0 Fast, Mini, and standard video |
40
+ | `supplier.frank.people-data-labs` | 2 | Company and Person Enrichment |
41
+ | `supplier.frank.serper` | 5 | Google Image, Maps, News, Places, and Shopping Search |
42
+ | `supplier.frank.tikhub` | 20 | Instagram (4); Reddit (2); TikTok (4); X (3); Xiaohongshu (4); YouTube (3) |
43
+
44
+ ## Canonicalization rules
45
+
46
+ - Match aliases case-insensitively after ordinary Unicode normalization. For short
47
+ abbreviations such as `X`, `IG`, `TT`, `YT`, `PDL`, `TTS`, `T2I`, and `I2V`,
48
+ require a whole token and capability-relevant context.
49
+ - Prefer the longest, most specific alias when forms overlap. Preserve explicit
50
+ model variants such as `Fast` and `Mini`, and preserve every platform,
51
+ supplier, operation, object, and modality constraint the user actually gave.
52
+ - Preserve canonical phrases such as `Text to Image` and `Image to Video`
53
+ intact when extracting keywords; `to` defines the modality direction.
54
+ - Emit one canonical English form in the search query. Do not stuff aliases
55
+ into the query and do not fan out multiple searches.
56
+ - An alias supplies only the concept in its row. A platform alias does not
57
+ invent an operation or object, and a model-family alias does not invent a
58
+ version or input modality.
59
+ - Treat the canonicalized concept as a hard compatibility constraint when the
60
+ user stated it explicitly. Include a supplier in the query only when the
61
+ user explicitly requires that supplier.
62
+
63
+ ## Service and supplier aliases
64
+
65
+ Every current entry uses a `supplier.frank.*` Supplier ID. `Frank` alone is
66
+ non-discriminating across the present inventory, so omit it from the search
67
+ query unless the user explicitly makes it a constraint.
68
+
69
+ | Canonical form | Curated aliases | Current inventory family |
70
+ | --- | --- | --- |
71
+ | `Apify` | — | `supplier.frank.apify` |
72
+ | `Apollo` | `Apollo.io`, `Apollo IO` | `supplier.frank.apollo-io` |
73
+ | `ElevenLabs` | `Eleven Labs`, `11Labs` | `supplier.frank.elevenlabs` |
74
+ | `Exa` | `Exa.ai` | `supplier.frank.exa` |
75
+ | `Firecrawl` | `Fire Crawl` | `supplier.frank.firecrawl` |
76
+ | `Kie.ai` | `Kie AI`, `KIE` | `supplier.frank.kie-ai-image`, `supplier.frank.kie-ai-video` |
77
+ | `People Data Labs` | `PDL`, `PeopleDataLabs`, `People DataLabs` | `supplier.frank.people-data-labs` |
78
+ | `Serper` | `Serper.dev` | `supplier.frank.serper` |
79
+ | `TikHub` | `Tik Hub` | `supplier.frank.tikhub` |
80
+
81
+ ## Platform and product aliases
82
+
83
+ | Canonical form | Curated aliases | Current inventory scope |
84
+ | --- | --- | --- |
85
+ | `Facebook Ad Library` | `Facebook Ads Library`, `FB Ad Library`, `Meta Ad Library`, `Meta Ads Library`, `脸书广告库` | `action.apify.scrape_facebook_ad_library` |
86
+ | `Reddit` | `红迪` | `action.apify.scrape_reddit__practical-tools-apify`, `action.apify.monitor_reddit_mentions`, `action.tikhub.reddit-*` |
87
+ | `Google Keyword Volume` | `Google Search Volume`, `keyword search volume`, `关键词搜索量` | `action.apify.keyword_volume` |
88
+ | `Google Maps` | `Google Map`, `GMaps`, `谷歌地图` | `action.apify.scrape_google_maps_reviews`, `action.serper.maps` |
89
+ | `Google Trends` | `GTrends`, `谷歌趋势` | `action.apify.scrape_google_trends` |
90
+ | `Instagram` | `IG`, `Insta` | `action.apify.scrape_profiles`, `action.tikhub.instagram-*` |
91
+ | `TikTok Ads Library` | `TikTok Ads`, `TikTok广告库` | `action.apify.scrape_tiktok_ads_library` |
92
+ | `TikTok` | `Tik Tok`, `TT`, `抖音国际版`, `国际版抖音` | `action.apify.tiktok_api`, `action.tikhub.tiktok-*` |
93
+ | `Douyin` | `抖音`, `抖音短视频` | `catalogue-summary-only` |
94
+ | `X` | `Twitter`, `推特`, `X.com`, `X/Twitter` | `action.tikhub.twitter-*` |
95
+ | `Xiaohongshu` | `xhs`, `小红书`, `RedNote`, `Red Note`, `little red book`, `RED` | `action.tikhub.xhs-*` |
96
+ | `YouTube` | `YT`, `You Tube`, `油管` | `action.tikhub.youtube-*` |
97
+ | `Google Image` | `Google Images`, `谷歌图片` | `action.serper.images` |
98
+ | `Google News` | `谷歌新闻` | `action.serper.news` |
99
+ | `Google Places` | `Google Place`, `谷歌地点` | `action.serper.places` |
100
+ | `Google Shopping` | `谷歌购物` | `action.serper.shopping` |
101
+ | `Web` | `website`, `web page`, `网页`, `网站` | `action.exa.*`, `action.firecrawl.*` |
102
+
103
+ `Douyin` appears in the TikHub catalogue summary, but the audited 52-entry
104
+ inventory has no dedicated Douyin Action. Preserve `Douyin` as the platform
105
+ constraint and, if current discovery finds no compatible entry, report that
106
+ bounded result honestly. Never silently rewrite `Douyin` to `TikTok`.
107
+ Likewise, treat bare `X` as the social platform only when the surrounding
108
+ request refers to posts, profiles, social search, or `X.com`.
109
+
110
+ ## Model and vendor aliases
111
+
112
+ | Canonical form | Curated aliases | Current inventory scope |
113
+ | --- | --- | --- |
114
+ | `ByteDance` | `Bytedance`, `字节跳动`, `字节` | `action.kie-ai-image.seedream-*`, `action.kie-ai-video.bytedance-*` |
115
+ | `Seedream` | `即梦`, `即梦AI` | `action.kie-ai-image.seedream-5-lite-*` |
116
+ | `Seedream 5 Lite` | `Seedream5 Lite` | `action.kie-ai-image.seedream-5-lite-*` |
117
+ | `Nano Banana 2` | `NanoBanana2`, `Nano Banana` | `action.kie-ai-image.google-nanobanana2` |
118
+ | `OpenAI` | `Open AI` | `action.kie-ai-image.gpt-gpt-image-2-*` |
119
+ | `GPT Image 2` | `GPT-Image-2`, `GPT Image2` | `action.kie-ai-image.gpt-gpt-image-2-*` |
120
+ | `Seedance 2.0` | `Seedance 2`, `Seedance2` | `action.kie-ai-video.bytedance-seedance-2*` |
121
+
122
+ `Nano Banana` currently resolves to `Nano Banana 2` because it is the only
123
+ Nano Banana family in this inventory snapshot. Re-audit that shorthand as
124
+ soon as another version appears. Bare `Seedream` is a family form; `Seedream
125
+ 5 Lite` is the exact current model. Retain every explicit version, `Fast`, or
126
+ `Mini` modifier instead of silently selecting one.
127
+
128
+ ## Object, modality, and operation aliases
129
+
130
+ | Canonical form | Curated aliases | Current inventory meaning |
131
+ | --- | --- | --- |
132
+ | `Search` | `find`, `look up`, `lookup`, `query`, `搜索`, `查找`, `检索` | Locate existing catalogue data. |
133
+ | `Details` | `detail`, `info`, `information`, `详情`, `详细信息` | Fetch one exact post, note, or video. |
134
+ | `User Profile` | `profile`, `account profile`, `user info`, `账号资料`, `用户资料`, `主页` | Fetch a public account profile. |
135
+ | `User Posts` | `account posts`, `author posts`, `用户帖子`, `账号内容` | List content published by one user. |
136
+ | `Comments` | `comment`, `replies`, `responses`, `评论`, `回复` | Fetch replies on one content item. |
137
+ | `Reviews` | `review`, `ratings`, `评价`, `评分` | Fetch Google Maps reviews. |
138
+ | `Monitor` | `track`, `watch`, `monitoring`, `监控`, `追踪` | Monitor Reddit brand mentions. |
139
+ | `Scrape` | `scraper`, `crawl`, `抓取`, `爬取` | Retrieve public web or social data. |
140
+ | `Extract` | `extraction`, `抽取`, `提取` | Extract web content or structured fields. |
141
+ | `Enrichment` | `enrich`, `data enrichment`, `补全`, `数据补充` | Enrich a person, company, or organization. |
142
+ | `Post` | `posts`, `帖子`, `动态` | A social post; `tweet` and `推文` mean `X Post` only in X/Twitter context. |
143
+ | `Note` | `notes`, `笔记` | A Xiaohongshu content item. |
144
+ | `Video` | `videos`, `短视频` | A TikTok or YouTube video, or generated video. |
145
+ | `Image` | `images`, `picture`, `photo`, `图片`, `图像` | An existing or generated image. |
146
+ | `Text to Speech` | `TTS`, `text2speech`, `txt2speech`, `文本转语音`, `语音合成` | ElevenLabs speech generation. |
147
+ | `Text to Image` | `T2I`, `text2image`, `txt2img`, `文生图`, `文字生成图片` | Generate an image from text. |
148
+ | `Image to Image` | `I2I`, `image2image`, `img2img`, `图生图`, `图片编辑` | Edit or transform an existing image. |
149
+ | `Text to Video` | `T2V`, `text2video`, `txt2vid`, `文生视频`, `文字生成视频` | Generate video with text input. |
150
+ | `Image to Video` | `I2V`, `image2video`, `img2vid`, `图生视频`, `图片生成视频` | Generate video with image input. |
151
+
152
+ Operation and modality mappings are compatibility constraints, not synonyms
153
+ for one another. `Search` cannot satisfy `Details`; `Comments` cannot satisfy
154
+ `User Posts`; `Text to Image` cannot satisfy `Image to Image`; and `Text to
155
+ Video` cannot satisfy `Image to Video` when the user explicitly requires the
156
+ input modality.
@@ -0,0 +1,95 @@
1
+ # Action API discovery through the unified Meta Tools
2
+
3
+ Read this reference only when the Action API Skill needs discovery. It records
4
+ Agent behavior, not the Gateway wire contract. Runtime tool schemas and results
5
+ remain authoritative.
6
+
7
+ ## Build one search
8
+
9
+ Call `search_tools` with one concise English query. Translate a non-English
10
+ request yourself and preserve every explicit constraint that distinguishes the
11
+ operation: required supplier, platform or product, operation, object or
12
+ modality, and output type. Keep topic content, dates, formatting preferences,
13
+ and other execution arguments in task state unless they help identify the
14
+ operation.
15
+
16
+ Use [action-aliases.md](action-aliases.md) only to canonicalize an unambiguous
17
+ concept. Do not invent a supplier, model version, platform, operation, or
18
+ modality. Do not send synonyms as multiple searches.
19
+
20
+ Examples of useful queries:
21
+
22
+ - `Xiaohongshu note search`
23
+ - `TikHub Xiaohongshu note search` only when the user explicitly requires
24
+ TikHub
25
+ - `text to image`
26
+ - `Seedance 2.0 image to video` when both model and modality were explicit
27
+
28
+ SpringBrand host names, courtesy language, and generic phrases such as "use
29
+ an API" do not distinguish an Action and should not dominate the query.
30
+
31
+ ## Interpret the bounded result
32
+
33
+ Discovery returns one bounded list. It is not globally ranked and is not a
34
+ complete inventory. Preserve returned order while applying the user's hard
35
+ compatibility constraints:
36
+
37
+ 1. supplier, only when explicitly required;
38
+ 2. platform or product;
39
+ 3. operation, such as search, details, comments, or profile;
40
+ 4. object or modality, such as note, video, text to image, or image to video;
41
+ 5. required output type.
42
+
43
+ Recommend the first returned Action API operation that satisfies every
44
+ applicable constraint. This is compatibility filtering, not reranking: do not
45
+ invent scores, merge another list, or treat a score as task-success
46
+ probability.
47
+
48
+ Unified discovery can return Platform and Connector operations too. Ignore
49
+ those results here. Their presence does not authorize cross-domain execution.
50
+
51
+ ## Missing, empty, incomplete, and failed results
52
+
53
+ Keep these outcomes distinct:
54
+
55
+ - **Compatible candidate found** — preserve its opaque Tool ID exactly and
56
+ inspect its current contract with `get_tool_schemas`.
57
+ - **Complete empty or incompatible result** — report no fit for this query, or
58
+ narrow/revise it once when the user's explicit constraints support a more
59
+ precise query.
60
+ - **Incomplete result** — it cannot establish no-match. Narrow or revise the
61
+ English query; there is no search pagination contract to invent.
62
+ - **Provider or tool failure** — report the actual transport, authentication,
63
+ permission, schema, or upstream error. An error is not a no-match.
64
+
65
+ Do not fan out over query variants. Do not use an inventory crawl as a hidden
66
+ fallback. If safe refinement lacks enough identifying signal, ask the user one
67
+ focused question instead of guessing.
68
+
69
+ ## Contract inspection
70
+
71
+ Search summaries are not executable contracts. Send the selected opaque Tool
72
+ ID unchanged to `get_tool_schemas` and use the returned current contract to
73
+ check:
74
+
75
+ - the operation description and access state;
76
+ - exact input and output schemas;
77
+ - risk and known costs;
78
+ - revision information;
79
+ - attachment and produced-material requirements.
80
+
81
+ Never construct, edit, decode, or classify the Tool ID. A contract error is a
82
+ lookup failure, not proof that the Action does not exist. Do not fall through
83
+ to another candidate silently.
84
+
85
+ ## Execution association and reuse
86
+
87
+ Use the runtime `execute_tools` schema exactly. One logical run gets one stable
88
+ idempotency key, retained with the exact Tool ID and arguments before the call.
89
+ Do not invent observation fields, discovery IDs, expected revisions, or
90
+ classification metadata that the runtime tool schema does not declare.
91
+
92
+ When execution returns an exact execution ID, retain it with task state. A
93
+ later status or result read uses `get_execution` with that same ID. It never
94
+ searches again, invokes again, or charges again. Only a new user-approved run
95
+ gets a new logical invocation and key.
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: springbrand-connector
3
+ description: Use SpringBrand Connector for Gmail, GitHub, Slack, and other connected third-party services, including account connection management and external reads or writes.
4
+ ---
5
+
6
+ # SpringBrand Connector
7
+
8
+ Use the unified SpringBrand MCP for third-party services. The CLI has already
9
+ configured and authenticated the MCP connection. Provider credentials are
10
+ owned by the Gateway and must never be requested, copied, logged, or placed in
11
+ an argument, URL, prompt, or result.
12
+
13
+ ## Discover and inspect
14
+
15
+ Call `search_tools` once with a concise English query naming the service and
16
+ operation. Preserve the user's requested account and effect. Select a
17
+ Connector operation, copy its opaque Tool ID unchanged, and inspect its current
18
+ contract with `get_tool_schemas`. Ignore Platform and Action API candidates;
19
+ use an explicit state-preserving transition when the task belongs elsewhere.
20
+
21
+ ## Connections
22
+
23
+ Use `manage_connections` only when the current Connector contract requires an
24
+ account or the user asks about connections. Use exactly one operation at a
25
+ time: list, start, status, repair, or disconnect. Preserve the exact
26
+ connection or authorization-attempt identifier returned by the Gateway. Show
27
+ an authorization link unchanged when one is returned, but never handle the
28
+ Provider credential itself.
29
+
30
+ An API-key-authenticated Gateway session may have Connector limitations. Report
31
+ a dedicated capability error or warning when the Gateway says Connector API
32
+ key support is unavailable; do not turn that condition into a generic
33
+ authorization failure or invent an OAuth session.
34
+
35
+ ## Execute and read results
36
+
37
+ Build arguments from the current schema and ask for missing service values.
38
+ Before a write, explain the target account, effect, known risk, and approval
39
+ requirement. Execute once with a stable idempotency key. Only `succeeded`
40
+ confirms completion. Use `get_execution` only with an exact returned execution
41
+ ID. An unknown write result is never automatically retried; verify the
42
+ external effect first.
43
+
44
+ ## Boundaries
45
+
46
+ Connector owns third-party operations and their connection lifecycle. It does
47
+ not acquire Plugins, publish Creations, or execute Action APIs. Keep one
48
+ executor active at a time and preserve state across an explicit Domain
49
+ transition.