set up npx app

This commit is contained in:
Ramnique Singh 2025-11-05 13:28:38 +05:30
parent 3645f92774
commit 776be21fbd
6 changed files with 40 additions and 59 deletions

4
apps/cli/bin/app.js Executable file
View file

@ -0,0 +1,4 @@
#!/usr/bin/env node
import { start } from '../dist/x.js';
start();

View file

@ -1,6 +1,6 @@
{ {
"name": "cli", "name": "@rowboatlabs/rowboatx",
"version": "1.0.0", "version": "0.2.0",
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",
"scripts": { "scripts": {
@ -8,9 +8,16 @@
"build": "rm -rf dist && tsc", "build": "rm -rf dist && tsc",
"copilot": "npm run build && node dist/x.js" "copilot": "npm run build && node dist/x.js"
}, },
"files": [
"dist",
"bin"
],
"bin": {
"rowboatx": "bin/app.js"
},
"keywords": [], "keywords": [],
"author": "", "author": "Rowboat Labs",
"license": "ISC", "license": "MIT",
"description": "", "description": "",
"devDependencies": { "devDependencies": {
"@types/node": "^24.9.1", "@types/node": "^24.9.1",

View file

@ -2,12 +2,10 @@ import fs from "fs";
import path from "path"; import path from "path";
import { z } from "zod"; import { z } from "zod";
import { McpServerConfig } from "../../entities/mcp.js"; import { McpServerConfig } from "../../entities/mcp.js";
import { ensureBaseDirs, getStoragePaths } from "../services/storage.js"; import { WorkDir } from "../../config/config.js";
export function mcpConfigPath(): string { export function mcpConfigPath(): string {
const base = getStoragePaths(); return path.join(WorkDir, "mcp", "servers.json");
ensureBaseDirs(base);
return path.join(base.workDir, "mcp", "servers.json");
} }
export function readMcpConfig(): z.infer<typeof McpServerConfig> { export function readMcpConfig(): z.infer<typeof McpServerConfig> {

View file

@ -1,48 +1,22 @@
import fs from "fs"; import fs from "fs";
import path from "path"; import path from "path";
import { fileURLToPath } from "url"; import { WorkDir } from "../../config/config.js";
export type DirKind = "workflows" | "agents" | "mcp"; export type DirKind = "workflows" | "agents" | "mcp";
export interface StoragePaths { export function dirFor(kind: DirKind): string {
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 {
switch (kind) { switch (kind) {
case "workflows": case "workflows":
return path.join(base.workDir, "workflows"); return path.join(WorkDir, "workflows");
case "agents": case "agents":
return path.join(base.workDir, "agents"); return path.join(WorkDir, "agents");
case "mcp": case "mcp":
return path.join(base.workDir, "mcp"); return path.join(WorkDir, "mcp");
} }
} }
export function listJson(kind: DirKind, base: StoragePaths = defaultPaths): string[] { export function listJson(kind: DirKind): string[] {
const d = dirFor(kind, base); const d = dirFor(kind);
if (!fs.existsSync(d)) return []; if (!fs.existsSync(d)) return [];
return fs return fs
.readdirSync(d) .readdirSync(d)
@ -50,20 +24,20 @@ export function listJson(kind: DirKind, base: StoragePaths = defaultPaths): stri
.map((f) => f.replace(/\.json$/, "")); .map((f) => f.replace(/\.json$/, ""));
} }
export function readJson<T>(kind: DirKind, id: string, base: StoragePaths = defaultPaths): T | undefined { export function readJson<T>(kind: DirKind, id: string): T | undefined {
const p = path.join(dirFor(kind, base), `${id}.json`); const p = path.join(dirFor(kind), `${id}.json`);
if (!fs.existsSync(p)) return undefined; if (!fs.existsSync(p)) return undefined;
const raw = fs.readFileSync(p, "utf8"); const raw = fs.readFileSync(p, "utf8");
return JSON.parse(raw) as T; return JSON.parse(raw) as T;
} }
export function writeJson(kind: DirKind, id: string, value: unknown, base: StoragePaths = defaultPaths): void { export function writeJson(kind: DirKind, id: string, value: unknown): void {
const p = path.join(dirFor(kind, base), `${id}.json`); const p = path.join(dirFor(kind), `${id}.json`);
fs.writeFileSync(p, JSON.stringify(value, null, 2) + "\n", "utf8"); fs.writeFileSync(p, JSON.stringify(value, null, 2) + "\n", "utf8");
} }
export function deleteJson(kind: DirKind, id: string, base: StoragePaths = defaultPaths): boolean { export function deleteJson(kind: DirKind, id: string): boolean {
const p = path.join(dirFor(kind, base), `${id}.json`); const p = path.join(dirFor(kind), `${id}.json`);
if (!fs.existsSync(p)) return false; if (!fs.existsSync(p)) return false;
fs.rmSync(p); fs.rmSync(p);
return true; return true;

View file

@ -1,13 +1,11 @@
import path from "path"; import path from "path";
import fs from "fs"; import fs from "fs";
import { fileURLToPath } from "url";
import { McpServerConfig } from "../entities/mcp.js"; import { McpServerConfig } from "../entities/mcp.js";
import { z } from "zod"; import { z } from "zod";
import { homedir } from "os";
// Resolve app root relative to compiled file location (dist/...) // Resolve app root relative to compiled file location (dist/...)
const __dirname = path.dirname(fileURLToPath(import.meta.url)); export const WorkDir = path.join(homedir(), ".rowboat");
const AppRoot = path.resolve(__dirname, "../../..");
export const WorkDir = path.join(AppRoot, ".rowboat");
function ensureDirs() { function ensureDirs() {
const ensure = (p: string) => { if (!fs.existsSync(p)) fs.mkdirSync(p, { recursive: true }); }; const ensure = (p: string) => { if (!fs.existsSync(p)) fs.mkdirSync(p, { recursive: true }); };
@ -17,8 +15,9 @@ function ensureDirs() {
ensure(path.join(WorkDir, "mcp")); ensure(path.join(WorkDir, "mcp"));
} }
ensureDirs();
function loadMcpServerConfig(): z.infer<typeof McpServerConfig> { function loadMcpServerConfig(): z.infer<typeof McpServerConfig> {
ensureDirs();
const configPath = path.join(WorkDir, "mcp", "servers.json"); const configPath = path.join(WorkDir, "mcp", "servers.json");
if (!fs.existsSync(configPath)) return { mcpServers: [] }; if (!fs.existsSync(configPath)) return { mcpServers: [] };
const config = fs.readFileSync(configPath, "utf8"); const config = fs.readFileSync(configPath, "utf8");

View file

@ -1,9 +1,8 @@
import { ensureBaseDirs } from "./application/assistant/services/storage.js";
import { startCopilot } from "./application/assistant/chat.js"; import { startCopilot } from "./application/assistant/chat.js";
ensureBaseDirs(); export const start = () => {
startCopilot().catch((err) => {
startCopilot().catch((err) => { console.error("Failed to run copilot:", err);
console.error("Failed to run copilot:", err); process.exitCode = 1;
process.exitCode = 1; });
}); }