@vm0/cli 9.9.2 → 9.11.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 (2) hide show
  1. package/index.js +247 -109
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1904,19 +1904,55 @@ var MODEL_PROVIDER_TYPES = {
1904
1904
  label: "Anthropic API Key",
1905
1905
  credentialLabel: "API key",
1906
1906
  helpText: "Get your API key at: https://console.anthropic.com/settings/keys"
1907
+ },
1908
+ "moonshot-api-key": {
1909
+ framework: "claude-code",
1910
+ credentialName: "MOONSHOT_API_KEY",
1911
+ label: "Moonshot API Key (Kimi)",
1912
+ credentialLabel: "API key",
1913
+ helpText: "Get your API key at: https://platform.moonshot.ai/console/api-keys",
1914
+ environmentMapping: {
1915
+ ANTHROPIC_AUTH_TOKEN: "$credential",
1916
+ ANTHROPIC_BASE_URL: "https://api.moonshot.ai/anthropic",
1917
+ ANTHROPIC_MODEL: "$model",
1918
+ ANTHROPIC_DEFAULT_OPUS_MODEL: "$model",
1919
+ ANTHROPIC_DEFAULT_SONNET_MODEL: "$model",
1920
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: "$model",
1921
+ CLAUDE_CODE_SUBAGENT_MODEL: "$model"
1922
+ },
1923
+ models: [
1924
+ "kimi-k2.5",
1925
+ "kimi-k2-thinking-turbo",
1926
+ "kimi-k2-thinking"
1927
+ ],
1928
+ defaultModel: "kimi-k2.5"
1907
1929
  }
1908
1930
  };
1909
1931
  var modelProviderTypeSchema = z14.enum([
1910
1932
  "claude-code-oauth-token",
1911
- "anthropic-api-key"
1933
+ "anthropic-api-key",
1934
+ "moonshot-api-key"
1912
1935
  ]);
1913
1936
  var modelProviderFrameworkSchema = z14.enum(["claude-code", "codex"]);
1937
+ function getModels(type) {
1938
+ const config = MODEL_PROVIDER_TYPES[type];
1939
+ return "models" in config ? config.models : void 0;
1940
+ }
1941
+ function getDefaultModel(type) {
1942
+ const config = MODEL_PROVIDER_TYPES[type];
1943
+ return "defaultModel" in config ? config.defaultModel : void 0;
1944
+ }
1945
+ function hasModelSelection(type) {
1946
+ const config = MODEL_PROVIDER_TYPES[type];
1947
+ return "models" in config && config.models.length > 0;
1948
+ }
1914
1949
  var modelProviderResponseSchema = z14.object({
1915
1950
  id: z14.string().uuid(),
1916
1951
  type: modelProviderTypeSchema,
1917
1952
  framework: modelProviderFrameworkSchema,
1918
1953
  credentialName: z14.string(),
1919
1954
  isDefault: z14.boolean(),
1955
+ selectedModel: z14.string().nullable(),
1920
1956
  createdAt: z14.string(),
1921
1957
  updatedAt: z14.string()
1922
1958
  });
