@genspark/cli 1.4.1 → 1.5.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 +23 -1
- package/dist/config.d.ts +11 -8
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +100 -13
- package/dist/config.js.map +1 -1
- package/dist/index.js +91 -27
- package/dist/index.js.map +1 -1
- package/dist/localFiles.d.ts +62 -0
- package/dist/localFiles.d.ts.map +1 -0
- package/dist/localFiles.js +130 -0
- package/dist/localFiles.js.map +1 -0
- package/dist/logger.d.ts +8 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +13 -0
- package/dist/logger.js.map +1 -1
- package/dist/mesh/checkupdate.js +3 -3
- package/dist/mesh/checkupdate.js.map +1 -1
- package/dist/runtime.d.ts +44 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +62 -0
- package/dist/runtime.js.map +1 -0
- package/dist/updater.d.ts +1 -0
- package/dist/updater.d.ts.map +1 -1
- package/dist/updater.js +10 -0
- package/dist/updater.js.map +1 -1
- package/docs/skills.md +20 -20
- package/package.json +1 -1
- package/skills/gsk-analyze-media/SKILL.md +2 -1
- package/skills/gsk-audio-generation/SKILL.md +1 -1
- package/skills/gsk-connector/SKILL.md +52 -0
- package/skills/gsk-github/SKILL.md +2 -0
- package/skills/gsk-gmail/SKILL.md +2 -0
- package/skills/gsk-google-calendar/SKILL.md +4 -1
- package/skills/gsk-google-chat/SKILL.md +4 -1
- package/skills/gsk-google-contacts/SKILL.md +2 -0
- package/skills/gsk-google-docs/SKILL.md +2 -0
- package/skills/gsk-google-drive/SKILL.md +3 -0
- package/skills/gsk-google-sheets/SKILL.md +4 -2
- package/skills/gsk-hub/SKILL.md +15 -5
- package/skills/gsk-image-generation/SKILL.md +2 -2
- package/skills/gsk-microsoft-teams/SKILL.md +4 -2
- package/skills/gsk-notion/SKILL.md +2 -0
- package/skills/gsk-onedrive/SKILL.md +3 -0
- package/skills/gsk-outlook-calendar/SKILL.md +3 -1
- package/skills/gsk-outlook-contacts/SKILL.md +2 -0
- package/skills/gsk-outlook-email/SKILL.md +3 -10
- package/skills/gsk-salesforce/SKILL.md +2 -0
- package/skills/gsk-shared/SKILL.md +12 -1
- package/skills/gsk-sharepoint/SKILL.md +3 -0
- package/skills/gsk-sharepoint-upload/SKILL.md +2 -0
- package/skills/gsk-slack/SKILL.md +12 -7
- package/skills/gsk-task-continue/SKILL.md +4 -3
- package/skills/gsk-video-generation/SKILL.md +8 -7
package/README.md
CHANGED
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
- [Media Analysis & Transcription](#media-analysis--transcription)
|
|
42
42
|
- [AI Drive (Cloud Storage)](#ai-drive-cloud-storage)
|
|
43
43
|
- [AI Agents & Tasks](#ai-agents--tasks)
|
|
44
|
+
- [Connectors (Unified)](#connectors-unified)
|
|
44
45
|
- [Service-Level Tools](#service-level-tools)
|
|
45
46
|
- [AI Phone Calls](#ai-phone-calls)
|
|
46
47
|
- [Stock Prices](#stock-prices)
|
|
@@ -84,7 +85,10 @@ Log in with your Genspark account:
|
|
|
84
85
|
gsk login
|
|
85
86
|
```
|
|
86
87
|
|
|
87
|
-
This opens a browser for authentication and saves the API key
|
|
88
|
+
This opens a browser for authentication and saves the API key plus the effective
|
|
89
|
+
API base URL to the selected config. The default is
|
|
90
|
+
`~/.genspark-tool-cli/config.json`; use `--config <path>` or `GSK_CONFIG` for a
|
|
91
|
+
separate profile.
|
|
88
92
|
|
|
89
93
|
Alternatively, provide an API key directly:
|
|
90
94
|
|
|
@@ -138,6 +142,7 @@ Config is loaded from three sources (highest priority first):
|
|
|
138
142
|
| `--timeout <ms>` | — | `300000` (5 min) | Request timeout |
|
|
139
143
|
| `--output <format>` | — | `json` | Output format: `json` or `text` |
|
|
140
144
|
| `--refresh` | — | — | Force refresh cached tool schemas |
|
|
145
|
+
| `--config <path>` | `GSK_CONFIG` | `~/.genspark-tool-cli/config.json` | Config profile path |
|
|
141
146
|
|
|
142
147
|
## Commands
|
|
143
148
|
|
|
@@ -526,10 +531,27 @@ gsk stock AAPL
|
|
|
526
531
|
gsk stock MSFT
|
|
527
532
|
```
|
|
528
533
|
|
|
534
|
+
### Connectors (unified)
|
|
535
|
+
|
|
536
|
+
One fixed flow discovers and invokes **any** connector — Gmail, Slack, Notion, HubSpot, custom MCP servers, and every connector added after this README was written:
|
|
537
|
+
|
|
538
|
+
```bash
|
|
539
|
+
gsk connector list # what is already connected?
|
|
540
|
+
gsk connector search <keyword> # does a connector for X exist?
|
|
541
|
+
gsk connector tools <identifier> # full JSON schema per tool
|
|
542
|
+
gsk connector call <identifier> -t <tool> -a '<json>' # invoke it
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
`<identifier>` accepts a connector id (`gmail`, `slack`, `hubspot`), a display name (`"Google Drive"`), or an MCP slug. Prefer this over the per-service commands below — see `skills/gsk-connector/SKILL.md` for the full flow, error codes, and examples.
|
|
546
|
+
|
|
547
|
+
> **Requirements:** Connect services in [Genspark Account Settings → Integrations](https://www.genspark.ai/settings/integrations).
|
|
548
|
+
|
|
529
549
|
### Service-Level Tools
|
|
530
550
|
|
|
531
551
|
External service integrations are available as **service-level tools** — each service is a single command with an `action` parameter that dispatches to the underlying operation.
|
|
532
552
|
|
|
553
|
+
> **Deprecated but working:** these per-service commands still work and are documented below for reference, but new integrations only ship in the unified `gsk connector` flow above — prefer that for anything new.
|
|
554
|
+
|
|
533
555
|
> **Requirements:** Connect services in [Genspark Account Settings → Integrations](https://www.genspark.ai/settings/integrations).
|
|
534
556
|
|
|
535
557
|
#### gmail
|
package/dist/config.d.ts
CHANGED
|
@@ -34,23 +34,26 @@ export declare function setConfigPathOverride(absPath: string | undefined): void
|
|
|
34
34
|
* Get the path to the config file — honours a `--config` override.
|
|
35
35
|
*/
|
|
36
36
|
export declare function getConfigPath(): string;
|
|
37
|
+
/**
|
|
38
|
+
* Keep one canonical spelling for endpoint persistence and cache keys.
|
|
39
|
+
*/
|
|
40
|
+
export declare function normalizeBaseUrl(baseUrl: string): string;
|
|
37
41
|
/**
|
|
38
42
|
* Load configuration from the config file
|
|
39
43
|
* Returns an empty object if the file doesn't exist or is invalid
|
|
40
44
|
*/
|
|
41
45
|
export declare function loadConfigFile(): ConfigFile;
|
|
42
46
|
/**
|
|
43
|
-
*
|
|
47
|
+
* Replace the selected config file.
|
|
44
48
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* `--config /tmp/my-profile.json` is active, the write lands on
|
|
48
|
-
* `/tmp/my-profile.json`, not `/tmp/config.json`. Using the raw
|
|
49
|
-
* `CONFIG_FILE` constant here would make `login`/`logout` silently write
|
|
50
|
-
* to the wrong file while reads still target the override — a
|
|
51
|
-
* split-brain state.
|
|
49
|
+
* Prefer `updateConfigFile` for login/logout-style field changes because this
|
|
50
|
+
* replacement API intentionally cannot preserve fields absent from `config`.
|
|
52
51
|
*/
|
|
53
52
|
export declare function saveConfigFile(config: ConfigFile): void;
|
|
53
|
+
/**
|
|
54
|
+
* Patch known fields in the selected config without dropping extension fields.
|
|
55
|
+
*/
|
|
56
|
+
export declare function updateConfigFile(updates: Partial<ConfigFile>, removeKeys?: (keyof ConfigFile)[]): void;
|
|
54
57
|
/**
|
|
55
58
|
* Load tools from the cache file.
|
|
56
59
|
* Returns null if cache doesn't exist, is stale (>24h), or base_url doesn't match.
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAYD,eAAO,MAAM,YAAY,+BAA+B,CAAA;AA+BxD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEvE;AAYD;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAKtC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,UAAU,CAiC3C;AAmFD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAEvD;AAuBD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,EAC5B,UAAU,GAAE,CAAC,MAAM,UAAU,CAAC,EAAO,GACpC,IAAI,CASN;AA8BD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,GAAG,IAAI,CAyCnE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,IAAI,CAmBzE"}
|
package/dist/config.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import * as fs from 'fs';
|
|
10
10
|
import * as path from 'path';
|
|
11
11
|
import * as os from 'os';
|
|
12
|
+
import { randomUUID } from 'crypto';
|
|
12
13
|
// Capability string sent on every request (X-GSK-CLI-Caps) and stamped into
|
|
13
14
|
// the tools cache. The server tailors /tools CLI metadata to it (grouped
|
|
14
15
|
// phone-call view vs the flat legacy view), so a cache written by a CLI with
|
|
@@ -66,6 +67,12 @@ export function getConfigPath() {
|
|
|
66
67
|
}
|
|
67
68
|
return path.join(getConfigDir(), CONFIG_FILE);
|
|
68
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Keep one canonical spelling for endpoint persistence and cache keys.
|
|
72
|
+
*/
|
|
73
|
+
export function normalizeBaseUrl(baseUrl) {
|
|
74
|
+
return baseUrl.trim().replace(/\/+$/, '');
|
|
75
|
+
}
|
|
69
76
|
/**
|
|
70
77
|
* Load configuration from the config file
|
|
71
78
|
* Returns an empty object if the file doesn't exist or is invalid
|
|
@@ -99,23 +106,101 @@ export function loadConfigFile() {
|
|
|
99
106
|
}
|
|
100
107
|
}
|
|
101
108
|
/**
|
|
102
|
-
*
|
|
109
|
+
* Write a complete configuration object atomically with private permissions.
|
|
110
|
+
*
|
|
111
|
+
* The temporary file lives beside the destination so rename is atomic. Its
|
|
112
|
+
* mode is fixed before rename, so an API key is never exposed through the
|
|
113
|
+
* process umask or a partially written destination.
|
|
114
|
+
*/
|
|
115
|
+
function resolveConfigWriteTarget(configPath, visited = new Set()) {
|
|
116
|
+
const absolutePath = path.resolve(configPath);
|
|
117
|
+
if (visited.has(absolutePath)) {
|
|
118
|
+
throw new Error(`Cannot update config through symlink cycle at ${configPath}`);
|
|
119
|
+
}
|
|
120
|
+
let stats;
|
|
121
|
+
try {
|
|
122
|
+
stats = fs.lstatSync(absolutePath);
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
if (err.code === 'ENOENT') {
|
|
126
|
+
return absolutePath;
|
|
127
|
+
}
|
|
128
|
+
throw err;
|
|
129
|
+
}
|
|
130
|
+
if (!stats.isSymbolicLink()) {
|
|
131
|
+
return absolutePath;
|
|
132
|
+
}
|
|
133
|
+
visited.add(absolutePath);
|
|
134
|
+
const linkTarget = fs.readlinkSync(absolutePath);
|
|
135
|
+
return resolveConfigWriteTarget(path.resolve(path.dirname(absolutePath), linkTarget), visited);
|
|
136
|
+
}
|
|
137
|
+
function writeConfigFileAtomic(configPath, config) {
|
|
138
|
+
const targetPath = resolveConfigWriteTarget(configPath);
|
|
139
|
+
const configDir = path.dirname(targetPath);
|
|
140
|
+
fs.mkdirSync(configDir, { recursive: true, mode: 0o700 });
|
|
141
|
+
const tempPath = path.join(configDir, `.${path.basename(targetPath)}.${process.pid}.${randomUUID()}.tmp`);
|
|
142
|
+
let fileDescriptor;
|
|
143
|
+
try {
|
|
144
|
+
fileDescriptor = fs.openSync(tempPath, 'wx', 0o600);
|
|
145
|
+
fs.writeFileSync(fileDescriptor, `${JSON.stringify(config, null, 2)}\n`, 'utf-8');
|
|
146
|
+
fs.fsyncSync(fileDescriptor);
|
|
147
|
+
if (process.platform !== 'win32') {
|
|
148
|
+
fs.fchmodSync(fileDescriptor, 0o600);
|
|
149
|
+
}
|
|
150
|
+
fs.closeSync(fileDescriptor);
|
|
151
|
+
fileDescriptor = undefined;
|
|
152
|
+
fs.renameSync(tempPath, targetPath);
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
if (fileDescriptor !== undefined) {
|
|
156
|
+
fs.closeSync(fileDescriptor);
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
fs.unlinkSync(tempPath);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// The file may not have been created or may already have been renamed.
|
|
163
|
+
}
|
|
164
|
+
throw err;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Replace the selected config file.
|
|
103
169
|
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* `--config /tmp/my-profile.json` is active, the write lands on
|
|
107
|
-
* `/tmp/my-profile.json`, not `/tmp/config.json`. Using the raw
|
|
108
|
-
* `CONFIG_FILE` constant here would make `login`/`logout` silently write
|
|
109
|
-
* to the wrong file while reads still target the override — a
|
|
110
|
-
* split-brain state.
|
|
170
|
+
* Prefer `updateConfigFile` for login/logout-style field changes because this
|
|
171
|
+
* replacement API intentionally cannot preserve fields absent from `config`.
|
|
111
172
|
*/
|
|
112
173
|
export function saveConfigFile(config) {
|
|
174
|
+
writeConfigFileAtomic(getConfigPath(), { ...config });
|
|
175
|
+
}
|
|
176
|
+
function loadConfigObjectForUpdate(configPath) {
|
|
177
|
+
if (!fs.existsSync(configPath)) {
|
|
178
|
+
return {};
|
|
179
|
+
}
|
|
180
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
181
|
+
let parsed;
|
|
182
|
+
try {
|
|
183
|
+
parsed = JSON.parse(content);
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
throw new Error(`Cannot update invalid config JSON at ${configPath}`);
|
|
187
|
+
}
|
|
188
|
+
if (parsed === null || Array.isArray(parsed) || typeof parsed !== 'object') {
|
|
189
|
+
throw new Error(`Cannot update invalid config object at ${configPath}`);
|
|
190
|
+
}
|
|
191
|
+
return parsed;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Patch known fields in the selected config without dropping extension fields.
|
|
195
|
+
*/
|
|
196
|
+
export function updateConfigFile(updates, removeKeys = []) {
|
|
113
197
|
const configPath = getConfigPath();
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
198
|
+
const config = loadConfigObjectForUpdate(configPath);
|
|
199
|
+
for (const key of removeKeys) {
|
|
200
|
+
delete config[key];
|
|
117
201
|
}
|
|
118
|
-
|
|
202
|
+
Object.assign(config, updates);
|
|
203
|
+
writeConfigFileAtomic(configPath, config);
|
|
119
204
|
}
|
|
120
205
|
/**
|
|
121
206
|
* Delete a legacy `tools-cache.json` that was written by a caps-bearing CLI
|
|
@@ -132,7 +217,9 @@ function healPoisonedLegacyCache() {
|
|
|
132
217
|
return;
|
|
133
218
|
}
|
|
134
219
|
const legacy = JSON.parse(fs.readFileSync(legacyPath, 'utf-8'));
|
|
135
|
-
if (legacy &&
|
|
220
|
+
if (legacy &&
|
|
221
|
+
typeof legacy === 'object' &&
|
|
222
|
+
typeof legacy.caps === 'string') {
|
|
136
223
|
fs.unlinkSync(legacyPath);
|
|
137
224
|
}
|
|
138
225
|
}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -27,12 +27,14 @@ import * as pathModule from 'path';
|
|
|
27
27
|
import { createRequire } from 'module';
|
|
28
28
|
import { spawn } from 'child_process';
|
|
29
29
|
import { ApiClient, unauthenticatedRequest } from './client.js';
|
|
30
|
+
import { classifyFileArg, awaitLocalFileReady, decideAfterWait, localFileNotReadyError, } from './localFiles.js';
|
|
30
31
|
import { setDebugEnabled, setOutputFormat, debug, info, error as logError, output, } from './logger.js';
|
|
31
|
-
import { loadConfigFile,
|
|
32
|
+
import { loadConfigFile, getConfigPath, loadToolsCache, normalizeBaseUrl, saveToolsCache, setConfigPathOverride, updateConfigFile, } from './config.js';
|
|
32
33
|
import { checkForUpdates } from './updater.js';
|
|
34
|
+
import { getSandboxRuntime } from './runtime.js';
|
|
33
35
|
import { registerDesignCommand } from './commands/design.js';
|
|
34
36
|
import { pickExistingFileOperand } from './commands/aidrive-upload.js';
|
|
35
|
-
import { parseLastSeenIndex, eventStdoutLine
|
|
37
|
+
import { parseLastSeenIndex, eventStdoutLine } from './commands/chat-events.js';
|
|
36
38
|
import { mediaItemsKeyFor, mediaSummaryLines } from './mediaSummary.js';
|
|
37
39
|
import { registerMeshCommand, getMeshInvocation, runMesh, } from './commands/mesh.js';
|
|
38
40
|
import { executeCloneUrl, normalizeCloneUrlForGit, } from './commands/sb-git-clone.js';
|
|
@@ -104,9 +106,13 @@ function getGlobalOptions() {
|
|
|
104
106
|
// API key priority: CLI > env > config file
|
|
105
107
|
const apiKey = opts.apiKey || process.env.GSK_API_KEY || fileConfig.api_key;
|
|
106
108
|
// Base URL priority: CLI > env > config file > default
|
|
107
|
-
const
|
|
109
|
+
const explicitBaseUrl = program.getOptionValueSource('baseUrl') === 'cli'
|
|
108
110
|
? opts.baseUrl
|
|
109
|
-
:
|
|
111
|
+
: undefined;
|
|
112
|
+
const baseUrl = normalizeBaseUrl(explicitBaseUrl ||
|
|
113
|
+
process.env.GSK_BASE_URL ||
|
|
114
|
+
fileConfig.base_url ||
|
|
115
|
+
DEFAULT_BASE_URL);
|
|
110
116
|
// Timeout priority: CLI > config file > default
|
|
111
117
|
const timeout = opts.timeout !== String(DEFAULT_TIMEOUT)
|
|
112
118
|
? parseInt(opts.timeout, 10)
|
|
@@ -338,9 +344,27 @@ function isLocalFilePath(value) {
|
|
|
338
344
|
fs.existsSync(value));
|
|
339
345
|
}
|
|
340
346
|
async function resolveFileArg(value, client) {
|
|
341
|
-
|
|
347
|
+
// Classify the RAW value: a leading '~' is positive local evidence and must
|
|
348
|
+
// hit classifyFileArg's relative-marker branch before any expansion.
|
|
349
|
+
const kind = classifyFileArg(value);
|
|
350
|
+
if (kind === 'remote' || kind === 'aidrive')
|
|
342
351
|
return value;
|
|
343
|
-
|
|
352
|
+
// fs never expands '~' — expand only for the filesystem operations below.
|
|
353
|
+
const localPath = expandHome(value);
|
|
354
|
+
// Tolerate the same-batch create-then-read race (a parallel sibling tool
|
|
355
|
+
// call may still be writing the file) before deciding what the arg is.
|
|
356
|
+
const readiness = await awaitLocalFileReady(localPath);
|
|
357
|
+
switch (decideAfterWait(kind, readiness)) {
|
|
358
|
+
case 'upload':
|
|
359
|
+
return await uploadLocalFile(localPath, client);
|
|
360
|
+
case 'error':
|
|
361
|
+
throw new Error(localFileNotReadyError(localPath, readiness));
|
|
362
|
+
case 'passthrough':
|
|
363
|
+
// No local evidence beyond the parent directory: let the backend try
|
|
364
|
+
// it as an AI Drive path (its failure mode is a per-URL actionable
|
|
365
|
+
// error, not a generic one).
|
|
366
|
+
return value;
|
|
367
|
+
}
|
|
344
368
|
}
|
|
345
369
|
/**
|
|
346
370
|
* Inline-base64 transport limit for email `attachments`. Anything larger
|
|
@@ -547,7 +571,9 @@ function registerToolCommand(parentProgram, tool, clientFactory, vdProjectIdDefa
|
|
|
547
571
|
const prefix = groupName + '_';
|
|
548
572
|
cmdName =
|
|
549
573
|
tool.cli.subcommand ||
|
|
550
|
-
(tool.name.startsWith(prefix)
|
|
574
|
+
(tool.name.startsWith(prefix)
|
|
575
|
+
? tool.name.slice(prefix.length)
|
|
576
|
+
: tool.name);
|
|
551
577
|
}
|
|
552
578
|
const cmd = targetProgram
|
|
553
579
|
.command(cmdName, cmdOpts?.hidden ? { hidden: true } : {})
|
|
@@ -569,8 +595,12 @@ function registerToolCommand(parentProgram, tool, clientFactory, vdProjectIdDefa
|
|
|
569
595
|
// invocation reaches the handler and prints the available actions instead
|
|
570
596
|
// of Commander's terse "missing required argument" error.
|
|
571
597
|
const isServiceAction = tool.cli.primary_arg === 'action' && Array.isArray(param.enum);
|
|
572
|
-
|
|
573
|
-
|
|
598
|
+
// Name the positional after the real parameter so Commander's errors and
|
|
599
|
+
// usage say e.g. "missing required argument 'deck'" instead of 'value'
|
|
600
|
+
// (#43556: the anonymous form sent agents guessing).
|
|
601
|
+
const argName = tool.cli.primary_arg;
|
|
602
|
+
const bracket = isRequired && !isServiceAction ? `<${argName}>` : `[${argName}]`;
|
|
603
|
+
cmd.argument(bracket, param.description || argName);
|
|
574
604
|
}
|
|
575
605
|
// Add remaining params as --options
|
|
576
606
|
const aliases = tool.cli.parameter_aliases || {};
|
|
@@ -1182,8 +1212,7 @@ function registerToolCommand(parentProgram, tool, clientFactory, vdProjectIdDefa
|
|
|
1182
1212
|
// web_search payloads are large and agent-consumed — indent-2 here
|
|
1183
1213
|
// is pure token overhead on every SAS/Claw search
|
|
1184
1214
|
output(result, {
|
|
1185
|
-
compact: tool.name === 'web_search' ||
|
|
1186
|
-
Boolean(mediaItemsKeyFor(tool.name)),
|
|
1215
|
+
compact: tool.name === 'web_search' || Boolean(mediaItemsKeyFor(tool.name)),
|
|
1187
1216
|
});
|
|
1188
1217
|
}
|
|
1189
1218
|
catch (err) {
|
|
@@ -1360,10 +1389,10 @@ program
|
|
|
1360
1389
|
const remainingSec = expires_in - elapsedSec;
|
|
1361
1390
|
const tokenResp = await unauthenticatedRequest(baseUrl, `/api/cli_auth/token?code=${encodeURIComponent(device_code)}`, 'GET');
|
|
1362
1391
|
if (tokenResp.status === 'approved' && tokenResp.api_key) {
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1392
|
+
updateConfigFile({
|
|
1393
|
+
api_key: tokenResp.api_key,
|
|
1394
|
+
base_url: baseUrl,
|
|
1395
|
+
});
|
|
1367
1396
|
info('Login successful! API key saved.');
|
|
1368
1397
|
output({
|
|
1369
1398
|
status: 'ok',
|
|
@@ -1401,8 +1430,7 @@ program
|
|
|
1401
1430
|
info('Already logged out (no API key in config).');
|
|
1402
1431
|
return;
|
|
1403
1432
|
}
|
|
1404
|
-
|
|
1405
|
-
saveConfigFile(config);
|
|
1433
|
+
updateConfigFile({}, ['api_key']);
|
|
1406
1434
|
info('Logged out. API key removed.');
|
|
1407
1435
|
output({
|
|
1408
1436
|
status: 'ok',
|
|
@@ -1435,6 +1463,25 @@ program
|
|
|
1435
1463
|
process.exit(1);
|
|
1436
1464
|
}
|
|
1437
1465
|
});
|
|
1466
|
+
// Runtime - report the sandbox environment this CLI process runs in
|
|
1467
|
+
program
|
|
1468
|
+
.command('runtime')
|
|
1469
|
+
.description('Show the Genspark sandbox runtime this CLI is running in ' +
|
|
1470
|
+
'(reads the /opt/genspark template marker; all-null outside a sandbox)')
|
|
1471
|
+
.action(() => {
|
|
1472
|
+
const runtime = getSandboxRuntime();
|
|
1473
|
+
output({
|
|
1474
|
+
status: 'ok',
|
|
1475
|
+
message: 'success',
|
|
1476
|
+
data: {
|
|
1477
|
+
family: runtime.family,
|
|
1478
|
+
version: runtime.version,
|
|
1479
|
+
is_sb_box: runtime.isSbBox,
|
|
1480
|
+
is_super_agent_sandbox: runtime.isSuperAgentSandbox,
|
|
1481
|
+
is_genspark_sandbox: runtime.isGensparkSandbox,
|
|
1482
|
+
},
|
|
1483
|
+
});
|
|
1484
|
+
});
|
|
1438
1485
|
// Init OpenCode - generate opencode.json config
|
|
1439
1486
|
program
|
|
1440
1487
|
.command('init-opencode')
|
|
@@ -1648,6 +1695,13 @@ function _generateContextMd(projectRoot, relSkillsDir, skillDirs) {
|
|
|
1648
1695
|
|
|
1649
1696
|
Read [gsk-shared](${sharedSkill}) for authentication, global flags, and output conventions.
|
|
1650
1697
|
|
|
1698
|
+
## Connectors
|
|
1699
|
+
|
|
1700
|
+
For any third-party integration (Gmail, Slack, Notion, HubSpot, custom MCP
|
|
1701
|
+
servers, ...), start with [gsk-connector](${relSkillsDir}/gsk-connector/SKILL.md) —
|
|
1702
|
+
one fixed \`list\` → \`search\` → \`tools <id>\` → \`call <id>\` flow covers every
|
|
1703
|
+
connector instead of memorizing per-service commands below.
|
|
1704
|
+
|
|
1651
1705
|
## Available Skills
|
|
1652
1706
|
|
|
1653
1707
|
${skillList}
|
|
@@ -1888,12 +1942,16 @@ _groupCommands.set('chat', chatCmd);
|
|
|
1888
1942
|
chatCmd
|
|
1889
1943
|
.command('events <project_id>')
|
|
1890
1944
|
.description("Attach to the conversation's in-flight run and stream its events " +
|
|
1891
|
-
'live (one JSON line per event on stdout):
|
|
1892
|
-
'
|
|
1893
|
-
'
|
|
1894
|
-
'
|
|
1895
|
-
'
|
|
1896
|
-
|
|
1945
|
+
'live (one JSON line per event on stdout): the first line is a ' +
|
|
1946
|
+
'project_data snapshot event, buffered events since run start ' +
|
|
1947
|
+
'replay next, then live events follow until the run ends. Every ' +
|
|
1948
|
+
'event line carries an _event_index. Prints no_running_agent when ' +
|
|
1949
|
+
'the conversation is idle. Upstream segment ends during long runs ' +
|
|
1950
|
+
'are reattached automatically; after a real disconnect, reattach ' +
|
|
1951
|
+
'with --last-seen <highest _event_index already processed> to ' +
|
|
1952
|
+
'skip the replayed prefix.')
|
|
1953
|
+
.option('--last-seen <index>', 'resume cursor: only replay events with _event_index greater than ' +
|
|
1954
|
+
'this (take it from the last event line of the previous stream)')
|
|
1897
1955
|
.action(async (projectId, opts) => {
|
|
1898
1956
|
try {
|
|
1899
1957
|
const lastSeen = parseLastSeenIndex(opts.lastSeen);
|
|
@@ -1917,6 +1975,11 @@ chatCmd
|
|
|
1917
1975
|
else if (msg.heartbeat !== undefined) {
|
|
1918
1976
|
debug(` Heartbeat #${msg.heartbeat}`);
|
|
1919
1977
|
}
|
|
1978
|
+
else if (msg.debug && typeof msg.message === 'string') {
|
|
1979
|
+
// Server-side notices (e.g. transparent segment reattach)
|
|
1980
|
+
// are context, not payload — stderr, --debug only.
|
|
1981
|
+
debug(` ${msg.message}`);
|
|
1982
|
+
}
|
|
1920
1983
|
});
|
|
1921
1984
|
output(result);
|
|
1922
1985
|
if (result.status === 'error') {
|
|
@@ -1940,11 +2003,12 @@ async function main() {
|
|
|
1940
2003
|
if (meshArgs !== null) {
|
|
1941
2004
|
program.parseOptions(process.argv);
|
|
1942
2005
|
setDebugEnabled(getGlobalOptions().debug);
|
|
1943
|
-
// Forward an explicit `--base-url` flag only
|
|
1944
|
-
//
|
|
1945
|
-
// inside the mesh layer so it doesn't inherit gsk's localhost default.
|
|
2006
|
+
// Forward an explicit `--base-url` flag only; env/config/default resolution
|
|
2007
|
+
// happens inside the mesh layer.
|
|
1946
2008
|
const rawBase = program.opts().baseUrl;
|
|
1947
|
-
const baseUrlOverride = rawBase &&
|
|
2009
|
+
const baseUrlOverride = rawBase && program.getOptionValueSource('baseUrl') === 'cli'
|
|
2010
|
+
? normalizeBaseUrl(rawBase)
|
|
2011
|
+
: undefined;
|
|
1948
2012
|
await runMesh(meshArgs, baseUrlOverride);
|
|
1949
2013
|
return;
|
|
1950
2014
|
}
|