@302ai/media-studio-cli 0.1.1-beta.2 → 0.1.2-beta.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.
Files changed (3) hide show
  1. package/README.md +5 -5
  2. package/dist/index.js +201 -243
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -10,11 +10,11 @@ npm install -g @302ai/media-studio-cli
10
10
  # requires Node.js >= 22
11
11
  ```
12
12
 
13
- > **No stable release exists yet.** `latest` currently points at a prerelease.
14
- > Staging- and Local-server visibility is gated on the package *version*
15
- > carrying a prerelease tag — not on the dist-tag — so **Staging** and
16
- > **Local** appear in `msc login` and in `--region` whichever way you install.
17
- > A future stable release will hide them from both channels.
13
+ > **Staging and Local servers are not in released builds.** Region visibility
14
+ > is gated on the package *version* carrying a prerelease tag — not on the
15
+ > dist-tag — so **Staging** and **Local** are absent from `msc login` and from
16
+ > `--region` for every version published to npm. Only a working tree whose
17
+ > `version` is still a prerelease shows them.
18
18
 
19
19
  > If you installed via **bun** and get `command not found`: bun's global bin
20
20
  > dir is not on PATH by default. Run once:
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-beta.2",
4287
+ version: "0.1.2-beta.0",
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",
@@ -16975,7 +16975,7 @@ function saveConfigFile(data) {
16975
16975
  const dir = getConfigDir();
16976
16976
  mkdirSync(dir, { recursive: true });
16977
16977
  const configPath = getConfigFilePath();
16978
- const tmpPath = `${configPath}.${nanoid3()}.tmp`;
16978
+ const tmpPath = `${configPath}.tmp.${process.pid}.${nanoid3()}`;
16979
16979
  writeFileSync(tmpPath, JSON.stringify(data, null, 2), "utf8");
16980
16980
  chmodSync(tmpPath, 384);
16981
16981
  renameSync(tmpPath, configPath);
@@ -17541,6 +17541,12 @@ class MediaStudioClient {
17541
17541
  }, MeResponseSchema, (status) => `Authentication verification failed with status ${status}`);
17542
17542
  }
17543
17543
  }
17544
+ function createCliClient(options) {
17545
+ return new MediaStudioClient({
17546
+ baseUrl: options?.baseUrl ?? resolveApiBaseUrl(),
17547
+ apiKey: options?.apiKey ?? resolveApiKey()
17548
+ });
17549
+ }
17544
17550
  // src/client/tool-formatter.ts
17545
17551
  var ASPECT_RATIO_PATTERN = /aspect_ratio:\s*([^\s,;]+)/i;
17546
17552
  var MODEL_PATTERN = /(?:^|\n)\s*-\s*model:\s*([^\s,;]+)/i;
@@ -18065,7 +18071,7 @@ async function resolvePromptAttachments(options) {
18065
18071
  typed: typedByResolved[abs] ?? abs,
18066
18072
  file: await readAttachment(typedByResolved[abs] ?? abs, abs)
18067
18073
  })));
18068
- const client = new MediaStudioClient({
18074
+ const client = createCliClient({
18069
18075
  baseUrl: options.apiBaseUrl,
18070
18076
  apiKey: options.apiKey
18071
18077
  });
@@ -18129,7 +18135,7 @@ class SessionNotFoundError extends Error {
18129
18135
  }
18130
18136
  }
18131
18137
  async function ensureSessionExists(options) {
18132
- const client = new MediaStudioClient({
18138
+ const client = createCliClient({
18133
18139
  baseUrl: options.apiBaseUrl,
18134
18140
  apiKey: options.apiKey
18135
18141
  });
@@ -18149,7 +18155,7 @@ function finalizeProvision(result, spinner) {
18149
18155
  return result.sessionId;
18150
18156
  }
18151
18157
  async function provisionSession(options) {
18152
- const client = new MediaStudioClient({
18158
+ const client = createCliClient({
18153
18159
  baseUrl: options.apiBaseUrl,
18154
18160
  apiKey: options.apiKey
18155
18161
  });
@@ -18227,7 +18233,7 @@ async function resolvePromptSkills(options) {
18227
18233
  if (spans.length === 0) {
18228
18234
  return { text: options.prompt, skillUrls: [], autoEnabled: [] };
18229
18235
  }
18230
- const client = new MediaStudioClient({
18236
+ const client = createCliClient({
18231
18237
  baseUrl: options.apiBaseUrl,
18232
18238
  apiKey: options.apiKey
18233
18239
  });
@@ -18352,7 +18358,7 @@ async function streamTurn(options) {
18352
18358
  if (!args.json) {
18353
18359
  spinner.start("Connecting to Media Studio...");
18354
18360
  }
18355
- const stream = await new MediaStudioClient({
18361
+ const stream = await createCliClient({
18356
18362
  baseUrl: options.apiBaseUrl,
18357
18363
  apiKey: options.apiKey
18358
18364
  }).chat.stream({
@@ -18608,7 +18614,7 @@ var chatCommand = defineCommand({
18608
18614
  const shouldPatchNote = Boolean(explicitSessionDetail && !explicitSessionDetail.titleCustomized && explicitSessionDetail.isEmpty || !args.session && !args.new && readLastSessionPendingNote());
18609
18615
  if (shouldPatchNote) {
18610
18616
  const derivedNote = deriveFirstTurnNote(buildNotePrompt(promptWithAttachments, attachments), { fallbackTitle: CLI_DEFAULT_SESSION_NOTE });
18611
- new MediaStudioClient({
18617
+ createCliClient({
18612
18618
  baseUrl: apiBaseUrl,
18613
18619
  apiKey: resolveApiKey()
18614
18620
  }).sessions.updateNote(resolved.sessionId, derivedNote).then(() => clearLastSessionPendingNote()).catch(() => {});
@@ -20764,9 +20770,24 @@ var logoutCommand = defineCommand({
20764
20770
  }
20765
20771
  });
20766
20772
 
20773
+ // src/lib/run-command.ts
20774
+ async function runCliCommand(fn, options) {
20775
+ try {
20776
+ await fn();
20777
+ } catch (err) {
20778
+ if (isTransportFailure(err))
20779
+ throw err;
20780
+ reportCommandError(err, { json: options?.json });
20781
+ return;
20782
+ }
20783
+ }
20784
+
20767
20785
  // src/commands/sessions.ts
20768
20786
  function formatLastActive(iso) {
20769
- return iso.replace("T", " ").slice(0, 19);
20787
+ const date = new Date(iso);
20788
+ if (!iso || Number.isNaN(date.getTime()))
20789
+ return "";
20790
+ return date.toLocaleString("sv-SE", { hour12: false }).replace(", ", " ");
20770
20791
  }
20771
20792
  function renderSessionsTable(sessions, currentSessionId) {
20772
20793
  const rows = sessions.map((s) => ({
@@ -20792,11 +20813,6 @@ ${bodyLines.join(`
20792
20813
  `)}
20793
20814
  `;
