@tiny-fish/cli 0.2.2 → 0.3.1-next.87
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 +11 -0
- package/dist/commands/connect.d.ts +4 -0
- package/dist/commands/connect.js +53 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,6 +38,17 @@ One-command OAuth requires a Codex release whose `codex mcp add` command support
|
|
|
38
38
|
`--oauth-resource`. Update Codex if support is unavailable, or add TinyFish manually with
|
|
39
39
|
`codex mcp add`.
|
|
40
40
|
|
|
41
|
+
### Connect Hermes
|
|
42
|
+
|
|
43
|
+
Add TinyFish, complete MCP OAuth, and start the interactive walkthrough with one command:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx -y @tiny-fish/cli@latest connect hermes --launch
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Hermes completes OAuth while adding the MCP server. After setup, the command starts the walkthrough
|
|
50
|
+
in a Hermes session and leaves that session open for your replies.
|
|
51
|
+
|
|
41
52
|
## Authentication
|
|
42
53
|
|
|
43
54
|
Get your API key from [agent.tinyfish.ai](https://agent.tinyfish.ai).
|
|
@@ -8,4 +8,8 @@ export declare function connectCodex(options: {
|
|
|
8
8
|
mcpUrl: string;
|
|
9
9
|
launch: boolean;
|
|
10
10
|
}): void;
|
|
11
|
+
export declare function connectHermes(options: {
|
|
12
|
+
mcpUrl: string;
|
|
13
|
+
launch: boolean;
|
|
14
|
+
}): void;
|
|
11
15
|
export declare function registerConnect(program: Command): void;
|
package/dist/commands/connect.js
CHANGED
|
@@ -2,11 +2,14 @@ import spawn from "cross-spawn";
|
|
|
2
2
|
import { errLine } from "../lib/output.js";
|
|
3
3
|
const DEFAULT_MCP_URL = "https://agent.tinyfish.ai/mcp";
|
|
4
4
|
const NON_INTERACTIVE_TIMEOUT_MS = 10_000;
|
|
5
|
+
const HERMES_SEED_TIMEOUT_MS = 120_000;
|
|
5
6
|
const MCP_LOGIN_UNAVAILABLE_MESSAGE = "This Claude Code installation does not expose `claude mcp login`, which is required for " +
|
|
6
7
|
"one-command MCP authentication. Update Claude Code and retry, or authenticate TinyFish " +
|
|
7
8
|
"manually from /mcp.";
|
|
8
9
|
const CODEX_OAUTH_RESOURCE_UNAVAILABLE_MESSAGE = "This Codex installation does not support one-command MCP authentication. Update Codex and " +
|
|
9
10
|
"retry, or add TinyFish manually with `codex mcp add`.";
|
|
11
|
+
const HERMES_OAUTH_UNAVAILABLE_MESSAGE = "This Hermes installation does not support one-command MCP authentication. Update Hermes and " +
|
|
12
|
+
"retry, or add TinyFish manually with `hermes mcp add`.";
|
|
10
13
|
export const DEFAULT_ONBOARDING_PROMPT = "I just connected TinyFish. Call the guide_next_step tool now to begin. Then follow its " +
|
|
11
14
|
"instructions one step at a time. Ask for my input and wait for my reply before each subsequent " +
|
|
12
15
|
"TinyFish tool call.";
|
|
@@ -38,15 +41,44 @@ const CODEX = {
|
|
|
38
41
|
unavailableMessage: CODEX_OAUTH_RESOURCE_UNAVAILABLE_MESSAGE,
|
|
39
42
|
},
|
|
40
43
|
removals: [{ args: ["mcp", "remove", "tinyfish"], label: "TinyFish registration from Codex" }],
|
|
41
|
-
addArgs: (mcpUrl) => [
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
addArgs: (mcpUrl) => ["mcp", "add", "tinyfish", "--url", mcpUrl, "--oauth-resource", mcpUrl],
|
|
45
|
+
};
|
|
46
|
+
function launchHermesWalkthrough() {
|
|
47
|
+
const seedResult = spawn.sync("hermes", ["chat", "-Q", "-q", DEFAULT_ONBOARDING_PROMPT], {
|
|
48
|
+
encoding: "utf8",
|
|
49
|
+
timeout: HERMES_SEED_TIMEOUT_MS,
|
|
50
|
+
});
|
|
51
|
+
if (seedResult.error || seedResult.status !== 0) {
|
|
52
|
+
throw new Error("Could not start the TinyFish walkthrough in Hermes", {
|
|
53
|
+
cause: seedResult.error,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
const sessionId = seedResult.stderr?.match(/session_id:\s*([^\s]+)/i)?.[1];
|
|
57
|
+
if (!sessionId) {
|
|
58
|
+
throw new Error("Hermes did not return a walkthrough session ID");
|
|
59
|
+
}
|
|
60
|
+
const result = spawn.sync("hermes", ["--resume", sessionId], { stdio: "inherit" });
|
|
61
|
+
if (result.error) {
|
|
62
|
+
throw new Error("Could not launch Hermes", { cause: result.error });
|
|
63
|
+
}
|
|
64
|
+
if (result.signal === "SIGINT" || result.signal === "SIGTERM")
|
|
65
|
+
return;
|
|
66
|
+
if (result.status !== 0) {
|
|
67
|
+
throw new Error(`Hermes walkthrough exited with status ${result.status ?? "unknown"}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const HERMES = {
|
|
71
|
+
command: "hermes",
|
|
72
|
+
displayName: "Hermes",
|
|
73
|
+
supportCheck: {
|
|
74
|
+
args: ["mcp", "add", "--help"],
|
|
75
|
+
pattern: /--auth\s+\{[^}]*oauth[^}]*\}/,
|
|
76
|
+
unavailableMessage: HERMES_OAUTH_UNAVAILABLE_MESSAGE,
|
|
77
|
+
},
|
|
78
|
+
removals: [{ args: ["mcp", "remove", "tinyfish"], label: "TinyFish registration from Hermes" }],
|
|
79
|
+
// Hermes completes OAuth while adding the server; a separate `mcp login` would authenticate twice.
|
|
80
|
+
addArgs: (mcpUrl) => ["mcp", "add", "tinyfish", "--url", mcpUrl, "--auth", "oauth"],
|
|
81
|
+
launchWalkthrough: launchHermesWalkthrough,
|
|
50
82
|
};
|
|
51
83
|
function requireNativeMcpSupport(client) {
|
|
52
84
|
const result = spawn.sync(client.command, client.supportCheck.args, {
|
|
@@ -112,6 +144,10 @@ function connectNativeMcpClient(client, options) {
|
|
|
112
144
|
return;
|
|
113
145
|
}
|
|
114
146
|
errLine(`Starting the TinyFish walkthrough in ${client.displayName}...`);
|
|
147
|
+
if (client.launchWalkthrough) {
|
|
148
|
+
client.launchWalkthrough();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
115
151
|
const result = spawn.sync(client.command, [DEFAULT_ONBOARDING_PROMPT], { stdio: "inherit" });
|
|
116
152
|
if (result.error) {
|
|
117
153
|
throw new Error(`Could not launch ${client.displayName}`, { cause: result.error });
|
|
@@ -128,11 +164,14 @@ export function connectClaudeCode(options) {
|
|
|
128
164
|
export function connectCodex(options) {
|
|
129
165
|
connectNativeMcpClient(CODEX, options);
|
|
130
166
|
}
|
|
167
|
+
export function connectHermes(options) {
|
|
168
|
+
connectNativeMcpClient(HERMES, options);
|
|
169
|
+
}
|
|
131
170
|
export function registerConnect(program) {
|
|
132
171
|
program
|
|
133
172
|
.command("connect")
|
|
134
173
|
.description("Connect TinyFish to an AI agent")
|
|
135
|
-
.argument("<client>", "Agent client to connect (claude-code or
|
|
174
|
+
.argument("<client>", "Agent client to connect (claude-code, codex, or hermes)")
|
|
136
175
|
.option("--launch", "Launch the agent and start the TinyFish walkthrough")
|
|
137
176
|
.option("--url <mcpUrl>", "MCP endpoint override")
|
|
138
177
|
.action((client, options) => {
|
|
@@ -157,8 +196,11 @@ export function registerConnect(program) {
|
|
|
157
196
|
else if (client === "codex") {
|
|
158
197
|
connectCodex(connectOptions);
|
|
159
198
|
}
|
|
199
|
+
else if (client === "hermes") {
|
|
200
|
+
connectHermes(connectOptions);
|
|
201
|
+
}
|
|
160
202
|
else {
|
|
161
|
-
throw new Error(`Unsupported client: ${client}. Supported clients: claude-code, codex`);
|
|
203
|
+
throw new Error(`Unsupported client: ${client}. Supported clients: claude-code, codex, hermes`);
|
|
162
204
|
}
|
|
163
205
|
});
|
|
164
206
|
}
|