@302ai/media-studio-cli 0.1.1 → 0.1.2-beta.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/README.md +1 -1
- package/dist/index.js +327 -270
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -215,7 +215,7 @@ The CLI mirrors the web composer's upload flow:
|
|
|
215
215
|
1. Validates each referenced file locally (exists, readable, supported extension, under 50 MB) before any network call.
|
|
216
216
|
2. Uploads each file via the web app's `POST /api/chat/attachments` endpoint with a terminal spinner (`Uploading attachment 1/2: cover.png`).
|
|
217
217
|
3. Rewrites the prompt to inline the remote URL using the web's `&&<url>&&` marker, which the upstream model and web session history natively understand.
|
|
218
|
-
4. Up to
|
|
218
|
+
4. Up to 10 unique attachments per turn (same as the web composer); referencing the same file twice uploads it once.
|
|
219
219
|
5. An unattachable reference (missing file, unsupported format) fails the turn before any session is provisioned.
|
|
220
220
|
6. Prose mentions (`@team 辛苦了`, email addresses) stay literal text — only tokens with a file extension or path slash are treated as attachments.
|
|
221
221
|
7. `@path` is local-filesystem-only: `@https://example.com/a.png` fails with `no such file`. There is no `@url` form — remote URLs are not attachments.
|
package/dist/index.js
CHANGED
|
@@ -4284,7 +4284,7 @@ var consola = createConsola2();
|
|
|
4284
4284
|
// package.json
|
|
4285
4285
|
var package_default = {
|
|
4286
4286
|
name: "@302ai/media-studio-cli",
|
|
4287
|
-
version: "0.1.1",
|
|
4287
|
+
version: "0.1.2-beta.1",
|
|
4288
4288
|
description: "CLI for AI Media Studio — let external agents drive the core media-studio features",
|
|
4289
4289
|
author: "302.AI",
|
|
4290
4290
|
license: "Apache-2.0",
|
|
@@ -9648,7 +9648,7 @@ var ArtifactItemSchema = object({
|
|
|
9648
9648
|
var ArtifactItemsSchema = array(ArtifactItemSchema);
|
|
9649
9649
|
|
|
9650
9650
|
// ../media-studio-contract/src/attachments/constants.ts
|
|
9651
|
-
var MAX_ATTACHMENT_COUNT =
|
|
9651
|
+
var MAX_ATTACHMENT_COUNT = 10;
|
|
9652
9652
|
var MAX_ATTACHMENT_BYTES = 50 * 1024 * 1024;
|
|
9653
9653
|
var ATTACHMENT_MIME_BY_EXTENSION = {
|
|
9654
9654
|
png: "image/png",
|
|
@@ -10058,6 +10058,17 @@ var MEDIA_STUDIO_URLS = {
|
|
|
10058
10058
|
cn: "https://media.302ai.cn",
|
|
10059
10059
|
staging: "https://media.tool302.com"
|
|
10060
10060
|
};
|
|
10061
|
+
var OSS_GLOBAL_ORIGIN = "https://sonier-file-oss.small-base-aaeb.workers.dev";
|
|
10062
|
+
var OSS_CN_ORIGIN = "https://sonier.oss-cn-shenzhen.aliyuncs.com";
|
|
10063
|
+
function resolveOssUrl(url, useCnDomain) {
|
|
10064
|
+
if (!useCnDomain || !url.startsWith(OSS_GLOBAL_ORIGIN))
|
|
10065
|
+
return url;
|
|
10066
|
+
const suffix = url.slice(OSS_GLOBAL_ORIGIN.length);
|
|
10067
|
+
const boundary = suffix[0];
|
|
10068
|
+
if (boundary && !"/?#".includes(boundary))
|
|
10069
|
+
return url;
|
|
10070
|
+
return OSS_CN_ORIGIN + suffix;
|
|
10071
|
+
}
|
|
10061
10072
|
var MEDIA_STUDIO_HOSTS = [
|
|
10062
10073
|
new URL(MEDIA_STUDIO_URLS.default).hostname,
|
|
10063
10074
|
new URL(MEDIA_STUDIO_URLS.cn).hostname,
|
|
@@ -10073,6 +10084,34 @@ var APP_ENV_HOSTS = {
|
|
|
10073
10084
|
]
|
|
10074
10085
|
};
|
|
10075
10086
|
|
|
10087
|
+
// ../media-studio-contract/src/model-flag.ts
|
|
10088
|
+
var MODEL_FLAG_BLOCK_RE = /\$(?=\s*--model\b)([^$]+)\$/gi;
|
|
10089
|
+
var MODEL_FLAG_HEAD_RE = /^--model\s+("(?:[^"\\]|\\.)+"|[^\s]+)/i;
|
|
10090
|
+
function findModelFlagMatches(text) {
|
|
10091
|
+
const pattern = new RegExp(MODEL_FLAG_BLOCK_RE.source, "gi");
|
|
10092
|
+
return Array.from(text.matchAll(pattern)).flatMap((match) => {
|
|
10093
|
+
const start = match.index;
|
|
10094
|
+
const body = match[1]?.trim();
|
|
10095
|
+
if (start === undefined || !body)
|
|
10096
|
+
return [];
|
|
10097
|
+
const token = body.match(MODEL_FLAG_HEAD_RE)?.[1];
|
|
10098
|
+
if (!token)
|
|
10099
|
+
return [];
|
|
10100
|
+
let modelId = token;
|
|
10101
|
+
if (token.startsWith('"')) {
|
|
10102
|
+
try {
|
|
10103
|
+
const decoded = JSON.parse(token);
|
|
10104
|
+
if (typeof decoded !== "string")
|
|
10105
|
+
return [];
|
|
10106
|
+
modelId = decoded;
|
|
10107
|
+
} catch {
|
|
10108
|
+
return [];
|
|
10109
|
+
}
|
|
10110
|
+
}
|
|
10111
|
+
return [{ start, end: start + match[0].length, body, modelId }];
|
|
10112
|
+
});
|
|
10113
|
+
}
|
|
10114
|
+
|
|
10076
10115
|
// ../media-studio-contract/src/skills/activation.ts
|
|
10077
10116
|
var SKILL_ACTIVATION_MARKER = "%%";
|
|
10078
10117
|
var SKILL_ACTIVATION_RE = /%%(\/[^%\s]+)%%/g;
|
|
@@ -10102,21 +10141,20 @@ function findSkillActivationMatches(text) {
|
|
|
10102
10141
|
|
|
10103
10142
|
// ../media-studio-contract/src/sessions/derive-first-turn-note.ts
|
|
10104
10143
|
var DEFAULT_FALLBACK_TITLE = "Agent Task";
|
|
10105
|
-
var
|
|
10144
|
+
var MAX_PROJECT_TITLE_LENGTH = 64;
|
|
10145
|
+
function clampSessionTitle(title) {
|
|
10146
|
+
return Array.from(title).slice(0, MAX_PROJECT_TITLE_LENGTH).join("");
|
|
10147
|
+
}
|
|
10106
10148
|
function deriveFirstTurnNote(rawText, options) {
|
|
10107
10149
|
const fallback = options?.fallbackTitle ?? DEFAULT_FALLBACK_TITLE;
|
|
10108
10150
|
if (!rawText) {
|
|
10109
10151
|
return fallback;
|
|
10110
10152
|
}
|
|
10111
|
-
const unwrapped = rawText.
|
|
10153
|
+
const unwrapped = findModelFlagMatches(rawText).toReversed().reduce((text, match) => `${text.slice(0, match.start)}${match.modelId} ${text.slice(match.end)}`, rawText).replace(SKILL_ACTIVATION_RE, "$1").replace(ATTACHMENT_MARKER_REGEX, "$1").replace(/\s+/g, " ").trim();
|
|
10112
10154
|
if (!unwrapped) {
|
|
10113
10155
|
return fallback;
|
|
10114
10156
|
}
|
|
10115
|
-
|
|
10116
|
-
if (codePoints.length > MAX_NOTE_LENGTH) {
|
|
10117
|
-
return codePoints.slice(0, MAX_NOTE_LENGTH).join("");
|
|
10118
|
-
}
|
|
10119
|
-
return unwrapped;
|
|
10157
|
+
return clampSessionTitle(unwrapped);
|
|
10120
10158
|
}
|
|
10121
10159
|
|
|
10122
10160
|
// ../media-studio-contract/src/skills/compose-turn.ts
|
|
@@ -16975,7 +17013,7 @@ function saveConfigFile(data) {
|
|
|
16975
17013
|
const dir = getConfigDir();
|
|
16976
17014
|
mkdirSync(dir, { recursive: true });
|
|
16977
17015
|
const configPath = getConfigFilePath();
|
|
16978
|
-
const tmpPath = `${configPath}.${nanoid3()}
|
|
17016
|
+
const tmpPath = `${configPath}.tmp.${process.pid}.${nanoid3()}`;
|
|
16979
17017
|
writeFileSync(tmpPath, JSON.stringify(data, null, 2), "utf8");
|
|
16980
17018
|
chmodSync(tmpPath, 384);
|
|
16981
17019
|
renameSync(tmpPath, configPath);
|
|
@@ -17541,6 +17579,12 @@ class MediaStudioClient {
|
|
|
17541
17579
|
}, MeResponseSchema, (status) => `Authentication verification failed with status ${status}`);
|
|
17542
17580
|
}
|
|
17543
17581
|
}
|
|
17582
|
+
function createCliClient(options) {
|
|
17583
|
+
return new MediaStudioClient({
|
|
17584
|
+
baseUrl: options?.baseUrl ?? resolveApiBaseUrl(),
|
|
17585
|
+
apiKey: options?.apiKey ?? resolveApiKey()
|
|
17586
|
+
});
|
|
17587
|
+
}
|
|
17544
17588
|
// src/client/tool-formatter.ts
|
|
17545
17589
|
var ASPECT_RATIO_PATTERN = /aspect_ratio:\s*([^\s,;]+)/i;
|
|
17546
17590
|
var MODEL_PATTERN = /(?:^|\n)\s*-\s*model:\s*([^\s,;]+)/i;
|
|
@@ -17903,6 +17947,26 @@ function reportCommandError(err, options) {
|
|
|
17903
17947
|
process.exit(1);
|
|
17904
17948
|
}
|
|
17905
17949
|
|
|
17950
|
+
// src/lib/open-url.ts
|
|
17951
|
+
var OPEN_URL_NOTE = "Open or render open_url. Submit or forward url unchanged.";
|
|
17952
|
+
function loginUsesCnOss(apiBaseUrl) {
|
|
17953
|
+
try {
|
|
17954
|
+
return new URL(apiBaseUrl).origin === MEDIA_STUDIO_URLS.cn;
|
|
17955
|
+
} catch {
|
|
17956
|
+
return false;
|
|
17957
|
+
}
|
|
17958
|
+
}
|
|
17959
|
+
function resolveOpenUrl(url, apiBaseUrl) {
|
|
17960
|
+
return resolveOssUrl(url, loginUsesCnOss(apiBaseUrl));
|
|
17961
|
+
}
|
|
17962
|
+
function deriveOpenUrl(rawUrl, apiBaseUrl) {
|
|
17963
|
+
const sanitized = rawUrl?.replace(/\r?\n/g, " ").trim();
|
|
17964
|
+
if (!sanitized)
|
|
17965
|
+
return;
|
|
17966
|
+
const openUrl = resolveOpenUrl(sanitized, apiBaseUrl);
|
|
17967
|
+
return openUrl === sanitized ? undefined : openUrl;
|
|
17968
|
+
}
|
|
17969
|
+
|
|
17906
17970
|
// src/lib/spinner.ts
|
|
17907
17971
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
17908
17972
|
var BRAILLE_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
@@ -18065,7 +18129,7 @@ async function resolvePromptAttachments(options) {
|
|
|
18065
18129
|
typed: typedByResolved[abs] ?? abs,
|
|
18066
18130
|
file: await readAttachment(typedByResolved[abs] ?? abs, abs)
|
|
18067
18131
|
})));
|
|
18068
|
-
const client =
|
|
18132
|
+
const client = createCliClient({
|
|
18069
18133
|
baseUrl: options.apiBaseUrl,
|
|
18070
18134
|
apiKey: options.apiKey
|
|
18071
18135
|
});
|
|
@@ -18129,7 +18193,7 @@ class SessionNotFoundError extends Error {
|
|
|
18129
18193
|
}
|
|
18130
18194
|
}
|
|
18131
18195
|
async function ensureSessionExists(options) {
|
|
18132
|
-
const client =
|
|
18196
|
+
const client = createCliClient({
|
|
18133
18197
|
baseUrl: options.apiBaseUrl,
|
|
18134
18198
|
apiKey: options.apiKey
|
|
18135
18199
|
});
|
|
@@ -18149,7 +18213,7 @@ function finalizeProvision(result, spinner) {
|
|
|
18149
18213
|
return result.sessionId;
|
|
18150
18214
|
}
|
|
18151
18215
|
async function provisionSession(options) {
|
|
18152
|
-
const client =
|
|
18216
|
+
const client = createCliClient({
|
|
18153
18217
|
baseUrl: options.apiBaseUrl,
|
|
18154
18218
|
apiKey: options.apiKey
|
|
18155
18219
|
});
|
|
@@ -18227,7 +18291,7 @@ async function resolvePromptSkills(options) {
|
|
|
18227
18291
|
if (spans.length === 0) {
|
|
18228
18292
|
return { text: options.prompt, skillUrls: [], autoEnabled: [] };
|
|
18229
18293
|
}
|
|
18230
|
-
const client =
|
|
18294
|
+
const client = createCliClient({
|
|
18231
18295
|
baseUrl: options.apiBaseUrl,
|
|
18232
18296
|
apiKey: options.apiKey
|
|
18233
18297
|
});
|
|
@@ -18266,7 +18330,11 @@ var PROVISION_STAGE_LABELS = {
|
|
|
18266
18330
|
skills: "Installing skills...",
|
|
18267
18331
|
finishing: "Finishing session setup..."
|
|
18268
18332
|
};
|
|
18269
|
-
function
|
|
18333
|
+
function withMediaOpenUrl(asset, apiBaseUrl) {
|
|
18334
|
+
const openUrl = deriveOpenUrl(asset.resultUrl, apiBaseUrl);
|
|
18335
|
+
return openUrl ? { ...asset, openUrl } : asset;
|
|
18336
|
+
}
|
|
18337
|
+
function printTerminalMediaAssets(mediaAssets, fullText, apiBaseUrl) {
|
|
18270
18338
|
if (mediaAssets.length === 0) {
|
|
18271
18339
|
if (fullText && !fullText.endsWith(`
|
|
18272
18340
|
`)) {
|
|
@@ -18283,13 +18351,20 @@ function printTerminalMediaAssets(mediaAssets, fullText) {
|
|
|
18283
18351
|
process.stdout.write(`
|
|
18284
18352
|
=== MEDIA ASSETS ===
|
|
18285
18353
|
`);
|
|
18354
|
+
let noted = false;
|
|
18286
18355
|
for (const asset of mediaAssets) {
|
|
18356
|
+
const openUrl = deriveOpenUrl(asset.resultUrl, apiBaseUrl);
|
|
18357
|
+
noted ||= Boolean(openUrl);
|
|
18287
18358
|
process.stdout.write(`- type: ${asset.domain ?? "media"}
|
|
18288
18359
|
` + (asset.resultUrl ? `- url: ${asset.resultUrl}
|
|
18360
|
+
` : "") + (openUrl ? `- open_url: ${openUrl}
|
|
18289
18361
|
` : "") + (asset.modelUsed ? `- model: ${asset.modelUsed}
|
|
18290
18362
|
` : "") + (asset.taskId ? `- task_id: ${asset.taskId}
|
|
18291
18363
|
` : ""));
|
|
18292
18364
|
}
|
|
18365
|
+
if (noted)
|
|
18366
|
+
process.stdout.write(`${OPEN_URL_NOTE}
|
|
18367
|
+
`);
|
|
18293
18368
|
process.stdout.write(`====================
|
|
18294
18369
|
`);
|
|
18295
18370
|
}
|
|
@@ -18348,11 +18423,11 @@ function describeStreamFailure(err) {
|
|
|
18348
18423
|
return String(err);
|
|
18349
18424
|
}
|
|
18350
18425
|
async function streamTurn(options) {
|
|
18351
|
-
const { args, sessionId, spinner, autoEnabled, attachments } = options;
|
|
18426
|
+
const { args, sessionId, spinner, autoEnabled, attachments, apiBaseUrl } = options;
|
|
18352
18427
|
if (!args.json) {
|
|
18353
18428
|
spinner.start("Connecting to Media Studio...");
|
|
18354
18429
|
}
|
|
18355
|
-
const stream = await
|
|
18430
|
+
const stream = await createCliClient({
|
|
18356
18431
|
baseUrl: options.apiBaseUrl,
|
|
18357
18432
|
apiKey: options.apiKey
|
|
18358
18433
|
}).chat.stream({
|
|
@@ -18435,7 +18510,7 @@ async function streamTurn(options) {
|
|
|
18435
18510
|
sessionId,
|
|
18436
18511
|
text: fullText,
|
|
18437
18512
|
steps,
|
|
18438
|
-
media: mediaAssets,
|
|
18513
|
+
media: mediaAssets.map((asset) => withMediaOpenUrl(asset, apiBaseUrl)),
|
|
18439
18514
|
...attachments.length > 0 ? { attachments } : {},
|
|
18440
18515
|
...autoEnabled.length > 0 ? { autoEnabled } : {},
|
|
18441
18516
|
...args["show-reasoning"] && reasoning ? { reasoning } : {}
|
|
@@ -18445,7 +18520,7 @@ async function streamTurn(options) {
|
|
|
18445
18520
|
emitting = false;
|
|
18446
18521
|
return;
|
|
18447
18522
|
}
|
|
18448
|
-
printTerminalMediaAssets(mediaAssets, fullText);
|
|
18523
|
+
printTerminalMediaAssets(mediaAssets, fullText, apiBaseUrl);
|
|
18449
18524
|
process.stdout.write(`session: ${sessionId}
|
|
18450
18525
|
`);
|
|
18451
18526
|
emitting = false;
|
|
@@ -18469,7 +18544,7 @@ async function streamTurn(options) {
|
|
|
18469
18544
|
sessionId,
|
|
18470
18545
|
text: fullText,
|
|
18471
18546
|
steps,
|
|
18472
|
-
media: mediaAssets,
|
|
18547
|
+
media: mediaAssets.map((asset) => withMediaOpenUrl(asset, apiBaseUrl)),
|
|
18473
18548
|
...attachments.length > 0 ? { attachments } : {},
|
|
18474
18549
|
...autoEnabled.length > 0 ? { autoEnabled } : {},
|
|
18475
18550
|
...args["show-reasoning"] && reasoning ? { reasoning } : {}
|
|
@@ -18477,7 +18552,7 @@ async function streamTurn(options) {
|
|
|
18477
18552
|
process.stdout.write(`${JSON.stringify(output, null, 2)}
|
|
18478
18553
|
`);
|
|
18479
18554
|
} else {
|
|
18480
|
-
printTerminalMediaAssets(mediaAssets, fullText);
|
|
18555
|
+
printTerminalMediaAssets(mediaAssets, fullText, apiBaseUrl);
|
|
18481
18556
|
process.stdout.write(`session: ${sessionId}
|
|
18482
18557
|
`);
|
|
18483
18558
|
}
|
|
@@ -18608,7 +18683,7 @@ var chatCommand = defineCommand({
|
|
|
18608
18683
|
const shouldPatchNote = Boolean(explicitSessionDetail && !explicitSessionDetail.titleCustomized && explicitSessionDetail.isEmpty || !args.session && !args.new && readLastSessionPendingNote());
|
|
18609
18684
|
if (shouldPatchNote) {
|
|
18610
18685
|
const derivedNote = deriveFirstTurnNote(buildNotePrompt(promptWithAttachments, attachments), { fallbackTitle: CLI_DEFAULT_SESSION_NOTE });
|
|
18611
|
-
|
|
18686
|
+
createCliClient({
|
|
18612
18687
|
baseUrl: apiBaseUrl,
|
|
18613
18688
|
apiKey: resolveApiKey()
|
|
18614
18689
|
}).sessions.updateNote(resolved.sessionId, derivedNote).then(() => clearLastSessionPendingNote()).catch(() => {});
|
|
@@ -18714,7 +18789,7 @@ ${getAvailableRegions().map((r) => ` ${r.key.padEnd(8)} - ${r.url} (${r.des
|
|
|
18714
18789
|
|
|
18715
18790
|
The CLI validates files locally (existence, supported format, under 50 MB),
|
|
18716
18791
|
uploads them with progress indication, and inlines remote URLs into the prompt.
|
|
18717
|
-
Up to
|
|
18792
|
+
Up to 10 attachments per turn. Referencing the same file multiple times
|
|
18718
18793
|
uploads it only once. Plain prose mentions (@team) and emails are ignored.
|
|
18719
18794
|
|
|
18720
18795
|
@path is local-filesystem-only: @https://example.com/a.png fails with
|
|
@@ -18768,7 +18843,9 @@ ${getAvailableRegions().map((r) => ` ${r.key.padEnd(8)} - ${r.url} (${r.des
|
|
|
18768
18843
|
|
|
18769
18844
|
msc sessions artifacts <session-id>
|
|
18770
18845
|
List all generated assets (images, videos, audio) produced in that session,
|
|
18771
|
-
including download URLs and model metadata.
|
|
18846
|
+
including download URLs and model metadata. Text output adds an OPEN column
|
|
18847
|
+
only when the signed-in site needs a different origin; JSON adds the openUrl
|
|
18848
|
+
field in the same case. Submit or forward the link unchanged.
|
|
18772
18849
|
|
|
18773
18850
|
msc sessions use <session-id>
|
|
18774
18851
|
Switch your active session pointer to an existing session. The id is
|
|
@@ -18802,7 +18879,8 @@ ${getAvailableRegions().map((r) => ` ${r.key.padEnd(8)} - ${r.url}`).join(`
|
|
|
18802
18879
|
"status": "completed",
|
|
18803
18880
|
"domain": "image", // "image" | "video" | etc.
|
|
18804
18881
|
"operation": "t2i", // "t2i", "t2v", etc.
|
|
18805
|
-
"resultUrl": "https://...",
|
|
18882
|
+
"resultUrl": "https://...", // stored address; submit this unchanged
|
|
18883
|
+
"openUrl": "https://...", // present only when rendering needs another origin
|
|
18806
18884
|
"modelUsed": "string",
|
|
18807
18885
|
"taskId": "string"
|
|
18808
18886
|
}
|
|
@@ -18818,8 +18896,17 @@ ${getAvailableRegions().map((r) => ` ${r.key.padEnd(8)} - ${r.url}`).join(`
|
|
|
18818
18896
|
"reasoning": "string?" // present if --show-reasoning was passed
|
|
18819
18897
|
}
|
|
18820
18898
|
|
|
18821
|
-
|
|
18822
|
-
|
|
18899
|
+
resultUrl is the stored address. Submit or forward it unchanged. openUrl is
|
|
18900
|
+
present only when the signed-in site needs a different origin to render the
|
|
18901
|
+
object. Text output names that address open_url and adds one fixed note;
|
|
18902
|
+
JSON does not contain the note.
|
|
18903
|
+
|
|
18904
|
+
Extracting each role (e.g. with jq):
|
|
18905
|
+
result=$(msc chat "a red balloon" --json)
|
|
18906
|
+
url=$(printf '%s
|
|
18907
|
+
' "$result" | jq -r '.media[0].resultUrl')
|
|
18908
|
+
open=$(printf '%s
|
|
18909
|
+
' "$result" | jq -r '.media[0].openUrl // .media[0].resultUrl')
|
|
18823
18910
|
|
|
18824
18911
|
Exit codes: 0 = the turn ran to completion OR its stream ended early; 1 =
|
|
18825
18912
|
\`status: "error"\`, a usage error, or any other failure. Only what the parser
|
|
@@ -18901,6 +18988,7 @@ ${getAvailableRegions().map((r) => ` ${r.key.padEnd(8)} - ${r.url}`).join(`
|
|
|
18901
18988
|
msc sessions --json # list: [{ sessionId, note, ... }]
|
|
18902
18989
|
msc sessions use <id> --json # { "sessionId": "string" }
|
|
18903
18990
|
msc sessions use --new --json # { "sessionId": "string" } (newly created)
|
|
18991
|
+
msc sessions artifacts <id> --json # [{..., link, openUrl?}]
|
|
18904
18992
|
\`--session\`/\`use <id>\` verify the id upstream; an unknown id exits 1 with
|
|
18905
18993
|
the \`--new\` hint and leaves the default session untouched.
|
|
18906
18994
|
|
|
@@ -20764,9 +20852,24 @@ var logoutCommand = defineCommand({
|
|
|
20764
20852
|
}
|
|
20765
20853
|
});
|
|
20766
20854
|
|
|
20855
|
+
// src/lib/run-command.ts
|
|
20856
|
+
async function runCliCommand(fn, options) {
|
|
20857
|
+
try {
|
|
20858
|
+
await fn();
|
|
20859
|
+
} catch (err) {
|
|
20860
|
+
if (isTransportFailure(err))
|
|
20861
|
+
throw err;
|
|
20862
|
+
reportCommandError(err, { json: options?.json });
|
|
20863
|
+
return;
|
|
20864
|
+
}
|
|
20865
|
+
}
|
|
20866
|
+
|
|
20767
20867
|
// src/commands/sessions.ts
|
|
20768
20868
|
function formatLastActive(iso) {
|
|
20769
|
-
|
|
20869
|
+
const date = new Date(iso);
|
|
20870
|
+
if (!iso || Number.isNaN(date.getTime()))
|
|
20871
|
+
return "";
|
|
20872
|
+
return date.toLocaleString("sv-SE", { hour12: false }).replace(", ", " ");
|
|
20770
20873
|
}
|
|
20771
20874
|
function renderSessionsTable(sessions, currentSessionId) {
|
|
20772
20875
|
const rows = sessions.map((s) => ({
|
|
@@ -20792,27 +20895,31 @@ ${bodyLines.join(`
|
|
|
20792
20895
|
`)}
|
|
20793
20896
|
`;
|
|
20794
20897
|
}
|
|
20795
|
-
function
|
|
20796
|
-
|
|
20797
|
-
|
|
20798
|
-
|
|
20799
|
-
|
|
20800
|
-
|
|
20801
|
-
|
|
20802
|
-
|
|
20803
|
-
|
|
20804
|
-
|
|
20805
|
-
|
|
20806
|
-
})
|
|
20898
|
+
function artifactRows(artifacts, apiBaseUrl) {
|
|
20899
|
+
return artifacts.map((a) => {
|
|
20900
|
+
const link = a.link ? a.link.replace(/\r?\n/g, " ").trim() || "-" : "-";
|
|
20901
|
+
const openUrl = link === "-" ? undefined : deriveOpenUrl(link, apiBaseUrl);
|
|
20902
|
+
return {
|
|
20903
|
+
type: a.type,
|
|
20904
|
+
status: a.status,
|
|
20905
|
+
title: a.title ? a.title.replace(/\r?\n/g, " ").trim() || "-" : "-",
|
|
20906
|
+
link,
|
|
20907
|
+
openUrl: openUrl ?? ""
|
|
20908
|
+
};
|
|
20909
|
+
});
|
|
20910
|
+
}
|
|
20911
|
+
function renderArtifactsTable(rows) {
|
|
20912
|
+
const showOpen = rows.some((row) => row.openUrl);
|
|
20807
20913
|
const headers = {
|
|
20808
20914
|
type: "TYPE",
|
|
20809
20915
|
status: "STATUS",
|
|
20810
20916
|
title: "TITLE",
|
|
20811
|
-
link: "LINK"
|
|
20917
|
+
link: "LINK",
|
|
20918
|
+
openUrl: "OPEN"
|
|
20812
20919
|
};
|
|
20813
20920
|
const typeWidth = Math.max(headers.type.length, ...rows.map((r) => r.type.length));
|
|
20814
20921
|
const statusWidth = Math.max(headers.status.length, ...rows.map((r) => r.status.length));
|
|
20815
|
-
const formatRow = (r) => `${r.type.padEnd(typeWidth)} ${r.status.padEnd(statusWidth)} ${r.title} ${r.link}`;
|
|
20922
|
+
const formatRow = (r) => `${r.type.padEnd(typeWidth)} ${r.status.padEnd(statusWidth)} ${r.title} ${r.link}${showOpen ? ` ${r.openUrl}` : ""}`;
|
|
20816
20923
|
return `${formatRow(headers)}
|
|
20817
20924
|
${rows.map(formatRow).join(`
|
|
20818
20925
|
`)}
|
|
@@ -20830,27 +20937,21 @@ var listSessionsCommand = defineCommand({
|
|
|
20830
20937
|
description: "Output machine-readable JSON array"
|
|
20831
20938
|
}
|
|
20832
20939
|
},
|
|
20833
|
-
run:
|
|
20834
|
-
|
|
20835
|
-
|
|
20836
|
-
|
|
20837
|
-
|
|
20838
|
-
process.stdout.write(`${JSON.stringify(response.data, null, 2)}
|
|
20940
|
+
run: ({ args }) => runCliCommand(async () => {
|
|
20941
|
+
const client = createCliClient();
|
|
20942
|
+
const response = await client.sessions.list();
|
|
20943
|
+
if (args.json) {
|
|
20944
|
+
process.stdout.write(`${JSON.stringify(response.data, null, 2)}
|
|
20839
20945
|
`);
|
|
20840
|
-
|
|
20841
|
-
}
|
|
20842
|
-
if (response.data.length === 0) {
|
|
20843
|
-
consola.info("No sessions found.");
|
|
20844
|
-
return;
|
|
20845
|
-
}
|
|
20846
|
-
const currentId = readLastSessionId();
|
|
20847
|
-
consola.log(renderSessionsTable(response.data, currentId));
|
|
20848
|
-
} catch (err) {
|
|
20849
|
-
if (isTransportFailure(err))
|
|
20850
|
-
throw err;
|
|
20851
|
-
reportCommandError(err, { json: args.json });
|
|
20946
|
+
return;
|
|
20852
20947
|
}
|
|
20853
|
-
|
|
20948
|
+
if (response.data.length === 0) {
|
|
20949
|
+
consola.info("No sessions found.");
|
|
20950
|
+
return;
|
|
20951
|
+
}
|
|
20952
|
+
const currentId = readLastSessionId();
|
|
20953
|
+
consola.log(renderSessionsTable(response.data, currentId));
|
|
20954
|
+
}, { json: args.json })
|
|
20854
20955
|
});
|
|
20855
20956
|
var artifactsCommand = defineCommand({
|
|
20856
20957
|
meta: {
|
|
@@ -20869,28 +20970,30 @@ var artifactsCommand = defineCommand({
|
|
|
20869
20970
|
description: "Output machine-readable JSON array"
|
|
20870
20971
|
}
|
|
20871
20972
|
},
|
|
20872
|
-
run:
|
|
20873
|
-
|
|
20874
|
-
|
|
20875
|
-
|
|
20876
|
-
|
|
20973
|
+
run: ({ args }) => runCliCommand(async () => {
|
|
20974
|
+
const client = createCliClient();
|
|
20975
|
+
const response = await client.sessions.artifacts({
|
|
20976
|
+
sessionId: args.sessionId
|
|
20977
|
+
});
|
|
20978
|
+
if (args.json) {
|
|
20979
|
+
const apiBaseUrl = resolveApiBaseUrl();
|
|
20980
|
+
const data = response.data.map((item) => {
|
|
20981
|
+
const openUrl = deriveOpenUrl(item.link, apiBaseUrl);
|
|
20982
|
+
return openUrl ? { ...item, openUrl } : item;
|
|
20877
20983
|
});
|
|
20878
|
-
|
|
20879
|
-
process.stdout.write(`${JSON.stringify(response.data, null, 2)}
|
|
20984
|
+
process.stdout.write(`${JSON.stringify(data, null, 2)}
|
|
20880
20985
|
`);
|
|
20881
|
-
|
|
20882
|
-
}
|
|
20883
|
-
if (response.data.length === 0) {
|
|
20884
|
-
consola.info("No artifacts found.");
|
|
20885
|
-
return;
|
|
20886
|
-
}
|
|
20887
|
-
consola.log(renderArtifactsTable(response.data));
|
|
20888
|
-
} catch (err) {
|
|
20889
|
-
if (isTransportFailure(err))
|
|
20890
|
-
throw err;
|
|
20891
|
-
reportCommandError(err, { json: args.json });
|
|
20986
|
+
return;
|
|
20892
20987
|
}
|
|
20893
|
-
|
|
20988
|
+
if (response.data.length === 0) {
|
|
20989
|
+
consola.info("No artifacts found.");
|
|
20990
|
+
return;
|
|
20991
|
+
}
|
|
20992
|
+
const rows = artifactRows(response.data, resolveApiBaseUrl());
|
|
20993
|
+
consola.log(renderArtifactsTable(rows));
|
|
20994
|
+
if (rows.some((row) => row.openUrl))
|
|
20995
|
+
consola.log(OPEN_URL_NOTE);
|
|
20996
|
+
}, { json: args.json })
|
|
20894
20997
|
});
|
|
20895
20998
|
var useSessionCommand = defineCommand({
|
|
20896
20999
|
meta: {
|
|
@@ -20913,50 +21016,44 @@ var useSessionCommand = defineCommand({
|
|
|
20913
21016
|
description: "Output machine-readable JSON: { sessionId }"
|
|
20914
21017
|
}
|
|
20915
21018
|
},
|
|
20916
|
-
run:
|
|
20917
|
-
|
|
20918
|
-
|
|
20919
|
-
|
|
20920
|
-
if (
|
|
20921
|
-
|
|
20922
|
-
throw new Error("--new and <session-id> cannot be combined: pass one, not both.");
|
|
20923
|
-
}
|
|
20924
|
-
const result = await provisionSession({
|
|
20925
|
-
apiBaseUrl,
|
|
20926
|
-
apiKey: resolveApiKey(),
|
|
20927
|
-
note: CLI_DEFAULT_SESSION_NOTE
|
|
20928
|
-
});
|
|
20929
|
-
const created = finalizeProvision(result);
|
|
20930
|
-
saveLastSessionId(created, { pendingNote: true });
|
|
20931
|
-
if (args.json) {
|
|
20932
|
-
process.stdout.write(`${JSON.stringify({ sessionId: created })}
|
|
20933
|
-
`);
|
|
20934
|
-
return;
|
|
20935
|
-
}
|
|
20936
|
-
consola.success(`Created and switched to session ${created}`);
|
|
20937
|
-
return;
|
|
21019
|
+
run: ({ args }) => runCliCommand(async () => {
|
|
21020
|
+
const sessionId = args.sessionId;
|
|
21021
|
+
const apiBaseUrl = resolveApiBaseUrl();
|
|
21022
|
+
if (args.new) {
|
|
21023
|
+
if (sessionId) {
|
|
21024
|
+
throw new Error("--new and <session-id> cannot be combined: pass one, not both.");
|
|
20938
21025
|
}
|
|
20939
|
-
|
|
20940
|
-
throw new Error("Pass the session id to switch to, or --new to create a new session.");
|
|
20941
|
-
}
|
|
20942
|
-
await ensureSessionExists({
|
|
21026
|
+
const result = await provisionSession({
|
|
20943
21027
|
apiBaseUrl,
|
|
20944
21028
|
apiKey: resolveApiKey(),
|
|
20945
|
-
|
|
21029
|
+
note: CLI_DEFAULT_SESSION_NOTE
|
|
20946
21030
|
});
|
|
20947
|
-
|
|
21031
|
+
const created = finalizeProvision(result);
|
|
21032
|
+
saveLastSessionId(created, { pendingNote: true });
|
|
20948
21033
|
if (args.json) {
|
|
20949
|
-
process.stdout.write(`${JSON.stringify({ sessionId })}
|
|
21034
|
+
process.stdout.write(`${JSON.stringify({ sessionId: created })}
|
|
20950
21035
|
`);
|
|
20951
21036
|
return;
|
|
20952
21037
|
}
|
|
20953
|
-
consola.success(`
|
|
20954
|
-
|
|
20955
|
-
if (isTransportFailure(err))
|
|
20956
|
-
throw err;
|
|
20957
|
-
reportCommandError(err, { json: args.json });
|
|
21038
|
+
consola.success(`Created and switched to session ${created}`);
|
|
21039
|
+
return;
|
|
20958
21040
|
}
|
|
20959
|
-
|
|
21041
|
+
if (!sessionId) {
|
|
21042
|
+
throw new Error("Pass the session id to switch to, or --new to create a new session.");
|
|
21043
|
+
}
|
|
21044
|
+
await ensureSessionExists({
|
|
21045
|
+
apiBaseUrl,
|
|
21046
|
+
apiKey: resolveApiKey(),
|
|
21047
|
+
sessionId
|
|
21048
|
+
});
|
|
21049
|
+
saveLastSessionId(sessionId);
|
|
21050
|
+
if (args.json) {
|
|
21051
|
+
process.stdout.write(`${JSON.stringify({ sessionId })}
|
|
21052
|
+
`);
|
|
21053
|
+
return;
|
|
21054
|
+
}
|
|
21055
|
+
consola.success(`Switched default session to ${sessionId}`);
|
|
21056
|
+
}, { json: args.json })
|
|
20960
21057
|
});
|
|
20961
21058
|
var sessionsCommand = defineCommand({
|
|
20962
21059
|
meta: {
|
|
@@ -20980,26 +21077,19 @@ function needsConfirmationRefusal(yes) {
|
|
|
20980
21077
|
}
|
|
20981
21078
|
|
|
20982
21079
|
// src/commands/skills.ts
|
|
20983
|
-
function resolveClient2() {
|
|
20984
|
-
return new MediaStudioClient({
|
|
20985
|
-
baseUrl: resolveApiBaseUrl(),
|
|
20986
|
-
apiKey: resolveApiKey()
|
|
20987
|
-
});
|
|
20988
|
-
}
|
|
20989
21080
|
function stateMarker(state) {
|
|
20990
|
-
|
|
20991
|
-
|
|
20992
|
-
if (state === "off")
|
|
20993
|
-
return "[off]";
|
|
20994
|
-
return "[-] ";
|
|
21081
|
+
const marker = state === "on" ? "[on]" : state === "off" ? "[off]" : "[-]";
|
|
21082
|
+
return marker.padEnd(5);
|
|
20995
21083
|
}
|
|
21084
|
+
var NAME_SEP = " ";
|
|
21085
|
+
var NAME_INDENT = stateMarker("off").length + NAME_SEP.length;
|
|
20996
21086
|
function renderSkillRow(state, name, description) {
|
|
20997
21087
|
const marker = stateMarker(state);
|
|
20998
21088
|
const colorize = state === "on" ? import_picocolors2.green : state === "off" ? import_picocolors2.red : import_picocolors2.dim;
|
|
20999
|
-
const head = `${colorize(marker)}
|
|
21089
|
+
const head = `${colorize(marker)}${NAME_SEP}${stripControlChars(name)}`;
|
|
21000
21090
|
const clean = stripControlChars(description).trim();
|
|
21001
21091
|
return clean ? `${head}
|
|
21002
|
-
${" ".repeat(
|
|
21092
|
+
${" ".repeat(NAME_INDENT)}${clean}` : head;
|
|
21003
21093
|
}
|
|
21004
21094
|
var addSkillCommand = defineCommand({
|
|
21005
21095
|
meta: {
|
|
@@ -21018,23 +21108,17 @@ var addSkillCommand = defineCommand({
|
|
|
21018
21108
|
description: "Output machine-readable JSON"
|
|
21019
21109
|
}
|
|
21020
21110
|
},
|
|
21021
|
-
run:
|
|
21022
|
-
|
|
21023
|
-
|
|
21024
|
-
|
|
21025
|
-
|
|
21026
|
-
|
|
21027
|
-
process.stdout.write(`${JSON.stringify(skill, null, 2)}
|
|
21111
|
+
run: ({ args }) => runCliCommand(async () => {
|
|
21112
|
+
const client = createCliClient();
|
|
21113
|
+
const entry = await findPlazaEntry(client, args["skill-slug"]);
|
|
21114
|
+
const skill = await client.skills.install(entry);
|
|
21115
|
+
if (args.json) {
|
|
21116
|
+
process.stdout.write(`${JSON.stringify(skill, null, 2)}
|
|
21028
21117
|
`);
|
|
21029
|
-
|
|
21030
|
-
}
|
|
21031
|
-
consola.success(`Installed ${stripControlChars(skill.command)} (${stripControlChars(skill.name)}).`);
|
|
21032
|
-
} catch (err) {
|
|
21033
|
-
if (isTransportFailure(err))
|
|
21034
|
-
throw err;
|
|
21035
|
-
reportCommandError(err, { json: args.json });
|
|
21118
|
+
return;
|
|
21036
21119
|
}
|
|
21037
|
-
|
|
21120
|
+
consola.success(`Installed ${stripControlChars(skill.command)} (${stripControlChars(skill.name)}).`);
|
|
21121
|
+
}, { json: args.json })
|
|
21038
21122
|
});
|
|
21039
21123
|
var rmSkillCommand = defineCommand({
|
|
21040
21124
|
meta: {
|
|
@@ -21058,36 +21142,30 @@ var rmSkillCommand = defineCommand({
|
|
|
21058
21142
|
description: "Output machine-readable JSON"
|
|
21059
21143
|
}
|
|
21060
21144
|
},
|
|
21061
|
-
run:
|
|
21062
|
-
|
|
21063
|
-
|
|
21064
|
-
|
|
21065
|
-
|
|
21066
|
-
|
|
21067
|
-
|
|
21068
|
-
|
|
21069
|
-
|
|
21070
|
-
|
|
21071
|
-
|
|
21072
|
-
consola.info("Skill removal cancelled.");
|
|
21073
|
-
return;
|
|
21074
|
-
}
|
|
21075
|
-
}
|
|
21076
|
-
const client = resolveClient2();
|
|
21077
|
-
const skill = await findLibraryEntry(client, args["skill-command"]);
|
|
21078
|
-
await client.skills.remove(skill.id);
|
|
21079
|
-
if (args.json) {
|
|
21080
|
-
process.stdout.write(`${JSON.stringify({ success: true, id: skill.id, deleted: true }, null, 2)}
|
|
21081
|
-
`);
|
|
21145
|
+
run: ({ args }) => runCliCommand(async () => {
|
|
21146
|
+
if (needsConfirmationRefusal(args.yes === true)) {
|
|
21147
|
+
throw new Error("Confirmation required. Pass --yes to confirm removal non-interactively.");
|
|
21148
|
+
}
|
|
21149
|
+
if (!args.yes) {
|
|
21150
|
+
const confirmed = await confirm({
|
|
21151
|
+
message: `Remove skill "${args["skill-command"]}" from your library? Re-installing needs a fresh plaza install.`,
|
|
21152
|
+
initialValue: false
|
|
21153
|
+
});
|
|
21154
|
+
if (isCancel(confirmed) || !confirmed) {
|
|
21155
|
+
consola.info("Skill removal cancelled.");
|
|
21082
21156
|
return;
|
|
21083
21157
|
}
|
|
21084
|
-
consola.success(`Skill "${args["skill-command"]}" removed from your library.`);
|
|
21085
|
-
} catch (err) {
|
|
21086
|
-
if (isTransportFailure(err))
|
|
21087
|
-
throw err;
|
|
21088
|
-
reportCommandError(err, { json: args.json });
|
|
21089
21158
|
}
|
|
21090
|
-
|
|
21159
|
+
const client = createCliClient();
|
|
21160
|
+
const skill = await findLibraryEntry(client, args["skill-command"]);
|
|
21161
|
+
await client.skills.remove(skill.id);
|
|
21162
|
+
if (args.json) {
|
|
21163
|
+
process.stdout.write(`${JSON.stringify({ success: true, id: skill.id, deleted: true }, null, 2)}
|
|
21164
|
+
`);
|
|
21165
|
+
return;
|
|
21166
|
+
}
|
|
21167
|
+
consola.success(`Skill "${args["skill-command"]}" removed from your library.`);
|
|
21168
|
+
}, { json: args.json })
|
|
21091
21169
|
});
|
|
21092
21170
|
function makeSetEnabledCommand(name, enabled, description) {
|
|
21093
21171
|
return defineCommand({
|
|
@@ -21104,23 +21182,17 @@ function makeSetEnabledCommand(name, enabled, description) {
|
|
|
21104
21182
|
description: "Output machine-readable JSON"
|
|
21105
21183
|
}
|
|
21106
21184
|
},
|
|
21107
|
-
run:
|
|
21108
|
-
|
|
21109
|
-
|
|
21110
|
-
|
|
21111
|
-
|
|
21112
|
-
|
|
21113
|
-
process.stdout.write(`${JSON.stringify(skill, null, 2)}
|
|
21185
|
+
run: ({ args }) => runCliCommand(async () => {
|
|
21186
|
+
const client = createCliClient();
|
|
21187
|
+
const found = await findLibraryEntry(client, args["skill-command"]);
|
|
21188
|
+
const skill = await client.skills.setEnabled(found.id, enabled);
|
|
21189
|
+
if (args.json) {
|
|
21190
|
+
process.stdout.write(`${JSON.stringify(skill, null, 2)}
|
|
21114
21191
|
`);
|
|
21115
|
-
|
|
21116
|
-
}
|
|
21117
|
-
consola.success(`${enabled ? "Enabled" : "Disabled"} ${stripControlChars(skill.command)}.`);
|
|
21118
|
-
} catch (err) {
|
|
21119
|
-
if (isTransportFailure(err))
|
|
21120
|
-
throw err;
|
|
21121
|
-
reportCommandError(err, { json: args.json });
|
|
21192
|
+
return;
|
|
21122
21193
|
}
|
|
21123
|
-
|
|
21194
|
+
consola.success(`${enabled ? "Enabled" : "Disabled"} ${stripControlChars(skill.command)}.`);
|
|
21195
|
+
}, { json: args.json })
|
|
21124
21196
|
});
|
|
21125
21197
|
}
|
|
21126
21198
|
var enableSkillCommand = makeSetEnabledCommand("enable", true, "Enable a skill in your library");
|
|
@@ -21162,59 +21234,53 @@ var skillsCommand = defineCommand({
|
|
|
21162
21234
|
enable: enableSkillCommand,
|
|
21163
21235
|
rm: rmSkillCommand
|
|
21164
21236
|
},
|
|
21165
|
-
run:
|
|
21166
|
-
|
|
21167
|
-
|
|
21168
|
-
|
|
21169
|
-
const plaza = await client.skills.browsePlaza();
|
|
21170
|
-
if (args.json) {
|
|
21171
|
-
process.stdout.write(`${JSON.stringify(plaza, null, 2)}
|
|
21172
|
-
`);
|
|
21173
|
-
return;
|
|
21174
|
-
}
|
|
21175
|
-
if (plaza.length === 0) {
|
|
21176
|
-
consola.info("The Skill Plaza has no entries yet.");
|
|
21177
|
-
return;
|
|
21178
|
-
}
|
|
21179
|
-
const installed = plaza.filter((s) => s.added);
|
|
21180
|
-
const available = plaza.filter((s) => !s.added);
|
|
21181
|
-
const installedRows = installed.map((s) => renderSkillRow(s.enabled ? "on" : "off", s.name, s.descriptionEn));
|
|
21182
|
-
const availableRows = available.map((s) => renderSkillRow("none", s.name, s.descriptionEn));
|
|
21183
|
-
consola.log([
|
|
21184
|
-
`Installed (${installed.length})`,
|
|
21185
|
-
...installedRows,
|
|
21186
|
-
"",
|
|
21187
|
-
`Available (${available.length})`,
|
|
21188
|
-
...availableRows,
|
|
21189
|
-
"",
|
|
21190
|
-
import_picocolors2.gray(`install with msc skills add <slug> · slug names are in --json`)
|
|
21191
|
-
].join(`
|
|
21192
|
-
`));
|
|
21193
|
-
return;
|
|
21194
|
-
}
|
|
21195
|
-
const skills = await client.skills.listAll();
|
|
21237
|
+
run: ({ args }) => runCliCommand(async () => {
|
|
21238
|
+
const client = createCliClient();
|
|
21239
|
+
if (args.plaza) {
|
|
21240
|
+
const plaza = await client.skills.browsePlaza();
|
|
21196
21241
|
if (args.json) {
|
|
21197
|
-
process.stdout.write(`${JSON.stringify(
|
|
21242
|
+
process.stdout.write(`${JSON.stringify(plaza, null, 2)}
|
|
21198
21243
|
`);
|
|
21199
21244
|
return;
|
|
21200
21245
|
}
|
|
21201
|
-
if (
|
|
21202
|
-
consola.info("
|
|
21246
|
+
if (plaza.length === 0) {
|
|
21247
|
+
consola.info("The Skill Plaza has no entries yet.");
|
|
21203
21248
|
return;
|
|
21204
21249
|
}
|
|
21205
|
-
const
|
|
21250
|
+
const installed = plaza.filter((s) => s.added);
|
|
21251
|
+
const available = plaza.filter((s) => !s.added);
|
|
21252
|
+
const installedRows = installed.map((s) => renderSkillRow(s.enabled ? "on" : "off", s.name, s.descriptionEn));
|
|
21253
|
+
const availableRows = available.map((s) => renderSkillRow("none", s.name, s.descriptionEn));
|
|
21206
21254
|
consola.log([
|
|
21207
|
-
|
|
21255
|
+
`Installed (${installed.length})`,
|
|
21256
|
+
...installedRows,
|
|
21257
|
+
"",
|
|
21258
|
+
`Available (${available.length})`,
|
|
21259
|
+
...availableRows,
|
|
21208
21260
|
"",
|
|
21209
|
-
import_picocolors2.gray(
|
|
21261
|
+
import_picocolors2.gray(`install with msc skills add <slug> · slug names are in --json`)
|
|
21210
21262
|
].join(`
|
|
21211
21263
|
`));
|
|
21212
|
-
|
|
21213
|
-
if (isTransportFailure(err))
|
|
21214
|
-
throw err;
|
|
21215
|
-
reportCommandError(err, { json: args.json });
|
|
21264
|
+
return;
|
|
21216
21265
|
}
|
|
21217
|
-
|
|
21266
|
+
const skills = await client.skills.listAll();
|
|
21267
|
+
if (args.json) {
|
|
21268
|
+
process.stdout.write(`${JSON.stringify(skills, null, 2)}
|
|
21269
|
+
`);
|
|
21270
|
+
return;
|
|
21271
|
+
}
|
|
21272
|
+
if (skills.length === 0) {
|
|
21273
|
+
consola.info("Your skill library is empty. Browse the plaza with --plaza, or add skills in the Media Studio web app.");
|
|
21274
|
+
return;
|
|
21275
|
+
}
|
|
21276
|
+
const rows = skills.map((s) => renderSkillRow(s.enabled ? "on" : "off", s.name, s.descriptionEn));
|
|
21277
|
+
consola.log([
|
|
21278
|
+
...rows,
|
|
21279
|
+
"",
|
|
21280
|
+
import_picocolors2.gray("skills in this list can be referenced as %%skill-name%% in a prompt")
|
|
21281
|
+
].join(`
|
|
21282
|
+
`));
|
|
21283
|
+
}, { json: args.json })
|
|
21218
21284
|
});
|
|
21219
21285
|
|
|
21220
21286
|
// src/commands/whoami.ts
|
|
@@ -21226,7 +21292,7 @@ var whoamiCommand = defineCommand({
|
|
|
21226
21292
|
name: "whoami",
|
|
21227
21293
|
description: "Display current authentication status"
|
|
21228
21294
|
},
|
|
21229
|
-
run: async () => {
|
|
21295
|
+
run: () => runCliCommand(async () => {
|
|
21230
21296
|
let auth;
|
|
21231
21297
|
try {
|
|
21232
21298
|
auth = readAuthFile();
|
|
@@ -21243,50 +21309,41 @@ var whoamiCommand = defineCommand({
|
|
|
21243
21309
|
return;
|
|
21244
21310
|
}
|
|
21245
21311
|
const apiUrl = resolveApiBaseUrl();
|
|
21246
|
-
const client =
|
|
21247
|
-
|
|
21248
|
-
|
|
21249
|
-
|
|
21250
|
-
|
|
21251
|
-
|
|
21252
|
-
|
|
21253
|
-
|
|
21254
|
-
|
|
21255
|
-
|
|
21256
|
-
|
|
21257
|
-
|
|
21258
|
-
|
|
21259
|
-
|
|
21260
|
-
|
|
21261
|
-
|
|
21262
|
-
|
|
21263
|
-
|
|
21264
|
-
|
|
21265
|
-
|
|
21266
|
-
|
|
21267
|
-
|
|
21268
|
-
|
|
21269
|
-
|
|
21270
|
-
|
|
21271
|
-
|
|
21272
|
-
}
|
|
21273
|
-
|
|
21274
|
-
|
|
21275
|
-
|
|
21276
|
-
|
|
21277
|
-
|
|
21278
|
-
data.apiKeyMasked ? ` API Key: ${data.apiKeyMasked}` : null,
|
|
21279
|
-
` Token: ${maskToken(client.apiKey)}`
|
|
21280
|
-
].filter(Boolean);
|
|
21281
|
-
consola.log(`${lines.join(`
|
|
21312
|
+
const client = createCliClient({ baseUrl: apiUrl, apiKey: auth.token });
|
|
21313
|
+
const data = await client.getMe();
|
|
21314
|
+
if (!data.valid) {
|
|
21315
|
+
consola.error("Session expired or token invalid.\nPlease run `msc login` to re-authenticate.");
|
|
21316
|
+
process.exit(1);
|
|
21317
|
+
return;
|
|
21318
|
+
}
|
|
21319
|
+
const updatedName = data.name ?? auth.username;
|
|
21320
|
+
const updatedUid = data.uid ?? auth.uid;
|
|
21321
|
+
const updatedEmail = data.email ?? auth.email;
|
|
21322
|
+
if (updatedName !== auth.username || updatedUid !== auth.uid || updatedEmail !== auth.email) {
|
|
21323
|
+
try {
|
|
21324
|
+
saveAuthFile({
|
|
21325
|
+
...auth,
|
|
21326
|
+
token: client.apiKey,
|
|
21327
|
+
username: updatedName,
|
|
21328
|
+
uid: updatedUid,
|
|
21329
|
+
email: updatedEmail
|
|
21330
|
+
});
|
|
21331
|
+
} catch (err) {
|
|
21332
|
+
consola.warn(err instanceof Error ? err.message : String(err));
|
|
21333
|
+
}
|
|
21334
|
+
}
|
|
21335
|
+
consola.success("Authenticated");
|
|
21336
|
+
const lines = [
|
|
21337
|
+
updatedName ? ` User: ${updatedName}` : null,
|
|
21338
|
+
updatedUid ? ` UID: ${updatedUid}` : null,
|
|
21339
|
+
updatedEmail ? ` Email: ${updatedEmail}` : null,
|
|
21340
|
+
data.apiKeyMasked ? ` API Key: ${data.apiKeyMasked}` : null,
|
|
21341
|
+
` Token: ${maskToken(client.apiKey)}`
|
|
21342
|
+
].filter(Boolean);
|
|
21343
|
+
consola.log(`${lines.join(`
|
|
21282
21344
|
`)}
|
|
21283
21345
|
`);
|
|
21284
|
-
|
|
21285
|
-
if (isTransportFailure(err))
|
|
21286
|
-
throw err;
|
|
21287
|
-
reportCommandError(err);
|
|
21288
|
-
}
|
|
21289
|
-
}
|
|
21346
|
+
})
|
|
21290
21347
|
});
|
|
21291
21348
|
|
|
21292
21349
|
// src/lib/update-check.ts
|
package/package.json
CHANGED