@tiny-fish/cli 0.45.2-next.354 → 0.45.2-next.357
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/config-claude.js +1 -1
- package/dist/commands/connect.d.ts +0 -37
- package/dist/commands/connect.js +29 -846
- package/dist/commands/onboard.js +1 -1
- package/dist/lib/auth.d.ts +4 -0
- package/dist/lib/auth.js +26 -4
- package/dist/lib/config/cline-config.d.ts +4 -0
- package/dist/lib/config/cline-config.js +36 -0
- package/dist/lib/config/connect-config-file.d.ts +76 -0
- package/dist/lib/config/connect-config-file.js +241 -0
- package/dist/lib/{hermes-config.js → config/hermes-config.js} +2 -2
- package/dist/lib/{mcp-json-config.d.ts → config/mcp-json-config.d.ts} +2 -0
- package/dist/lib/{mcp-json-config.js → config/mcp-json-config.js} +11 -5
- package/dist/lib/{omp-config.js → config/omp-config.js} +2 -2
- package/dist/lib/{pi-config.js → config/pi-config.js} +1 -1
- package/dist/lib/connect-all-uninstall.js +3 -3
- package/dist/lib/connect-all.js +1 -1
- package/dist/lib/connect-clients.d.ts +1 -1
- package/dist/lib/connect-clients.js +8 -1
- package/dist/lib/connect-harness.d.ts +4 -0
- package/dist/lib/connect-harness.js +76 -0
- package/dist/lib/connect-native.d.ts +4 -0
- package/dist/lib/connect-native.js +389 -0
- package/dist/lib/connect-openclaw.d.ts +3 -0
- package/dist/lib/connect-openclaw.js +71 -0
- package/dist/lib/connect-steps.d.ts +38 -0
- package/dist/lib/connect-steps.js +104 -0
- package/dist/lib/doctor-checks.js +1 -1
- package/dist/lib/doctor-repairs.js +1 -1
- package/dist/lib/doctor-report.d.ts +6 -0
- package/dist/lib/harness-detect.js +7 -3
- package/dist/lib/harness-spec.d.ts +23 -2
- package/dist/lib/harness-spec.js +23 -0
- package/dist/lib/harness.js +5 -0
- package/dist/lib/hermes-plugin.js +1 -1
- package/dist/lib/registration-detect.js +22 -5
- package/dist/lib/setup-telemetry.d.ts +10 -0
- package/dist/lib/skill-paths.js +1 -0
- package/package.json +1 -1
- /package/dist/lib/{claude-config.d.ts → config/claude-config.d.ts} +0 -0
- /package/dist/lib/{claude-config.js → config/claude-config.js} +0 -0
- /package/dist/lib/{command-code-config.d.ts → config/command-code-config.d.ts} +0 -0
- /package/dist/lib/{command-code-config.js → config/command-code-config.js} +0 -0
- /package/dist/lib/{cursor-config.d.ts → config/cursor-config.d.ts} +0 -0
- /package/dist/lib/{cursor-config.js → config/cursor-config.js} +0 -0
- /package/dist/lib/{hermes-config.d.ts → config/hermes-config.d.ts} +0 -0
- /package/dist/lib/{omp-config.d.ts → config/omp-config.d.ts} +0 -0
- /package/dist/lib/{pi-config.d.ts → config/pi-config.d.ts} +0 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { verifyMcpHealth } from './verify.js';
|
|
2
|
+
import { installTinyFishCli } from './cli-install.js';
|
|
3
|
+
import { createStdinPrompt, runCliFallback } from './connect-fallback.js';
|
|
4
|
+
import { detectHumanInitiated } from './harness.js';
|
|
5
|
+
import { errLine } from './output.js';
|
|
6
|
+
import { ConnectInterruptedError, ConnectStepError, HoistedFailureReportedError, finishSetupCommand, requireCommandSupport, settle, stageDurationOf, withStageDuration, } from './connect-runtime.js';
|
|
7
|
+
export async function requireKeylessMcp(mcpUrl) {
|
|
8
|
+
if ((await verifyMcpHealth(mcpUrl, true)).ok)
|
|
9
|
+
return;
|
|
10
|
+
throw new ConnectStepError('TinyFish keyless Search is unavailable', 'invalid_config');
|
|
11
|
+
}
|
|
12
|
+
function isMissingHarness(error) {
|
|
13
|
+
return error instanceof ConnectStepError && error.failureReason === 'harness_not_installed';
|
|
14
|
+
}
|
|
15
|
+
/** Undefined means the rescue ran; the caller returns immediately. */
|
|
16
|
+
export async function requireSupportOrRescue(client, connectClient, state, telemetry, options) {
|
|
17
|
+
try {
|
|
18
|
+
return requireCommandSupport(client);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
if (!options.fallbackWhenMissing || !isMissingHarness(error))
|
|
22
|
+
throw error;
|
|
23
|
+
await runMissingHarnessFallback(client.displayName, connectClient, state, telemetry, options);
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// The harness attempt stays failed; the rescue rides fallback_outcome (PF-3707).
|
|
28
|
+
async function runMissingHarnessFallback(displayName, connectClient, state, telemetry, options) {
|
|
29
|
+
// Stamped before any step: Ctrl+C settles before an outcome exists.
|
|
30
|
+
telemetry.setFallbackOutcome('abandoned');
|
|
31
|
+
errLine(`${displayName} was not found on PATH. Setting up the TinyFish CLI instead.`);
|
|
32
|
+
const outcome = await runCliFallback({
|
|
33
|
+
apiKey: options.apiKey,
|
|
34
|
+
verbose: options.verbose ?? false,
|
|
35
|
+
prompt: detectHumanInitiated() ? createStdinPrompt() : undefined,
|
|
36
|
+
retryCommand: `npx @tiny-fish/cli connect ${connectClient}`,
|
|
37
|
+
hooks: {
|
|
38
|
+
// Terminal detail is explicit below; abort rows still name the step.
|
|
39
|
+
onStepStart: (stage) => {
|
|
40
|
+
state.stage = stage;
|
|
41
|
+
},
|
|
42
|
+
onStepDone: (phase) => telemetry.track('checkpoint', { phase }),
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
telemetry.setFallbackOutcome(outcome);
|
|
46
|
+
// Never `completed`: dashboards read that as "the harness install worked".
|
|
47
|
+
settle(state, telemetry, 'failed', {
|
|
48
|
+
failedStage: 'prerequisite_check',
|
|
49
|
+
failureReason: 'harness_not_installed',
|
|
50
|
+
});
|
|
51
|
+
if (outcome !== 'cli_verified') {
|
|
52
|
+
process.exitCode = 1;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
errLine('The TinyFish CLI is installed and working.');
|
|
56
|
+
errLine('Using a different agent? Run: tinyfish connect --all');
|
|
57
|
+
}
|
|
58
|
+
/** Fails on a carried failure; only the first take reports anything. */
|
|
59
|
+
function takeHoistedCliInstall(take, telemetry) {
|
|
60
|
+
const { outcome, firstTake } = take();
|
|
61
|
+
if (!outcome.ok) {
|
|
62
|
+
// Late takers fail too; only the first reports the install.
|
|
63
|
+
if (!firstTake)
|
|
64
|
+
throw new HoistedFailureReportedError(outcome.error.message);
|
|
65
|
+
throw withStageDuration(outcome.error, outcome.durationMs);
|
|
66
|
+
}
|
|
67
|
+
if (firstTake) {
|
|
68
|
+
telemetry.track('checkpoint', {
|
|
69
|
+
phase: 'cli_installed',
|
|
70
|
+
stageDurationMs: outcome.durationMs,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** Consumes the `--all` hoist when present; installs inline otherwise. */
|
|
75
|
+
export function runCliInstallStep(options, telemetry) {
|
|
76
|
+
if (options.hoistedCliInstall) {
|
|
77
|
+
takeHoistedCliInstall(options.hoistedCliInstall, telemetry);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
installTinyFishCli({ verbose: options.verbose ?? false, announce: true });
|
|
81
|
+
telemetry.track('checkpoint', { phase: 'cli_installed' });
|
|
82
|
+
}
|
|
83
|
+
export function walkthroughPhase(outcome) {
|
|
84
|
+
return outcome === 'printed' ? 'walkthrough_prompt_printed' : 'walkthrough_launched';
|
|
85
|
+
}
|
|
86
|
+
export function finishSetupHint(connectClient) {
|
|
87
|
+
return `Finish setup with: ${finishSetupCommand(connectClient)}`;
|
|
88
|
+
}
|
|
89
|
+
/** Warn + report post_install_failed; interrupts are abandonment, not failure. */
|
|
90
|
+
export function trackPostInstallFailure(displayName, state, telemetry, error) {
|
|
91
|
+
if (error instanceof ConnectInterruptedError)
|
|
92
|
+
return;
|
|
93
|
+
// An earlier harness already owns the shared install's failure record.
|
|
94
|
+
if (!(error instanceof HoistedFailureReportedError)) {
|
|
95
|
+
telemetry.track('post_install_failed', {
|
|
96
|
+
failedStage: state.stage,
|
|
97
|
+
failureReason: error instanceof ConnectStepError ? error.failureReason : 'unexpected_error',
|
|
98
|
+
failureDetail: error instanceof ConnectStepError ? (error.failureDetail ?? error.message) : undefined,
|
|
99
|
+
stageDurationMs: stageDurationOf(error),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
errLine(`The ${displayName} MCP connection succeeded, but a finishing step ` +
|
|
103
|
+
`(${state.stage}) failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
104
|
+
}
|
|
@@ -4,7 +4,7 @@ import { AuthMode, Registered } from './harness-detect.js';
|
|
|
4
4
|
import { resolveHermesHome } from './hermes-env.js';
|
|
5
5
|
import { hermesWebBackendsOurs, readHermesPluginStatus, } from './hermes-plugin.js';
|
|
6
6
|
import { endpointOf, isDefaultEndpoint } from './mcp-endpoint.js';
|
|
7
|
-
import { PI_ADAPTER_INSTALL_COMMAND, piMcpAdapterState } from './pi-config.js';
|
|
7
|
+
import { PI_ADAPTER_INSTALL_COMMAND, piMcpAdapterState } from './config/pi-config.js';
|
|
8
8
|
import { boundedVersion } from './output.js';
|
|
9
9
|
import { verifyMcpHealth } from './verify.js';
|
|
10
10
|
// A green auth mode with a red auth call proves nothing, so the call's verdict gates the claim.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import spawn from 'cross-spawn';
|
|
2
|
-
import { connectHarness } from '
|
|
2
|
+
import { connectHarness } from './connect-harness.js';
|
|
3
3
|
import { OAUTH_SIGN_IN_TIMEOUT_MS } from './connect-all-auth.js';
|
|
4
4
|
import { Registered } from './harness-detect.js';
|
|
5
5
|
import { detectHumanInitiated } from './harness.js';
|
|
@@ -43,6 +43,7 @@ declare const doctorCheckSchema: z.ZodObject<{
|
|
|
43
43
|
"command-code": "command-code";
|
|
44
44
|
opencode: "opencode";
|
|
45
45
|
pi: "pi";
|
|
46
|
+
cline: "cline";
|
|
46
47
|
"claude-code": "claude-code";
|
|
47
48
|
}>>;
|
|
48
49
|
scope: z.ZodEnum<{
|
|
@@ -62,6 +63,7 @@ declare const doctorHarnessSchema: z.ZodObject<{
|
|
|
62
63
|
"command-code": "command-code";
|
|
63
64
|
opencode: "opencode";
|
|
64
65
|
pi: "pi";
|
|
66
|
+
cline: "cline";
|
|
65
67
|
"claude-code": "claude-code";
|
|
66
68
|
}>;
|
|
67
69
|
detected: z.ZodBoolean;
|
|
@@ -91,6 +93,7 @@ declare const doctorRepairSchema: z.ZodObject<{
|
|
|
91
93
|
"command-code": "command-code";
|
|
92
94
|
opencode: "opencode";
|
|
93
95
|
pi: "pi";
|
|
96
|
+
cline: "cline";
|
|
94
97
|
"claude-code": "claude-code";
|
|
95
98
|
}>>;
|
|
96
99
|
command: z.ZodString;
|
|
@@ -129,6 +132,7 @@ export declare const doctorReportSchema: z.ZodObject<{
|
|
|
129
132
|
"command-code": "command-code";
|
|
130
133
|
opencode: "opencode";
|
|
131
134
|
pi: "pi";
|
|
135
|
+
cline: "cline";
|
|
132
136
|
"claude-code": "claude-code";
|
|
133
137
|
}>>;
|
|
134
138
|
scope: z.ZodEnum<{
|
|
@@ -148,6 +152,7 @@ export declare const doctorReportSchema: z.ZodObject<{
|
|
|
148
152
|
"command-code": "command-code";
|
|
149
153
|
opencode: "opencode";
|
|
150
154
|
pi: "pi";
|
|
155
|
+
cline: "cline";
|
|
151
156
|
"claude-code": "claude-code";
|
|
152
157
|
}>;
|
|
153
158
|
detected: z.ZodBoolean;
|
|
@@ -177,6 +182,7 @@ export declare const doctorReportSchema: z.ZodObject<{
|
|
|
177
182
|
"command-code": "command-code";
|
|
178
183
|
opencode: "opencode";
|
|
179
184
|
pi: "pi";
|
|
185
|
+
cline: "cline";
|
|
180
186
|
"claude-code": "claude-code";
|
|
181
187
|
}>>;
|
|
182
188
|
command: z.ZodString;
|
|
@@ -3,7 +3,8 @@ import * as os from 'os';
|
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import which from 'which';
|
|
5
5
|
import { ALL_HARNESSES, harnessSpec } from './harness-spec.js';
|
|
6
|
-
import {
|
|
6
|
+
import { clineConfigDir } from './config/cline-config.js';
|
|
7
|
+
import { piAgentDir, piBinaryIsPi } from './config/pi-config.js';
|
|
7
8
|
export { ALL_HARNESSES };
|
|
8
9
|
export const HARNESS_DISPLAY_NAMES = Object.fromEntries(ALL_HARNESSES.map((harness) => [harness, harnessSpec(harness).displayName]));
|
|
9
10
|
export const RELOAD_ACTION = Object.fromEntries(ALL_HARNESSES.map((harness) => [harness, harnessSpec(harness).reloadAction]));
|
|
@@ -33,8 +34,11 @@ export function commandOnPath(command) {
|
|
|
33
34
|
return false;
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
|
-
// PI_CODING_AGENT_DIR
|
|
37
|
-
const CONFIG_PATH_RESOLVERS = {
|
|
37
|
+
// PI_CODING_AGENT_DIR and CLINE_DIR move these dirs; a guessed path would be written unread.
|
|
38
|
+
const CONFIG_PATH_RESOLVERS = {
|
|
39
|
+
cline: clineConfigDir,
|
|
40
|
+
pi: piAgentDir,
|
|
41
|
+
};
|
|
38
42
|
export function harnessConfigPath(harness) {
|
|
39
43
|
const resolved = CONFIG_PATH_RESOLVERS[harness]?.();
|
|
40
44
|
return resolved ?? path.join(os.homedir(), harnessSpec(harness).configDir); // nosemgrep: path-join-resolve-traversal -- fixed dir names under os.homedir()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Our skill-path slugs, inherited from the `skills` CLI era. */
|
|
2
|
-
export type SkillAgent = 'claude-code' | 'codex' | 'command-code' | 'cursor' | 'hermes-agent' | 'opencode' | 'pi';
|
|
2
|
+
export type SkillAgent = 'claude-code' | 'cline' | 'codex' | 'command-code' | 'cursor' | 'hermes-agent' | 'opencode' | 'pi';
|
|
3
3
|
export interface HarnessSupportCheck {
|
|
4
4
|
args: string[];
|
|
5
5
|
/** Missing → nothing can work; setup fails. */
|
|
@@ -114,6 +114,27 @@ export declare const HARNESS_SPECS: {
|
|
|
114
114
|
label: string;
|
|
115
115
|
}[];
|
|
116
116
|
};
|
|
117
|
+
cline: {
|
|
118
|
+
command: string;
|
|
119
|
+
displayName: string;
|
|
120
|
+
configDir: string;
|
|
121
|
+
reloadAction: string;
|
|
122
|
+
skillAgent: "cline";
|
|
123
|
+
nonInteractiveAdd: true;
|
|
124
|
+
keyRequired: true;
|
|
125
|
+
supportCheck: {
|
|
126
|
+
args: string[];
|
|
127
|
+
patterns: RegExp[];
|
|
128
|
+
keyAuthPattern: RegExp;
|
|
129
|
+
unavailableMessage: string;
|
|
130
|
+
};
|
|
131
|
+
urlStyle: "positional";
|
|
132
|
+
addFlags: string[];
|
|
133
|
+
header: {
|
|
134
|
+
name: string;
|
|
135
|
+
sep: ": ";
|
|
136
|
+
};
|
|
137
|
+
};
|
|
117
138
|
codex: {
|
|
118
139
|
command: string;
|
|
119
140
|
displayName: string;
|
|
@@ -286,4 +307,4 @@ export type NonNativeHarness = {
|
|
|
286
307
|
[K in Harness]: 'urlStyle' extends keyof (typeof HARNESS_SPECS)[K] ? never : 'keyRequired' extends keyof (typeof HARNESS_SPECS)[K] ? never : K;
|
|
287
308
|
}[Harness];
|
|
288
309
|
/** Native MCP harnesses generate an add; key-only ones generate only the keyed form. */
|
|
289
|
-
export declare const NATIVE_HARNESSES: ("openclaw" | "omp" | "grok" | "cursor" | "codex" | "hermes" | "command-code" | "opencode" | "pi" | "claude-code")[];
|
|
310
|
+
export declare const NATIVE_HARNESSES: ("openclaw" | "omp" | "grok" | "cursor" | "codex" | "hermes" | "command-code" | "opencode" | "pi" | "cline" | "claude-code")[];
|
package/dist/lib/harness-spec.js
CHANGED
|
@@ -46,6 +46,9 @@ const OPENCODE_MODEL_NOTE = 'Note: TinyFish runs on tool calls, so OpenCode need
|
|
|
46
46
|
'models (e.g. Nano Banana Pro) will show "No endpoints found that support tool use" — switch ' +
|
|
47
47
|
"OpenCode's model if the walkthrough can't start.";
|
|
48
48
|
const HERMES_RESTART_NOTE = 'Restart your Hermes session to pick up TinyFish — Hermes discovers MCP servers at startup.';
|
|
49
|
+
const CLINE_MCP_ADD_UNAVAILABLE_MESSAGE = 'Could not confirm this Cline installation supports non-interactive MCP setup: `cline mcp add ' +
|
|
50
|
+
'--help` did not list `--transport` and `--yes`. Update Cline with `cline --update` and retry.' +
|
|
51
|
+
SUPPORT_CHECK_DEBUG_HINT;
|
|
49
52
|
const COMMAND_CODE_ADD_JSON_UNAVAILABLE_MESSAGE = 'Could not confirm this Command Code installation supports keyed MCP setup: `commandcode mcp ' +
|
|
50
53
|
'--help` did not list `add-json`. Run `commandcode update` and retry.' +
|
|
51
54
|
SUPPORT_CHECK_DEBUG_HINT;
|
|
@@ -87,6 +90,26 @@ export const HARNESS_SPECS = {
|
|
|
87
90
|
},
|
|
88
91
|
],
|
|
89
92
|
},
|
|
93
|
+
cline: {
|
|
94
|
+
command: 'cline',
|
|
95
|
+
displayName: 'Cline',
|
|
96
|
+
configDir: '.cline',
|
|
97
|
+
reloadAction: 'restart it',
|
|
98
|
+
skillAgent: 'cline',
|
|
99
|
+
nonInteractiveAdd: true,
|
|
100
|
+
// Key-only by decision: TinyFish never sends CLI-harness users through OAuth.
|
|
101
|
+
keyRequired: true,
|
|
102
|
+
supportCheck: {
|
|
103
|
+
args: ['mcp', 'add', '--help'],
|
|
104
|
+
// Without `--yes` the add opens a wizard and exits non-zero off a TTY.
|
|
105
|
+
patterns: [/--transport(?:[\s<=]|$)/m, /--yes(?:[\s<=]|$)/m],
|
|
106
|
+
keyAuthPattern: HEADER_FLAG,
|
|
107
|
+
unavailableMessage: CLINE_MCP_ADD_UNAVAILABLE_MESSAGE,
|
|
108
|
+
},
|
|
109
|
+
urlStyle: 'positional',
|
|
110
|
+
addFlags: ['--transport', 'http', '--yes'],
|
|
111
|
+
header: { name: 'X-API-Key', sep: ': ' },
|
|
112
|
+
},
|
|
90
113
|
codex: {
|
|
91
114
|
command: 'codex',
|
|
92
115
|
displayName: 'Codex',
|
package/dist/lib/harness.js
CHANGED
|
@@ -32,6 +32,11 @@ const HARNESS_FINGERPRINTS = [
|
|
|
32
32
|
{ name: 'opencode', matches: (env) => Boolean(env['OPENCODE']) },
|
|
33
33
|
// Observed: pi launched from Claude Code inherits CLAUDECODE=1.
|
|
34
34
|
{ name: 'pi', matches: (env) => env['PI_CODING_AGENT'] === 'true' },
|
|
35
|
+
// Runtime-only markers; users export CLINE_API_KEY, so no prefix match.
|
|
36
|
+
{
|
|
37
|
+
name: 'cline',
|
|
38
|
+
matches: (env) => Boolean(env['CLINE_CONNECTOR_CLI_LAUNCH'] || env['CLINE_WRAPPER_PATH']),
|
|
39
|
+
},
|
|
35
40
|
{
|
|
36
41
|
name: 'claude-code',
|
|
37
42
|
matches: (env) => env['CLAUDECODE'] === '1' || Boolean(env['CLAUDE_CODE_ENTRYPOINT']),
|
|
@@ -7,7 +7,7 @@ import { z } from 'zod';
|
|
|
7
7
|
import { capturedOutput, replay, SKILL_INSTALL_TIMEOUT_MS, STEP_MAX_BUFFER, } from './cli-install.js';
|
|
8
8
|
import { commandNotFound, ConnectStepError, spawnStepError, throwIfInterrupted, } from './connect-runtime.js';
|
|
9
9
|
import { HARNESS_PROBE_TIMEOUT_MS, TINYFISH_ACCESS_MODE_HEADER, TINYFISH_KEYLESS_ACCESS_MODE, } from './constants.js';
|
|
10
|
-
import { HERMES_HEADER_TEMPLATE, HERMES_MCP_SERVER_KEY } from './hermes-config.js';
|
|
10
|
+
import { HERMES_HEADER_TEMPLATE, HERMES_MCP_SERVER_KEY } from './config/hermes-config.js';
|
|
11
11
|
import { errLine, parseJson } from './output.js';
|
|
12
12
|
// Resolved at connect time, so plugin releases need no CLI release.
|
|
13
13
|
export const HERMES_PLUGIN_PACKAGE = '@tiny-fish/hermes';
|
|
@@ -6,12 +6,13 @@ import { loadConfig, matchesCliKey } from './auth.js';
|
|
|
6
6
|
import { NATIVE_BY_HARNESS } from './connect-clients.js';
|
|
7
7
|
import { HARNESS_PROBE_TIMEOUT_MS } from './constants.js';
|
|
8
8
|
import { errLine } from './output.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
9
|
+
import { readClineTinyfishEntry } from './config/cline-config.js';
|
|
10
|
+
import { readCommandCodeTinyfishEntry } from './config/command-code-config.js';
|
|
11
|
+
import { readCursorTinyfishEntry } from './config/cursor-config.js';
|
|
12
|
+
import { readOmpTinyfishEntry } from './config/omp-config.js';
|
|
13
|
+
import { readPiTinyfishEntry } from './config/pi-config.js';
|
|
13
14
|
import { readHermesKey, resolveHermesHome } from './hermes-env.js';
|
|
14
|
-
import { readHermesEntry } from './hermes-config.js';
|
|
15
|
+
import { readHermesEntry } from './config/hermes-config.js';
|
|
15
16
|
import { detectInstalledHarnesses, harnessConfigPath, harnessDisplayPath, AuthMode, Registered, } from './harness-detect.js';
|
|
16
17
|
const NOT_REGISTERED = Object.freeze({
|
|
17
18
|
registered: Registered.No,
|
|
@@ -279,6 +280,21 @@ function probeCodex() {
|
|
|
279
280
|
...(envVar ? envKeyVerdict(envVar) : {}),
|
|
280
281
|
};
|
|
281
282
|
}
|
|
283
|
+
// No `cline mcp list`, so the settings file is the only registration evidence.
|
|
284
|
+
function probeCline() {
|
|
285
|
+
const entry = readClineTinyfishEntry();
|
|
286
|
+
if (entry.error) {
|
|
287
|
+
return unverified('cline_mcp_settings.json exists but could not be read or parsed');
|
|
288
|
+
}
|
|
289
|
+
if (!entry.present)
|
|
290
|
+
return NOT_REGISTERED;
|
|
291
|
+
return {
|
|
292
|
+
registered: Registered.Yes,
|
|
293
|
+
authMode: entry.hasApiKeyHeader ? AuthMode.ApiKey : AuthMode.Unknown,
|
|
294
|
+
...(entry.url ? { registeredUrl: entry.url } : {}),
|
|
295
|
+
...(entry.keyMatchesCliKey ? { keyMatchesCliKey: true } : {}),
|
|
296
|
+
};
|
|
297
|
+
}
|
|
282
298
|
function probeCommandCode() {
|
|
283
299
|
const entry = readCommandCodeTinyfishEntry();
|
|
284
300
|
if (entry.error)
|
|
@@ -523,6 +539,7 @@ function probeGrok() {
|
|
|
523
539
|
}
|
|
524
540
|
const PROBES = {
|
|
525
541
|
'claude-code': () => fromMcpGet('claude'),
|
|
542
|
+
cline: probeCline,
|
|
526
543
|
codex: probeCodex,
|
|
527
544
|
'command-code': probeCommandCode,
|
|
528
545
|
cursor: probeCursor,
|
|
@@ -31,6 +31,7 @@ declare const harnessResultSchema: z.ZodObject<{
|
|
|
31
31
|
"command-code": "command-code";
|
|
32
32
|
opencode: "opencode";
|
|
33
33
|
pi: "pi";
|
|
34
|
+
cline: "cline";
|
|
34
35
|
"claude-code": "claude-code";
|
|
35
36
|
}>;
|
|
36
37
|
detected: z.ZodBoolean;
|
|
@@ -67,6 +68,7 @@ export declare const setupCompletedPayloadSchema: z.ZodObject<{
|
|
|
67
68
|
"command-code": "command-code";
|
|
68
69
|
opencode: "opencode";
|
|
69
70
|
pi: "pi";
|
|
71
|
+
cline: "cline";
|
|
70
72
|
"claude-code": "claude-code";
|
|
71
73
|
}>;
|
|
72
74
|
detected: z.ZodBoolean;
|
|
@@ -130,6 +132,7 @@ declare const doctorCompletedPayloadSchema: z.ZodObject<{
|
|
|
130
132
|
"command-code": "command-code";
|
|
131
133
|
opencode: "opencode";
|
|
132
134
|
pi: "pi";
|
|
135
|
+
cline: "cline";
|
|
133
136
|
"claude-code": "claude-code";
|
|
134
137
|
all: "all";
|
|
135
138
|
}>;
|
|
@@ -145,6 +148,7 @@ declare const doctorCompletedPayloadSchema: z.ZodObject<{
|
|
|
145
148
|
"command-code": "command-code";
|
|
146
149
|
opencode: "opencode";
|
|
147
150
|
pi: "pi";
|
|
151
|
+
cline: "cline";
|
|
148
152
|
"claude-code": "claude-code";
|
|
149
153
|
}>>;
|
|
150
154
|
harnesses: z.ZodArray<z.ZodObject<{
|
|
@@ -158,6 +162,7 @@ declare const doctorCompletedPayloadSchema: z.ZodObject<{
|
|
|
158
162
|
"command-code": "command-code";
|
|
159
163
|
opencode: "opencode";
|
|
160
164
|
pi: "pi";
|
|
165
|
+
cline: "cline";
|
|
161
166
|
"claude-code": "claude-code";
|
|
162
167
|
}>;
|
|
163
168
|
detected: z.ZodBoolean;
|
|
@@ -200,6 +205,7 @@ declare const doctorCouldNotRunPayloadSchema: z.ZodObject<{
|
|
|
200
205
|
"command-code": "command-code";
|
|
201
206
|
opencode: "opencode";
|
|
202
207
|
pi: "pi";
|
|
208
|
+
cline: "cline";
|
|
203
209
|
"claude-code": "claude-code";
|
|
204
210
|
all: "all";
|
|
205
211
|
}>;
|
|
@@ -238,6 +244,7 @@ declare const doctorPayloadSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
238
244
|
"command-code": "command-code";
|
|
239
245
|
opencode: "opencode";
|
|
240
246
|
pi: "pi";
|
|
247
|
+
cline: "cline";
|
|
241
248
|
"claude-code": "claude-code";
|
|
242
249
|
all: "all";
|
|
243
250
|
}>;
|
|
@@ -253,6 +260,7 @@ declare const doctorPayloadSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
253
260
|
"command-code": "command-code";
|
|
254
261
|
opencode: "opencode";
|
|
255
262
|
pi: "pi";
|
|
263
|
+
cline: "cline";
|
|
256
264
|
"claude-code": "claude-code";
|
|
257
265
|
}>>;
|
|
258
266
|
harnesses: z.ZodArray<z.ZodObject<{
|
|
@@ -266,6 +274,7 @@ declare const doctorPayloadSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
266
274
|
"command-code": "command-code";
|
|
267
275
|
opencode: "opencode";
|
|
268
276
|
pi: "pi";
|
|
277
|
+
cline: "cline";
|
|
269
278
|
"claude-code": "claude-code";
|
|
270
279
|
}>;
|
|
271
280
|
detected: z.ZodBoolean;
|
|
@@ -307,6 +316,7 @@ declare const doctorPayloadSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
307
316
|
"command-code": "command-code";
|
|
308
317
|
opencode: "opencode";
|
|
309
318
|
pi: "pi";
|
|
319
|
+
cline: "cline";
|
|
310
320
|
"claude-code": "claude-code";
|
|
311
321
|
all: "all";
|
|
312
322
|
}>;
|
package/dist/lib/skill-paths.js
CHANGED
|
@@ -14,6 +14,7 @@ const SKILL_DIR_BY_AGENT = {
|
|
|
14
14
|
'claude-code': () => path.join(agentHome('CLAUDE_CONFIG_DIR', '.claude'), 'skills'),
|
|
15
15
|
// The env value, not resolveHermesHome(): skills@1.5.15 reads $HERMES_HOME directly.
|
|
16
16
|
'hermes-agent': () => path.join(agentHome('HERMES_HOME', '.hermes'), 'skills'),
|
|
17
|
+
cline: canonicalSkillsDir,
|
|
17
18
|
codex: canonicalSkillsDir,
|
|
18
19
|
// Not the canonical dir: `skills` writes this one under the harness's own config dir.
|
|
19
20
|
'command-code': () => path.join(os.homedir(), '.commandcode', 'skills'), // nosemgrep: path-join-resolve-traversal -- fixed dir names under os.homedir()
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|