20794
20815
  }
20795
- function resolveClient() {
20796
- const apiKey = resolveApiKey();
20797
- const apiBaseUrl = resolveApiBaseUrl();
20798
- return new MediaStudioClient({ baseUrl: apiBaseUrl, apiKey });
20799
- }
20800
20816
  function renderArtifactsTable(artifacts) {
20801
20817
  const rows = artifacts.map((a) => ({
20802
20818
  type: a.type,
@@ -20830,27 +20846,21 @@ var listSessionsCommand = defineCommand({
20830
20846
  description: "Output machine-readable JSON array"
20831
20847
  }
20832
20848
  },
20833
- run: async ({ args }) => {
20834
- try {
20835
- const client = resolveClient();
20836
- const response = await client.sessions.list();
20837
- if (args.json) {
20838
- process.stdout.write(`${JSON.stringify(response.data, null, 2)}
20849
+ run: ({ args }) => runCliCommand(async () => {
20850
+ const client = createCliClient();
20851
+ const response = await client.sessions.list();
20852
+ if (args.json) {
20853
+ process.stdout.write(`${JSON.stringify(response.data, null, 2)}
20839
20854
  `);
20840
- return;
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 });
20855
+ return;
20852
20856
  }
20853
- }
20857
+ if (response.data.length === 0) {
20858
+ consola.info("No sessions found.");
20859
+ return;
20860
+ }
20861
+ const currentId = readLastSessionId();
20862
+ consola.log(renderSessionsTable(response.data, currentId));
20863
+ }, { json: args.json })
20854
20864
  });
20855
20865
  var artifactsCommand = defineCommand({
20856
20866
  meta: {
@@ -20869,28 +20879,22 @@ var artifactsCommand = defineCommand({
20869
20879
  description: "Output machine-readable JSON array"
20870
20880
  }
20871
20881
  },
20872
- run: async ({ args }) => {
20873
- try {
20874
- const client = resolveClient();
20875
- const response = await client.sessions.artifacts({
20876
- sessionId: args.sessionId
20877
- });
20878
- if (args.json) {
20879
- process.stdout.write(`${JSON.stringify(response.data, null, 2)}
20882
+ run: ({ args }) => runCliCommand(async () => {
20883
+ const client = createCliClient();
20884
+ const response = await client.sessions.artifacts({
20885
+ sessionId: args.sessionId
20886
+ });
20887
+ if (args.json) {
20888
+ process.stdout.write(`${JSON.stringify(response.data, null, 2)}
20880
20889
  `);
20881
- return;
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 });
20890
+ return;
20892
20891
  }
20893
- }
20892
+ if (response.data.length === 0) {
20893
+ consola.info("No artifacts found.");
20894
+ return;
20895
+ }
20896
+ consola.log(renderArtifactsTable(response.data));
20897
+ }, { json: args.json })
20894
20898
  });
20895
20899
  var useSessionCommand = defineCommand({
20896
20900
  meta: {
@@ -20913,50 +20917,44 @@ var useSessionCommand = defineCommand({
20913
20917
  description: "Output machine-readable JSON: { sessionId }"
20914
20918
  }
20915
20919
  },
20916
- run: async ({ args }) => {
20917
- try {
20918
- const sessionId = args.sessionId;
20919
- const apiBaseUrl = resolveApiBaseUrl();
20920
- if (args.new) {
20921
- if (sessionId) {
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;
20938
- }
20939
- if (!sessionId) {
20940
- throw new Error("Pass the session id to switch to, or --new to create a new session.");
20920
+ run: ({ args }) => runCliCommand(async () => {
20921
+ const sessionId = args.sessionId;
20922
+ const apiBaseUrl = resolveApiBaseUrl();
20923
+ if (args.new) {
20924
+ if (sessionId) {
20925
+ throw new Error("--new and <session-id> cannot be combined: pass one, not both.");
20941
20926
  }
20942
- await ensureSessionExists({
20927
+ const result = await provisionSession({
20943
20928
  apiBaseUrl,
20944
20929
  apiKey: resolveApiKey(),
20945
- sessionId
20930
+ note: CLI_DEFAULT_SESSION_NOTE
20946
20931
  });
20947
- saveLastSessionId(sessionId);
20932
+ const created = finalizeProvision(result);
20933
+ saveLastSessionId(created, { pendingNote: true });
20948
20934
  if (args.json) {
20949
- process.stdout.write(`${JSON.stringify({ sessionId })}
20935
+ process.stdout.write(`${JSON.stringify({ sessionId: created })}
20950
20936
  `);
20951
20937
  return;
20952
20938
  }
20953
- consola.success(`Switched default session to ${sessionId}`);
20954
- } catch (err) {
20955
- if (isTransportFailure(err))
20956
- throw err;
20957
- reportCommandError(err, { json: args.json });
20939
+ consola.success(`Created and switched to session ${created}`);
20940
+ return;
20958
20941
  }
20959
- }
20942
+ if (!sessionId) {
20943
+ throw new Error("Pass the session id to switch to, or --new to create a new session.");
20944
+ }
20945
+ await ensureSessionExists({
20946
+ apiBaseUrl,
20947
+ apiKey: resolveApiKey(),
20948
+ sessionId
20949
+ });
20950
+ saveLastSessionId(sessionId);
20951
+ if (args.json) {
20952
+ process.stdout.write(`${JSON.stringify({ sessionId })}
20953
+ `);
20954
+ return;
20955
+ }
20956
+ consola.success(`Switched default session to ${sessionId}`);
20957
+ }, { json: args.json })
20960
20958
  });
20961
20959
  var sessionsCommand = defineCommand({
20962
20960
  meta: {
@@ -20980,26 +20978,19 @@ function needsConfirmationRefusal(yes) {
20980
20978
  }
20981
20979
 
20982
20980
  // src/commands/skills.ts
20983
- function resolveClient2() {
20984
- return new MediaStudioClient({
20985
- baseUrl: resolveApiBaseUrl(),
20986
- apiKey: resolveApiKey()
20987
- });
20988
- }
20989
20981
  function stateMarker(state) {
20990
- if (state === "on")
20991
- return "[on]";
20992
- if (state === "off")
20993
- return "[off]";
20994
- return "[-] ";
20982
+ const marker = state === "on" ? "[on]" : state === "off" ? "[off]" : "[-]";
20983
+ return marker.padEnd(5);
20995
20984
  }
20985
+ var NAME_SEP = " ";
20986
+ var NAME_INDENT = stateMarker("off").length + NAME_SEP.length;
20996
20987
  function renderSkillRow(state, name, description) {
20997
20988
  const marker = stateMarker(state);
20998
20989
  const colorize = state === "on" ? import_picocolors2.green : state === "off" ? import_picocolors2.red : import_picocolors2.dim;
20999
- const head = `${colorize(marker)} ${stripControlChars(name)}`;
20990
+ const head = `${colorize(marker)}${NAME_SEP}${stripControlChars(name)}`;
21000
20991
  const clean = stripControlChars(description).trim();
21001
20992
  return clean ? `${head}
21002
- ${" ".repeat(6)}${clean}` : head;
20993
+ ${" ".repeat(NAME_INDENT)}${clean}` : head;
21003
20994
  }
21004
20995
  var addSkillCommand = defineCommand({
21005
20996
  meta: {
@@ -21018,23 +21009,17 @@ var addSkillCommand = defineCommand({
21018
21009
  description: "Output machine-readable JSON"
21019
21010
  }
21020
21011
  },
21021
- run: async ({ args }) => {
21022
- try {
21023
- const client = resolveClient2();
21024
- const entry = await findPlazaEntry(client, args["skill-slug"]);
21025
- const skill = await client.skills.install(entry);
21026
- if (args.json) {
21027
- process.stdout.write(`${JSON.stringify(skill, null, 2)}
21012
+ run: ({ args }) => runCliCommand(async () => {
21013
+ const client = createCliClient();
21014
+ const entry = await findPlazaEntry(client, args["skill-slug"]);
21015
+ const skill = await client.skills.install(entry);
21016
+ if (args.json) {
21017
+ process.stdout.write(`${JSON.stringify(skill, null, 2)}
21028
21018
  `);
21029
- return;
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 });
21019
+ return;
21036
21020
  }
21037
- }
21021
+ consola.success(`Installed ${stripControlChars(skill.command)} (${stripControlChars(skill.name)}).`);
21022
+ }, { json: args.json })
21038
21023
  });
21039
21024
  var rmSkillCommand = defineCommand({
21040
21025
  meta: {
@@ -21058,36 +21043,30 @@ var rmSkillCommand = defineCommand({
21058
21043
  description: "Output machine-readable JSON"
21059
21044
  }
21060
21045
  },
21061
- run: async ({ args }) => {
21062
- try {
21063
- if (needsConfirmationRefusal(args.yes === true)) {
21064
- throw new Error("Confirmation required. Pass --yes to confirm removal non-interactively.");
21065
- }
21066
- if (!args.yes) {
21067
- const confirmed = await confirm({
21068
- message: `Remove skill "${args["skill-command"]}" from your library? Re-installing needs a fresh plaza install.`,
21069
- initialValue: false
21070
- });
21071
- if (isCancel(confirmed) || !confirmed) {
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
- `);
21046
+ run: ({ args }) => runCliCommand(async () => {
21047
+ if (needsConfirmationRefusal(args.yes === true)) {
21048
+ throw new Error("Confirmation required. Pass --yes to confirm removal non-interactively.");
21049
+ }
21050
+ if (!args.yes) {
21051
+ const confirmed = await confirm({
21052
+ message: `Remove skill "${args["skill-command"]}" from your library? Re-installing needs a fresh plaza install.`,
21053
+ initialValue: false
21054
+ });
21055
+ if (isCancel(confirmed) || !confirmed) {
21056
+ consola.info("Skill removal cancelled.");
21082
21057
  return;
21083
21058
  }
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
21059
  }
21090
- }
21060
+ const client = createCliClient();
21061
+ const skill = await findLibraryEntry(client, args["skill-command"]);
21062
+ await client.skills.remove(skill.id);
21063
+ if (args.json) {
21064
+ process.stdout.write(`${JSON.stringify({ success: true, id: skill.id, deleted: true }, null, 2)}
21065
+ `);
21066
+ return;
21067
+ }
21068
+ consola.success(`Skill "${args["skill-command"]}" removed from your library.`);
21069
+ }, { json: args.json })
21091
21070
  });
21092
21071
  function makeSetEnabledCommand(name, enabled, description) {
21093
21072
  return defineCommand({
@@ -21104,23 +21083,17 @@ function makeSetEnabledCommand(name, enabled, description) {
21104
21083
  description: "Output machine-readable JSON"
21105
21084
  }
21106
21085
  },
21107
- run: async ({ args }) => {
21108
- try {
21109
- const client = resolveClient2();
21110
- const found = await findLibraryEntry(client, args["skill-command"]);
21111
- const skill = await client.skills.setEnabled(found.id, enabled);
21112
- if (args.json) {
21113
- process.stdout.write(`${JSON.stringify(skill, null, 2)}
21086
+ run: ({ args }) => runCliCommand(async () => {
21087
+ const client = createCliClient();
21088
+ const found = await findLibraryEntry(client, args["skill-command"]);
21089
+ const skill = await client.skills.setEnabled(found.id, enabled);
21090
+ if (args.json) {
21091
+ process.stdout.write(`${JSON.stringify(skill, null, 2)}
21114
21092
  `);
21115
- return;
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 });
21093
+ return;
21122
21094
  }
21123
- }
21095
+ consola.success(`${enabled ? "Enabled" : "Disabled"} ${stripControlChars(skill.command)}.`);
21096
+ }, { json: args.json })
21124
21097
  });
21125
21098
  }
21126
21099
  var enableSkillCommand = makeSetEnabledCommand("enable", true, "Enable a skill in your library");
@@ -21162,59 +21135,53 @@ var skillsCommand = defineCommand({
21162
21135
  enable: enableSkillCommand,
21163
21136
  rm: rmSkillCommand
21164
21137
  },
21165
- run: async ({ args }) => {
21166
- try {
21167
- const client = resolveClient2();
21168
- if (args.plaza) {
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();
21138
+ run: ({ args }) => runCliCommand(async () => {
21139
+ const client = createCliClient();
21140
+ if (args.plaza) {
21141
+ const plaza = await client.skills.browsePlaza();
21196
21142
  if (args.json) {
21197
- process.stdout.write(`${JSON.stringify(skills, null, 2)}
21143
+ process.stdout.write(`${JSON.stringify(plaza, null, 2)}
21198
21144
  `);
21199
21145
  return;
21200
21146
  }
21201
- if (skills.length === 0) {
21202
- consola.info("Your skill library is empty. Browse the plaza with --plaza, or add skills in the Media Studio web app.");
21147
+ if (plaza.length === 0) {
21148
+ consola.info("The Skill Plaza has no entries yet.");
21203
21149
  return;
21204
21150
  }
21205
- const rows = skills.map((s) => renderSkillRow(s.enabled ? "on" : "off", s.name, s.descriptionEn));
21151
+ const installed = plaza.filter((s) => s.added);
21152
+ const available = plaza.filter((s) => !s.added);
21153
+ const installedRows = installed.map((s) => renderSkillRow(s.enabled ? "on" : "off", s.name, s.descriptionEn));
21154
+ const availableRows = available.map((s) => renderSkillRow("none", s.name, s.descriptionEn));
21206
21155
  consola.log([
21207
- ...rows,
21156
+ `Installed (${installed.length})`,
21157
+ ...installedRows,
21158
+ "",
21159
+ `Available (${available.length})`,
21160
+ ...availableRows,
21208
21161
  "",
21209
- import_picocolors2.gray("skills in this list can be referenced as %%skill-name%% in a prompt")
21162
+ import_picocolors2.gray(`install with msc skills add <slug> · slug names are in --json`)
21210
21163
  ].join(`
21211
21164
  `));
21212
- } catch (err) {
21213
- if (isTransportFailure(err))
21214
- throw err;
21215
- reportCommandError(err, { json: args.json });
21165
+ return;
21216
21166
  }
21217
- }
21167
+ const skills = await client.skills.listAll();
21168
+ if (args.json) {
21169
+ process.stdout.write(`${JSON.stringify(skills, null, 2)}
21170
+ `);
21171
+ return;
21172
+ }
21173
+ if (skills.length === 0) {
21174
+ consola.info("Your skill library is empty. Browse the plaza with --plaza, or add skills in the Media Studio web app.");
21175
+ return;
21176
+ }
21177
+ const rows = skills.map((s) => renderSkillRow(s.enabled ? "on" : "off", s.name, s.descriptionEn));
21178
+ consola.log([
21179
+ ...rows,
21180
+ "",
21181
+ import_picocolors2.gray("skills in this list can be referenced as %%skill-name%% in a prompt")
21182
+ ].join(`
21183
+ `));
21184
+ }, { json: args.json })
21218
21185
  });
21219
21186
 
21220
21187
  // src/commands/whoami.ts
@@ -21226,7 +21193,7 @@ var whoamiCommand = defineCommand({
21226
21193
  name: "whoami",
21227
21194
  description: "Display current authentication status"
21228
21195
  },
21229
- run: async () => {
21196
+ run: () => runCliCommand(async () => {
21230
21197
  let auth;
21231
21198
  try {
21232
21199
  auth = readAuthFile();
@@ -21243,50 +21210,41 @@ var whoamiCommand = defineCommand({
21243
21210
  return;
21244
21211
  }
21245
21212
  const apiUrl = resolveApiBaseUrl();
21246
- const client = new MediaStudioClient({
21247
- baseUrl: apiUrl,
21248
- apiKey: auth.token
21249
- });
21250
- try {
21251
- const data = await client.getMe();
21252
- if (!data.valid) {
21253
- consola.error("Session expired or token invalid.\nPlease run `msc login` to re-authenticate.");
21254
- process.exit(1);
21255
- return;
21256
- }
21257
- const updatedName = data.name ?? auth.username;
21258
- const updatedUid = data.uid ?? auth.uid;
21259
- const updatedEmail = data.email ?? auth.email;
21260
- if (updatedName !== auth.username || updatedUid !== auth.uid || updatedEmail !== auth.email) {
21261
- try {
21262
- saveAuthFile({
21263
- ...auth,
21264
- token: client.apiKey,
21265
- username: updatedName,
21266
- uid: updatedUid,
21267
- email: updatedEmail
21268
- });
21269
- } catch (err) {
21270
- consola.warn(err instanceof Error ? err.message : String(err));
21271
- }
21272
- }
21273
- consola.success("Authenticated");
21274
- const lines = [
21275
- updatedName ? ` User: ${updatedName}` : null,
21276
- updatedUid ? ` UID: ${updatedUid}` : null,
21277
- updatedEmail ? ` Email: ${updatedEmail}` : null,
21278
- data.apiKeyMasked ? ` API Key: ${data.apiKeyMasked}` : null,
21279
- ` Token: ${maskToken(client.apiKey)}`
21280
- ].filter(Boolean);
21281
- consola.log(`${lines.join(`
21213
+ const client = createCliClient({ baseUrl: apiUrl, apiKey: auth.token });
21214
+ const data = await client.getMe();
21215
+ if (!data.valid) {
21216
+ consola.error("Session expired or token invalid.\nPlease run `msc login` to re-authenticate.");
21217
+ process.exit(1);
21218
+ return;
21219
+ }
21220
+ const updatedName = data.name ?? auth.username;
21221
+ const updatedUid = data.uid ?? auth.uid;
21222
+ const updatedEmail = data.email ?? auth.email;
21223
+ if (updatedName !== auth.username || updatedUid !== auth.uid || updatedEmail !== auth.email) {
21224
+ try {
21225
+ saveAuthFile({
21226
+ ...auth,
21227
+ token: client.apiKey,
21228
+ username: updatedName,
21229
+ uid: updatedUid,
21230
+ email: updatedEmail
21231
+ });
21232
+ } catch (err) {
21233
+ consola.warn(err instanceof Error ? err.message : String(err));
21234
+ }
21235
+ }
21236
+ consola.success("Authenticated");
21237
+ const lines = [
21238
+ updatedName ? ` User: ${updatedName}` : null,
21239
+ updatedUid ? ` UID: ${updatedUid}` : null,
21240
+ updatedEmail ? ` Email: ${updatedEmail}` : null,
21241
+ data.apiKeyMasked ? ` API Key: ${data.apiKeyMasked}` : null,
21242
+ ` Token: ${maskToken(client.apiKey)}`
21243
+ ].filter(Boolean);
21244
+ consola.log(`${lines.join(`
21282
21245
  `)}
21283
21246
  `);
21284
- } catch (err) {
21285
- if (isTransportFailure(err))
21286
- throw err;
21287
- reportCommandError(err);
21288
- }
21289
- }
21247
+ })
21290
21248
  });
21291
21249
 
21292
21250
  // src/lib/update-check.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@302ai/media-studio-cli",
3
- "version": "0.1.1-beta.2",
3
+ "version": "0.1.2-beta.0",
4
4
  "description": "CLI for AI Media Studio — let external agents drive the core media-studio features",
5
5
  "author": "302.AI",
6
6
  "license": "Apache-2.0",