@zokizuan/satori-cli 0.1.1 → 0.3.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 CHANGED
@@ -14,10 +14,11 @@ Shell CLI for Satori installation, skill packaging, and direct tool invocation w
14
14
  ## Install / Uninstall
15
15
 
16
16
  ```bash
17
- npx -y @zokizuan/satori-cli@0.1.1 install --client codex
18
- npx -y @zokizuan/satori-cli@0.1.1 install --client claude
19
- npx -y @zokizuan/satori-cli@0.1.1 install --client all --dry-run
20
- npx -y @zokizuan/satori-cli@0.1.1 uninstall --client codex
17
+ npx -y @zokizuan/satori-cli@0.3.0 install --client codex
18
+ npx -y @zokizuan/satori-cli@0.3.0 install --client claude
19
+ npx -y @zokizuan/satori-cli@0.3.0 install --client all --dry-run
20
+ npx -y @zokizuan/satori-cli@0.3.0 uninstall --client codex
21
+ npx -y @zokizuan/satori-cli@0.3.0 doctor
21
22
  ```
22
23
 
23
24
  Managed install writes MCP config that launches:
@@ -25,13 +26,14 @@ Managed install writes MCP config that launches:
25
26
  ```toml
26
27
  [mcp_servers.satori]
27
28
  command = "npx"
28
- args = ["-y", "@zokizuan/satori-mcp@4.4.1"]
29
+ args = ["-y", "@zokizuan/satori-mcp@4.9.0"]
29
30
  startup_timeout_ms = 180000
30
31
  ```
31
32
 
32
33
  ## Commands
33
34
 
34
35
  ```bash
36
+ satori-cli doctor
35
37
  satori-cli tools list
36
38
  satori-cli tool call <toolName> --args-json '{"path":"/abs/repo","query":"auth"}'
37
39
  satori-cli tool call <toolName> --args-file ./args.json
@@ -41,6 +43,8 @@ satori-cli <toolName> [schema-subset flags]
41
43
 
42
44
  Global flags (`--startup-timeout-ms`, `--call-timeout-ms`, `--format`, `--debug`) must appear before the command token.
43
45
 
46
+ `doctor` checks local setup without starting an MCP client: Node version, npm package visibility, provider env, and Milvus env.
47
+
44
48
  ## Development
45
49
 
46
50
  ```bash