@@ -1926,7 +1962,8 @@ var modelProviderListResponseSchema = z14.object({
1926
1962
  var upsertModelProviderRequestSchema = z14.object({
1927
1963
  type: modelProviderTypeSchema,
1928
1964
  credential: z14.string().min(1, "Credential is required"),
1929
- convert: z14.boolean().optional()
1965
+ convert: z14.boolean().optional(),
1966
+ selectedModel: z14.string().optional()
1930
1967
  });
1931
1968
  var upsertModelProviderResponseSchema = z14.object({
1932
1969
  provider: modelProviderResponseSchema,
@@ -6655,12 +6692,11 @@ function showNextSteps(result) {
6655
6692
  function handleGenericRunError(error, commandLabel) {
6656
6693
  if (error instanceof ApiRequestError && error.code === "concurrent_run_limit_exceeded") {
6657
6694
  console.error(chalk7.red(`\u2717 ${commandLabel} failed`));
6658
- console.error(chalk7.dim(` ${error.message}`));
6659
- console.log();
6660
- console.log(" To view active runs:");
6661
- console.log(chalk7.cyan(" vm0 run list"));
6662
- console.log(" To cancel a run:");
6663
- console.log(chalk7.cyan(" vm0 run kill <run-id>"));
6695
+ console.error(
6696
+ chalk7.dim(
6697
+ ` ${error.message} Use 'vm0 run list' to view runs, 'vm0 run kill <id>' to cancel.`
6698
+ )
6699
+ );
6664
6700
  } else {
6665
6701
  console.error(chalk7.red(`\u2717 ${commandLabel} failed`));
6666
6702
  console.error(chalk7.dim(` ${error.message}`));
@@ -8465,7 +8501,7 @@ var cookAction = new Command27().name("cook").description("Quick start: prepare,
8465
8501
  ).option("-y, --yes", "Skip confirmation prompts").option("-v, --verbose", "Show full tool inputs and outputs").addOption(new Option4("--debug-no-mock-claude").hideHelp()).addOption(new Option4("--no-auto-update").hideHelp()).action(
8466
8502
  async (prompt, options) => {
8467
8503
  if (!options.noAutoUpdate) {
8468
- const shouldExit = await checkAndUpgrade("9.9.2", prompt);
8504
+ const shouldExit = await checkAndUpgrade("9.11.0", prompt);
8469
8505
  if (shouldExit) {
8470
8506
  process.exit(0);
8471
8507
  }
@@ -10843,7 +10879,8 @@ var listCommand7 = new Command51().name("list").alias("ls").description("List al
10843
10879
  console.log(` ${chalk50.cyan(framework)}:`);
10844
10880
  for (const provider of providers) {
10845
10881
  const defaultTag = provider.isDefault ? chalk50.green(" (default)") : "";
10846
- console.log(` ${provider.type}${defaultTag}`);
10882
+ const modelTag = provider.selectedModel ? chalk50.dim(` [${provider.selectedModel}]`) : "";
10883
+ console.log(` ${provider.type}${defaultTag}${modelTag}`);
10847
10884
  console.log(
10848
10885
  chalk50.dim(
10849
10886
  ` Updated: ${new Date(provider.updatedAt).toLocaleString()}`
@@ -10879,122 +10916,184 @@ var providerChoices = Object.entries(MODEL_PROVIDER_TYPES).map(
10879
10916
  value: type
10880
10917
  })
10881
10918
  );
10919
+ function validateProviderType(typeStr) {
10920
+ if (!Object.keys(MODEL_PROVIDER_TYPES).includes(typeStr)) {
10921
+ console.error(chalk51.red(`\u2717 Invalid type "${typeStr}"`));
10922
+ console.log();
10923
+ console.log("Valid types:");
10924
+ for (const [t, config] of Object.entries(MODEL_PROVIDER_TYPES)) {
10925
+ console.log(` ${chalk51.cyan(t)} - ${config.label}`);
10926
+ }
10927
+ process.exit(1);
10928
+ }
10929
+ return typeStr;
10930
+ }
10931
+ function validateModel(type, modelStr) {
10932
+ const models = getModels(type);
10933
+ if (models && !models.includes(modelStr)) {
10934
+ console.error(chalk51.red(`\u2717 Invalid model "${modelStr}"`));
10935
+ console.log();
10936
+ console.log("Valid models:");
10937
+ for (const m of models) {
10938
+ console.log(` ${chalk51.cyan(m)}`);
10939
+ }
10940
+ process.exit(1);
10941
+ }
10942
+ return modelStr;
10943
+ }
10944
+ function handleNonInteractiveMode(options) {
10945
+ const type = validateProviderType(options.type);
10946
+ let selectedModel;
10947
+ if (options.model) {
10948
+ selectedModel = validateModel(type, options.model);
10949
+ } else if (hasModelSelection(type)) {
10950
+ selectedModel = getDefaultModel(type);
10951
+ }
10952
+ return { type, credential: options.credential, selectedModel };
10953
+ }
10954
+ async function promptForModelSelection(type) {
10955
+ if (!hasModelSelection(type)) {
10956
+ return void 0;
10957
+ }
10958
+ const models = getModels(type) ?? [];
10959
+ const defaultModel = getDefaultModel(type);
10960
+ const modelChoices = models.map((model) => ({
10961
+ title: model === defaultModel ? `${model} (Recommended)` : model,
10962
+ value: model
10963
+ }));
10964
+ const modelResponse = await prompts2(
10965
+ {
10966
+ type: "select",
10967
+ name: "model",
10968
+ message: "Select model:",
10969
+ choices: modelChoices
10970
+ },
10971
+ { onCancel: () => process.exit(0) }
10972
+ );
10973
+ return modelResponse.model;
10974
+ }
10975
+ async function handleInteractiveMode() {
10976
+ if (!isInteractive()) {
10977
+ console.error(chalk51.red("\u2717 Interactive mode requires a TTY"));
10978
+ console.log();
10979
+ console.log("Use non-interactive mode:");
10980
+ console.log(
10981
+ chalk51.cyan(
10982
+ ' vm0 model-provider setup --type <type> --credential "<value>"'
10983
+ )
10984
+ );
10985
+ process.exit(1);
10986
+ }
10987
+ const typeResponse = await prompts2(
10988
+ {
10989
+ type: "select",
10990
+ name: "type",
10991
+ message: "Select provider type:",
10992
+ choices: providerChoices
10993
+ },
10994
+ { onCancel: () => process.exit(0) }
10995
+ );
10996
+ const type = typeResponse.type;
10997
+ const checkResult = await checkModelProviderCredential(type);
10998
+ if (checkResult.exists && checkResult.currentType === "user") {
10999
+ const convertResponse = await prompts2(
11000
+ {
11001
+ type: "confirm",
11002
+ name: "convert",
11003
+ message: `Credential "${checkResult.credentialName}" already exists. Convert to model provider?`,
11004
+ initial: true
11005
+ },
11006
+ { onCancel: () => process.exit(0) }
11007
+ );
11008
+ if (convertResponse.convert) {
11009
+ const provider = await convertModelProviderCredential(type);
11010
+ const defaultNote = provider.isDefault ? ` (default for ${provider.framework})` : "";
11011
+ console.log(
11012
+ chalk51.green(
11013
+ `\u2713 Converted "${checkResult.credentialName}" to model provider${defaultNote}`
11014
+ )
11015
+ );
11016
+ return null;
11017
+ }
11018
+ console.log(chalk51.dim("Aborted"));
11019
+ process.exit(0);
11020
+ }
11021
+ const config = MODEL_PROVIDER_TYPES[type];
11022
+ console.log();
11023
+ console.log(chalk51.dim(config.helpText));
11024
+ console.log();
11025
+ const credentialResponse = await prompts2(
11026
+ {
11027
+ type: "password",
11028
+ name: "credential",
11029
+ message: `Enter your ${config.credentialLabel}:`,
11030
+ validate: (value) => value.length > 0 || `${config.credentialLabel} is required`
11031
+ },
11032
+ { onCancel: () => process.exit(0) }
11033
+ );
11034
+ const credential = credentialResponse.credential;
11035
+ const selectedModel = await promptForModelSelection(type);
11036
+ return { type, credential, selectedModel };
11037
+ }
11038
+ function handleSetupError2(error) {
11039
+ if (error instanceof Error) {
11040
+ if (error.message.includes("already exists")) {
11041
+ console.error(chalk51.red(`\u2717 ${error.message}`));
11042
+ console.log();
11043
+ console.log("To convert the existing credential, run:");
11044
+ console.log(chalk51.cyan(" vm0 model-provider setup --convert"));
11045
+ } else if (error.message.includes("Not authenticated")) {
11046
+ console.error(chalk51.red("\u2717 Not authenticated. Run: vm0 auth login"));
11047
+ } else {
11048
+ console.error(chalk51.red(`\u2717 ${error.message}`));
11049
+ }
11050
+ } else {
11051
+ console.error(chalk51.red("\u2717 An unexpected error occurred"));
11052
+ }
11053
+ process.exit(1);
11054
+ }
10882
11055
  var setupCommand2 = new Command52().name("setup").description("Configure a model provider").option("-t, --type <type>", "Provider type (for non-interactive mode)").option(
10883
11056
  "-c, --credential <credential>",
10884
11057
  "Credential value (for non-interactive mode)"
10885
- ).option("--convert", "Convert existing user credential to model provider").action(
11058
+ ).option("-m, --model <model>", "Model selection (for non-interactive mode)").option("--convert", "Convert existing user credential to model provider").action(
10886
11059
  async (options) => {
10887
11060
  try {
10888
- let type;
10889
- let credential;
11061
+ let input;
10890
11062
  const shouldConvert = options.convert ?? false;
10891
11063
  if (options.type && options.credential) {
10892
- if (!Object.keys(MODEL_PROVIDER_TYPES).includes(options.type)) {
10893
- console.error(chalk51.red(`\u2717 Invalid type "${options.type}"`));
10894
- console.log();
10895
- console.log("Valid types:");
10896
- for (const [t, config] of Object.entries(MODEL_PROVIDER_TYPES)) {
10897
- console.log(` ${chalk51.cyan(t)} - ${config.label}`);
10898
- }
10899
- process.exit(1);
10900
- }
10901
- type = options.type;
10902
- credential = options.credential;
11064
+ input = handleNonInteractiveMode({
11065
+ type: options.type,
11066
+ credential: options.credential,
11067
+ model: options.model
11068
+ });
10903
11069
  } else if (options.type || options.credential) {
10904
11070
  console.error(
10905
11071
  chalk51.red("\u2717 Both --type and --credential are required")
10906
11072
  );
10907
11073
  process.exit(1);
10908
11074
  } else {
10909
- if (!isInteractive()) {
10910
- console.error(chalk51.red("\u2717 Interactive mode requires a TTY"));
10911
- console.log();
10912
- console.log("Use non-interactive mode:");
10913
- console.log(
10914
- chalk51.cyan(
10915
- ' vm0 model-provider setup --type <type> --credential "<value>"'
10916
- )
10917
- );
10918
- process.exit(1);
10919
- }
10920
- const typeResponse = await prompts2(
10921
- {
10922
- type: "select",
10923
- name: "type",
10924
- message: "Select provider type:",
10925
- choices: providerChoices
10926
- },
10927
- { onCancel: () => process.exit(0) }
10928
- );
10929
- type = typeResponse.type;
10930
- const checkResult = await checkModelProviderCredential(type);
10931
- if (checkResult.exists && checkResult.currentType === "user") {
10932
- const convertResponse = await prompts2(
10933
- {
10934
- type: "confirm",
10935
- name: "convert",
10936
- message: `Credential "${checkResult.credentialName}" already exists. Convert to model provider?`,
10937
- initial: true
10938
- },
10939
- { onCancel: () => process.exit(0) }
10940
- );
10941
- if (convertResponse.convert) {
10942
- const provider2 = await convertModelProviderCredential(type);
10943
- const defaultNote2 = provider2.isDefault ? ` (default for ${provider2.framework})` : "";
10944
- console.log(
10945
- chalk51.green(
10946
- `\u2713 Converted "${checkResult.credentialName}" to model provider${defaultNote2}`
10947
- )
10948
- );
10949
- return;
10950
- } else {
10951
- console.log(chalk51.dim("Aborted"));
10952
- process.exit(0);
10953
- }
11075
+ const result = await handleInteractiveMode();
11076
+ if (result === null) {
11077
+ return;
10954
11078
  }
10955
- const config = MODEL_PROVIDER_TYPES[type];
10956
- console.log();
10957
- console.log(chalk51.dim(config.helpText));
10958
- console.log();
10959
- const credentialResponse = await prompts2(
10960
- {
10961
- type: "password",
10962
- name: "credential",
10963
- message: `Enter your ${config.credentialLabel}:`,
10964
- validate: (value) => value.length > 0 || `${config.credentialLabel} is required`
10965
- },
10966
- { onCancel: () => process.exit(0) }
10967
- );
10968
- credential = credentialResponse.credential;
11079
+ input = result;
10969
11080
  }
10970
11081
  const { provider, created } = await upsertModelProvider({
10971
- type,
10972
- credential,
10973
- convert: shouldConvert
11082
+ type: input.type,
11083
+ credential: input.credential,
11084
+ convert: shouldConvert,
11085
+ selectedModel: input.selectedModel
10974
11086
  });
10975
11087
  const action = created ? "created" : "updated";
10976
11088
  const defaultNote = provider.isDefault ? ` (default for ${provider.framework})` : "";
11089
+ const modelNote = provider.selectedModel ? ` with model: ${provider.selectedModel}` : "";
10977
11090
  console.log(
10978
- chalk51.green(`\u2713 Model provider "${type}" ${action}${defaultNote}`)
11091
+ chalk51.green(
11092
+ `\u2713 Model provider "${input.type}" ${action}${defaultNote}${modelNote}`
11093
+ )
10979
11094
  );
10980
11095
  } catch (error) {
10981
- if (error instanceof Error) {
10982
- if (error.message.includes("already exists")) {
10983
- console.error(chalk51.red(`\u2717 ${error.message}`));
10984
- console.log();
10985
- console.log("To convert the existing credential, run:");
10986
- console.log(chalk51.cyan(" vm0 model-provider setup --convert"));
10987
- } else if (error.message.includes("Not authenticated")) {
10988
- console.error(
10989
- chalk51.red("\u2717 Not authenticated. Run: vm0 auth login")
10990
- );
10991
- } else {
10992
- console.error(chalk51.red(`\u2717 ${error.message}`));
10993
- }
10994
- } else {
10995
- console.error(chalk51.red("\u2717 An unexpected error occurred"));
10996
- }
10997
- process.exit(1);
11096
+ handleSetupError2(error);
10998
11097
  }
10999
11098
  }
11000
11099
  );
@@ -11300,7 +11399,9 @@ function getProviderChoices() {
11300
11399
  type,
11301
11400
  label: MODEL_PROVIDER_TYPES[type].label,
11302
11401
  helpText: MODEL_PROVIDER_TYPES[type].helpText,
11303
- credentialLabel: MODEL_PROVIDER_TYPES[type].credentialLabel
11402
+ credentialLabel: MODEL_PROVIDER_TYPES[type].credentialLabel,
11403
+ models: getModels(type),
11404
+ defaultModel: getDefaultModel(type)
11304
11405
  })
11305
11406
  );
11306
11407
  }
@@ -11308,7 +11409,8 @@ async function setupModelProvider(type, credential, options) {
11308
11409
  const response = await upsertModelProvider({
11309
11410
  type,
11310
11411
  credential,
11311
- convert: options?.convert
11412
+ convert: options?.convert,
11413
+ selectedModel: options?.selectedModel
11312
11414
  });
11313
11415
  return {
11314
11416
  provider: response.provider,
@@ -11397,10 +11499,27 @@ async function addMarketplace() {
11397
11499
  );
11398
11500
  }
11399
11501
  }
11502
+ async function updateMarketplace() {
11503
+ const result = await runClaudeCommand([
11504
+ "plugin",
11505
+ "marketplace",
11506
+ "update",
11507
+ MARKETPLACE_NAME
11508
+ ]);
11509
+ if (!result.success) {
11510
+ console.warn(
11511
+ chalk56.yellow(
11512
+ `Warning: Could not update marketplace: ${result.error ?? "unknown error"}`
11513
+ )
11514
+ );
11515
+ }
11516
+ }
11400
11517
  async function ensureMarketplace() {
11401
11518
  const installed = await isMarketplaceInstalled();
11402
11519
  if (!installed) {
11403
11520
  await addMarketplace();
11521
+ } else {
11522
+ await updateMarketplace();
11404
11523
  }
11405
11524
  }
11406
11525
  async function installVm0Plugin(scope = "user", cwd) {
@@ -11491,10 +11610,29 @@ async function handleModelProvider(ctx) {
11491
11610
  console.log(chalk57.dim("Cancelled"));
11492
11611
  process.exit(0);
11493
11612
  }
11494
- const result = await setupModelProvider(providerType, credential);
11613
+ let selectedModel;
11614
+ if (selectedChoice?.models && selectedChoice.models.length > 0) {
11615
+ selectedModel = await step.prompt(
11616
+ () => promptSelect(
11617
+ "Select model:",
11618
+ selectedChoice.models.map((model) => ({
11619
+ title: model === selectedChoice.defaultModel ? `${model} (Recommended)` : model,
11620
+ value: model
11621
+ }))
11622
+ )
11623
+ );
11624
+ if (!selectedModel) {
11625
+ console.log(chalk57.dim("Cancelled"));
11626
+ process.exit(0);
11627
+ }
11628
+ }
11629
+ const result = await setupModelProvider(providerType, credential, {
11630
+ selectedModel
11631
+ });
11632
+ const modelNote = result.provider.selectedModel ? ` with model: ${result.provider.selectedModel}` : "";
11495
11633
  step.detail(
11496
11634
  chalk57.green(
11497
- `${providerType} ${result.created ? "created" : "updated"}${result.isDefault ? ` (default for ${result.framework})` : ""}`
11635
+ `${providerType} ${result.created ? "created" : "updated"}${result.isDefault ? ` (default for ${result.framework})` : ""}${modelNote}`
11498
11636
  )
11499
11637
  );
11500
11638
  });
@@ -11642,7 +11780,7 @@ var setupClaudeCommand = new Command57().name("setup-claude").description("Insta
11642
11780
 
11643
11781
  // src/index.ts
11644
11782
  var program = new Command58();
11645
- program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.9.2");
11783
+ program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.11.0");
11646
11784
  program.addCommand(authCommand);
11647
11785
  program.addCommand(infoCommand);
11648
11786
  program.addCommand(composeCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "9.9.2",
3
+ "version": "9.11.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",