@vm0/cli 4.24.0 → 4.26.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 +198 -22
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -6,8 +6,8 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // src/index.ts
9
- import { Command as Command23 } from "commander";
10
- import chalk24 from "chalk";
9
+ import { Command as Command24 } from "commander";
10
+ import chalk25 from "chalk";
11
11
 
12
12
  // src/lib/auth.ts
13
13
  import chalk from "chalk";
@@ -16520,22 +16520,62 @@ import { readFile as readFile5, writeFile as writeFile5, mkdir as mkdir5 } from
16520
16520
  import { existsSync as existsSync6 } from "fs";
16521
16521
  var CONFIG_DIR3 = join6(homedir2(), ".vm0");
16522
16522
  var COOK_STATE_FILE = join6(CONFIG_DIR3, "cook.json");
16523
- async function loadCookState() {
16523
+ var STALE_THRESHOLD_MS = 48 * 60 * 60 * 1e3;
16524
+ async function loadCookStateFile() {
16524
16525
  if (!existsSync6(COOK_STATE_FILE)) {
16525
- return {};
16526
+ return { ppid: {} };
16526
16527
  }
16527
16528
  try {
16528
16529
  const content = await readFile5(COOK_STATE_FILE, "utf8");
16529
- return JSON.parse(content);
16530
+ const data = JSON.parse(content);
16531
+ if (!data.ppid) {
16532
+ const oldState = data;
16533
+ return {
16534
+ ppid: {
16535
+ [String(process.ppid)]: {
16536
+ lastRunId: oldState.lastRunId,
16537
+ lastSessionId: oldState.lastSessionId,
16538
+ lastCheckpointId: oldState.lastCheckpointId,
16539
+ lastActiveAt: Date.now()
16540
+ }
16541
+ }
16542
+ };
16543
+ }
16544
+ return data;
16530
16545
  } catch {
16531
- return {};
16546
+ return { ppid: {} };
16532
16547
  }
16533
16548
  }
16549
+ async function loadCookState() {
16550
+ const file2 = await loadCookStateFile();
16551
+ const ppid = String(process.ppid);
16552
+ const entry = file2.ppid[ppid];
16553
+ if (!entry) return {};
16554
+ return {
16555
+ lastRunId: entry.lastRunId,
16556
+ lastSessionId: entry.lastSessionId,
16557
+ lastCheckpointId: entry.lastCheckpointId
16558
+ };
16559
+ }
16534
16560
  async function saveCookState(state) {
16535
16561
  await mkdir5(CONFIG_DIR3, { recursive: true });
16536
- const existing = await loadCookState();
16537
- const merged = { ...existing, ...state };
16538
- await writeFile5(COOK_STATE_FILE, JSON.stringify(merged, null, 2), "utf8");
16562
+ const file2 = await loadCookStateFile();
16563
+ const ppid = String(process.ppid);
16564
+ const now = Date.now();
16565
+ for (const key of Object.keys(file2.ppid)) {
16566
+ const entry = file2.ppid[key];
16567
+ if (entry && now - entry.lastActiveAt > STALE_THRESHOLD_MS) {
16568
+ delete file2.ppid[key];
16569
+ }
16570
+ }
16571
+ const existing = file2.ppid[ppid];
16572
+ file2.ppid[ppid] = {
16573
+ lastRunId: state.lastRunId ?? existing?.lastRunId,
16574
+ lastSessionId: state.lastSessionId ?? existing?.lastSessionId,
16575
+ lastCheckpointId: state.lastCheckpointId ?? existing?.lastCheckpointId,
16576
+ lastActiveAt: now
16577
+ };
16578
+ await writeFile5(COOK_STATE_FILE, JSON.stringify(file2, null, 2), "utf8");
16539
16579
  }
16540
16580
 
16541
16581
  // src/commands/cook.ts
@@ -16697,7 +16737,7 @@ async function autoPullArtifact(runOutput, artifactDir) {
16697
16737
  }
16698
16738
  var cookCmd = new Command13().name("cook").description("One-click agent preparation and execution from vm0.yaml");
16699
16739
  cookCmd.argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
16700
- const shouldExit = await checkAndUpgrade("4.24.0", prompt);
16740
+ const shouldExit = await checkAndUpgrade("4.26.0", prompt);
16701
16741
  if (shouldExit) {
16702
16742
  process.exit(0);
16703
16743
  }
@@ -16867,16 +16907,47 @@ cookCmd.argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
16867
16907
  );
16868
16908
  }
16869
16909
  });
