@genspark/cli 1.0.1

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/client.js ADDED
@@ -0,0 +1,202 @@
1
+ /**
2
+ * API Client for Genspark Tool CLI
3
+ */
4
+ import { debug, info, error as logError } from "./logger.js";
5
+ /**
6
+ * Make an unauthenticated request to the backend.
7
+ * Used for device-flow auth endpoints that don't require an API key.
8
+ */
9
+ export async function unauthenticatedRequest(baseUrl, endpoint, method = "GET", body) {
10
+ const url = `${baseUrl.replace(/\/$/, "")}${endpoint}`;
11
+ debug(`Unauthenticated request: ${method} ${url}`);
12
+ const headers = {
13
+ "Content-Type": "application/json",
14
+ };
15
+ const response = await fetch(url, {
16
+ method,
17
+ headers,
18
+ body: body ? JSON.stringify(body) : undefined,
19
+ });
20
+ if (!response.ok) {
21
+ const errorText = await response.text();
22
+ throw new Error(`HTTP ${response.status}: ${errorText}`);
23
+ }
24
+ return (await response.json());
25
+ }
26
+ export class ApiClient {
27
+ baseUrl;
28
+ apiKey;
29
+ timeout;
30
+ debugMode;
31
+ projectId;
32
+ constructor(options) {
33
+ this.baseUrl = options.baseUrl.replace(/\/$/, "");
34
+ this.apiKey = options.apiKey || "";
35
+ this.timeout = options.timeout;
36
+ this.debugMode = options.debug;
37
+ this.projectId = options.projectId;
38
+ }
39
+ async request(endpoint, method = "GET", body) {
40
+ const url = `${this.baseUrl}/api/tool_cli${endpoint}`;
41
+ debug(`Request: ${method} ${url}`);
42
+ debug(`Project ID for header: ${this.projectId || "(not set)"}`);
43
+ if (body) {
44
+ debug(`Body: ${JSON.stringify(body)}`);
45
+ }
46
+ const headers = {
47
+ "Content-Type": "application/json",
48
+ };
49
+ if (this.apiKey) {
50
+ headers["X-Api-Key"] = this.apiKey;
51
+ }
52
+ // Add project ID header for sandbox lookup when sandbox_id is not provided
53
+ if (this.projectId) {
54
+ headers["X-Project-ID"] = this.projectId;
55
+ }
56
+ // Add debug header to request more details from server
57
+ if (this.debugMode) {
58
+ headers["X-Debug"] = "true";
59
+ }
60
+ const controller = new AbortController();
61
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
62
+ try {
63
+ info(`Calling ${endpoint}...`);
64
+ const response = await fetch(url, {
65
+ method,
66
+ headers,
67
+ body: body ? JSON.stringify(body) : undefined,
68
+ signal: controller.signal,
69
+ });
70
+ clearTimeout(timeoutId);
71
+ debug(`Response status: ${response.status}`);
72
+ if (!response.ok) {
73
+ const errorText = await response.text();
74
+ debug(`Error response: ${errorText}`);
75
+ return {
76
+ status: "error",
77
+ message: `HTTP ${response.status}: ${response.statusText}`,
78
+ data: null,
79
+ };
80
+ }
81
+ // Handle streaming NDJSON response (Protocol v1)
82
+ // Server sends newline-delimited JSON with version field:
83
+ // - Debug/heartbeat messages: {"version": 1, "debug": true, "message": "..."}
84
+ // - Final result: {"version": 1, "status": "ok"|"error", "message": "...", "data": {...}}
85
+ //
86
+ // Protocol compatibility:
87
+ // - CLI ignores messages with version > SUPPORTED_VERSION (forward compatibility)
88
+ // - Messages without version field are treated as version 1
89
+ const SUPPORTED_VERSION = 1;
90
+ const text = await response.text();
91
+ debug(`Raw response length: ${text.length}`);
92
+ const lines = text.trim().split("\n");
93
+ let finalResult = null;
94
+ for (const rawLine of lines) {
95
+ const line = rawLine.trim();
96
+ if (!line || !line.startsWith("{")) {
97
+ continue;
98
+ }
99
+ try {
100
+ const parsed = JSON.parse(line);
101
+ // Check protocol version - ignore messages from future versions
102
+ const messageVersion = parsed.version ?? 1;
103
+ if (messageVersion > SUPPORTED_VERSION) {
104
+ debug(`Ignoring message with version ${messageVersion} (supported: ${SUPPORTED_VERSION})`);
105
+ continue;
106
+ }
107
+ // Check if it's a debug/heartbeat message
108
+ if (parsed.debug === true) {
109
+ // Only output debug messages to stderr when --debug is enabled
110
+ if (this.debugMode) {
111
+ debug(`[Server] ${parsed.message}`);
112
+ // Output additional debug info if present
113
+ if (parsed.tool) {
114
+ debug(` Tool: ${parsed.tool}`);
115
+ }
116
+ if (parsed.arguments) {
117
+ debug(` Arguments: ${JSON.stringify(parsed.arguments)}`);
118
+ }
119
+ if (parsed.heartbeat) {
120
+ debug(` Heartbeat #${parsed.heartbeat}`);
121
+ }
122
+ if (parsed.elapsed_seconds !== undefined) {
123
+ debug(` Elapsed: ${parsed.elapsed_seconds}s`);
124
+ }
125
+ }
126
+ }
127
+ else {
128
+ // This is the final result (has status field, no debug field)
129
+ finalResult = parsed;
130
+ }
131
+ }
132
+ catch {
133
+ // Skip malformed JSON lines
134
+ debug(`Skipping malformed JSON line: ${line.substring(0, 100)}`);
135
+ }
136
+ }
137
+ if (!finalResult) {
138
+ return {
139
+ status: "error",
140
+ message: "No valid result found in response",
141
+ data: null,
142
+ };
143
+ }
144
+ debug(`Final result status: ${finalResult.status}`);
145
+ return finalResult;
146
+ }
147
+ catch (err) {
148
+ clearTimeout(timeoutId);
149
+ if (err instanceof Error) {
150
+ if (err.name === "AbortError") {
151
+ logError(`Request timeout after ${this.timeout}ms`);
152
+ return {
153
+ status: "error",
154
+ message: `Request timeout after ${this.timeout}ms`,
155
+ data: null,
156
+ };
157
+ }
158
+ logError(`Request failed: ${err.message}`);
159
+ return {
160
+ status: "error",
161
+ message: err.message,
162
+ data: null,
163
+ };
164
+ }
165
+ return {
166
+ status: "error",
167
+ message: "Unknown error",
168
+ data: null,
169
+ };
170
+ }
171
+ }
172
+ /**
173
+ * List available tools with full schemas
174
+ */
175
+ async listTools() {
176
+ const response = await this.request("/tools", "GET");
177
+ if (response.status === "error") {
178
+ throw new Error(response.message);
179
+ }
180
+ // The /tools endpoint returns the data directly, not wrapped in ApiResponse
181
+ return response;
182
+ }
183
+ /**
184
+ * Execute any tool by name with arguments
185
+ */
186
+ async executeTool(toolName, args) {
187
+ return this.request(`/${toolName}`, "POST", args);
188
+ }
189
+ /**
190
+ * Get a pre-signed URL for uploading a file
191
+ */
192
+ async getUploadUrl(params) {
193
+ return this.request("/file/upload_url", "POST", params);
194
+ }
195
+ /**
196
+ * Get a downloadable URL for a file wrapper URL
197
+ */
198
+ async getDownloadUrl(params) {
199
+ return this.request("/file/download", "POST", params);
200
+ }
201
+ }
202
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Configuration loader for Genspark Tool CLI
3
+ *
4
+ * Loads configuration from multiple sources with the following priority (highest to lowest):
5
+ * 1. Command-line options
6
+ * 2. Environment variables (GSK_API_KEY, GSK_BASE_URL)
7
+ * 3. Config file (~/.genspark-tool-cli/config.json)
8
+ */
9
+ import type { ToolSchema } from "./types.js";
10
+ export interface ConfigFile {
11
+ api_key?: string;
12
+ base_url?: string;
13
+ timeout?: number;
14
+ debug?: boolean;
15
+ project_id?: string;
16
+ auto_update?: boolean;
17
+ }
18
+ /**
19
+ * Get the path to the config file
20
+ */
21
+ export declare function getConfigPath(): string;
22
+ /**
23
+ * Load configuration from the config file
24
+ * Returns an empty object if the file doesn't exist or is invalid
25
+ */
26
+ export declare function loadConfigFile(): ConfigFile;
27
+ /**
28
+ * Save configuration to the config file
29
+ */
30
+ export declare function saveConfigFile(config: ConfigFile): void;
31
+ /**
32
+ * Load tools from the cache file.
33
+ * Returns null if cache doesn't exist, is stale (>24h), or base_url doesn't match.
34
+ */
35
+ export declare function loadToolsCache(baseUrl: string): ToolSchema[] | null;
36
+ /**
37
+ * Save tools to the cache file.
38
+ */
39
+ export declare function saveToolsCache(baseUrl: string, tools: ToolSchema[]): void;
40
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAoBD;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,UAAU,CA6B3C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAUvD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,GAAG,IAAI,CA+BnE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,IAAI,CAezE"}
package/dist/config.js ADDED
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Configuration loader for Genspark Tool CLI
3
+ *
4
+ * Loads configuration from multiple sources with the following priority (highest to lowest):
5
+ * 1. Command-line options
6
+ * 2. Environment variables (GSK_API_KEY, GSK_BASE_URL)
7
+ * 3. Config file (~/.genspark-tool-cli/config.json)
8
+ */
9
+ import * as fs from "fs";
10
+ import * as path from "path";
11
+ import * as os from "os";
12
+ const CONFIG_DIR = ".genspark-tool-cli";
13
+ const CONFIG_FILE = "config.json";
14
+ const TOOLS_CACHE_FILE = "tools-cache.json";
15
+ const CACHE_MAX_AGE_MS = 24 * 60 * 60 * 1000; // 24 hours
16
+ /**
17
+ * Get the config directory path
18
+ */
19
+ function getConfigDir() {
20
+ return path.join(os.homedir(), CONFIG_DIR);
21
+ }
22
+ /**
23
+ * Get the path to the config file
24
+ */
25
+ export function getConfigPath() {
26
+ return path.join(getConfigDir(), CONFIG_FILE);
27
+ }
28
+ /**
29
+ * Load configuration from the config file
30
+ * Returns an empty object if the file doesn't exist or is invalid
31
+ */
32
+ export function loadConfigFile() {
33
+ const configPath = getConfigPath();
34
+ try {
35
+ if (!fs.existsSync(configPath)) {
36
+ return {};
37
+ }
38
+ const content = fs.readFileSync(configPath, "utf-8");
39
+ const config = JSON.parse(content);
40
+ // Validate and return only known fields
41
+ return {
42
+ api_key: typeof config.api_key === "string" ? config.api_key : undefined,
43
+ base_url: typeof config.base_url === "string" ? config.base_url : undefined,
44
+ timeout: typeof config.timeout === "number" ? config.timeout : undefined,
45
+ debug: typeof config.debug === "boolean" ? config.debug : undefined,
46
+ project_id: typeof config.project_id === "string" ? config.project_id : undefined,
47
+ auto_update: typeof config.auto_update === "boolean"
48
+ ? config.auto_update
49
+ : undefined,
50
+ };
51
+ }
52
+ catch {
53
+ // Silently ignore errors (file not found, invalid JSON, etc.)
54
+ return {};
55
+ }
56
+ }
57
+ /**
58
+ * Save configuration to the config file
59
+ */
60
+ export function saveConfigFile(config) {
61
+ const configDir = getConfigDir();
62
+ const configPath = path.join(configDir, CONFIG_FILE);
63
+ // Create config directory if it doesn't exist
64
+ if (!fs.existsSync(configDir)) {
65
+ fs.mkdirSync(configDir, { recursive: true });
66
+ }
67
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
68
+ }
69
+ /**
70
+ * Load tools from the cache file.
71
+ * Returns null if cache doesn't exist, is stale (>24h), or base_url doesn't match.
72
+ */
73
+ export function loadToolsCache(baseUrl) {
74
+ const cachePath = path.join(getConfigDir(), TOOLS_CACHE_FILE);
75
+ try {
76
+ if (!fs.existsSync(cachePath)) {
77
+ return null;
78
+ }
79
+ const content = fs.readFileSync(cachePath, "utf-8");
80
+ const cache = JSON.parse(content);
81
+ // Validate base_url matches
82
+ if (cache.base_url !== baseUrl) {
83
+ return null;
84
+ }
85
+ // Check age (treat invalid timestamps as stale)
86
+ const fetchedAt = new Date(cache.fetched_at).getTime();
87
+ if (isNaN(fetchedAt) || Date.now() - fetchedAt > CACHE_MAX_AGE_MS) {
88
+ return null;
89
+ }
90
+ // Validate tools array
91
+ if (!Array.isArray(cache.tools) || cache.tools.length === 0) {
92
+ return null;
93
+ }
94
+ return cache.tools;
95
+ }
96
+ catch {
97
+ return null;
98
+ }
99
+ }
100
+ /**
101
+ * Save tools to the cache file.
102
+ */
103
+ export function saveToolsCache(baseUrl, tools) {
104
+ const configDir = getConfigDir();
105
+ const cachePath = path.join(configDir, TOOLS_CACHE_FILE);
106
+ if (!fs.existsSync(configDir)) {
107
+ fs.mkdirSync(configDir, { recursive: true });
108
+ }
109
+ const cache = {
110
+ fetched_at: new Date().toISOString(),
111
+ base_url: baseUrl,
112
+ tools,
113
+ };
114
+ fs.writeFileSync(cachePath, JSON.stringify(cache, null, 2), "utf-8");
115
+ }
116
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Generic JSON-to-text formatter for --output text mode.
3
+ * No per-tool special cases — just walks the data structure:
4
+ * - string/number/boolean → as-is
5
+ * - array → numbered list
6
+ * - object → key: value pairs
7
+ */
8
+ /**
9
+ * Convert API response data to human-readable text.
10
+ * Unwraps { status, message, data } envelope if present.
11
+ */
12
+ export declare function formatAsMarkdown(data: unknown): string;
13
+ //# sourceMappingURL=formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../src/formatter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA8CH;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAetD"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Generic JSON-to-text formatter for --output text mode.
3
+ * No per-tool special cases — just walks the data structure:
4
+ * - string/number/boolean → as-is
5
+ * - array → numbered list
6
+ * - object → key: value pairs
7
+ */
8
+ function formatValue(data, indent = 0) {
9
+ if (data === null || data === undefined)
10
+ return "";
11
+ if (typeof data === "string")
12
+ return data;
13
+ if (typeof data === "number" || typeof data === "boolean")
14
+ return String(data);
15
+ const pad = " ".repeat(indent);
16
+ if (Array.isArray(data)) {
17
+ if (data.length === 0)
18
+ return "(empty)";
19
+ return data
20
+ .map((item, i) => {
21
+ const formatted = formatValue(item, indent + 1);
22
+ // For objects in arrays, put first line on same line as number, rest indented
23
+ if (typeof item === "object" && item !== null && !Array.isArray(item)) {
24
+ const lines = formatted.split("\n");
25
+ if (lines.length <= 1) {
26
+ return `${pad}${i + 1}. ${lines[0]}`;
27
+ }
28
+ return `${pad}${i + 1}. ${lines[0]}\n${lines.slice(1).join("\n")}`;
29
+ }
30
+ return `${pad}${i + 1}. ${formatted}`;
31
+ })
32
+ .join("\n");
33
+ }
34
+ if (typeof data === "object") {
35
+ const obj = data;
36
+ const entries = Object.entries(obj).filter(([, v]) => v !== null && v !== undefined);
37
+ if (entries.length === 0)
38
+ return "(empty)";
39
+ return entries
40
+ .map(([k, v]) => {
41
+ if (typeof v === "object") {
42
+ return `${pad}${k}:\n${formatValue(v, indent + 1)}`;
43
+ }
44
+ return `${pad}${k}: ${String(v)}`;
45
+ })
46
+ .join("\n");
47
+ }
48
+ return String(data);
49
+ }
50
+ /**
51
+ * Convert API response data to human-readable text.
52
+ * Unwraps { status, message, data } envelope if present.
53
+ */
54
+ export function formatAsMarkdown(data) {
55
+ if (data === null || data === undefined)
56
+ return "";
57
+ if (typeof data !== "object")
58
+ return String(data);
59
+ const obj = data;
60
+ // Error envelope
61
+ if (obj.status === "error") {
62
+ return `Error: ${obj.message || "Unknown error"}`;
63
+ }
64
+ // Unwrap ApiResponse { status: "ok", data: ... }
65
+ const inner = obj.status === "ok" && "data" in obj ? obj.data : data;
66
+ return formatValue(inner, 0);
67
+ }
68
+ //# sourceMappingURL=formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.js","sourceRoot":"","sources":["../src/formatter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Genspark Tool CLI
4
+ *
5
+ * A command-line interface for Genspark Tool API.
6
+ * Designed for integration with AI agents (e.g., Claude Code).
7
+ *
8
+ * Output conventions:
9
+ * - stderr: Debug info, progress, errors (for human reading)
10
+ * - stdout: API response JSON (for AI agent context)
11
+ *
12
+ * Command Naming Convention:
13
+ * - CLI commands are dynamically generated from server tool schemas
14
+ * - Tool name is always the canonical command name
15
+ * - Aliases provide human-friendly shortcuts (e.g., `search` for `web_search`)
16
+ *
17
+ * Example:
18
+ * Tool name: "web_search" -> Command: `gsk web_search`, Alias: `gsk search`
19
+ * Tool name: "crawler" -> Command: `gsk crawler`, Alias: `gsk crawl`
20
+ */
21
+ export {};
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;GAkBG"}