@meshxdata/fops 0.0.7 → 0.0.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshxdata/fops",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "CLI to install and manage Foundation data mesh platforms",
5
5
  "keywords": [
6
6
  "foundation",
@@ -25,9 +25,7 @@
25
25
  "test:watch": "vitest"
26
26
  },
27
27
  "dependencies": {
28
- "24": "^0.0.0",
29
- "@anthropic-ai/claude-code": "^1.0.0",
30
- "@meshxdata/fops": "0.0.6",
28
+ "@anthropic-ai/claude-code": "^2.1.39",
31
29
  "boxen": "^8.0.1",
32
30
  "chalk": "^5.3.0",
33
31
  "commander": "^12.0.0",
@@ -3,17 +3,9 @@ import os from "node:os";
3
3
  import path from "node:path";
4
4
  import https from "node:https";
5
5
  import chalk from "chalk";
6
- import { Command } from "commander";
7
6
  import { PKG } from "../config.js";
8
7
  import { rootDir, requireRoot, hasComposeInDir, isFoundationRoot, findComposeRootUp, checkInitState } from "../project.js";
9
- import { execa } from "execa";
10
8
  import { make, dockerCompose } from "../shell.js";
11
- import { runSetup, runInitWizard } from "../setup/index.js";
12
- import { ensureEcrAuth } from "../setup/aws.js";
13
- import { runAgentSingleTurn, runAgentInteractive } from "../agent/index.js";
14
- import { runDoctor } from "../doctor.js";
15
- import { runFeatureFlags } from "../feature-flags.js";
16
- import { runLogin, runCodaLogin } from "../auth/index.js";
17
9
  import { runHook, loadSkills } from "../plugins/index.js";
18
10
 
19
11
  export function registerCommands(program, registry) {
@@ -25,6 +17,7 @@ export function registerCommands(program, registry) {
25
17
  .argument("[service]", "Service to login to: claude (default) or coda")
26
18
  .option("--no-browser", "Paste API key in terminal instead of OAuth")
27
19
  .action(async (service, opts) => {
20
+ const { runLogin, runCodaLogin } = await import("../auth/index.js");
28
21
  const target = (service || "claude").toLowerCase();
29
22
  if (target === "coda") {
30
23
  await runCodaLogin();
@@ -46,6 +39,7 @@ export function registerCommands(program, registry) {
46
39
  .option("--download", "Run make download after submodules", false)
47
40
  .option("--yes", "Use defaults without prompting")
48
41
  .action(async (opts) => {
42
+ const { runSetup } = await import("../setup/index.js");
49
43
  const dir = opts.dir ? path.resolve(opts.dir) : (rootDir() || process.cwd());
50
44
  if (!fs.existsSync(path.join(dir, "docker-compose.yaml")) && !fs.existsSync(path.join(dir, "docker-compose.yml"))) {
51
45
  console.error(chalk.red("No docker-compose in %s. Run from foundation-compose root."), dir);
@@ -68,6 +62,7 @@ export function registerCommands(program, registry) {
68
62
  .option("--no-submodules", "Skip git submodule init/update")
69
63
  .option("--yes", "Use defaults without prompting; fail if no docker-compose in cwd")
70
64
  .action(async (opts) => {
65
+ const { runSetup, runInitWizard } = await import("../setup/index.js");
71
66
  const dir = opts.dir ? path.resolve(opts.dir) : process.cwd();
72
67
  const hasCompose = hasComposeInDir(dir);
73
68
  if (opts.yes) {
@@ -92,6 +87,7 @@ export function registerCommands(program, registry) {
92
87
  .option("--no-run", "Do not offer to run suggested commands (single-turn only)", false)
93
88
  .option("--model <id>", "Model override (e.g. claude-sonnet-4-20250514, gpt-4o-mini)")
94
89
  .action(async (opts) => {
90
+ const { runAgentSingleTurn, runAgentInteractive } = await import("../agent/index.js");
95
91
  const root = requireRoot(program);
96
92
  if (opts.message) {
97
93
  await runAgentSingleTurn(root, opts.message, { runSuggestions: opts.run !== false, model: opts.model, registry });
@@ -106,6 +102,8 @@ export function registerCommands(program, registry) {
106
102
  .option("-d, --detach", "Run in background", true)
107
103
  .option("--no-chat", "Skip interactive AI assistant after startup")
108
104
  .action(async (opts) => {
105
+ const { execa } = await import("execa");
106
+ const { ensureEcrAuth } = await import("../setup/aws.js");
109
107
  const root = requireRoot(program);
110
108
 
111
109
  // Pre-flight: check if project is initialised
@@ -116,6 +114,19 @@ export function registerCommands(program, registry) {
116
114
  process.exit(1);
117
115
  }
118
116
 
117
+ // Pre-flight: check Docker daemon is reachable
118
+ try {
119
+ await execa("docker", ["info"], { timeout: 10000, reject: true });
120
+ } catch {
121
+ console.error(chalk.red("\n Docker daemon is not running or not reachable."));
122
+ if (process.platform === "linux") {
123
+ console.error(chalk.dim(" Try: sudo service docker start"));
124
+ } else {
125
+ console.error(chalk.dim(" Start Docker Desktop and try again."));
126
+ }
127
+ process.exit(1);
128
+ }
129
+
119
130
  await ensureEcrAuth(root);
120
131
  await runHook(registry, "before:up", { root });
121
132
 
@@ -152,16 +163,21 @@ export function registerCommands(program, registry) {
152
163
  if (result.exitCode !== 0) {
153
164
  console.error(chalk.red(`\n Some services failed to start (exit code ${result.exitCode}).`));
154
165
  console.error(chalk.dim(" Dropping into debug agent to diagnose...\n"));
166
+ const { runAgentInteractive } = await import("../agent/index.js");
155
167
  await runAgentInteractive(root, { registry, initialAgent: "debug" });
156
168
  return;
157
169
  }
158
- if (opts.chat !== false) await runAgentInteractive(root, { registry });
170
+ if (opts.chat !== false) {
171
+ const { runAgentInteractive } = await import("../agent/index.js");
172
+ await runAgentInteractive(root, { registry });
173
+ }
159
174
  });
160
175
 
161
176
  program
162
177
  .command("chat")
163
178
  .description("Interactive AI assistant (same as foundation agent with no -m)")
164
179
  .action(async () => {
180
+ const { runAgentInteractive } = await import("../agent/index.js");
165
181
  const root = requireRoot(program);
166
182
  await runAgentInteractive(root, { registry });
167
183
  });
@@ -201,6 +217,7 @@ export function registerCommands(program, registry) {
201
217
  .description("Check environment and Foundation setup (Docker, git, .env, submodules)")
202
218
  .option("--fix", "Apply suggested fixes where possible", false)
203
219
  .action(async (opts) => {
220
+ const { runDoctor } = await import("../doctor.js");
204
221
  await runDoctor(opts, registry);
205
222
  });
206
223
 
@@ -208,6 +225,7 @@ export function registerCommands(program, registry) {
208
225
  .command("config")
209
226
  .description("Toggle MX_FF_* feature flags and restart affected services")
210
227
  .action(async () => {
228
+ const { runFeatureFlags } = await import("../feature-flags.js");
211
229
  const root = requireRoot(program);
212
230
  await runFeatureFlags(root);
213
231
  });
@@ -216,6 +234,7 @@ export function registerCommands(program, registry) {
216
234
  .command("build")
217
235
  .description("Build all Foundation service images from source")
218
236
  .action(async () => {
237
+ const { ensureEcrAuth } = await import("../setup/aws.js");
219
238
  const root = requireRoot(program);
220
239
  await ensureEcrAuth(root);
221
240
  await make(root, "build");
@@ -225,6 +244,7 @@ export function registerCommands(program, registry) {
225
244
  .command("download")
226
245
  .description("Pull all container images from registry (requires ECR auth)")
227
246
  .action(async () => {
247
+ const { ensureEcrAuth } = await import("../setup/aws.js");
228
248
  const root = requireRoot(program);
229
249
  await ensureEcrAuth(root);
230
250
  await make(root, "download");
@@ -235,6 +255,7 @@ export function registerCommands(program, registry) {
235
255
  .description("Update fops CLI to the latest version")
236
256
  .option("--check", "Only check for updates, don't install")
237
257
  .action(async (opts) => {
258
+ const { execa } = await import("execa");
238
259
  const currentVersion = PKG.version;
239
260
  console.log(chalk.dim(` Current version: ${currentVersion}`));
240
261
 
@@ -439,6 +460,7 @@ export function registerCommands(program, registry) {
439
460
  .command("add <repo>")
440
461
  .description("Install a plugin from GitHub (owner/repo)")
441
462
  .action(async (repo) => {
463
+ const { execa } = await import("execa");
442
464
  const parts = repo.split("/");
443
465
  if (parts.length !== 2 || !parts[0] || !parts[1]) {
444
466
  console.error(chalk.red(' Usage: fops plugin marketplace add <owner/repo>'));
@@ -2,7 +2,6 @@ import fs from "node:fs";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { execa } from "execa";
6
5
 
7
6
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
7
 
@@ -27,6 +26,7 @@ function parseFrontmatter(content) {
27
26
  */
28
27
  async function hasBin(name) {
29
28
  try {
29
+ const { execa } = await import("execa");
30
30
  await execa("which", [name], { reject: false, timeout: 2000 });
31
31
  return true;
32
32
  } catch {
package/src/shell.js CHANGED
@@ -1,9 +1,15 @@
1
- import { execa } from "execa";
1
+ let _execa;
2
+ async function lazyExeca() {
3
+ if (!_execa) _execa = (await import("execa")).execa;
4
+ return _execa;
5
+ }
2
6
 
3
7
  export async function make(root, target, args = []) {
8
+ const execa = await lazyExeca();
4
9
  return execa("make", [target, ...args], { cwd: root, stdio: "inherit", reject: false });
5
10
  }
6
11
 
7
12
  export async function dockerCompose(root, args) {
13
+ const execa = await lazyExeca();
8
14
  return execa("docker", ["compose", ...args], { cwd: root, stdio: "inherit", reject: false });
9
15
  }
package/src/ui/confirm.js CHANGED
@@ -76,7 +76,16 @@ export async function selectOption(message, options) {
76
76
  resolved = true;
77
77
  clear();
78
78
  unmount();
79
- setTimeout(() => resolve(selected ? selected.value : null), 50);
79
+ // Fix for Node 24+: restore stdin state after ink unmounts
80
+ // ink leaves stdin paused/in raw mode which breaks inquirer
81
+ setTimeout(() => {
82
+ if (process.stdin.isTTY) {
83
+ process.stdin.setRawMode(false);
84
+ process.stdin.resume();
85
+ process.stdin.ref();
86
+ }
87
+ resolve(selected ? selected.value : null);
88
+ }, 100);
80
89
  };
81
90
  const { unmount, clear } = render(
82
91
  h(SelectPrompt, { message, options: normalized, onResult })