refactor: single-package workspace with root esbuild build

Merge workflow and sense devDependencies into root, remove per-package package.json and workflow tsconfigs, add scripts/build.mjs for consistent outputs.

Fixes #22
This commit is contained in:
小橘 2026-04-30 09:03:05 +00:00
parent e4fd5d6ba4
commit f7cf1a1cb2
22 changed files with 85 additions and 216 deletions

View File

@ -4,7 +4,7 @@
"private": true,
"type": "module",
"scripts": {
"build": "pnpm -r build"
"build": "node scripts/build.mjs"
},
"dependencies": {
"@uncaged/nerve-adapter-cursor": "link:../repos/nerve/packages/adapter-cursor",
@ -19,7 +19,10 @@
"zod": "^4.3.6"
},
"devDependencies": {
"drizzle-kit": "latest"
"@types/node": "^22.0.0",
"drizzle-kit": "latest",
"esbuild": "^0.27.0",
"typescript": "^5.7.0"
},
"pnpm": {
"onlyBuiltDependencies": [

9
pnpm-lock.yaml generated
View File

@ -48,9 +48,18 @@ importers:
specifier: ^4.3.6
version: 4.3.6
devDependencies:
'@types/node':
specifier: ^22.0.0
version: 22.19.17
drizzle-kit:
specifier: latest
version: 0.31.10
esbuild:
specifier: ^0.27.0
version: 0.27.7
typescript:
specifier: ^5.7.0
version: 5.9.3
senses/git-workspace-status:
devDependencies:

View File

@ -1,3 +0,0 @@
packages:
- "workflows/*"
- "senses/*"

50
scripts/build.mjs Normal file
View File

@ -0,0 +1,50 @@
import * as esbuild from "esbuild";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const root = path.join(path.dirname(fileURLToPath(import.meta.url)), "..");
const opts = {
bundle: true,
platform: "node",
format: "esm",
packages: "external",
};
function listDirs(dir) {
if (!fs.existsSync(dir)) return [];
return fs
.readdirSync(dir)
.filter((name) => !name.startsWith("."))
.map((name) => path.join(dir, name))
.filter((p) => fs.statSync(p).isDirectory());
}
async function main() {
for (const dir of listDirs(path.join(root, "senses"))) {
const entry = path.join(dir, "src", "index.ts");
if (!fs.existsSync(entry)) continue;
await esbuild.build({
...opts,
entryPoints: [entry],
outfile: path.join(dir, "index.js"),
});
}
for (const dir of listDirs(path.join(root, "workflows"))) {
const base = path.basename(dir);
if (base.startsWith("_")) continue;
const entry = path.join(dir, "index.ts");
if (!fs.existsSync(entry)) continue;
const outDir = path.join(dir, "dist");
fs.mkdirSync(outDir, { recursive: true });
await esbuild.build({
...opts,
entryPoints: [entry],
outfile: path.join(outDir, "index.js"),
});
}
}
await main();

View File

@ -1,8 +1,8 @@
// src/index.ts
// senses/git-workspace-status/src/index.ts
import { execFileSync } from "node:child_process";
import { resolve } from "node:path";
// src/schema.ts
// senses/git-workspace-status/src/schema.ts
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
var snapshots = sqliteTable("snapshots", {
ts: integer("ts").primaryKey(),
@ -16,7 +16,7 @@ var snapshots = sqliteTable("snapshots", {
gitError: text("git_error").notNull()
});
// src/index.ts
// senses/git-workspace-status/src/index.ts
var GIT_TIMEOUT_MS = 15e3;
function workspaceRoot() {
const raw = process.env.GIT_WORKSPACE_ROOT;

View File

@ -1,14 +0,0 @@
{
"name": "sense-git-workspace-status",
"version": "0.0.1",
"private": true,
"type": "module",
"scripts": {
"build": "esbuild src/index.ts --bundle --platform=node --format=esm --outfile=index.js --packages=external"
},
"devDependencies": {
"@types/node": "^22.0.0",
"esbuild": "^0.27.0",
"typescript": "^5.7.0"
}
}

View File

@ -1,7 +1,7 @@
// src/index.ts
// senses/hermes-gateway-health/src/index.ts
import { execFile } from "node:child_process";
// src/schema.ts
// senses/hermes-gateway-health/src/schema.ts
import { integer, real, sqliteTable, text } from "drizzle-orm/sqlite-core";
var hermesGatewayHealth = sqliteTable("hermes_gateway_health", {
id: integer("id").primaryKey({ autoIncrement: true }),
@ -19,7 +19,7 @@ var hermesGatewayHealth = sqliteTable("hermes_gateway_health", {
httpError: text("http_error").notNull()
});
// src/index.ts
// senses/hermes-gateway-health/src/index.ts
var EXEC_TIMEOUT_MS = 25e3;
var HTTP_TIMEOUT_MS = Math.min(23e3, EXEC_TIMEOUT_MS - 2e3);
var HTTP_ERROR_MAX_LEN = 256;

View File

@ -1,14 +0,0 @@
{
"name": "sense-hermes-gateway-health",
"version": "0.0.1",
"private": true,
"type": "module",
"scripts": {
"build": "esbuild src/index.ts --bundle --platform=node --format=esm --outfile=index.js --packages=external"
},
"devDependencies": {
"@types/node": "^22.0.0",
"esbuild": "^0.27.0",
"typescript": "^5.7.0"
}
}

View File

@ -1,11 +1,11 @@
// src/index.ts
// senses/hermes-session-message-stats/src/index.ts
import { createReadStream } from "node:fs";
import { readdir } from "node:fs/promises";
import { homedir } from "node:os";
import { join } from "node:path";
import { createInterface } from "node:readline";
// src/schema.ts
// senses/hermes-session-message-stats/src/schema.ts
import { integer, sqliteTable } from "drizzle-orm/sqlite-core";
var hermesSessionMessageStats = sqliteTable("hermes_session_message_stats", {
id: integer("id").primaryKey({ autoIncrement: true }),
@ -18,7 +18,7 @@ var hermesSessionMessageStats = sqliteTable("hermes_session_message_stats", {
measurementWindowSeconds: integer("measurement_window_seconds").notNull()
});
// src/index.ts
// senses/hermes-session-message-stats/src/index.ts
var MEASUREMENT_WINDOW_MS = 9e5;
var MEASUREMENT_WINDOW_SECONDS = 900;
async function aggregateJsonlFile(filePath, cutoffMs, nowMs) {

View File

@ -1,14 +0,0 @@
{
"name": "sense-hermes-session-message-stats",
"version": "0.0.1",
"private": true,
"type": "module",
"scripts": {
"build": "esbuild src/index.ts --bundle --platform=node --format=esm --outfile=index.js --packages=external"
},
"devDependencies": {
"@types/node": "^22.0.0",
"esbuild": "^0.27.0",
"typescript": "^5.7.0"
}
}

View File

@ -1,9 +1,9 @@
// src/index.ts
// senses/linux-system-health/src/index.ts
import { loadavg, totalmem, freemem, uptime } from "node:os";
import { execSync } from "node:child_process";
import { readFile } from "node:fs/promises";
// src/schema.ts
// senses/linux-system-health/src/schema.ts
import { integer, real, sqliteTable } from "drizzle-orm/sqlite-core";
var snapshots = sqliteTable("snapshots", {
ts: integer("ts").primaryKey(),
@ -26,7 +26,7 @@ var snapshots = sqliteTable("snapshots", {
tcpMemPages: integer("tcp_mem_pages")
});
// src/index.ts
// senses/linux-system-health/src/index.ts
var SOCKSTAT_PATH = "/proc/net/sockstat";
function parseSockstat(content) {
let socketsUsed = 0, tcpInuse = 0, tcpOrphan = 0, tcpTw = 0, tcpAlloc = 0, tcpMemPages = 0;

View File

@ -1,14 +0,0 @@
{
"name": "sense-linux-system-health",
"version": "0.0.1",
"private": true,
"type": "module",
"scripts": {
"build": "esbuild src/index.ts --bundle --platform=node --format=esm --outfile=index.js --packages=external"
},
"devDependencies": {
"@types/node": "^22.0.0",
"esbuild": "^0.27.0",
"typescript": "^5.7.0"
}
}

View File

@ -1,4 +1,4 @@
// src/schema.ts
// senses/worker-process-metrics/src/schema.ts
import { integer, real, sqliteTable } from "drizzle-orm/sqlite-core";
var workerProcessMetrics = sqliteTable("worker_process_metrics", {
ts: integer("ts").primaryKey(),
@ -9,7 +9,7 @@ var workerProcessMetrics = sqliteTable("worker_process_metrics", {
externalMB: real("external_mb").notNull()
});
// src/index.ts
// senses/worker-process-metrics/src/index.ts
function round2(n) {
return Math.round(n * 100) / 100;
}

View File

@ -1,14 +0,0 @@
{
"name": "sense-worker-process-metrics",
"version": "0.0.1",
"private": true,
"type": "module",
"scripts": {
"build": "esbuild src/index.ts --bundle --platform=node --format=esm --outfile=index.js --packages=external"
},
"devDependencies": {
"@types/node": "^22.0.0",
"esbuild": "^0.27.0",
"typescript": "^5.7.0"
}
}

View File

@ -7,7 +7,13 @@
"strict": true,
"skipLibCheck": true,
"noEmit": true,
"allowImportingTsExtensions": true,
"types": ["node"]
},
"include": ["./**/*.ts", "../_shared/**/*.ts"]
"include": [
"senses/**/*.ts",
"workflows/**/*.ts",
"scripts/**/*.ts",
"workflows/_shared/**/*.ts"
]
}

View File

@ -1,22 +0,0 @@
{
"name": "generate-sense-workflow",
"version": "0.0.1",
"private": true,
"type": "module",
"scripts": {
"build": "esbuild index.ts --bundle --platform=node --format=esm --outdir=dist --packages=external"
},
"dependencies": {
"@uncaged/nerve-adapter-cursor": "latest",
"@uncaged/nerve-adapter-hermes": "latest",
"@uncaged/nerve-core": "latest",
"@uncaged/nerve-workflow-meta": "link:../../../repos/nerve/packages/workflow-meta",
"@uncaged/nerve-workflow-utils": "latest",
"zod": "^4.3.6"
},
"devDependencies": {
"@types/node": "^22.0.0",
"esbuild": "^0.27.0",
"typescript": "^5.7.0"
}
}

View File

@ -1,14 +0,0 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"skipLibCheck": true,
"noEmit": false,
"declaration": false,
"types": ["node"]
},
"include": ["./**/*.ts", "../_shared/**/*.ts"]
}

View File

@ -1,22 +0,0 @@
{
"name": "generate-workflow-workflow",
"version": "0.0.1",
"private": true,
"type": "module",
"scripts": {
"build": "esbuild index.ts --bundle --platform=node --format=esm --outdir=dist --packages=external"
},
"dependencies": {
"@uncaged/nerve-adapter-cursor": "latest",
"@uncaged/nerve-adapter-hermes": "latest",
"@uncaged/nerve-core": "latest",
"@uncaged/nerve-workflow-meta": "link:../../../repos/nerve/packages/workflow-meta",
"@uncaged/nerve-workflow-utils": "latest",
"zod": "^4.3.6"
},
"devDependencies": {
"@types/node": "^22.0.0",
"esbuild": "^0.27.0",
"typescript": "^5.7.0"
}
}

View File

@ -1,21 +0,0 @@
{
"name": "knowledge-extraction-workflow",
"version": "0.0.1",
"private": true,
"type": "module",
"scripts": {
"build": "esbuild index.ts --bundle --platform=node --format=esm --outdir=dist --packages=external"
},
"dependencies": {
"@uncaged/nerve-adapter-cursor": "latest",
"@uncaged/nerve-adapter-hermes": "latest",
"@uncaged/nerve-core": "latest",
"@uncaged/nerve-workflow-utils": "latest",
"zod": "^4.3.6"
},
"devDependencies": {
"@types/node": "^22.0.0",
"esbuild": "^0.27.0",
"typescript": "^5.7.0"
}
}

View File

@ -1,13 +0,0 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"skipLibCheck": true,
"noEmit": true,
"types": ["node"]
},
"include": ["./**/*.ts"]
}

View File

@ -1,21 +0,0 @@
{
"name": "solve-issue-workflow",
"version": "0.0.1",
"private": true,
"type": "module",
"scripts": {
"build": "esbuild index.ts --bundle --platform=node --format=esm --outdir=dist --packages=external"
},
"dependencies": {
"@uncaged/nerve-adapter-cursor": "latest",
"@uncaged/nerve-adapter-hermes": "latest",
"@uncaged/nerve-core": "latest",
"@uncaged/nerve-workflow-utils": "latest",
"zod": "^4.3.6"
},
"devDependencies": {
"@types/node": "^22.0.0",
"esbuild": "^0.27.0",
"typescript": "^5.7.0"
}
}

View File

@ -1,13 +0,0 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"skipLibCheck": true,
"noEmit": true,
"types": ["node"]
},
"include": ["./**/*.ts"]
}