bopodev 0.1.11 → 0.1.13

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/dist/index.js +37 -14
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -110,6 +110,13 @@ async function runDoctorChecks(options) {
110
110
  ok: codex.available && codex.exitCode === 0,
111
111
  details: codex.available && codex.exitCode === 0 ? `Command '${codexCommand}' is available` : codex.error ?? `Command '${codexCommand}' exited with ${String(codex.exitCode)}`
112
112
  });
113
+ const openCodeCommand = process.env.BOPO_OPENCODE_COMMAND?.trim() || "opencode";
114
+ const openCode = await checkRuntimeCommandHealth(openCodeCommand, options?.workspaceRoot);
115
+ checks.push({
116
+ label: "OpenCode runtime",
117
+ ok: openCode.available && openCode.exitCode === 0,
118
+ details: openCode.available && openCode.exitCode === 0 ? `Command '${openCodeCommand}' is available` : openCode.error ?? `Command '${openCodeCommand}' exited with ${String(openCode.exitCode)}`
119
+ });
113
120
  const instanceRoot = resolveInstanceRoot();
114
121
  const storageRoot = join2(instanceRoot, "data", "storage");
115
122
  const workspaceRoot = join2(instanceRoot, "workspaces");
@@ -298,6 +305,12 @@ var DEFAULT_COMPANY_NAME_ENV = "BOPO_DEFAULT_COMPANY_NAME";
298
305
  var DEFAULT_COMPANY_ID_ENV = "BOPO_DEFAULT_COMPANY_ID";
299
306
  var DEFAULT_PUBLIC_COMPANY_ID_ENV = "NEXT_PUBLIC_DEFAULT_COMPANY_ID";
300
307
  var DEFAULT_AGENT_PROVIDER_ENV = "BOPO_DEFAULT_AGENT_PROVIDER";
308
+ var DEFAULT_ENV_TEMPLATE = "NEXT_PUBLIC_API_URL=http://localhost:4020\n";
309
+ var CLI_ONBOARD_VISIBLE_PROVIDERS = [
310
+ { value: "codex", label: "Codex" },
311
+ { value: "claude_code", label: "Claude Code" },
312
+ { value: "opencode", label: "OpenCode" }
313
+ ];
301
314
  var defaultDeps = {
302
315
  installDependencies: async (workspaceRoot) => {
303
316
  const code = await runCommandStreaming("pnpm", ["install"], { cwd: workspaceRoot });
@@ -351,12 +364,7 @@ var defaultDeps = {
351
364
  const answer = await select({
352
365
  message: "Primary agent framework",
353
366
  initialValue: "codex",
354
- options: [
355
- { value: "codex", label: "Codex" },
356
- { value: "claude_code", label: "Claude Code" },
357
- { value: "opencode", label: "OpenCode" },
358
- { value: "shell", label: "Shell Runtime" }
359
- ]
367
+ options: CLI_ONBOARD_VISIBLE_PROVIDERS
360
368
  });
361
369
  if (isCancel(answer)) {
362
370
  throw new Error("Onboarding cancelled.");
@@ -399,8 +407,15 @@ async function runOnboardFlow(options, deps = defaultDeps) {
399
407
  }
400
408
  const envSpin = spinner();
401
409
  envSpin.start("Ensuring .env exists");
402
- const envCreated = await ensureEnvFile(workspaceRoot);
403
- envSpin.stop(envCreated ? "Created .env from .env.example" : ".env already present");
410
+ const envResult = await ensureEnvFile(workspaceRoot);
411
+ const envCreated = envResult.created;
412
+ if (!envResult.created) {
413
+ envSpin.stop(".env already present");
414
+ } else if (envResult.source === "example") {
415
+ envSpin.stop("Created .env from .env.example");
416
+ } else {
417
+ envSpin.stop("Created .env with defaults (.env.example not found)");
418
+ }
404
419
  const envPath = join3(workspaceRoot, ".env");
405
420
  dotenv.config({ path: envPath });
406
421
  const envValues = await readEnvValues(envPath);
@@ -493,14 +508,16 @@ async function ensureEnvFile(workspaceRoot) {
493
508
  const envExamplePath = join3(workspaceRoot, ".env.example");
494
509
  const envExists = await fileExists2(envPath);
495
510
  if (envExists) {
496
- return false;
511
+ return { created: false, source: null };
497
512
  }
498
513
  const envExampleExists = await fileExists2(envExamplePath);
499
- if (!envExampleExists) {
500
- throw new Error("Missing .env.example in workspace root.");
514
+ if (envExampleExists) {
515
+ await copyFile(envExamplePath, envPath);
516
+ return { created: true, source: "example" };
501
517
  }
502
- await copyFile(envExamplePath, envPath);
503
- return true;
518
+ await writeFile(envPath, DEFAULT_ENV_TEMPLATE, "utf8");
519
+ log.warn("Missing .env.example in workspace root. Created .env with built-in defaults.");
520
+ return { created: true, source: "default" };
504
521
  }
505
522
  async function readEnvValues(envPath) {
506
523
  const envContent = await readFile(envPath, "utf8");
@@ -547,7 +564,7 @@ function parseSeedResult(stdout) {
547
564
  };
548
565
  }
549
566
  function parseAgentProvider(value) {
550
- if (value === "codex" || value === "claude_code" || value === "opencode" || value === "shell") {
567
+ if (value === "codex" || value === "claude_code" || value === "opencode" || value === "openai_api" || value === "anthropic_api" || value === "shell") {
551
568
  return value;
552
569
  }
553
570
  return null;
@@ -562,6 +579,12 @@ function formatAgentProvider(provider) {
562
579
  if (provider === "opencode") {
563
580
  return "OpenCode";
564
581
  }
582
+ if (provider === "openai_api") {
583
+ return "OpenAI API (direct)";
584
+ }
585
+ if (provider === "anthropic_api") {
586
+ return "Anthropic API (direct)";
587
+ }
565
588
  return "Shell Runtime";
566
589
  }
567
590
  async function fileExists2(path) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bopodev",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "bin": {