@tiny-fish/cli 0.8.1-next.119 → 0.8.1-next.121
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/dist/commands/connect.js +32 -3
- package/package.json +1 -1
package/dist/commands/connect.js
CHANGED
|
@@ -138,9 +138,38 @@ const OPENCLAW = {
|
|
|
138
138
|
unavailableMessage: OPENCLAW_SKILL_UNAVAILABLE_MESSAGE,
|
|
139
139
|
},
|
|
140
140
|
};
|
|
141
|
-
|
|
141
|
+
// TinyFish-owned domains plus loopback are the only origins the API key may be sent to.
|
|
142
|
+
// `--url` accepts any http(s) URL, so a user-supplied origin must never receive the key.
|
|
143
|
+
const TRUSTED_TELEMETRY_HOST_SUFFIXES = [".tinyfish.ai", ".tinyfish.io"];
|
|
144
|
+
const TRUSTED_TELEMETRY_LOOPBACK_HOSTS = ["localhost", "127.0.0.1", "[::1]"];
|
|
145
|
+
function isTrustedTelemetryOrigin(endpoint) {
|
|
146
|
+
let url;
|
|
147
|
+
try {
|
|
148
|
+
url = new URL(endpoint);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
const host = url.hostname.toLowerCase();
|
|
154
|
+
// Loopback may use http for local dev; every other trusted origin must be https so the
|
|
155
|
+
// key is never sent over cleartext.
|
|
156
|
+
if (TRUSTED_TELEMETRY_LOOPBACK_HOSTS.includes(host))
|
|
157
|
+
return true;
|
|
158
|
+
if (url.protocol !== "https:")
|
|
159
|
+
return false;
|
|
160
|
+
return TRUSTED_TELEMETRY_HOST_SUFFIXES.some((suffix) => host === suffix.slice(1) || host.endsWith(suffix));
|
|
161
|
+
}
|
|
162
|
+
function createConnectTelemetry(mcpUrl, client, apiKey) {
|
|
142
163
|
const attemptId = randomUUID();
|
|
143
164
|
const endpoint = new URL("/api/cli/connect-event", mcpUrl).toString();
|
|
165
|
+
const telemetryKey = apiKey ?? process.env["TINYFISH_API_KEY"];
|
|
166
|
+
const headers = { "content-type": "application/json" };
|
|
167
|
+
// Attach the key so the endpoint can attribute the event to the signed-in user, but only
|
|
168
|
+
// when it is well-formed AND the endpoint is a trusted TinyFish origin. A user-supplied
|
|
169
|
+
// --url pointing elsewhere gets anonymous telemetry, never the key.
|
|
170
|
+
if (telemetryKey && validateKeyFormat(telemetryKey) && isTrustedTelemetryOrigin(endpoint)) {
|
|
171
|
+
headers["x-api-key"] = telemetryKey;
|
|
172
|
+
}
|
|
144
173
|
let enabled = true;
|
|
145
174
|
return {
|
|
146
175
|
attemptId,
|
|
@@ -150,7 +179,7 @@ function createConnectTelemetry(mcpUrl, client) {
|
|
|
150
179
|
try {
|
|
151
180
|
const response = await fetch(endpoint, {
|
|
152
181
|
method: "POST",
|
|
153
|
-
headers
|
|
182
|
+
headers,
|
|
154
183
|
body: JSON.stringify({
|
|
155
184
|
attempt_id: attemptId,
|
|
156
185
|
client,
|
|
@@ -309,7 +338,7 @@ function launchOpenClawWalkthrough() {
|
|
|
309
338
|
return true;
|
|
310
339
|
}
|
|
311
340
|
async function connectNativeMcpClient(client, options) {
|
|
312
|
-
const telemetry = createConnectTelemetry(options.mcpUrl, client.connectClient);
|
|
341
|
+
const telemetry = createConnectTelemetry(options.mcpUrl, client.connectClient, options.apiKey);
|
|
313
342
|
let failureStage = "prerequisite_check";
|
|
314
343
|
try {
|
|
315
344
|
await telemetry.track("started");
|