@beastmode-develeap/beastmode 0.1.267 → 0.1.269
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/dist/index.js +300 -258
- package/dist/index.js.map +1 -1
- package/dist/web/board.html +1 -1
- package/dist/web/build-commit.txt +1 -1
- package/dist/web/build-stamp.txt +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3223,8 +3223,18 @@ var init_bridge = __esm({
|
|
|
3223
3223
|
});
|
|
3224
3224
|
|
|
3225
3225
|
// src/engine/project-record.ts
|
|
3226
|
-
import { existsSync as existsSync8, writeFileSync as writeFileSync6, renameSync, readFileSync as readFileSync8, readdirSync as readdirSync3, mkdirSync as mkdirSync6 } from "fs";
|
|
3227
|
-
import { join as join8 } from "path";
|
|
3226
|
+
import { existsSync as existsSync8, writeFileSync as writeFileSync6, renameSync, readFileSync as readFileSync8, readdirSync as readdirSync3, mkdirSync as mkdirSync6, unlinkSync } from "fs";
|
|
3227
|
+
import { join as join8, basename as basename3 } from "path";
|
|
3228
|
+
function computeVerifyPort(existingProjects) {
|
|
3229
|
+
let port = 3001;
|
|
3230
|
+
if (existingProjects) {
|
|
3231
|
+
for (const p of existingProjects) {
|
|
3232
|
+
const v = p.deploy?.verify_port;
|
|
3233
|
+
if (typeof v === "number" && v >= port) port = v + 1;
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
return port;
|
|
3237
|
+
}
|
|
3228
3238
|
function detectShape(parsed) {
|
|
3229
3239
|
if (parsed.github && typeof parsed.github === "object" && parsed.slots && typeof parsed.slots === "object") {
|
|
3230
3240
|
return "canonical";
|
|
@@ -3234,10 +3244,34 @@ function detectShape(parsed) {
|
|
|
3234
3244
|
}
|
|
3235
3245
|
return "http-legacy";
|
|
3236
3246
|
}
|
|
3247
|
+
function hasMissingCanonicalFields(parsed) {
|
|
3248
|
+
if (!parsed.stack) return true;
|
|
3249
|
+
if (!parsed.plugins) return true;
|
|
3250
|
+
if (!parsed.infra) return true;
|
|
3251
|
+
const deploy = parsed.deploy;
|
|
3252
|
+
if (!deploy?.target) return true;
|
|
3253
|
+
return false;
|
|
3254
|
+
}
|
|
3255
|
+
function normalizeDeploy(existing) {
|
|
3256
|
+
return {
|
|
3257
|
+
...existing,
|
|
3258
|
+
target: existing?.target || "pr-only",
|
|
3259
|
+
verify_port: existing?.verify_port || 3001,
|
|
3260
|
+
config: existing?.config || {}
|
|
3261
|
+
};
|
|
3262
|
+
}
|
|
3237
3263
|
function normalizeToCanonical(parsed, name) {
|
|
3238
3264
|
const shape = detectShape(parsed);
|
|
3265
|
+
const existingDeploy = parsed.deploy;
|
|
3239
3266
|
if (shape === "canonical") {
|
|
3240
|
-
|
|
3267
|
+
const record = parsed;
|
|
3268
|
+
return {
|
|
3269
|
+
...record,
|
|
3270
|
+
stack: record.stack || DEFAULT_STACK,
|
|
3271
|
+
plugins: record.plugins || [],
|
|
3272
|
+
infra: record.infra || DEFAULT_INFRA,
|
|
3273
|
+
deploy: normalizeDeploy(existingDeploy)
|
|
3274
|
+
};
|
|
3241
3275
|
}
|
|
3242
3276
|
if (shape === "cli-legacy") {
|
|
3243
3277
|
const github = parsed.github;
|
|
@@ -3253,10 +3287,13 @@ function normalizeToCanonical(parsed, name) {
|
|
|
3253
3287
|
url: "http://127.0.0.1:8080",
|
|
3254
3288
|
auto_created: true
|
|
3255
3289
|
},
|
|
3256
|
-
|
|
3290
|
+
stack: parsed.stack || DEFAULT_STACK,
|
|
3291
|
+
deploy: normalizeDeploy(existingDeploy),
|
|
3257
3292
|
pipeline: parsed.pipeline || {},
|
|
3258
3293
|
models: parsed.models || {},
|
|
3294
|
+
plugins: parsed.plugins || [],
|
|
3259
3295
|
slots: { max: null },
|
|
3296
|
+
infra: parsed.infra || DEFAULT_INFRA,
|
|
3260
3297
|
registered_at: parsed.registered_at || (/* @__PURE__ */ new Date()).toISOString()
|
|
3261
3298
|
};
|
|
3262
3299
|
}
|
|
@@ -3264,34 +3301,85 @@ function normalizeToCanonical(parsed, name) {
|
|
|
3264
3301
|
name: parsed.name || name,
|
|
3265
3302
|
path: parsed.path || "",
|
|
3266
3303
|
github: {
|
|
3267
|
-
repo: parsed.repo || "",
|
|
3304
|
+
repo: parsed.repo || parsed.github?.repo || "",
|
|
3268
3305
|
default_branch: "main"
|
|
3269
3306
|
},
|
|
3270
|
-
board:
|
|
3271
|
-
|
|
3307
|
+
board: parsed.board || {
|
|
3308
|
+
id: null,
|
|
3309
|
+
url: "http://127.0.0.1:8080",
|
|
3310
|
+
auto_created: true
|
|
3311
|
+
},
|
|
3312
|
+
stack: parsed.stack || DEFAULT_STACK,
|
|
3313
|
+
deploy: normalizeDeploy(existingDeploy),
|
|
3272
3314
|
pipeline: parsed.pipeline || {},
|
|
3273
3315
|
models: parsed.models || {},
|
|
3274
|
-
|
|
3275
|
-
|
|
3316
|
+
plugins: parsed.plugins || [],
|
|
3317
|
+
slots: parsed.slots || { max: null },
|
|
3318
|
+
infra: parsed.infra || DEFAULT_INFRA,
|
|
3319
|
+
registered_at: parsed.registered_at || (/* @__PURE__ */ new Date()).toISOString()
|
|
3276
3320
|
};
|
|
3277
3321
|
}
|
|
3278
3322
|
function createProjectRecord(input) {
|
|
3323
|
+
const name = input.name || basename3(input.resolvedPath);
|
|
3324
|
+
let boardId = null;
|
|
3325
|
+
if (input.boardId !== void 0 && input.boardId !== null) {
|
|
3326
|
+
const parsed = typeof input.boardId === "string" ? parseInt(input.boardId, 10) : input.boardId;
|
|
3327
|
+
boardId = isNaN(parsed) ? null : parsed;
|
|
3328
|
+
}
|
|
3329
|
+
let stack = input.stack || { ...DEFAULT_STACK };
|
|
3330
|
+
let gitRemote = input.gitRemote;
|
|
3331
|
+
let plugins = input.plugins;
|
|
3332
|
+
let deployTarget = input.deployTarget;
|
|
3333
|
+
if (!input.stack || gitRemote === void 0 || plugins === void 0 || deployTarget === void 0) {
|
|
3334
|
+
try {
|
|
3335
|
+
const detected = detectStack(input.resolvedPath);
|
|
3336
|
+
if (!input.stack) {
|
|
3337
|
+
stack = {
|
|
3338
|
+
detected: detected.framework,
|
|
3339
|
+
build_command: detected.suggested_commands.build,
|
|
3340
|
+
dev_command: detected.suggested_commands.dev,
|
|
3341
|
+
test_command: detected.suggested_commands.test,
|
|
3342
|
+
install_command: detected.suggested_commands.install,
|
|
3343
|
+
dev_port: detected.dev_port,
|
|
3344
|
+
is_monorepo: detected.is_monorepo,
|
|
3345
|
+
total_packages: detected.total_packages,
|
|
3346
|
+
primary_languages: detected.primary_languages,
|
|
3347
|
+
...detected.packages ? { packages: detected.packages } : {}
|
|
3348
|
+
};
|
|
3349
|
+
}
|
|
3350
|
+
if (gitRemote === void 0) gitRemote = detected.git_remote || "";
|
|
3351
|
+
if (plugins === void 0) plugins = detected.suggested_plugins || [];
|
|
3352
|
+
if (deployTarget === void 0) deployTarget = detected.suggested_deploy || "pr-only";
|
|
3353
|
+
} catch {
|
|
3354
|
+
if (gitRemote === void 0) gitRemote = "";
|
|
3355
|
+
if (plugins === void 0) plugins = [];
|
|
3356
|
+
if (deployTarget === void 0) deployTarget = "pr-only";
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
const verifyPort = input.verifyPort ?? computeVerifyPort(input.existingProjects);
|
|
3279
3360
|
return {
|
|
3280
|
-
name
|
|
3361
|
+
name,
|
|
3281
3362
|
path: input.resolvedPath,
|
|
3282
3363
|
github: {
|
|
3283
|
-
repo:
|
|
3364
|
+
repo: gitRemote || "",
|
|
3284
3365
|
default_branch: "main"
|
|
3285
3366
|
},
|
|
3286
3367
|
board: {
|
|
3287
|
-
id:
|
|
3368
|
+
id: boardId,
|
|
3288
3369
|
url: process.env.BEASTMODE_BOARD_URL || "http://127.0.0.1:8080",
|
|
3289
|
-
auto_created:
|
|
3370
|
+
auto_created: boardId === null
|
|
3371
|
+
},
|
|
3372
|
+
stack,
|
|
3373
|
+
deploy: {
|
|
3374
|
+
target: deployTarget,
|
|
3375
|
+
verify_port: verifyPort,
|
|
3376
|
+
config: {}
|
|
3290
3377
|
},
|
|
3291
|
-
deploy: { verify_port: input.verifyPort ?? 3001 },
|
|
3292
3378
|
pipeline: {},
|
|
3293
3379
|
models: {},
|
|
3380
|
+
plugins,
|
|
3294
3381
|
slots: { max: null },
|
|
3382
|
+
infra: { credentials: { mode: "factory" }, state_backend: "auto" },
|
|
3295
3383
|
registered_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
3296
3384
|
};
|
|
3297
3385
|
}
|
|
@@ -3339,8 +3427,16 @@ function readProjectRecord(projectsDir, name) {
|
|
|
3339
3427
|
}
|
|
3340
3428
|
const shape = detectShape(parsed);
|
|
3341
3429
|
const record = normalizeToCanonical(parsed, name);
|
|
3342
|
-
|
|
3430
|
+
const needsWrite = shape !== "canonical" || isFlat || hasMissingCanonicalFields(parsed);
|
|
3431
|
+
if (needsWrite) {
|
|
3343
3432
|
writeProjectRecord(projectsDir, name, record);
|
|
3433
|
+
console.error(`[project-record] Migrated ${name} from ${shape} to canonical schema`);
|
|
3434
|
+
if (isFlat) {
|
|
3435
|
+
try {
|
|
3436
|
+
unlinkSync(flatPath);
|
|
3437
|
+
} catch {
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3344
3440
|
}
|
|
3345
3441
|
return record;
|
|
3346
3442
|
}
|
|
@@ -3358,7 +3454,7 @@ function listProjectRecords(projectsDir) {
|
|
|
3358
3454
|
}
|
|
3359
3455
|
continue;
|
|
3360
3456
|
}
|
|
3361
|
-
if (entry.endsWith(".json")) {
|
|
3457
|
+
if (entry.endsWith(".json") && !entry.endsWith(".json.bak") && !entry.includes(".verifier")) {
|
|
3362
3458
|
const name = entry.slice(0, -5);
|
|
3363
3459
|
if (!seen.has(name)) {
|
|
3364
3460
|
seen.add(name);
|
|
@@ -3369,9 +3465,23 @@ function listProjectRecords(projectsDir) {
|
|
|
3369
3465
|
}
|
|
3370
3466
|
return records;
|
|
3371
3467
|
}
|
|
3468
|
+
var DEFAULT_STACK, DEFAULT_INFRA;
|
|
3372
3469
|
var init_project_record = __esm({
|
|
3373
3470
|
"src/engine/project-record.ts"() {
|
|
3374
3471
|
"use strict";
|
|
3472
|
+
init_stack_detector();
|
|
3473
|
+
DEFAULT_STACK = {
|
|
3474
|
+
detected: "unknown",
|
|
3475
|
+
build_command: "",
|
|
3476
|
+
dev_command: "",
|
|
3477
|
+
test_command: "",
|
|
3478
|
+
install_command: "",
|
|
3479
|
+
dev_port: 3e3
|
|
3480
|
+
};
|
|
3481
|
+
DEFAULT_INFRA = {
|
|
3482
|
+
credentials: { mode: "factory" },
|
|
3483
|
+
state_backend: "auto"
|
|
3484
|
+
};
|
|
3375
3485
|
}
|
|
3376
3486
|
});
|
|
3377
3487
|
|
|
@@ -3690,7 +3800,7 @@ var init_api_routes = __esm({
|
|
|
3690
3800
|
});
|
|
3691
3801
|
|
|
3692
3802
|
// src/cli/ui/archival.ts
|
|
3693
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync8, readdirSync as readdirSync4, renameSync as renameSync2, readFileSync as readFileSync9, statSync as statSync3, writeFileSync as writeFileSync9, unlinkSync } from "fs";
|
|
3803
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync8, readdirSync as readdirSync4, renameSync as renameSync2, readFileSync as readFileSync9, statSync as statSync3, writeFileSync as writeFileSync9, unlinkSync as unlinkSync2 } from "fs";
|
|
3694
3804
|
import { join as join10 } from "path";
|
|
3695
3805
|
function archiveOldRuns(runsDir, archiveAfterDays) {
|
|
3696
3806
|
if (archiveAfterDays <= 0 || !existsSync12(runsDir)) return { archived: 0 };
|
|
@@ -3731,7 +3841,7 @@ function pinRun(runsDir, runId) {
|
|
|
3731
3841
|
function unpinRun(runsDir, runId) {
|
|
3732
3842
|
const pinFile = join10(runsDir, runId, "pinned");
|
|
3733
3843
|
if (!existsSync12(pinFile)) return false;
|
|
3734
|
-
|
|
3844
|
+
unlinkSync2(pinFile);
|
|
3735
3845
|
return true;
|
|
3736
3846
|
}
|
|
3737
3847
|
function isRunPinned(runsDir, runId) {
|
|
@@ -3760,7 +3870,7 @@ __export(inception_exports, {
|
|
|
3760
3870
|
saveArtifact: () => saveArtifact,
|
|
3761
3871
|
saveInceptionState: () => saveInceptionState
|
|
3762
3872
|
});
|
|
3763
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync9, writeFileSync as writeFileSync10, readFileSync as readFileSync10, readdirSync as readdirSync5, unlinkSync as
|
|
3873
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync9, writeFileSync as writeFileSync10, readFileSync as readFileSync10, readdirSync as readdirSync5, unlinkSync as unlinkSync3 } from "fs";
|
|
3764
3874
|
import { join as join11, dirname as dirname4 } from "path";
|
|
3765
3875
|
import { fileURLToPath } from "url";
|
|
3766
3876
|
function getMethodologiesDir() {
|
|
@@ -3891,10 +4001,10 @@ function migrateInceptionToSession(factoryDir, productName) {
|
|
|
3891
4001
|
const src = join11(productDir, file);
|
|
3892
4002
|
if (existsSync13(src)) {
|
|
3893
4003
|
writeFileSync10(join11(sessionDir, file), readFileSync10(src, "utf-8"));
|
|
3894
|
-
|
|
4004
|
+
unlinkSync3(src);
|
|
3895
4005
|
}
|
|
3896
4006
|
}
|
|
3897
|
-
|
|
4007
|
+
unlinkSync3(oldInception);
|
|
3898
4008
|
return true;
|
|
3899
4009
|
}
|
|
3900
4010
|
function listProducts(factoryDir) {
|
|
@@ -5129,8 +5239,8 @@ var init_chat_handler = __esm({
|
|
|
5129
5239
|
});
|
|
5130
5240
|
|
|
5131
5241
|
// src/cli/ui/board-api-routes.ts
|
|
5132
|
-
import { readFileSync as readFileSync13, writeFileSync as writeFileSync13, existsSync as existsSync16, readdirSync as readdirSync8, unlinkSync as
|
|
5133
|
-
import { join as join14, basename as
|
|
5242
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync13, existsSync as existsSync16, readdirSync as readdirSync8, unlinkSync as unlinkSync4, mkdirSync as mkdirSync12, statSync as statSync6, rmSync as rmSync3 } from "fs";
|
|
5243
|
+
import { join as join14, basename as basename5, resolve as resolve4, dirname as dirname5 } from "path";
|
|
5134
5244
|
import { homedir } from "os";
|
|
5135
5245
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
5136
5246
|
import { execSync as execSync3, spawnSync } from "child_process";
|
|
@@ -5395,14 +5505,6 @@ function _gitHeadSha(repoPath) {
|
|
|
5395
5505
|
return "no-git";
|
|
5396
5506
|
}
|
|
5397
5507
|
}
|
|
5398
|
-
function _hasClaudeCli() {
|
|
5399
|
-
try {
|
|
5400
|
-
execSync3("which claude", { encoding: "utf-8" });
|
|
5401
|
-
return true;
|
|
5402
|
-
} catch {
|
|
5403
|
-
return false;
|
|
5404
|
-
}
|
|
5405
|
-
}
|
|
5406
5508
|
function getBoardRoutes(factoryDir) {
|
|
5407
5509
|
return [
|
|
5408
5510
|
// ── Status ──
|
|
@@ -5986,6 +6088,34 @@ function getBoardRoutes(factoryDir) {
|
|
|
5986
6088
|
return { success: true };
|
|
5987
6089
|
}
|
|
5988
6090
|
},
|
|
6091
|
+
// ── Doctor ──
|
|
6092
|
+
{
|
|
6093
|
+
method: "GET",
|
|
6094
|
+
pattern: "/api/doctor",
|
|
6095
|
+
handler: () => {
|
|
6096
|
+
const projectsDir = join14(factoryDir, ".beastmode", "projects");
|
|
6097
|
+
const projects = listProjectRecords(projectsDir);
|
|
6098
|
+
const checks = [];
|
|
6099
|
+
for (const p of projects) {
|
|
6100
|
+
const hasStack = !!(p.stack && p.stack.detected);
|
|
6101
|
+
const hasPlugins = Array.isArray(p.plugins);
|
|
6102
|
+
const hasInfra = !!(p.infra && p.infra.credentials);
|
|
6103
|
+
const hasDeployTarget = !!(p.deploy && p.deploy.target);
|
|
6104
|
+
const isCanonical = hasStack && hasPlugins && hasInfra && hasDeployTarget;
|
|
6105
|
+
checks.push({
|
|
6106
|
+
name: p.name,
|
|
6107
|
+
status: isCanonical ? "ok" : "warning",
|
|
6108
|
+
details: isCanonical ? "canonical schema" : `missing: ${[!hasStack && "stack", !hasPlugins && "plugins", !hasInfra && "infra", !hasDeployTarget && "deploy.target"].filter(Boolean).join(", ")}`
|
|
6109
|
+
});
|
|
6110
|
+
}
|
|
6111
|
+
const overallStatus = checks.every((c) => c.status === "ok") ? "ok" : "warning";
|
|
6112
|
+
return {
|
|
6113
|
+
status: overallStatus,
|
|
6114
|
+
project_count: projects.length,
|
|
6115
|
+
checks
|
|
6116
|
+
};
|
|
6117
|
+
}
|
|
6118
|
+
},
|
|
5989
6119
|
// ── Projects ──
|
|
5990
6120
|
{
|
|
5991
6121
|
method: "GET",
|
|
@@ -6118,7 +6248,7 @@ function getBoardRoutes(factoryDir) {
|
|
|
6118
6248
|
} else {
|
|
6119
6249
|
throw new Error("Missing required field: provide either `path` (local) or `github_url` (clone)");
|
|
6120
6250
|
}
|
|
6121
|
-
const projectName =
|
|
6251
|
+
const projectName = basename5(resolvedPath);
|
|
6122
6252
|
const stack = detectStack(resolvedPath);
|
|
6123
6253
|
let verifyPort = 3001;
|
|
6124
6254
|
for (const existing of listProjectRecords(projectsDir)) {
|
|
@@ -6129,21 +6259,22 @@ function getBoardRoutes(factoryDir) {
|
|
|
6129
6259
|
name: projectName,
|
|
6130
6260
|
resolvedPath,
|
|
6131
6261
|
gitRemote: stack.git_remote || void 0,
|
|
6132
|
-
verifyPort
|
|
6262
|
+
verifyPort,
|
|
6263
|
+
plugins: stack.suggested_plugins || [],
|
|
6264
|
+
deployTarget: stack.suggested_deploy || "pr-only",
|
|
6265
|
+
stack: {
|
|
6266
|
+
detected: stack.framework,
|
|
6267
|
+
build_command: stack.suggested_commands.build,
|
|
6268
|
+
dev_command: stack.suggested_commands.dev,
|
|
6269
|
+
test_command: stack.suggested_commands.test,
|
|
6270
|
+
install_command: stack.suggested_commands.install,
|
|
6271
|
+
dev_port: stack.dev_port,
|
|
6272
|
+
is_monorepo: stack.is_monorepo,
|
|
6273
|
+
total_packages: stack.total_packages,
|
|
6274
|
+
primary_languages: stack.primary_languages,
|
|
6275
|
+
...stack.packages ? { packages: stack.packages } : {}
|
|
6276
|
+
}
|
|
6133
6277
|
});
|
|
6134
|
-
record.stack = {
|
|
6135
|
-
detected: stack.framework,
|
|
6136
|
-
build_command: stack.suggested_commands.build,
|
|
6137
|
-
dev_command: stack.suggested_commands.dev,
|
|
6138
|
-
test_command: stack.suggested_commands.test,
|
|
6139
|
-
install_command: stack.suggested_commands.install,
|
|
6140
|
-
dev_port: stack.dev_port,
|
|
6141
|
-
is_monorepo: stack.is_monorepo,
|
|
6142
|
-
total_packages: stack.total_packages,
|
|
6143
|
-
primary_languages: stack.primary_languages,
|
|
6144
|
-
...stack.packages ? { packages: stack.packages } : {}
|
|
6145
|
-
};
|
|
6146
|
-
record.infra = { credentials: { mode: "factory" }, state_backend: "auto" };
|
|
6147
6278
|
writeProjectRecord(projectsDir, projectName, record);
|
|
6148
6279
|
const infraDir = join14(projectsDir, projectName, "infra");
|
|
6149
6280
|
mkdirSync12(join14(infraDir, "terraform"), { recursive: true });
|
|
@@ -6165,11 +6296,24 @@ function getBoardRoutes(factoryDir) {
|
|
|
6165
6296
|
if (!hasSubDir && !hasFlat) throw new Error(`Project not found: ${name}`);
|
|
6166
6297
|
if (hasSubDir) rmSync3(subDir, { recursive: true, force: true });
|
|
6167
6298
|
else if (existsSync16(subDir)) rmSync3(subDir, { recursive: true, force: true });
|
|
6168
|
-
if (hasFlat)
|
|
6299
|
+
if (hasFlat) unlinkSync4(flatPath);
|
|
6169
6300
|
return { success: true };
|
|
6170
6301
|
}
|
|
6171
6302
|
},
|
|
6172
6303
|
{
|
|
6304
|
+
// Trigger brownfield analysis for a project.
|
|
6305
|
+
//
|
|
6306
|
+
// POST body: { tier?: "quick" | "standard" | "full" }
|
|
6307
|
+
// tier "quick" — writes a lightweight detectStack() placeholder, no Claude invocation.
|
|
6308
|
+
// tier "standard" / "full" (default) — delegates real analysis to the daemon via
|
|
6309
|
+
// a trigger file in the shared .beastmode volume. The daemon has access to the
|
|
6310
|
+
// project source files (/app/project) which the UI container does NOT have.
|
|
6311
|
+
// Query params: force=true — bypass cache and re-run even if HEAD hasn't changed.
|
|
6312
|
+
//
|
|
6313
|
+
// Returns immediately (analysis runs in daemon background):
|
|
6314
|
+
// { analyzing: true, project: string, job_id: string, status: "running" }
|
|
6315
|
+
// { analyzed: true, project: string, cached: true, analyzed_at: string } (cache hit)
|
|
6316
|
+
// { analyzed: true, project: string, tier: "quick" } (quick tier)
|
|
6173
6317
|
method: "POST",
|
|
6174
6318
|
pattern: "/api/projects/:name/analyze",
|
|
6175
6319
|
handler: async (body, params, query) => {
|
|
@@ -6207,59 +6351,36 @@ Path: ${projectPath}
|
|
|
6207
6351
|
}
|
|
6208
6352
|
if (!force) {
|
|
6209
6353
|
const meta = _readAnalyzeMeta(projectsDir, name);
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6354
|
+
if (meta && meta.status === "complete") {
|
|
6355
|
+
const currentSha = _gitHeadSha(projectPath);
|
|
6356
|
+
if (currentSha === "no-git" || meta.target_repo_head_sha === currentSha) {
|
|
6357
|
+
return { analyzed: true, project: name, cached: true, analyzed_at: meta.analyzed_at };
|
|
6358
|
+
}
|
|
6213
6359
|
}
|
|
6214
6360
|
}
|
|
6215
6361
|
const existingJob = _analyzeJobs.get(name);
|
|
6216
6362
|
if (existingJob && existingJob.status === "running") {
|
|
6217
6363
|
return { analyzing: true, project: name, job_id: existingJob.job_id, status: "running" };
|
|
6218
6364
|
}
|
|
6219
|
-
const
|
|
6365
|
+
const triggerPath = join14(subDir, ".analyze-request.json");
|
|
6366
|
+
const inProgressPath = join14(subDir, ".analyze-in-progress.json");
|
|
6367
|
+
if (existsSync16(triggerPath) || existsSync16(inProgressPath)) {
|
|
6368
|
+
const existingTrigger = existsSync16(triggerPath) ? triggerPath : inProgressPath;
|
|
6220
6369
|
try {
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
const brownfieldPath = join14(subDir, "brownfield.md");
|
|
6232
|
-
if (!existsSync16(brownfieldPath)) {
|
|
6233
|
-
const { detectStack: detectStackFn } = await Promise.resolve().then(() => (init_engine(), engine_exports));
|
|
6234
|
-
let stackInfo = "Unknown stack";
|
|
6235
|
-
try {
|
|
6236
|
-
const stack = detectStackFn(projectPath);
|
|
6237
|
-
const cmds = stack.suggested_commands;
|
|
6238
|
-
stackInfo = `Framework: ${stack.framework || "unknown"}
|
|
6239
|
-
Build: ${cmds?.build || "unknown"}
|
|
6240
|
-
Dev: ${cmds?.dev || "unknown"}`;
|
|
6241
|
-
} catch {
|
|
6242
|
-
}
|
|
6243
|
-
writeFileSync13(brownfieldPath, `# Brownfield Analysis: ${name}
|
|
6244
|
-
|
|
6245
|
-
${stackInfo}
|
|
6246
|
-
|
|
6247
|
-
Path: ${projectPath}
|
|
6248
|
-
`);
|
|
6370
|
+
const t = JSON.parse(readFileSync13(existingTrigger, "utf-8"));
|
|
6371
|
+
const job2 = {
|
|
6372
|
+
job_id: t.job_id,
|
|
6373
|
+
project: name,
|
|
6374
|
+
status: "running",
|
|
6375
|
+
started_at: t.requested_at
|
|
6376
|
+
};
|
|
6377
|
+
_analyzeJobs.set(name, job2);
|
|
6378
|
+
return { analyzing: true, project: name, job_id: t.job_id, status: "running" };
|
|
6379
|
+
} catch {
|
|
6249
6380
|
}
|
|
6250
|
-
writeMeta({
|
|
6251
|
-
analyzed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6252
|
-
target_repo_head_sha: _gitHeadSha(projectPath),
|
|
6253
|
-
status: "failed",
|
|
6254
|
-
error: "Claude CLI not available",
|
|
6255
|
-
duration_seconds: 0
|
|
6256
|
-
});
|
|
6257
|
-
console.warn(`[analyze] Claude CLI unavailable for project ${name}; wrote detectStack() fallback.`);
|
|
6258
|
-
return { analyzed: true, project: name, fallback: true };
|
|
6259
6381
|
}
|
|
6260
6382
|
const jobId = randomUUID2();
|
|
6261
6383
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
6262
|
-
const startMs = Date.now();
|
|
6263
6384
|
const job = {
|
|
6264
6385
|
job_id: jobId,
|
|
6265
6386
|
project: name,
|
|
@@ -6267,171 +6388,86 @@ Path: ${projectPath}
|
|
|
6267
6388
|
started_at: startedAt
|
|
6268
6389
|
};
|
|
6269
6390
|
_analyzeJobs.set(name, job);
|
|
6270
|
-
(
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
].join("\n");
|
|
6282
|
-
const isRoot = process.getuid?.() === 0;
|
|
6283
|
-
const claudeArgs = [
|
|
6284
|
-
"-p",
|
|
6285
|
-
prompt,
|
|
6286
|
-
"--agent",
|
|
6287
|
-
"brownfield-analyst",
|
|
6288
|
-
"--output-format",
|
|
6289
|
-
"stream-json",
|
|
6290
|
-
"--verbose",
|
|
6291
|
-
"--dangerously-skip-permissions"
|
|
6292
|
-
];
|
|
6293
|
-
const spawnCmd = isRoot ? "runuser" : "claude";
|
|
6294
|
-
const spawnArgs = isRoot ? ["-u", "node", "--", "claude", ...claudeArgs] : claudeArgs;
|
|
6295
|
-
const child = spawn4(spawnCmd, spawnArgs, {
|
|
6296
|
-
cwd: projectPath,
|
|
6297
|
-
env: {
|
|
6298
|
-
...process.env,
|
|
6299
|
-
BEASTMODE_PROJECT: name,
|
|
6300
|
-
BEASTMODE_OUTPUT_DIR: subDir,
|
|
6301
|
-
...isRoot ? { HOME: "/home/node" } : {}
|
|
6302
|
-
},
|
|
6303
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
6304
|
-
});
|
|
6305
|
-
child.stdout?.on("data", () => {
|
|
6306
|
-
});
|
|
6307
|
-
child.stderr?.on("data", () => {
|
|
6308
|
-
});
|
|
6309
|
-
child.on("close", (code) => {
|
|
6310
|
-
const durationSeconds = (Date.now() - startMs) / 1e3;
|
|
6311
|
-
const sha = _gitHeadSha(projectPath);
|
|
6312
|
-
const guidePath = join14(subDir, "codebase-guide.md");
|
|
6313
|
-
const ok = code === 0 && existsSync16(guidePath);
|
|
6314
|
-
if (ok) {
|
|
6315
|
-
writeMeta({
|
|
6316
|
-
analyzed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6317
|
-
analyst_version: "brownfield-analyst-v1",
|
|
6318
|
-
target_repo_head_sha: sha,
|
|
6319
|
-
project_name: name,
|
|
6320
|
-
duration_seconds: durationSeconds,
|
|
6321
|
-
status: "complete"
|
|
6322
|
-
});
|
|
6323
|
-
const legacy = join14(subDir, "brownfield.md");
|
|
6324
|
-
if (existsSync16(legacy)) {
|
|
6325
|
-
try {
|
|
6326
|
-
unlinkSync3(legacy);
|
|
6327
|
-
} catch {
|
|
6328
|
-
}
|
|
6329
|
-
}
|
|
6330
|
-
_analyzeJobs.set(name, {
|
|
6331
|
-
...job,
|
|
6332
|
-
status: "complete",
|
|
6333
|
-
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6334
|
-
duration_seconds: durationSeconds
|
|
6335
|
-
});
|
|
6336
|
-
} else {
|
|
6337
|
-
const errMsg = `claude exited with code ${code}`;
|
|
6338
|
-
writeMeta({
|
|
6339
|
-
analyzed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6340
|
-
target_repo_head_sha: sha,
|
|
6341
|
-
status: "failed",
|
|
6342
|
-
error: errMsg,
|
|
6343
|
-
duration_seconds: durationSeconds
|
|
6344
|
-
});
|
|
6345
|
-
_analyzeJobs.set(name, {
|
|
6346
|
-
...job,
|
|
6347
|
-
status: "failed",
|
|
6348
|
-
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6349
|
-
duration_seconds: durationSeconds,
|
|
6350
|
-
error: errMsg
|
|
6351
|
-
});
|
|
6352
|
-
}
|
|
6353
|
-
});
|
|
6354
|
-
child.on("error", (err) => {
|
|
6355
|
-
const durationSeconds = (Date.now() - startMs) / 1e3;
|
|
6356
|
-
const sha = _gitHeadSha(projectPath);
|
|
6357
|
-
writeMeta({
|
|
6358
|
-
analyzed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6359
|
-
target_repo_head_sha: sha,
|
|
6360
|
-
status: "failed",
|
|
6361
|
-
error: String(err),
|
|
6362
|
-
duration_seconds: durationSeconds
|
|
6363
|
-
});
|
|
6364
|
-
_analyzeJobs.set(name, {
|
|
6365
|
-
...job,
|
|
6366
|
-
status: "failed",
|
|
6367
|
-
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6368
|
-
duration_seconds: durationSeconds,
|
|
6369
|
-
error: String(err)
|
|
6370
|
-
});
|
|
6371
|
-
});
|
|
6372
|
-
} catch (err) {
|
|
6373
|
-
const durationSeconds = (Date.now() - startMs) / 1e3;
|
|
6374
|
-
const sha = _gitHeadSha(projectPath);
|
|
6375
|
-
writeMeta({
|
|
6376
|
-
analyzed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6377
|
-
target_repo_head_sha: sha,
|
|
6378
|
-
status: "failed",
|
|
6379
|
-
error: String(err),
|
|
6380
|
-
duration_seconds: durationSeconds
|
|
6381
|
-
});
|
|
6382
|
-
_analyzeJobs.set(name, {
|
|
6383
|
-
...job,
|
|
6384
|
-
status: "failed",
|
|
6385
|
-
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6386
|
-
duration_seconds: durationSeconds,
|
|
6387
|
-
error: String(err)
|
|
6388
|
-
});
|
|
6389
|
-
}
|
|
6390
|
-
})();
|
|
6391
|
+
writeFileSync13(
|
|
6392
|
+
triggerPath,
|
|
6393
|
+
JSON.stringify({
|
|
6394
|
+
job_id: jobId,
|
|
6395
|
+
project_name: name,
|
|
6396
|
+
project_path: projectPath,
|
|
6397
|
+
requested_at: startedAt,
|
|
6398
|
+
force
|
|
6399
|
+
}, null, 2) + "\n",
|
|
6400
|
+
"utf-8"
|
|
6401
|
+
);
|
|
6391
6402
|
return { analyzing: true, project: name, job_id: jobId, status: "running" };
|
|
6392
6403
|
}
|
|
6393
6404
|
},
|
|
6394
6405
|
{
|
|
6406
|
+
// Poll the status of a background brownfield analysis job.
|
|
6407
|
+
//
|
|
6408
|
+
// Returns one of:
|
|
6409
|
+
// { status: "running", job_id: string, started_at: string }
|
|
6410
|
+
// { status: "complete", analyzed_at: string, duration_seconds: number, target_repo_head_sha: string }
|
|
6411
|
+
// { status: "cached", analyzed_at: string, duration_seconds: number, target_repo_head_sha: string }
|
|
6412
|
+
// { status: "failed", job_id?: string, error: string, started_at?: string, completed_at?: string }
|
|
6413
|
+
// { status: "idle" } — no analysis has been requested for this project
|
|
6395
6414
|
method: "GET",
|
|
6396
6415
|
pattern: "/api/projects/:name/analyze/status",
|
|
6397
6416
|
handler: (_body, params) => {
|
|
6398
6417
|
const { name } = params;
|
|
6399
6418
|
assertSafeName(name);
|
|
6400
6419
|
const projectsDir = join14(factoryDir, ".beastmode", "projects");
|
|
6401
|
-
const
|
|
6402
|
-
const
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
status: "
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
completed_at: job.completed_at,
|
|
6417
|
-
duration_seconds: job.duration_seconds
|
|
6418
|
-
};
|
|
6420
|
+
const subDir = join14(projectsDir, name);
|
|
6421
|
+
const triggerPath = join14(subDir, ".analyze-request.json");
|
|
6422
|
+
const inProgressPath = join14(subDir, ".analyze-in-progress.json");
|
|
6423
|
+
if (existsSync16(triggerPath) || existsSync16(inProgressPath)) {
|
|
6424
|
+
const job2 = _analyzeJobs.get(name);
|
|
6425
|
+
try {
|
|
6426
|
+
const p = existsSync16(triggerPath) ? triggerPath : inProgressPath;
|
|
6427
|
+
const t = JSON.parse(readFileSync13(p, "utf-8"));
|
|
6428
|
+
if (!job2 || job2.status !== "running") {
|
|
6429
|
+
_analyzeJobs.set(name, { job_id: t.job_id, project: name, status: "running", started_at: t.requested_at });
|
|
6430
|
+
}
|
|
6431
|
+
return { status: "running", job_id: t.job_id, started_at: t.requested_at };
|
|
6432
|
+
} catch {
|
|
6433
|
+
return { status: "running", job_id: job2?.job_id, started_at: job2?.started_at };
|
|
6434
|
+
}
|
|
6419
6435
|
}
|
|
6436
|
+
const meta = _readAnalyzeMeta(projectsDir, name);
|
|
6420
6437
|
if (meta && meta.status === "complete") {
|
|
6438
|
+
const job2 = _analyzeJobs.get(name);
|
|
6439
|
+
if (job2?.status === "running") {
|
|
6440
|
+
_analyzeJobs.set(name, { ...job2, status: "complete" });
|
|
6441
|
+
}
|
|
6421
6442
|
return {
|
|
6422
|
-
status:
|
|
6443
|
+
status: "complete",
|
|
6423
6444
|
analyzed_at: meta.analyzed_at,
|
|
6424
6445
|
duration_seconds: meta.duration_seconds,
|
|
6425
6446
|
target_repo_head_sha: meta.target_repo_head_sha
|
|
6426
6447
|
};
|
|
6427
6448
|
}
|
|
6428
6449
|
if (meta && meta.status === "failed") {
|
|
6450
|
+
const job2 = _analyzeJobs.get(name);
|
|
6451
|
+
if (job2?.status === "running") {
|
|
6452
|
+
_analyzeJobs.set(name, { ...job2, status: "failed", error: meta.error });
|
|
6453
|
+
}
|
|
6429
6454
|
return {
|
|
6430
6455
|
status: "failed",
|
|
6431
6456
|
analyzed_at: meta.analyzed_at,
|
|
6432
6457
|
error: meta.error
|
|
6433
6458
|
};
|
|
6434
6459
|
}
|
|
6460
|
+
const job = _analyzeJobs.get(name);
|
|
6461
|
+
if (job && job.status === "failed") {
|
|
6462
|
+
return {
|
|
6463
|
+
status: "failed",
|
|
6464
|
+
job_id: job.job_id,
|
|
6465
|
+
error: job.error,
|
|
6466
|
+
started_at: job.started_at,
|
|
6467
|
+
completed_at: job.completed_at,
|
|
6468
|
+
duration_seconds: job.duration_seconds
|
|
6469
|
+
};
|
|
6470
|
+
}
|
|
6435
6471
|
return { status: "idle" };
|
|
6436
6472
|
}
|
|
6437
6473
|
},
|
|
@@ -7979,7 +8015,7 @@ __export(sync_claude_creds_exports, {
|
|
|
7979
8015
|
});
|
|
7980
8016
|
import { Command as Command2 } from "commander";
|
|
7981
8017
|
import { execSync as execSync5, spawnSync as spawnSync2 } from "child_process";
|
|
7982
|
-
import { writeFileSync as writeFileSync15, readFileSync as readFileSync16, chmodSync, mkdirSync as mkdirSync14, existsSync as existsSync19, unlinkSync as
|
|
8018
|
+
import { writeFileSync as writeFileSync15, readFileSync as readFileSync16, chmodSync, mkdirSync as mkdirSync14, existsSync as existsSync19, unlinkSync as unlinkSync5 } from "fs";
|
|
7983
8019
|
import { join as join17 } from "path";
|
|
7984
8020
|
import { homedir as homedir2, platform } from "os";
|
|
7985
8021
|
function systemdUserDir() {
|
|
@@ -8052,7 +8088,7 @@ function removeUrgencyMarker(factoryDir) {
|
|
|
8052
8088
|
if (!factoryDir) return;
|
|
8053
8089
|
const markerPath = urgencyMarkerHostPath(factoryDir);
|
|
8054
8090
|
try {
|
|
8055
|
-
|
|
8091
|
+
unlinkSync5(markerPath);
|
|
8056
8092
|
} catch {
|
|
8057
8093
|
}
|
|
8058
8094
|
}
|
|
@@ -8158,7 +8194,7 @@ function uninstallAgent() {
|
|
|
8158
8194
|
warn(`launchctl bootout returned: ${result.stderr || result.stdout}`);
|
|
8159
8195
|
}
|
|
8160
8196
|
try {
|
|
8161
|
-
|
|
8197
|
+
unlinkSync5(plist);
|
|
8162
8198
|
} catch {
|
|
8163
8199
|
}
|
|
8164
8200
|
success(`LaunchAgent removed: ${LAUNCH_AGENT_LABEL}`);
|
|
@@ -8344,14 +8380,14 @@ function uninstallAgentLinux() {
|
|
|
8344
8380
|
let removed = false;
|
|
8345
8381
|
if (existsSync19(servicePath)) {
|
|
8346
8382
|
try {
|
|
8347
|
-
|
|
8383
|
+
unlinkSync5(servicePath);
|
|
8348
8384
|
removed = true;
|
|
8349
8385
|
} catch {
|
|
8350
8386
|
}
|
|
8351
8387
|
}
|
|
8352
8388
|
if (existsSync19(timerPath)) {
|
|
8353
8389
|
try {
|
|
8354
|
-
|
|
8390
|
+
unlinkSync5(timerPath);
|
|
8355
8391
|
removed = true;
|
|
8356
8392
|
} catch {
|
|
8357
8393
|
}
|
|
@@ -8529,7 +8565,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
8529
8565
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
8530
8566
|
import { z as z2 } from "zod";
|
|
8531
8567
|
import { readFileSync as readFileSync29, writeFileSync as writeFileSync25, existsSync as existsSync32, readdirSync as readdirSync12 } from "fs";
|
|
8532
|
-
import { join as join30, resolve as resolve18, basename as
|
|
8568
|
+
import { join as join30, resolve as resolve18, basename as basename7 } from "path";
|
|
8533
8569
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
8534
8570
|
function readJsonFile2(filePath) {
|
|
8535
8571
|
if (!existsSync32(filePath)) return null;
|
|
@@ -8848,7 +8884,7 @@ function createMcpServer() {
|
|
|
8848
8884
|
if (!existsSync32(resolvedPath)) {
|
|
8849
8885
|
return { content: [{ type: "text", text: `Directory not found: ${resolvedPath}` }], isError: true };
|
|
8850
8886
|
}
|
|
8851
|
-
const projectName =
|
|
8887
|
+
const projectName = basename7(resolvedPath);
|
|
8852
8888
|
const stack = detectStack(resolvedPath);
|
|
8853
8889
|
const projectsDir = join30(factoryDir, ".beastmode", "projects");
|
|
8854
8890
|
let verifyPort = 3001;
|
|
@@ -8966,7 +9002,7 @@ init_engine();
|
|
|
8966
9002
|
init_file_writer();
|
|
8967
9003
|
import { Command as Command3 } from "commander";
|
|
8968
9004
|
import inquirer from "inquirer";
|
|
8969
|
-
import { resolve as resolve6, basename as
|
|
9005
|
+
import { resolve as resolve6, basename as basename6, join as join18 } from "path";
|
|
8970
9006
|
import { existsSync as existsSync20, writeFileSync as writeFileSync16, mkdirSync as mkdirSync15, readFileSync as readFileSync17 } from "fs";
|
|
8971
9007
|
|
|
8972
9008
|
// src/cli/utils/docker.ts
|
|
@@ -9227,7 +9263,7 @@ function isSourceRepo(dir) {
|
|
|
9227
9263
|
async function runInit(name, opts) {
|
|
9228
9264
|
if (opts.ui) {
|
|
9229
9265
|
const { startServer: startServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
9230
|
-
const factoryName2 = name ||
|
|
9266
|
+
const factoryName2 = name || basename6(resolve6("."));
|
|
9231
9267
|
const projectPath2 = opts.project ? resolve6(opts.project) : void 0;
|
|
9232
9268
|
info("Starting init wizard...");
|
|
9233
9269
|
const uiServer = await startServer2({
|
|
@@ -9260,7 +9296,7 @@ async function runInit(name, opts) {
|
|
|
9260
9296
|
const totalSteps = 5;
|
|
9261
9297
|
header("BeastMode \u2014 Dark Factory Init");
|
|
9262
9298
|
info("Creating your Custom Dark Factory\n");
|
|
9263
|
-
const factoryName = name ||
|
|
9299
|
+
const factoryName = name || basename6(resolve6("."));
|
|
9264
9300
|
if (existsSync20(factoryName) && existsSync20(resolve6(factoryName, ".beastmode"))) {
|
|
9265
9301
|
throw new Error(`Factory already exists at ./${factoryName}. Use 'beastmode config' to modify.`);
|
|
9266
9302
|
}
|
|
@@ -9276,7 +9312,7 @@ async function runInit(name, opts) {
|
|
|
9276
9312
|
}
|
|
9277
9313
|
const templateProjectPath = resolve6(opts.project);
|
|
9278
9314
|
const templateStack = detectStack(templateProjectPath);
|
|
9279
|
-
const templateProjectName =
|
|
9315
|
+
const templateProjectName = basename6(templateProjectPath);
|
|
9280
9316
|
const actions2 = scaffoldFactory(factoryName, template.config, {
|
|
9281
9317
|
name: templateProjectName,
|
|
9282
9318
|
repo: templateStack.git_remote || void 0,
|
|
@@ -9471,7 +9507,7 @@ async function runInit(name, opts) {
|
|
|
9471
9507
|
success("Board UI password set");
|
|
9472
9508
|
}
|
|
9473
9509
|
step(5, totalSteps, "Boot");
|
|
9474
|
-
const projectName =
|
|
9510
|
+
const projectName = basename6(projectPath);
|
|
9475
9511
|
const actions = scaffoldFactory(factoryName, config, {
|
|
9476
9512
|
name: projectName,
|
|
9477
9513
|
repo: stack.git_remote || void 0,
|
|
@@ -10250,8 +10286,8 @@ for (const artifact of VALID_ARTIFACTS) {
|
|
|
10250
10286
|
|
|
10251
10287
|
// src/cli/commands/status.ts
|
|
10252
10288
|
init_status_checker();
|
|
10289
|
+
init_engine();
|
|
10253
10290
|
init_schemas();
|
|
10254
|
-
init_project_record();
|
|
10255
10291
|
init_display();
|
|
10256
10292
|
import { Command as Command10 } from "commander";
|
|
10257
10293
|
import { existsSync as existsSync24, readFileSync as readFileSync21, readdirSync as readdirSync10 } from "fs";
|
|
@@ -12572,8 +12608,8 @@ async function runDaemon(opts) {
|
|
|
12572
12608
|
const exitCode = await new Promise((resolvePromise) => {
|
|
12573
12609
|
child.on("exit", (code) => {
|
|
12574
12610
|
try {
|
|
12575
|
-
const { unlinkSync:
|
|
12576
|
-
|
|
12611
|
+
const { unlinkSync: unlinkSync8 } = __require("fs");
|
|
12612
|
+
unlinkSync8(pidFile);
|
|
12577
12613
|
} catch {
|
|
12578
12614
|
}
|
|
12579
12615
|
resolvePromise(code ?? 1);
|
|
@@ -13214,7 +13250,7 @@ init_display();
|
|
|
13214
13250
|
import { Command as Command23 } from "commander";
|
|
13215
13251
|
import { spawn as spawn3 } from "child_process";
|
|
13216
13252
|
import { existsSync as existsSync38 } from "fs";
|
|
13217
|
-
import { basename as
|
|
13253
|
+
import { basename as basename8, join as join37, resolve as resolve20 } from "path";
|
|
13218
13254
|
|
|
13219
13255
|
// src/cli/runner-image-builder.ts
|
|
13220
13256
|
import { execSync as execSync10 } from "child_process";
|
|
@@ -13800,7 +13836,7 @@ import {
|
|
|
13800
13836
|
createWriteStream,
|
|
13801
13837
|
existsSync as existsSync36,
|
|
13802
13838
|
mkdirSync as mkdirSync22,
|
|
13803
|
-
unlinkSync as
|
|
13839
|
+
unlinkSync as unlinkSync6,
|
|
13804
13840
|
writeFileSync as writeFileSync29
|
|
13805
13841
|
} from "fs";
|
|
13806
13842
|
import { homedir as homedir4 } from "os";
|
|
@@ -13868,7 +13904,7 @@ async function downloadAndExtractRunner(installDir, os, arch) {
|
|
|
13868
13904
|
);
|
|
13869
13905
|
}
|
|
13870
13906
|
try {
|
|
13871
|
-
|
|
13907
|
+
unlinkSync6(tarball);
|
|
13872
13908
|
} catch {
|
|
13873
13909
|
}
|
|
13874
13910
|
if (os === "darwin") {
|
|
@@ -14106,7 +14142,7 @@ import {
|
|
|
14106
14142
|
existsSync as existsSync37,
|
|
14107
14143
|
mkdirSync as mkdirSync23,
|
|
14108
14144
|
readFileSync as readFileSync34,
|
|
14109
|
-
unlinkSync as
|
|
14145
|
+
unlinkSync as unlinkSync7,
|
|
14110
14146
|
writeFileSync as writeFileSync30
|
|
14111
14147
|
} from "fs";
|
|
14112
14148
|
import { dirname as dirname9, join as join36 } from "path";
|
|
@@ -14198,7 +14234,7 @@ async function restoreWorkflows(projectDir) {
|
|
|
14198
14234
|
jobCount: fileState.originals.length
|
|
14199
14235
|
});
|
|
14200
14236
|
}
|
|
14201
|
-
|
|
14237
|
+
unlinkSync7(statePath);
|
|
14202
14238
|
return { nothingToRestore: false, files: resultFiles };
|
|
14203
14239
|
}
|
|
14204
14240
|
|
|
@@ -14217,7 +14253,7 @@ function resolveProjectName(projectDir) {
|
|
|
14217
14253
|
} catch {
|
|
14218
14254
|
}
|
|
14219
14255
|
}
|
|
14220
|
-
return
|
|
14256
|
+
return basename8(resolve20(projectDir));
|
|
14221
14257
|
}
|
|
14222
14258
|
async function runnerSetupAction(opts) {
|
|
14223
14259
|
if (opts.service !== void 0 && !opts.native) {
|
|
@@ -14593,7 +14629,7 @@ runnerCommand.command("build-image").description(
|
|
|
14593
14629
|
init_engine();
|
|
14594
14630
|
import { Command as Command24 } from "commander";
|
|
14595
14631
|
import { existsSync as existsSync39, mkdirSync as mkdirSync24, readFileSync as readFileSync35, renameSync as renameSync3 } from "fs";
|
|
14596
|
-
import { join as join38, resolve as resolve21, basename as
|
|
14632
|
+
import { join as join38, resolve as resolve21, basename as basename9 } from "path";
|
|
14597
14633
|
import { execSync as execSync13 } from "child_process";
|
|
14598
14634
|
var DEFAULT_MAX_PROJECTS = 5;
|
|
14599
14635
|
var MIN_DISK_WARNING_GB = 10;
|
|
@@ -14621,7 +14657,7 @@ function getFreeDiskGB() {
|
|
|
14621
14657
|
function projectAddAction(factoryDir, projectPath, opts) {
|
|
14622
14658
|
const resolvedPath = resolve21(projectPath);
|
|
14623
14659
|
if (!existsSync39(resolvedPath)) throw new Error(`Directory not found: ${resolvedPath}`);
|
|
14624
|
-
const projectName = opts.name ||
|
|
14660
|
+
const projectName = opts.name || basename9(resolvedPath);
|
|
14625
14661
|
const projectsDir = join38(factoryDir, ".beastmode", "projects");
|
|
14626
14662
|
if (existsSync39(join38(projectsDir, projectName, "project.json"))) {
|
|
14627
14663
|
throw new Error(`Project already exists: ${projectName}`);
|
|
@@ -14652,9 +14688,15 @@ function projectAddAction(factoryDir, projectPath, opts) {
|
|
|
14652
14688
|
if (typeof port === "number" && port >= verifyPort) verifyPort = port + 1;
|
|
14653
14689
|
}
|
|
14654
14690
|
const boardId = opts.boardId ? parseInt(opts.boardId, 10) : null;
|
|
14655
|
-
const record = createProjectRecord({
|
|
14656
|
-
|
|
14657
|
-
|
|
14691
|
+
const record = createProjectRecord({
|
|
14692
|
+
name: projectName,
|
|
14693
|
+
resolvedPath,
|
|
14694
|
+
boardId,
|
|
14695
|
+
verifyPort,
|
|
14696
|
+
gitRemote,
|
|
14697
|
+
plugins: detectedStack?.suggested_plugins || [],
|
|
14698
|
+
deployTarget: detectedStack?.suggested_deploy || "pr-only",
|
|
14699
|
+
stack: detectedStack ? {
|
|
14658
14700
|
detected: detectedStack.framework,
|
|
14659
14701
|
build_command: detectedStack.suggested_commands.build,
|
|
14660
14702
|
dev_command: detectedStack.suggested_commands.dev,
|
|
@@ -14665,8 +14707,8 @@ function projectAddAction(factoryDir, projectPath, opts) {
|
|
|
14665
14707
|
total_packages: detectedStack.total_packages,
|
|
14666
14708
|
primary_languages: detectedStack.primary_languages,
|
|
14667
14709
|
...detectedStack.packages ? { packages: detectedStack.packages } : {}
|
|
14668
|
-
}
|
|
14669
|
-
}
|
|
14710
|
+
} : void 0
|
|
14711
|
+
});
|
|
14670
14712
|
writeProjectRecord(projectsDir, projectName, record);
|
|
14671
14713
|
const runsDir = join38(factoryDir, "runs", projectName);
|
|
14672
14714
|
if (!existsSync39(runsDir)) mkdirSync24(runsDir, { recursive: true });
|
|
@@ -14712,7 +14754,7 @@ var projectCommand = new Command24("project").description("Manage projects in th
|
|
|
14712
14754
|
projectCommand.command("add <path>").description("Register a project").option("--name <name>", "Override project name").option("--board-id <id>", "Link to existing board ID").action((path, opts) => {
|
|
14713
14755
|
const factoryDir = resolve21(".");
|
|
14714
14756
|
projectAddAction(factoryDir, path, opts);
|
|
14715
|
-
console.log(`Project registered: ${opts.name ||
|
|
14757
|
+
console.log(`Project registered: ${opts.name || basename9(resolve21(path))}`);
|
|
14716
14758
|
});
|
|
14717
14759
|
projectCommand.command("list").description("List registered projects").action(() => {
|
|
14718
14760
|
const projects = projectListAction(resolve21("."));
|