diff --git a/apps/cli/bin/app.js b/apps/cli/bin/app.js new file mode 100755 index 00000000..af06a71f --- /dev/null +++ b/apps/cli/bin/app.js @@ -0,0 +1,4 @@ +#!/usr/bin/env node + +import { start } from '../dist/x.js'; +start(); \ No newline at end of file diff --git a/apps/cli/package.json b/apps/cli/package.json index 8a16c38f..c8b1b154 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,6 +1,6 @@ { - "name": "cli", - "version": "1.0.0", + "name": "@rowboatlabs/rowboatx", + "version": "0.2.0", "main": "index.js", "type": "module", "scripts": { @@ -8,9 +8,16 @@ "build": "rm -rf dist && tsc", "copilot": "npm run build && node dist/x.js" }, + "files": [ + "dist", + "bin" + ], + "bin": { + "rowboatx": "bin/app.js" + }, "keywords": [], - "author": "", - "license": "ISC", + "author": "Rowboat Labs", + "license": "MIT", "description": "", "devDependencies": { "@types/node": "^24.9.1", diff --git a/apps/cli/src/application/assistant/mcp/service.ts b/apps/cli/src/application/assistant/mcp/service.ts index c9d6da44..f5f27597 100644 --- a/apps/cli/src/application/assistant/mcp/service.ts +++ b/apps/cli/src/application/assistant/mcp/service.ts @@ -2,12 +2,10 @@ import fs from "fs"; import path from "path"; import { z } from "zod"; import { McpServerConfig } from "../../entities/mcp.js"; -import { ensureBaseDirs, getStoragePaths } from "../services/storage.js"; +import { WorkDir } from "../../config/config.js"; export function mcpConfigPath(): string { - const base = getStoragePaths(); - ensureBaseDirs(base); - return path.join(base.workDir, "mcp", "servers.json"); + return path.join(WorkDir, "mcp", "servers.json"); } export function readMcpConfig(): z.infer { diff --git a/apps/cli/src/application/assistant/services/storage.ts b/apps/cli/src/application/assistant/services/storage.ts index ccf14c44..4ec0f2c9 100644 --- a/apps/cli/src/application/assistant/services/storage.ts +++ b/apps/cli/src/application/assistant/services/storage.ts @@ -1,48 +1,22 @@ import fs from "fs"; import path from "path"; -import { fileURLToPath } from "url"; +import { WorkDir } from "../../config/config.js"; export type DirKind = "workflows" | "agents" | "mcp"; -export interface StoragePaths { - appRoot: string; - workDir: string; // .rowboat -} - -const defaultPaths: StoragePaths = (() => { - const __dirname = path.dirname(fileURLToPath(import.meta.url)); - const appRoot = path.resolve(__dirname, "../../../../"); - const workDir = path.join(appRoot, ".rowboat"); - return { appRoot, workDir }; -})(); - -export function getStoragePaths(): StoragePaths { - return defaultPaths; -} - -export function ensureBaseDirs(base: StoragePaths = defaultPaths) { - const ensure = (p: string) => { - if (!fs.existsSync(p)) fs.mkdirSync(p, { recursive: true }); - }; - ensure(base.workDir); - ensure(path.join(base.workDir, "workflows")); - ensure(path.join(base.workDir, "agents")); - ensure(path.join(base.workDir, "mcp")); -} - -export function dirFor(kind: DirKind, base: StoragePaths = defaultPaths): string { +export function dirFor(kind: DirKind): string { switch (kind) { case "workflows": - return path.join(base.workDir, "workflows"); + return path.join(WorkDir, "workflows"); case "agents": - return path.join(base.workDir, "agents"); + return path.join(WorkDir, "agents"); case "mcp": - return path.join(base.workDir, "mcp"); + return path.join(WorkDir, "mcp"); } } -export function listJson(kind: DirKind, base: StoragePaths = defaultPaths): string[] { - const d = dirFor(kind, base); +export function listJson(kind: DirKind): string[] { + const d = dirFor(kind); if (!fs.existsSync(d)) return []; return fs .readdirSync(d) @@ -50,20 +24,20 @@ export function listJson(kind: DirKind, base: StoragePaths = defaultPaths): stri .map((f) => f.replace(/\.json$/, "")); } -export function readJson(kind: DirKind, id: string, base: StoragePaths = defaultPaths): T | undefined { - const p = path.join(dirFor(kind, base), `${id}.json`); +export function readJson(kind: DirKind, id: string): T | undefined { + const p = path.join(dirFor(kind), `${id}.json`); if (!fs.existsSync(p)) return undefined; const raw = fs.readFileSync(p, "utf8"); return JSON.parse(raw) as T; } -export function writeJson(kind: DirKind, id: string, value: unknown, base: StoragePaths = defaultPaths): void { - const p = path.join(dirFor(kind, base), `${id}.json`); +export function writeJson(kind: DirKind, id: string, value: unknown): void { + const p = path.join(dirFor(kind), `${id}.json`); fs.writeFileSync(p, JSON.stringify(value, null, 2) + "\n", "utf8"); } -export function deleteJson(kind: DirKind, id: string, base: StoragePaths = defaultPaths): boolean { - const p = path.join(dirFor(kind, base), `${id}.json`); +export function deleteJson(kind: DirKind, id: string): boolean { + const p = path.join(dirFor(kind), `${id}.json`); if (!fs.existsSync(p)) return false; fs.rmSync(p); return true; diff --git a/apps/cli/src/application/config/config.ts b/apps/cli/src/application/config/config.ts index 2692b300..9ab37014 100644 --- a/apps/cli/src/application/config/config.ts +++ b/apps/cli/src/application/config/config.ts @@ -1,13 +1,11 @@ import path from "path"; import fs from "fs"; -import { fileURLToPath } from "url"; import { McpServerConfig } from "../entities/mcp.js"; import { z } from "zod"; +import { homedir } from "os"; // Resolve app root relative to compiled file location (dist/...) -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const AppRoot = path.resolve(__dirname, "../../.."); -export const WorkDir = path.join(AppRoot, ".rowboat"); +export const WorkDir = path.join(homedir(), ".rowboat"); function ensureDirs() { const ensure = (p: string) => { if (!fs.existsSync(p)) fs.mkdirSync(p, { recursive: true }); }; @@ -17,8 +15,9 @@ function ensureDirs() { ensure(path.join(WorkDir, "mcp")); } +ensureDirs(); + function loadMcpServerConfig(): z.infer { - ensureDirs(); const configPath = path.join(WorkDir, "mcp", "servers.json"); if (!fs.existsSync(configPath)) return { mcpServers: [] }; const config = fs.readFileSync(configPath, "utf8"); diff --git a/apps/cli/src/x.ts b/apps/cli/src/x.ts index cf823710..9dbd8edb 100644 --- a/apps/cli/src/x.ts +++ b/apps/cli/src/x.ts @@ -1,9 +1,8 @@ -import { ensureBaseDirs } from "./application/assistant/services/storage.js"; import { startCopilot } from "./application/assistant/chat.js"; -ensureBaseDirs(); - -startCopilot().catch((err) => { - console.error("Failed to run copilot:", err); - process.exitCode = 1; -}); +export const start = () => { + startCopilot().catch((err) => { + console.error("Failed to run copilot:", err); + process.exitCode = 1; + }); +}