@genspark/cli 1.5.1 → 1.5.3
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 +22 -14
- package/dist/client.d.ts +5 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +107 -0
- package/dist/client.js.map +1 -1
- package/dist/commands/aidrive-upload.d.ts +10 -7
- package/dist/commands/aidrive-upload.d.ts.map +1 -1
- package/dist/commands/aidrive-upload.js +35 -8
- package/dist/commands/aidrive-upload.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +187 -34
- package/dist/index.js.map +1 -1
- package/dist/localFiles.d.ts +25 -0
- package/dist/localFiles.d.ts.map +1 -1
- package/dist/localFiles.js +40 -0
- package/dist/localFiles.js.map +1 -1
- package/dist/mesh/manifest.d.ts +4 -4
- package/dist/mesh/manifest.d.ts.map +1 -1
- package/dist/mesh/manifest.js +9 -9
- package/dist/mesh/manifest.js.map +1 -1
- package/dist/task-shim.d.ts +13 -0
- package/dist/task-shim.d.ts.map +1 -0
- package/dist/task-shim.js +40 -0
- package/dist/task-shim.js.map +1 -0
- package/docs/skills.md +8 -5
- package/package.json +1 -1
- package/skills/gsk-acp-agents/SKILL.md +2 -2
- package/skills/gsk-audio-processing/SKILL.md +5 -3
- package/skills/gsk-create-task/SKILL.md +7 -40
- package/skills/gsk-github/SKILL.md +4 -0
- package/skills/gsk-gmail/SKILL.md +4 -0
- package/skills/gsk-google-calendar/SKILL.md +5 -0
- package/skills/gsk-google-chat/SKILL.md +6 -2
- package/skills/gsk-google-docs/SKILL.md +4 -0
- package/skills/gsk-google-drive/SKILL.md +4 -0
- package/skills/gsk-google-sheets/SKILL.md +4 -0
- package/skills/gsk-google-slides/SKILL.md +4 -0
- package/skills/gsk-image-generation/SKILL.md +1 -1
- package/skills/gsk-microsoft-teams/SKILL.md +18 -5
- package/skills/gsk-notion/SKILL.md +4 -0
- package/skills/gsk-onedrive/SKILL.md +4 -0
- package/skills/gsk-outlook-calendar/SKILL.md +5 -0
- package/skills/gsk-outlook-email/SKILL.md +4 -0
- package/skills/gsk-shared/SKILL.md +5 -5
- package/skills/gsk-sharepoint/SKILL.md +4 -0
- package/skills/gsk-slack/SKILL.md +7 -1
- package/skills/gsk-task-artifacts/SKILL.md +35 -0
- package/skills/gsk-task-continue/SKILL.md +13 -10
- package/skills/gsk-task-info/SKILL.md +36 -0
- package/skills/gsk-task-status/SKILL.md +6 -6
- package/skills/gsk-task-stop/SKILL.md +35 -0
- package/skills/gsk-video-generation/SKILL.md +8 -5
package/dist/index.js
CHANGED
|
@@ -27,13 +27,14 @@ import * as pathModule from 'path';
|
|
|
27
27
|
import { createRequire } from 'module';
|
|
28
28
|
import { spawn } from 'child_process';
|
|
29
29
|
import { ApiClient, isAuthError, unauthenticatedRequest, } from './client.js';
|
|
30
|
-
import { classifyFileArg, awaitLocalFileReady, decideAfterWait, localFileNotReadyError, } from './localFiles.js';
|
|
30
|
+
import { classifyFileArg, awaitLocalFileReady, decideAfterWait, localFileNotReadyError, passthroughWarning, urlsParamItems, } from './localFiles.js';
|
|
31
31
|
import { setDebugEnabled, setOutputFormat, debug, info, warn, error as logError, output, } from './logger.js';
|
|
32
32
|
import { loadConfigFile, getConfigPath, loadToolsCache, normalizeBaseUrl, saveToolsCache, setConfigPathOverride, updateConfigFile, } from './config.js';
|
|
33
33
|
import { checkForUpdates } from './updater.js';
|
|
34
|
+
import { shimLegacyTaskInvocation } from './task-shim.js';
|
|
34
35
|
import { getSandboxRuntime } from './runtime.js';
|
|
35
36
|
import { registerDesignCommand } from './commands/design.js';
|
|
36
|
-
import {
|
|
37
|
+
import { collectUploadFiles, pickExistingUploadOperand, } from './commands/aidrive-upload.js';
|
|
37
38
|
import { parseLastSeenIndex, eventStdoutLine } from './commands/chat-events.js';
|
|
38
39
|
import { mediaItemsKeyFor, mediaSummaryLines } from './mediaSummary.js';
|
|
39
40
|
import { registerMeshCommand, getMeshInvocation, runMesh, } from './commands/mesh.js';
|
|
@@ -351,7 +352,7 @@ async function uploadLocalFile(filePath, client) {
|
|
|
351
352
|
*
|
|
352
353
|
* This avoids the roundabout blob-upload + download_file two-step approach.
|
|
353
354
|
*/
|
|
354
|
-
async function uploadToAiDrive(filePath, uploadPath, override = false) {
|
|
355
|
+
async function uploadToAiDrive(filePath, uploadPath, override = false, workspace = 'personal') {
|
|
355
356
|
const fileName = pathModule.basename(filePath);
|
|
356
357
|
const ext = pathModule.extname(filePath).toLowerCase();
|
|
357
358
|
const contentType = CONTENT_TYPE_MAP[ext] || 'application/octet-stream';
|
|
@@ -359,7 +360,7 @@ async function uploadToAiDrive(filePath, uploadPath, override = false) {
|
|
|
359
360
|
info(`Uploading ${fileName} (${formatFileSize(fileSize)}, ${contentType}) directly to AI Drive...`);
|
|
360
361
|
const globalOpts = getGlobalOptions();
|
|
361
362
|
const baseUrl = globalOpts.baseUrl.replace(/\/$/, '');
|
|
362
|
-
const uploadUrl = `${baseUrl}/api/tool_cli/aidrive/upload?upload_path=${encodeURIComponent(uploadPath)}${override ? '&override=true' : ''}`;
|
|
363
|
+
const uploadUrl = `${baseUrl}/api/tool_cli/aidrive/upload?upload_path=${encodeURIComponent(uploadPath)}&workspace=${encodeURIComponent(workspace)}${override ? '&override=true' : ''}`;
|
|
363
364
|
const headers = { 'Content-Type': contentType };
|
|
364
365
|
if (globalOpts.apiKey)
|
|
365
366
|
headers['X-Api-Key'] = globalOpts.apiKey;
|
|
@@ -417,7 +418,9 @@ async function resolveFileArg(value, client) {
|
|
|
417
418
|
case 'passthrough':
|
|
418
419
|
// No local evidence beyond the parent directory: let the backend try
|
|
419
420
|
// it as an AI Drive path (its failure mode is a per-URL actionable
|
|
420
|
-
// error, not a generic one).
|
|
421
|
+
// error, not a generic one). Warn first so a failed producer in the
|
|
422
|
+
// same batch is diagnosable from this call's own output.
|
|
423
|
+
warn(passthroughWarning(localPath, readiness));
|
|
421
424
|
return value;
|
|
422
425
|
}
|
|
423
426
|
}
|
|
@@ -485,23 +488,29 @@ async function resolveLocalFiles(args, client) {
|
|
|
485
488
|
}
|
|
486
489
|
// Other array-of-URLs params (e.g. image_urls) — keep the existing
|
|
487
490
|
// auto-upload-to-blob behaviour, which is the right thing for image
|
|
488
|
-
// generation sources etc.
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
491
|
+
// generation sources etc. urlsParamItems also accepts a plain-string
|
|
492
|
+
// value (an --args-file authored with a string where the schema wants
|
|
493
|
+
// an array) so the local path still gets uploaded instead of leaking
|
|
494
|
+
// to the server; writing the array back restores the schema shape.
|
|
495
|
+
else {
|
|
496
|
+
const urlsItems = urlsParamItems(key, value);
|
|
497
|
+
if (urlsItems) {
|
|
498
|
+
const resolvedUrls = [];
|
|
499
|
+
for (const item of urlsItems) {
|
|
500
|
+
if (typeof item === 'string') {
|
|
501
|
+
resolvedUrls.push(await resolveFileArg(item, client));
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
resolvedUrls.push(item);
|
|
505
|
+
}
|
|
497
506
|
}
|
|
507
|
+
resolved[key] = resolvedUrls;
|
|
508
|
+
}
|
|
509
|
+
// Handle single URL (e.g., url, audio_url)
|
|
510
|
+
else if ((key === 'url' || key.endsWith('_url')) &&
|
|
511
|
+
typeof value === 'string') {
|
|
512
|
+
resolved[key] = await resolveFileArg(value, client);
|
|
498
513
|
}
|
|
499
|
-
resolved[key] = resolvedUrls;
|
|
500
|
-
}
|
|
501
|
-
// Handle single URL (e.g., url, audio_url)
|
|
502
|
-
else if ((key === 'url' || key.endsWith('_url')) &&
|
|
503
|
-
typeof value === 'string') {
|
|
504
|
-
resolved[key] = await resolveFileArg(value, client);
|
|
505
514
|
}
|
|
506
515
|
}
|
|
507
516
|
return resolved;
|
|
@@ -754,9 +763,17 @@ function registerToolCommand(parentProgram, tool, clientFactory, vdProjectIdDefa
|
|
|
754
763
|
if (outputFileKeys.length > 0) {
|
|
755
764
|
cmd.option('-o, --output-file <path>', 'Download the generated file to a local path');
|
|
756
765
|
}
|
|
766
|
+
// task ask (task_continue) shares the async-first submit → --follow
|
|
767
|
+
// upgrades the stub into a live SSE follow, same as task create.
|
|
768
|
+
// (Named --follow, not --attach: tools with an attachments array param
|
|
769
|
+
// already own --attach as a file alias.)
|
|
770
|
+
if (tool.name === 'task_continue') {
|
|
771
|
+
cmd.option('--follow', 'After the async submit, follow the durable run live (SSE) and exit with the terminal result', false);
|
|
772
|
+
}
|
|
757
773
|
// For create_task, add --acp flag to enter ACP stdio bridge mode
|
|
758
774
|
if (tool.name === 'create_task') {
|
|
759
775
|
cmd.option('--acp', 'Start as ACP (Agent Client Protocol) stdio agent instead of one-shot execution', false);
|
|
776
|
+
cmd.option('--follow', 'After the async submit, follow the durable run live (SSE) and exit with the terminal result', false);
|
|
760
777
|
cmd.option('-o, --output-file <path>', 'Export the artifact (pptx/docx/xlsx) to a local file after task completes');
|
|
761
778
|
cmd.option('--session-id <id>', 'ACP session ID (used with get-project)');
|
|
762
779
|
cmd.option('--file <values...>', 'Import local files (Design: structured context; other tasks: CSV/Excel file_urls)');
|
|
@@ -774,6 +791,9 @@ function registerToolCommand(parentProgram, tool, clientFactory, vdProjectIdDefa
|
|
|
774
791
|
}
|
|
775
792
|
// For the aidrive tool, add client-side options used with --local_file upload
|
|
776
793
|
if (tool.name === 'aidrive') {
|
|
794
|
+
if (!Object.hasOwn(props, 'workspace')) {
|
|
795
|
+
cmd.option('--workspace <value>', 'AI Drive workspace: personal or public_brain');
|
|
796
|
+
}
|
|
777
797
|
cmd.option('--local_file <path>', 'Local file path to upload to AI Drive (supports files >5 MB; alternative to --file_content)');
|
|
778
798
|
cmd.option('--override', 'Overwrite an existing file at the destination path (used with --local_file)', false);
|
|
779
799
|
}
|
|
@@ -908,6 +928,11 @@ function registerToolCommand(parentProgram, tool, clientFactory, vdProjectIdDefa
|
|
|
908
928
|
const outputFilePath = opts.outputFile;
|
|
909
929
|
delete opts.outputFile;
|
|
910
930
|
delete opts.acp; // ACP flag is client-side only
|
|
931
|
+
// -o exports an artifact of the FINISHED project — an async submit
|
|
932
|
+
// stub has nothing to export yet, so an export request implies the
|
|
933
|
+
// live follow.
|
|
934
|
+
const attachTask = !!opts.follow || !!outputFilePath;
|
|
935
|
+
delete opts.follow; // client-side only
|
|
911
936
|
delete opts.sessionId; // get-project flag is client-side only
|
|
912
937
|
const argsFilePath = opts.argsFile;
|
|
913
938
|
delete opts.argsFile; // client-side only; merged below
|
|
@@ -1115,7 +1140,7 @@ function registerToolCommand(parentProgram, tool, clientFactory, vdProjectIdDefa
|
|
|
1115
1140
|
const operandCandidates = primaryArgValue !== undefined && primaryArgValue === args.action
|
|
1116
1141
|
? cmd.args.slice(1)
|
|
1117
1142
|
: cmd.args;
|
|
1118
|
-
const pathOperand =
|
|
1143
|
+
const pathOperand = pickExistingUploadOperand(operandCandidates);
|
|
1119
1144
|
if (pathOperand) {
|
|
1120
1145
|
opts.local_file = pathOperand;
|
|
1121
1146
|
}
|
|
@@ -1135,6 +1160,7 @@ function registerToolCommand(parentProgram, tool, clientFactory, vdProjectIdDefa
|
|
|
1135
1160
|
opts.local_file) {
|
|
1136
1161
|
const localFilePath = opts.local_file;
|
|
1137
1162
|
const override = !!opts.override;
|
|
1163
|
+
const workspace = args.workspace || 'personal';
|
|
1138
1164
|
if (!fs.existsSync(localFilePath)) {
|
|
1139
1165
|
logError(`File not found: ${localFilePath}`);
|
|
1140
1166
|
process.exit(1);
|
|
@@ -1146,9 +1172,35 @@ function registerToolCommand(parentProgram, tool, clientFactory, vdProjectIdDefa
|
|
|
1146
1172
|
const uploadPath = rawUploadPath.startsWith('/')
|
|
1147
1173
|
? rawUploadPath
|
|
1148
1174
|
: `/${rawUploadPath}`;
|
|
1149
|
-
|
|
1150
|
-
const
|
|
1151
|
-
|
|
1175
|
+
const localStat = fs.statSync(localFilePath);
|
|
1176
|
+
const files = collectUploadFiles(localFilePath);
|
|
1177
|
+
if (localStat.isDirectory()) {
|
|
1178
|
+
if (files.length === 0) {
|
|
1179
|
+
logError(`Folder has no files to upload: ${localFilePath}`);
|
|
1180
|
+
process.exit(1);
|
|
1181
|
+
}
|
|
1182
|
+
info(`Uploading folder ${localFilePath} (${files.length} files)...`);
|
|
1183
|
+
const uploaded = [];
|
|
1184
|
+
for (const file of files) {
|
|
1185
|
+
const destination = pathModule.posix.join(uploadPath, file.relativePath);
|
|
1186
|
+
const result = await uploadToAiDrive(file.absolutePath, destination, override, workspace);
|
|
1187
|
+
if (result.status !== 'ok') {
|
|
1188
|
+
output(result);
|
|
1189
|
+
process.exit(1);
|
|
1190
|
+
}
|
|
1191
|
+
uploaded.push(destination);
|
|
1192
|
+
}
|
|
1193
|
+
output({
|
|
1194
|
+
status: 'ok',
|
|
1195
|
+
message: `Uploaded ${uploaded.length} files`,
|
|
1196
|
+
data: { workspace, root: uploadPath, files: uploaded },
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
1199
|
+
else {
|
|
1200
|
+
// Stream directly to AI Drive — single request, no blob middleman
|
|
1201
|
+
const result = await uploadToAiDrive(localFilePath, uploadPath, override, workspace);
|
|
1202
|
+
output(result);
|
|
1203
|
+
}
|
|
1152
1204
|
return;
|
|
1153
1205
|
}
|
|
1154
1206
|
const designAttachmentArgs = collectDesignAttachmentArgs(process.argv);
|
|
@@ -1200,7 +1252,36 @@ function registerToolCommand(parentProgram, tool, clientFactory, vdProjectIdDefa
|
|
|
1200
1252
|
}
|
|
1201
1253
|
// Resolve local file paths to uploaded URLs
|
|
1202
1254
|
const resolvedArgs = await resolveLocalFiles(args, client);
|
|
1203
|
-
|
|
1255
|
+
// The server owns the async-first default: create_task /
|
|
1256
|
+
// task_continue return a submit stub ({status: "submitted",
|
|
1257
|
+
// run_id, stream_url}) unless `--wait true` was passed. --attach
|
|
1258
|
+
// upgrades the stub into a live SSE follow that exits with the
|
|
1259
|
+
// run's terminal result — the work still executes server-side.
|
|
1260
|
+
let result = await client.executeTool(tool.name, resolvedArgs);
|
|
1261
|
+
const stubData = result.data;
|
|
1262
|
+
if (attachTask &&
|
|
1263
|
+
result.status === 'ok' &&
|
|
1264
|
+
stubData &&
|
|
1265
|
+
typeof stubData.stream_url === 'string' &&
|
|
1266
|
+
(stubData.status === 'submitted' ||
|
|
1267
|
+
stubData.status === 'duplicate_submit_converged')) {
|
|
1268
|
+
const meta = await client.attachGskTaskRun(stubData.stream_url);
|
|
1269
|
+
const runStatus = String(meta.status || '');
|
|
1270
|
+
const summary = meta.result_summary && typeof meta.result_summary === 'object'
|
|
1271
|
+
? meta.result_summary
|
|
1272
|
+
: {};
|
|
1273
|
+
result = {
|
|
1274
|
+
status: runStatus === 'succeeded' ? 'ok' : 'error',
|
|
1275
|
+
message: runStatus === 'succeeded'
|
|
1276
|
+
? 'success'
|
|
1277
|
+
: `task ended with status ${runStatus || 'unknown'}`,
|
|
1278
|
+
data: {
|
|
1279
|
+
...summary,
|
|
1280
|
+
run_id: stubData.run_id,
|
|
1281
|
+
run_status: runStatus,
|
|
1282
|
+
},
|
|
1283
|
+
};
|
|
1284
|
+
}
|
|
1204
1285
|
const isSbGitCloneUrl = tool.name === 'sb-git' &&
|
|
1205
1286
|
resolvedArgs.action === 'clone-url';
|
|
1206
1287
|
if (isSbGitCloneUrl &&
|
|
@@ -2105,19 +2186,23 @@ _groupCommands.set('phone-call', phoneCallCmd);
|
|
|
2105
2186
|
// gk_tool_cli_conversation) and attach as dynamic subcommands via the
|
|
2106
2187
|
// seeded _groupCommands entry; this static parent only gives the group a
|
|
2107
2188
|
// real description instead of the generated "Commands for chat".
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2189
|
+
// The task command tree. Verbs are server-registered (create / status /
|
|
2190
|
+
// info / ask / answer / messages / wait / stop / delete / rename attach as
|
|
2191
|
+
// dynamic subcommands via the seeded group); this static parent gives the
|
|
2192
|
+
// group a description, and hosts the one static verb below.
|
|
2193
|
+
const taskCmd = program
|
|
2194
|
+
.command('task')
|
|
2195
|
+
.description('Agent tasks and conversations: create one (submits and returns in ' +
|
|
2196
|
+
'seconds), poll status, read outputs, send follow-ups, answer ' +
|
|
2197
|
+
'agent questions, stop, delete, rename (see subcommands).');
|
|
2198
|
+
_groupCommands.set('task', taskCmd);
|
|
2199
|
+
// `task events` is static (not server-registered): it needs real-time
|
|
2115
2200
|
// line-by-line output the generic dynamic-command handler cannot provide
|
|
2116
2201
|
// (that path buffers intermediate NDJSON messages and only prints the
|
|
2117
2202
|
// final result).
|
|
2118
|
-
|
|
2203
|
+
taskCmd
|
|
2119
2204
|
.command('events <project_id>')
|
|
2120
|
-
.description("Attach to the
|
|
2205
|
+
.description("Attach to the task's in-flight run and stream its events " +
|
|
2121
2206
|
'live (one JSON line per event on stdout): the first line is a ' +
|
|
2122
2207
|
'project_data snapshot event, buffered events since run start ' +
|
|
2123
2208
|
'replay next, then live events follow until the run ends. Every ' +
|
|
@@ -2167,10 +2252,78 @@ chatCmd
|
|
|
2167
2252
|
process.exit(1);
|
|
2168
2253
|
}
|
|
2169
2254
|
});
|
|
2255
|
+
// `task export` is static: it composes two calls (task_status to resolve
|
|
2256
|
+
// the task type, then /export_artifact) plus an optional local download —
|
|
2257
|
+
// the generic dynamic handler maps one verb to one server tool.
|
|
2258
|
+
taskCmd
|
|
2259
|
+
.command('export <project_id>')
|
|
2260
|
+
.description("Convert and download a task's deliverable (docs → docx/pdf, " +
|
|
2261
|
+
'slides → pptx/pdf, sheets → xlsx). Prints the download URL; with ' +
|
|
2262
|
+
'-o <path> also saves the file locally. The task type is resolved ' +
|
|
2263
|
+
'automatically from the project; `gsk task artifacts <project_id>` ' +
|
|
2264
|
+
'lists what a task produced and which formats it can export.')
|
|
2265
|
+
.option('--format <format>', 'export format: auto | docx | pdf | pptx | xlsx (auto picks the ' +
|
|
2266
|
+
"task type's natural format)", 'auto')
|
|
2267
|
+
.option('-o, --output-file <path>', 'save the exported file to this path')
|
|
2268
|
+
.action(async (projectId, opts) => {
|
|
2269
|
+
try {
|
|
2270
|
+
const client = createClient();
|
|
2271
|
+
const statusResult = await client.executeTool('task_status', {
|
|
2272
|
+
id: projectId,
|
|
2273
|
+
});
|
|
2274
|
+
const statusData = statusResult.data;
|
|
2275
|
+
const taskType = statusResult.status === 'ok' && statusData
|
|
2276
|
+
? statusData.task_type
|
|
2277
|
+
: undefined;
|
|
2278
|
+
if (!taskType) {
|
|
2279
|
+
output(statusResult.status === 'ok'
|
|
2280
|
+
? {
|
|
2281
|
+
status: 'error',
|
|
2282
|
+
message: `Cannot resolve task type for ${projectId}`,
|
|
2283
|
+
data: null,
|
|
2284
|
+
}
|
|
2285
|
+
: statusResult);
|
|
2286
|
+
process.exit(1);
|
|
2287
|
+
}
|
|
2288
|
+
const exportResult = await client.exportArtifact(projectId, taskType, opts.format || 'auto');
|
|
2289
|
+
const expData = exportResult.data;
|
|
2290
|
+
if (exportResult.status === 'ok' && expData && opts.outputFile) {
|
|
2291
|
+
const downloadUrl = expData.download_url;
|
|
2292
|
+
if (downloadUrl) {
|
|
2293
|
+
expData.local_path = await downloadToFile(downloadUrl, opts.outputFile, client);
|
|
2294
|
+
}
|
|
2295
|
+
else {
|
|
2296
|
+
// The converter can report ok with an empty URL (e.g. the
|
|
2297
|
+
// share-link build failed server-side) — surface it instead
|
|
2298
|
+
// of printing ok with no file on disk.
|
|
2299
|
+
output({
|
|
2300
|
+
status: 'error',
|
|
2301
|
+
message: 'Export produced no download_url — nothing was saved ' +
|
|
2302
|
+
`to ${opts.outputFile}`,
|
|
2303
|
+
data: expData,
|
|
2304
|
+
});
|
|
2305
|
+
process.exit(1);
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2308
|
+
output(exportResult);
|
|
2309
|
+
if (exportResult.status === 'error') {
|
|
2310
|
+
process.exit(1);
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
catch (err) {
|
|
2314
|
+
logError(err.message);
|
|
2315
|
+
process.exit(1);
|
|
2316
|
+
}
|
|
2317
|
+
});
|
|
2170
2318
|
// ============================================
|
|
2171
2319
|
// Dynamic Tool Registration & Startup
|
|
2172
2320
|
// ============================================
|
|
2173
2321
|
async function main() {
|
|
2322
|
+
// Pre-tree `gsk task <type>` compat (see shimLegacyTaskInvocation).
|
|
2323
|
+
process.argv = [
|
|
2324
|
+
...process.argv.slice(0, 2),
|
|
2325
|
+
...shimLegacyTaskInvocation(process.argv.slice(2)),
|
|
2326
|
+
];
|
|
2174
2327
|
// `gsk mesh ...` is a native-binary passthrough — intercept it before the
|
|
2175
2328
|
// tool-fetch path and npm self-update gating (it needs neither). Handling it
|
|
2176
2329
|
// outside commander keeps the rest of the CLI's option parsing intact (see
|