package/dist/args.d.ts CHANGED
@@ -19,6 +19,8 @@ export type ParsedCommand = {
19
19
  kind: "help";
20
20
  } | {
21
21
  kind: "version";
22
+ } | {
23
+ kind: "doctor";
22
24
  } | {
23
25
  kind: "install";
24
26
  client: InstallClient;
package/dist/args.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import { CliError } from "./errors.js";
3
- const RESERVED_SUBCOMMANDS = new Set(["tools", "tool", "help", "version", "install", "uninstall"]);
3
+ const RESERVED_SUBCOMMANDS = new Set(["tools", "tool", "help", "version", "doctor", "install", "uninstall"]);
4
4
  const PRIMITIVE_TYPES = new Set(["string", "number", "integer", "boolean"]);
5
5
  function parsePositiveInteger(value, flagName) {
6
6
  const parsed = Number.parseInt(value, 10);
@@ -145,6 +145,15 @@ export function parseCliArgs(argv) {
145
145
  command: { kind: "version" }
146
146
  };
147
147
  }
148
+ if (rest[0] === "doctor") {
149
+ if (rest.length !== 1) {
150
+ throw new CliError("E_USAGE", `Unknown arguments for doctor: ${rest.slice(1).join(" ")}`, 2);
151
+ }
152
+ return {
153
+ globals,
154
+ command: { kind: "doctor" }
155
+ };
156
+ }
148
157
  if (rest[0] === "install") {
149
158
  return {
150
159
  globals,
@@ -0,0 +1,20 @@
1
+ import { execFileSync } from "node:child_process";
2
+ type CheckStatus = "ok" | "warning" | "error";
3
+ export interface DoctorCheck {
4
+ name: string;
5
+ status: CheckStatus;
6
+ message: string;
7
+ }
8
+ export interface DoctorResult {
9
+ status: CheckStatus;
10
+ checks: DoctorCheck[];
11
+ nextSteps: string[];
12
+ }
13
+ export interface DoctorOptions {
14
+ env?: NodeJS.ProcessEnv;
15
+ nodeVersion?: string;
16
+ execFileSyncImpl?: typeof execFileSync;
17
+ }
18
+ export declare function runDoctor(options?: DoctorOptions): DoctorResult;
19
+ export {};
20
+ //# sourceMappingURL=doctor.d.ts.map
package/dist/doctor.js ADDED
@@ -0,0 +1,92 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { readManagedPackageJson, resolveManagedPackageSpecifier } from "./managed-package.js";
3
+ function parseNodeMajor(version) {
4
+ const match = version.match(/^v?(\d+)/);
5
+ return match ? Number(match[1]) : 0;
6
+ }
7
+ function selectedProvider(env) {
8
+ return env.EMBEDDING_PROVIDER || "VoyageAI";
9
+ }
10
+ function requiredEmbeddingEnv(provider) {
11
+ switch (provider) {
12
+ case "OpenAI":
13
+ return "OPENAI_API_KEY";
14
+ case "VoyageAI":
15
+ return "VOYAGEAI_API_KEY";
16
+ case "Gemini":
17
+ return "GEMINI_API_KEY";
18
+ case "Ollama":
19
+ return null;
20
+ default:
21
+ return "VOYAGEAI_API_KEY";
22
+ }
23
+ }
24
+ function addCheck(checks, name, status, message) {
25
+ checks.push({ name, status, message });
26
+ }
27
+ function overallStatus(checks) {
28
+ if (checks.some((check) => check.status === "error")) {
29
+ return "error";
30
+ }
31
+ if (checks.some((check) => check.status === "warning")) {
32
+ return "warning";
33
+ }
34
+ return "ok";
35
+ }
36
+ export function runDoctor(options = {}) {
37
+ const env = options.env || process.env;
38
+ const nodeVersion = options.nodeVersion || process.version;
39
+ const execImpl = options.execFileSyncImpl || execFileSync;
40
+ const checks = [];
41
+ const nextSteps = [];
42
+ const nodeMajor = parseNodeMajor(nodeVersion);
43
+ if (nodeMajor >= 20) {
44
+ addCheck(checks, "node_version", "ok", `Node ${nodeVersion} satisfies >=20.`);
45
+ }
46
+ else {
47
+ addCheck(checks, "node_version", "error", `Node ${nodeVersion} is unsupported. Install Node.js 20 or newer.`);
48
+ nextSteps.push("Install Node.js 20 or newer.");
49
+ }
50
+ try {
51
+ const specifier = resolveManagedPackageSpecifier();
52
+ const pkg = readManagedPackageJson();
53
+ execImpl("npm", ["view", `${pkg.name}@${pkg.version}`, "version", "--json"], {
54
+ encoding: "utf8",
55
+ stdio: ["ignore", "pipe", "pipe"],
56
+ });
57
+ addCheck(checks, "npm_package_access", "ok", `${specifier} is visible to npm.`);
58
+ }
59
+ catch (error) {
60
+ const message = error instanceof Error ? error.message : String(error);
61
+ addCheck(checks, "npm_package_access", "warning", `Could not verify npm package access: ${message}`);
62
+ nextSteps.push("Verify npm can access @zokizuan/satori-mcp from this machine.");
63
+ }
64
+ const provider = selectedProvider(env);
65
+ const requiredKey = requiredEmbeddingEnv(provider);
66
+ if (requiredKey && !env[requiredKey]) {
67
+ addCheck(checks, "embedding_provider_env", "error", `${provider} requires ${requiredKey}.`);
68
+ nextSteps.push(`Set ${requiredKey}.`);
69
+ }
70
+ else {
71
+ addCheck(checks, "embedding_provider_env", "ok", requiredKey ? `${requiredKey} is present.` : `${provider} does not require an API key.`);
72
+ }
73
+ if (!env.MILVUS_ADDRESS) {
74
+ addCheck(checks, "milvus_address", "error", "MILVUS_ADDRESS is required for index/search/clear operations.");
75
+ nextSteps.push("Set MILVUS_ADDRESS.");
76
+ }
77
+ else {
78
+ addCheck(checks, "milvus_address", "ok", "MILVUS_ADDRESS is present.");
79
+ }
80
+ if (env.MILVUS_TOKEN) {
81
+ addCheck(checks, "milvus_token", "ok", "MILVUS_TOKEN is present.");
82
+ }
83
+ else {
84
+ addCheck(checks, "milvus_token", "ok", "MILVUS_TOKEN is not set; local/unauthenticated Milvus endpoints are supported.");
85
+ }
86
+ return {
87
+ status: overallStatus(checks),
88
+ checks,
89
+ nextSteps: [...new Set(nextSteps)],
90
+ };
91
+ }
92
+ //# sourceMappingURL=doctor.js.map
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import type { DoctorResult } from "./doctor.js";
2
3
  interface RunCliOptions {
3
4
  writeStdout?: (text: string) => void;
4
5
  writeStderr?: (text: string) => void;
@@ -11,6 +12,9 @@ interface RunCliOptions {
11
12
  callTimeoutMs?: number;
12
13
  cwd?: string;
13
14
  installabilityVerifier?: () => string | Promise<string>;
15
+ doctorRunner?: (options: {
16
+ env: NodeJS.ProcessEnv;
17
+ }) => DoctorResult;
14
18
  connectSession?: (options: {
15
19
  command: string;
16
20
  args: string[];
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ import { emitError, emitJson, inferManageStatusState, parseStructuredEnvelope }
9
9
  import { executeInstallCommand } from "./install.js";
10
10
  import { verifyManagedPackageInstallability } from "./package-installability.js";
11
11
  import { resolveServerEntryPath } from "./resolve-server-entry.js";
12
+ import { runDoctor } from "./doctor.js";
12
13
  const MANAGE_INDEX_MIN_POLL_TIMEOUT_MS = 10 * 60 * 1000;
13
14
  function firstText(result) {
14
15
  const content = result?.content;
@@ -46,6 +47,7 @@ function buildHelpPayload() {
46
47
  commands: [
47
48
  "install [--client all|codex|claude] [--dry-run]",
48
49
  "uninstall [--client all|codex|claude] [--dry-run]",
50
+ "doctor",
49
51
  "tools list",
50
52
  "tool call <toolName> --args-json '<json>'",
51
53
  "tool call <toolName> --args-file <path>",
@@ -195,6 +197,19 @@ export async function runCli(argv, options = {}) {
195
197
  }
196
198
  return 0;
197
199
  }
200
+ if (parsed.command.kind === "doctor") {
201
+ const result = (options.doctorRunner || ((doctorOptions) => runDoctor({ env: doctorOptions.env })))({
202
+ env: effectiveEnv,
203
+ });
204
+ emitJson(writers, result);
205
+ if (parsed.globals.format === "text") {
206
+ writers.writeStderr(`satori-cli doctor status=${result.status}.\n`);
207
+ for (const step of result.nextSteps) {
208
+ writers.writeStderr(`next: ${step}\n`);
209
+ }
210
+ }
211
+ return result.status === "error" ? 1 : 0;
212
+ }
198
213
  if (parsed.command.kind === "install" || parsed.command.kind === "uninstall") {
199
214
  if (parsed.command.kind === "install") {
200
215
  await (options.installabilityVerifier || verifyManagedPackageInstallability)();
@@ -54,7 +54,7 @@ function assertPublishedVersion(packageName, version, ownerPackageName, ownerPac
54
54
  stdio: ["ignore", "pipe", "pipe"],
55
55
  });
56
56
  }
57
- catch (error) {
57
+ catch {
58
58
  if (relation === "self") {
59
59
  throw new CliError("E_USAGE", `Cannot install ${ownerPackageName}@${ownerPackageVersion} because that package version is not published on npm. Publish ${ownerPackageName}@${ownerPackageVersion} first or use a local dev server config instead.`, 2);
60
60
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zokizuan/satori-cli",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "Shell CLI for Satori MCP installation and skill-based workflows",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "@modelcontextprotocol/sdk": "^1.12.1",
13
- "@zokizuan/satori-mcp": "4.4.1"
13
+ "@zokizuan/satori-mcp": "4.9.0"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@types/node": "^20.0.0",