@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.
- package/README.md +167 -0
- package/dist/commands/auth.d.ts +4 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +241 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/check-version.d.ts +3 -0
- package/dist/commands/check-version.d.ts.map +1 -0
- package/dist/commands/check-version.js +112 -0
- package/dist/commands/check-version.js.map +1 -0
- package/dist/commands/config-claude.d.ts +4 -0
- package/dist/commands/config-claude.d.ts.map +1 -0
- package/dist/commands/config-claude.js +78 -0
- package/dist/commands/config-claude.js.map +1 -0
- package/dist/commands/connect.d.ts +41 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +901 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/doctor.d.ts +6 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +124 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/upgrade.d.ts +9 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +133 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/agent-detect.d.ts +33 -0
- package/dist/lib/agent-detect.d.ts.map +1 -0
- package/dist/lib/agent-detect.js +81 -0
- package/dist/lib/agent-detect.js.map +1 -0
- package/dist/lib/agent-launcher.d.ts +22 -0
- package/dist/lib/agent-launcher.d.ts.map +1 -0
- package/dist/lib/agent-launcher.js +67 -0
- package/dist/lib/agent-launcher.js.map +1 -0
- package/dist/lib/auth.d.ts +90 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +327 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/bundled-skill.d.ts +5 -0
- package/dist/lib/bundled-skill.d.ts.map +1 -0
- package/dist/lib/bundled-skill.js +13 -0
- package/dist/lib/bundled-skill.js.map +1 -0
- package/dist/lib/claude-config.d.ts +19 -0
- package/dist/lib/claude-config.d.ts.map +1 -0
- package/dist/lib/claude-config.js +202 -0
- package/dist/lib/claude-config.js.map +1 -0
- package/dist/lib/cli-install.d.ts +40 -0
- package/dist/lib/cli-install.d.ts.map +1 -0
- package/dist/lib/cli-install.js +42 -0
- package/dist/lib/cli-install.js.map +1 -0
- package/dist/lib/command-code-config.d.ts +5 -0
- package/dist/lib/command-code-config.d.ts.map +1 -0
- package/dist/lib/command-code-config.js +16 -0
- package/dist/lib/command-code-config.js.map +1 -0
- package/dist/lib/connect-all-auth.d.ts +21 -0
- package/dist/lib/connect-all-auth.d.ts.map +1 -0
- package/dist/lib/connect-all-auth.js +113 -0
- package/dist/lib/connect-all-auth.js.map +1 -0
- package/dist/lib/connect-all-summary.d.ts +10 -0
- package/dist/lib/connect-all-summary.d.ts.map +1 -0
- package/dist/lib/connect-all-summary.js +153 -0
- package/dist/lib/connect-all-summary.js.map +1 -0
- package/dist/lib/connect-all-uninstall.d.ts +7 -0
- package/dist/lib/connect-all-uninstall.d.ts.map +1 -0
- package/dist/lib/connect-all-uninstall.js +249 -0
- package/dist/lib/connect-all-uninstall.js.map +1 -0
- package/dist/lib/connect-all.d.ts +42 -0
- package/dist/lib/connect-all.d.ts.map +1 -0
- package/dist/lib/connect-all.js +438 -0
- package/dist/lib/connect-all.js.map +1 -0
- package/dist/lib/connect-auth.d.ts +7 -0
- package/dist/lib/connect-auth.d.ts.map +1 -0
- package/dist/lib/connect-auth.js +50 -0
- package/dist/lib/connect-auth.js.map +1 -0
- package/dist/lib/connect-clients.d.ts +108 -0
- package/dist/lib/connect-clients.d.ts.map +1 -0
- package/dist/lib/connect-clients.js +358 -0
- package/dist/lib/connect-clients.js.map +1 -0
- package/dist/lib/connect-fallback.d.ts +27 -0
- package/dist/lib/connect-fallback.d.ts.map +1 -0
- package/dist/lib/connect-fallback.js +166 -0
- package/dist/lib/connect-fallback.js.map +1 -0
- package/dist/lib/connect-picker.d.ts +19 -0
- package/dist/lib/connect-picker.d.ts.map +1 -0
- package/dist/lib/connect-picker.js +155 -0
- package/dist/lib/connect-picker.js.map +1 -0
- package/dist/lib/connect-preflight.d.ts +17 -0
- package/dist/lib/connect-preflight.d.ts.map +1 -0
- package/dist/lib/connect-preflight.js +81 -0
- package/dist/lib/connect-preflight.js.map +1 -0
- package/dist/lib/connect-runtime.d.ts +109 -0
- package/dist/lib/connect-runtime.d.ts.map +1 -0
- package/dist/lib/connect-runtime.js +360 -0
- package/dist/lib/connect-runtime.js.map +1 -0
- package/dist/lib/constants.d.ts +23 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +87 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/cursor-config.d.ts +16 -0
- package/dist/lib/cursor-config.d.ts.map +1 -0
- package/dist/lib/cursor-config.js +34 -0
- package/dist/lib/cursor-config.js.map +1 -0
- package/dist/lib/doctor-checks.d.ts +21 -0
- package/dist/lib/doctor-checks.d.ts.map +1 -0
- package/dist/lib/doctor-checks.js +312 -0
- package/dist/lib/doctor-checks.js.map +1 -0
- package/dist/lib/doctor-repairs.d.ts +11 -0
- package/dist/lib/doctor-repairs.d.ts.map +1 -0
- package/dist/lib/doctor-repairs.js +130 -0
- package/dist/lib/doctor-repairs.js.map +1 -0
- package/dist/lib/doctor-report.d.ts +195 -0
- package/dist/lib/doctor-report.d.ts.map +1 -0
- package/dist/lib/doctor-report.js +102 -0
- package/dist/lib/doctor-report.js.map +1 -0
- package/dist/lib/doctor-telemetry.d.ts +9 -0
- package/dist/lib/doctor-telemetry.d.ts.map +1 -0
- package/dist/lib/doctor-telemetry.js +63 -0
- package/dist/lib/doctor-telemetry.js.map +1 -0
- package/dist/lib/harness-detect.d.ts +33 -0
- package/dist/lib/harness-detect.d.ts.map +1 -0
- package/dist/lib/harness-detect.js +70 -0
- package/dist/lib/harness-detect.js.map +1 -0
- package/dist/lib/harness-spec.d.ts +285 -0
- package/dist/lib/harness-spec.d.ts.map +1 -0
- package/dist/lib/harness-spec.js +268 -0
- package/dist/lib/harness-spec.js.map +1 -0
- package/dist/lib/harness.d.ts +27 -0
- package/dist/lib/harness.d.ts.map +1 -0
- package/dist/lib/harness.js +125 -0
- package/dist/lib/harness.js.map +1 -0
- package/dist/lib/hermes-config.d.ts +22 -0
- package/dist/lib/hermes-config.d.ts.map +1 -0
- package/dist/lib/hermes-config.js +76 -0
- package/dist/lib/hermes-config.js.map +1 -0
- package/dist/lib/hermes-env.d.ts +19 -0
- package/dist/lib/hermes-env.d.ts.map +1 -0
- package/dist/lib/hermes-env.js +169 -0
- package/dist/lib/hermes-env.js.map +1 -0
- package/dist/lib/hermes-plugin.d.ts +40 -0
- package/dist/lib/hermes-plugin.d.ts.map +1 -0
- package/dist/lib/hermes-plugin.js +168 -0
- package/dist/lib/hermes-plugin.js.map +1 -0
- package/dist/lib/install-root.d.ts +18 -0
- package/dist/lib/install-root.d.ts.map +1 -0
- package/dist/lib/install-root.js +55 -0
- package/dist/lib/install-root.js.map +1 -0
- package/dist/lib/mcp-config.d.ts +36 -0
- package/dist/lib/mcp-config.d.ts.map +1 -0
- package/dist/lib/mcp-config.js +90 -0
- package/dist/lib/mcp-config.js.map +1 -0
- package/dist/lib/mcp-endpoint.d.ts +16 -0
- package/dist/lib/mcp-endpoint.d.ts.map +1 -0
- package/dist/lib/mcp-endpoint.js +41 -0
- package/dist/lib/mcp-endpoint.js.map +1 -0
- package/dist/lib/mcp-json-config.d.ts +43 -0
- package/dist/lib/mcp-json-config.d.ts.map +1 -0
- package/dist/lib/mcp-json-config.js +164 -0
- package/dist/lib/mcp-json-config.js.map +1 -0
- package/dist/lib/notice.d.ts +13 -0
- package/dist/lib/notice.d.ts.map +1 -0
- package/dist/lib/notice.js +73 -0
- package/dist/lib/notice.js.map +1 -0
- package/dist/lib/omp-config.d.ts +18 -0
- package/dist/lib/omp-config.d.ts.map +1 -0
- package/dist/lib/omp-config.js +73 -0
- package/dist/lib/omp-config.js.map +1 -0
- package/dist/lib/output.d.ts +22 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +92 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/pi-config.d.ts +27 -0
- package/dist/lib/pi-config.d.ts.map +1 -0
- package/dist/lib/pi-config.js +113 -0
- package/dist/lib/pi-config.js.map +1 -0
- package/dist/lib/registration-detect.d.ts +28 -0
- package/dist/lib/registration-detect.d.ts.map +1 -0
- package/dist/lib/registration-detect.js +563 -0
- package/dist/lib/registration-detect.js.map +1 -0
- package/dist/lib/setup-telemetry.d.ts +273 -0
- package/dist/lib/setup-telemetry.d.ts.map +1 -0
- package/dist/lib/setup-telemetry.js +309 -0
- package/dist/lib/setup-telemetry.js.map +1 -0
- package/dist/lib/signals.d.ts +14 -0
- package/dist/lib/signals.d.ts.map +1 -0
- package/dist/lib/signals.js +29 -0
- package/dist/lib/signals.js.map +1 -0
- package/dist/lib/skill-install.d.ts +10 -0
- package/dist/lib/skill-install.d.ts.map +1 -0
- package/dist/lib/skill-install.js +94 -0
- package/dist/lib/skill-install.js.map +1 -0
- package/dist/lib/skill-paths.d.ts +7 -0
- package/dist/lib/skill-paths.d.ts.map +1 -0
- package/dist/lib/skill-paths.js +37 -0
- package/dist/lib/skill-paths.js.map +1 -0
- package/dist/lib/skill-vendor.d.ts +20 -0
- package/dist/lib/skill-vendor.d.ts.map +1 -0
- package/dist/lib/skill-vendor.js +215 -0
- package/dist/lib/skill-vendor.js.map +1 -0
- package/dist/lib/skill.d.ts +14 -0
- package/dist/lib/skill.d.ts.map +1 -0
- package/dist/lib/skill.js +87 -0
- package/dist/lib/skill.js.map +1 -0
- package/dist/lib/verify.d.ts +35 -0
- package/dist/lib/verify.d.ts.map +1 -0
- package/dist/lib/verify.js +169 -0
- package/dist/lib/verify.js.map +1 -0
- package/dist/program.d.ts +8 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +54 -0
- package/dist/program.js.map +1 -0
- package/package.json +55 -0
- package/skill/springbrand-action-api/SKILL.md +49 -0
- package/skill/springbrand-action-api/references/action-aliases.md +156 -0
- package/skill/springbrand-action-api/references/action-discovery.md +95 -0
- package/skill/springbrand-connector/SKILL.md +49 -0
- package/skill/springbrand-gtm/SKILL.md +34 -0
- package/skill/springbrand-platform/SKILL.md +55 -0
- package/skill/springbrand-platform/references/plugin-discovery.md +94 -0
- 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":"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"}
|
|
@@ -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"}
|
package/dist/program.js
ADDED
|
@@ -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.
|