16870
- cookCmd.command("logs").description("View logs from the last cook run").action(async () => {
16871
- const state = await loadCookState();
16872
- if (!state.lastRunId) {
16873
- console.error(chalk16.red("\u2717 No previous run found"));
16874
- console.error(chalk16.gray(" Run 'vm0 cook <prompt>' first"));
16875
- process.exit(1);
16910
+ cookCmd.command("logs").description("View logs from the last cook run").option("-a, --agent", "Show agent events (default)").option("-s, --system", "Show system log").option("-m, --metrics", "Show metrics").option("-n, --network", "Show network logs (proxy traffic)").option(
16911
+ "--since <time>",
16912
+ "Show logs since timestamp (e.g., 5m, 2h, 1d, 2024-01-15T10:30:00Z)"
16913
+ ).option("--limit <n>", "Maximum number of entries to show (default: 5)").action(
16914
+ async (options) => {
16915
+ const state = await loadCookState();
16916
+ if (!state.lastRunId) {
16917
+ console.error(chalk16.red("\u2717 No previous run found"));
16918
+ console.error(chalk16.gray(" Run 'vm0 cook <prompt>' first"));
16919
+ process.exit(1);
16920
+ }
16921
+ const args = ["logs", state.lastRunId];
16922
+ const displayArgs = [`vm0 logs ${state.lastRunId}`];
16923
+ if (options.agent) {
16924
+ args.push("--agent");
16925
+ displayArgs.push("--agent");
16926
+ }
16927
+ if (options.system) {
16928
+ args.push("--system");
16929
+ displayArgs.push("--system");
16930
+ }
16931
+ if (options.metrics) {
16932
+ args.push("--metrics");
16933
+ displayArgs.push("--metrics");
16934
+ }
16935
+ if (options.network) {
16936
+ args.push("--network");
16937
+ displayArgs.push("--network");
16938
+ }
16939
+ if (options.since) {
16940
+ args.push("--since", options.since);
16941
+ displayArgs.push(`--since ${options.since}`);
16942
+ }
16943
+ if (options.limit) {
16944
+ args.push("--limit", options.limit);
16945
+ displayArgs.push(`--limit ${options.limit}`);
16946
+ }
16947
+ printCommand(displayArgs.join(" "));
16948
+ await execVm0Command(args);
16876
16949
  }
16877
- printCommand(`vm0 logs ${state.lastRunId}`);
16878
- await execVm0Command(["logs", state.lastRunId]);
16879
- });
16950
+ );
16880
16951
  cookCmd.command("continue").description(
16881
16952
  "Continue from the last session (latest conversation and artifact)"
16882
16953
  ).argument("<prompt>", "Prompt for the continued agent").action(async (prompt) => {
@@ -17700,11 +17771,115 @@ var setCommand = new Command21().name("set").description("Set your scope slug").
17700
17771
  // src/commands/scope/index.ts
17701
17772
  var scopeCommand = new Command22().name("scope").description("Manage your scope (namespace for images)").addCommand(statusCommand3).addCommand(setCommand);
17702
17773
 
17774
+ // src/commands/init.ts
17775
+ import { Command as Command23 } from "commander";
17776
+ import chalk24 from "chalk";
17777
+ import * as readline2 from "readline";
17778
+ import { existsSync as existsSync9 } from "fs";
17779
+ import { writeFile as writeFile7 } from "fs/promises";
17780
+ var VM0_YAML_FILE = "vm0.yaml";
17781
+ var AGENTS_MD_FILE = "AGENTS.md";
17782
+ function generateVm0Yaml(agentName) {
17783
+ return `version: "1.0"
17784
+
17785
+ agents:
17786
+ ${agentName}:
17787
+ provider: claude-code
17788
+ # Build agentic workflow using natural language
17789
+ instructions: AGENTS.md
17790
+ # Agent skills - see https://github.com/vm0-ai/vm0-skills for available skills
17791
+ # skills:
17792
+ # - https://github.com/vm0-ai/vm0-skills/tree/main/github
17793
+ environment:
17794
+ # Get token using: claude setup-token, then add to .env file
17795
+ CLAUDE_CODE_OAUTH_TOKEN: \${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
17796
+ `;
17797
+ }
17798
+ function generateAgentsMd() {
17799
+ return `# Agent Instructions
17800
+
17801
+ You are a HackerNews AI content curator.
17802
+
17803
+ ## Workflow
17804
+
17805
+ 1. Go to HackerNews and read the top 10 articles
17806
+ 2. Find and extract AI-related content from these articles
17807
+ 3. Summarize the findings into a X (Twitter) post format
17808
+ 4. Write the summary to content.md
17809
+ `;
17810
+ }
17811
+ function checkExistingFiles() {
17812
+ const existingFiles = [];
17813
+ if (existsSync9(VM0_YAML_FILE)) existingFiles.push(VM0_YAML_FILE);
17814
+ if (existsSync9(AGENTS_MD_FILE)) existingFiles.push(AGENTS_MD_FILE);
17815
+ return existingFiles;
17816
+ }
17817
+ async function promptAgentName() {
17818
+ const rl = readline2.createInterface({
17819
+ input: process.stdin,
17820
+ output: process.stdout
17821
+ });
17822
+ return new Promise((resolve2, reject) => {
17823
+ rl.question(chalk24.cyan("? Enter agent name: "), (answer) => {
17824
+ rl.close();
17825
+ resolve2(answer.trim());
17826
+ });
17827
+ rl.on("SIGINT", () => {
17828
+ rl.close();
17829
+ console.log();
17830
+ reject(new Error("User cancelled"));
17831
+ });
17832
+ });
17833
+ }
17834
+ var initCommand3 = new Command23().name("init").description("Initialize a new VM0 project in the current directory").option("-f, --force", "Overwrite existing files").option("-n, --name <name>", "Agent name (skips interactive prompt)").action(async (options) => {
17835
+ const existingFiles = checkExistingFiles();
17836
+ if (existingFiles.length > 0 && !options.force) {
17837
+ for (const file2 of existingFiles) {
17838
+ console.log(chalk24.red(`\u2717 ${file2} already exists`));
17839
+ }
17840
+ console.log();
17841
+ console.log(`To overwrite: ${chalk24.cyan("vm0 init --force")}`);
17842
+ process.exit(1);
17843
+ }
17844
+ let agentName;
17845
+ if (options.name) {
17846
+ agentName = options.name.trim();
17847
+ } else {
17848
+ try {
17849
+ agentName = await promptAgentName();
17850
+ } catch {
17851
+ process.exit(0);
17852
+ }
17853
+ }
17854
+ if (!agentName || !validateAgentName(agentName)) {
17855
+ console.log(chalk24.red("\u2717 Invalid agent name"));
17856
+ console.log(
17857
+ chalk24.gray(" Must be 3-64 characters, alphanumeric and hyphens only")
17858
+ );
17859
+ console.log(chalk24.gray(" Must start and end with letter or number"));
17860
+ process.exit(1);
17861
+ }
17862
+ await writeFile7(VM0_YAML_FILE, generateVm0Yaml(agentName));
17863
+ const vm0Status = existingFiles.includes(VM0_YAML_FILE) ? " (overwritten)" : "";
17864
+ console.log(chalk24.green(`\u2713 Created ${VM0_YAML_FILE}${vm0Status}`));
17865
+ await writeFile7(AGENTS_MD_FILE, generateAgentsMd());
17866
+ const agentsStatus = existingFiles.includes(AGENTS_MD_FILE) ? " (overwritten)" : "";
17867
+ console.log(chalk24.green(`\u2713 Created ${AGENTS_MD_FILE}${agentsStatus}`));
17868
+ console.log();
17869
+ console.log("Next steps:");
17870
+ console.log(
17871
+ ` 1. Get your Claude Code token: ${chalk24.cyan("claude setup-token")}`
17872
+ );
17873
+ console.log(` 2. Set the environment variable (or add to .env file):`);
17874
+ console.log(chalk24.gray(` export CLAUDE_CODE_OAUTH_TOKEN=<your-token>`));
17875
+ console.log(` 3. Run your agent: ${chalk24.cyan('vm0 cook "your prompt"')}`);
17876
+ });
17877
+
17703
17878
  // src/index.ts
17704
- var program = new Command23();
17705
- program.name("vm0").description("VM0 CLI - A modern build tool").version("4.24.0");
17879
+ var program = new Command24();
17880
+ program.name("vm0").description("VM0 CLI - A modern build tool").version("4.26.0");
17706
17881
  program.command("info").description("Display environment information").action(async () => {
17707
- console.log(chalk24.cyan("System Information:"));
17882
+ console.log(chalk25.cyan("System Information:"));
17708
17883
  console.log(`Node Version: ${process.version}`);
17709
17884
  console.log(`Platform: ${process.platform}`);
17710
17885
  console.log(`Architecture: ${process.arch}`);
@@ -17732,6 +17907,7 @@ program.addCommand(cookCommand);
17732
17907
  program.addCommand(imageCommand);
17733
17908
  program.addCommand(logsCommand);
17734
17909
  program.addCommand(scopeCommand);
17910
+ program.addCommand(initCommand3);
17735
17911
  if (process.argv[1]?.endsWith("index.js") || process.argv[1]?.endsWith("index.ts") || process.argv[1]?.endsWith("vm0")) {
17736
17912
  program.parse();
17737
17913
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "4.24.0",
3
+ "version": "4.26.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",