@tiny-fish/cli 0.7.2-next.115 → 0.7.2-next.118
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/lib/client.js +7 -1
- package/dist/lib/harness.d.ts +18 -0
- package/dist/lib/harness.js +40 -0
- package/package.json +2 -1
package/dist/lib/client.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { APIStatusError, agentRunAsyncResponseSchema, agentRunResponseSchema, agentRunWithStreamingResponseSchema, fetchResponseSchema, browserSessionSchema, searchQueryResponseSchema, TinyFish, runSchema, runStatusSchema, } from "@tiny-fish/sdk";
|
|
2
2
|
import { BASE_URL, CLI_VERSION } from "./constants.js";
|
|
3
|
+
import { detectHarness, detectHumanInitiated } from "./harness.js";
|
|
3
4
|
import { ApiError } from "./output.js";
|
|
4
5
|
import { z } from "zod";
|
|
5
6
|
class TinyFishCliClient extends TinyFish {
|
|
@@ -13,12 +14,17 @@ class TinyFishCliClient extends TinyFish {
|
|
|
13
14
|
// Forwarded explicitly: the pinned published SDK may predate TF_CLIENT_* support.
|
|
14
15
|
// Non-printable chars make fetch throw; 128 is the server cap (client_name varchar(128)).
|
|
15
16
|
const sanitize = (value) => (value ?? "").replace(/[^\x20-\x7E]/g, "").trim().slice(0, 128);
|
|
16
|
-
|
|
17
|
+
// An explicit TF_CLIENT_NAME always wins over auto-detection, preserving the
|
|
18
|
+
// env-var forwarding contract added in PR #3781; otherwise fingerprint the
|
|
19
|
+
// calling harness so cli usage can be split by client (PF-3168).
|
|
20
|
+
const clientName = sanitize(process.env["TF_CLIENT_NAME"]) || sanitize(detectHarness() ?? undefined);
|
|
17
21
|
const clientVersion = sanitize(process.env["TF_CLIENT_VERSION"]);
|
|
18
22
|
if (clientName)
|
|
19
23
|
headers["X-TF-Client-Name"] = clientName;
|
|
20
24
|
if (clientVersion)
|
|
21
25
|
headers["X-TF-Client-Version"] = clientVersion;
|
|
26
|
+
// Agent-vs-human signal, independent of harness detection or skill install.
|
|
27
|
+
headers["X-TF-Human-Initiated"] = detectHumanInitiated() ? "true" : "false";
|
|
22
28
|
return headers;
|
|
23
29
|
}
|
|
24
30
|
// The SDK base client only exposes get/post/postStream; DELETE is needed for
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type Env = Record<string, string | undefined>;
|
|
2
|
+
/** Returns the detected harness name, or null when none match. */
|
|
3
|
+
export declare function detectHarness(env?: Env): string | null;
|
|
4
|
+
interface HumanInitiatedStreams {
|
|
5
|
+
stdin: {
|
|
6
|
+
isTTY?: boolean;
|
|
7
|
+
};
|
|
8
|
+
stdout: {
|
|
9
|
+
isTTY?: boolean;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* True only when both ends are a real terminal — a human at a prompt. Agents
|
|
14
|
+
* shell out without a TTY, so this reads false for every harness above and is
|
|
15
|
+
* the free agent-vs-human signal behind `X-TF-Human-Initiated`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function detectHumanInitiated(streams?: HumanInitiatedStreams): boolean;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Detects the coding-agent harness that shelled out to the CLI, so usage events
|
|
2
|
+
// can be split by harness (PF-3168). Names become the `X-TF-Client-Name` header
|
|
3
|
+
// value (unenumerated, lowercase-kebab, matching MCP client_name like
|
|
4
|
+
// "claude-code"). Explicit TF_CLIENT_NAME always wins upstream in client.ts.
|
|
5
|
+
//
|
|
6
|
+
// Fingerprints verified by running scripts/harness-probe against each harness.
|
|
7
|
+
// Order matters: wrappers that embed another agent must precede the embedded
|
|
8
|
+
// one. OpenClaw drives Claude Code via `sdk-cli`, so its env carries both
|
|
9
|
+
// CLAUDECODE=1 and OPENCLAW_MCP_*; it must be checked before claude-code.
|
|
10
|
+
const hasVarWithPrefix = (env, prefix) => Object.keys(env).some((key) => key.startsWith(prefix));
|
|
11
|
+
// First match wins. Base agents (claude-code) go last so embedding wrappers win.
|
|
12
|
+
const HARNESS_FINGERPRINTS = [
|
|
13
|
+
{ name: "openclaw", matches: (env) => hasVarWithPrefix(env, "OPENCLAW_MCP_") },
|
|
14
|
+
{ name: "grok", matches: (env) => env["GROK_AGENT"] === "1" },
|
|
15
|
+
// Cursor's VS Code host sets CURSOR_* broadly; CURSOR_AGENT=1 flags the
|
|
16
|
+
// agent specifically, so gate on it rather than the prefix.
|
|
17
|
+
{ name: "cursor", matches: (env) => env["CURSOR_AGENT"] === "1" },
|
|
18
|
+
// Antigravity is Google's successor to the (deprecated) gemini-cli.
|
|
19
|
+
{ name: "antigravity", matches: (env) => env["ANTIGRAVITY_AGENT"] === "1" },
|
|
20
|
+
// CODEX_CI seen in probe; CODEX_SANDBOX* appear under seatbelt. Match the
|
|
21
|
+
// prefix so we catch a Codex run regardless of which of its vars are set.
|
|
22
|
+
{ name: "codex", matches: (env) => hasVarWithPrefix(env, "CODEX_") },
|
|
23
|
+
{ name: "hermes", matches: (env) => hasVarWithPrefix(env, "HERMES_") },
|
|
24
|
+
{
|
|
25
|
+
name: "claude-code",
|
|
26
|
+
matches: (env) => env["CLAUDECODE"] === "1" || Boolean(env["CLAUDE_CODE_ENTRYPOINT"]),
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
/** Returns the detected harness name, or null when none match. */
|
|
30
|
+
export function detectHarness(env = process.env) {
|
|
31
|
+
return HARNESS_FINGERPRINTS.find((fingerprint) => fingerprint.matches(env))?.name ?? null;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* True only when both ends are a real terminal — a human at a prompt. Agents
|
|
35
|
+
* shell out without a TTY, so this reads false for every harness above and is
|
|
36
|
+
* the free agent-vs-human signal behind `X-TF-Human-Initiated`.
|
|
37
|
+
*/
|
|
38
|
+
export function detectHumanInitiated(streams = process) {
|
|
39
|
+
return Boolean(streams.stdin.isTTY && streams.stdout.isTTY);
|
|
40
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiny-fish/cli",
|
|
3
|
-
"version": "0.7.2-next.
|
|
3
|
+
"version": "0.7.2-next.118",
|
|
4
4
|
"description": "TinyFish CLI — run web automations from your terminal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"esbuild": "0.28.1",
|
|
55
55
|
"vite": "7.3.5",
|
|
56
56
|
"brace-expansion": "^5.0.9",
|
|
57
|
+
"ip-address": ">=10.3.1",
|
|
57
58
|
"postcss": ">=8.5.23",
|
|
58
59
|
"tar": "^7.5.21"
|
|
59
60
|
},
|