@vladimir-ks/aigile 0.2.7 → 0.2.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/dist/bin/aigile.js +162 -82
- package/dist/bin/aigile.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/bin/aigile.js
CHANGED
|
@@ -1246,7 +1246,7 @@ var init_connection = __esm({
|
|
|
1246
1246
|
import { Command as Command23 } from "commander";
|
|
1247
1247
|
|
|
1248
1248
|
// src/index.ts
|
|
1249
|
-
var VERSION = true ? "0.2.
|
|
1249
|
+
var VERSION = true ? "0.2.8" : "0.0.0-dev";
|
|
1250
1250
|
|
|
1251
1251
|
// src/bin/aigile.ts
|
|
1252
1252
|
init_connection();
|
|
@@ -1254,7 +1254,7 @@ init_connection();
|
|
|
1254
1254
|
// src/commands/init.ts
|
|
1255
1255
|
import { Command } from "commander";
|
|
1256
1256
|
import { existsSync as existsSync4, mkdirSync as mkdirSync4, appendFileSync, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
1257
|
-
import { resolve, join as join4, relative, basename as basename2 } from "path";
|
|
1257
|
+
import { resolve as resolve2, join as join4, relative, basename as basename2 } from "path";
|
|
1258
1258
|
|
|
1259
1259
|
// src/utils/git.ts
|
|
1260
1260
|
import { execSync } from "child_process";
|
|
@@ -1413,7 +1413,7 @@ function header(title, opts = {}) {
|
|
|
1413
1413
|
|
|
1414
1414
|
// src/services/template-loader.ts
|
|
1415
1415
|
import { readdirSync, statSync, readFileSync as readFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
1416
|
-
import { join as join3, dirname as dirname2 } from "path";
|
|
1416
|
+
import { join as join3, dirname as dirname2, resolve, sep } from "path";
|
|
1417
1417
|
import { fileURLToPath } from "url";
|
|
1418
1418
|
var __filename = fileURLToPath(import.meta.url);
|
|
1419
1419
|
var __dirname = dirname2(__filename);
|
|
@@ -1465,8 +1465,17 @@ function writeTemplates(targetDir, templates) {
|
|
|
1465
1465
|
let written = 0;
|
|
1466
1466
|
let skipped = 0;
|
|
1467
1467
|
const errors = [];
|
|
1468
|
+
const resolvedTargetDir = resolve(targetDir);
|
|
1468
1469
|
for (const template of templates) {
|
|
1469
1470
|
const fullPath = join3(targetDir, template.relativePath);
|
|
1471
|
+
const resolvedFullPath = resolve(fullPath);
|
|
1472
|
+
if (!resolvedFullPath.startsWith(resolvedTargetDir + sep) && resolvedFullPath !== resolvedTargetDir) {
|
|
1473
|
+
errors.push({
|
|
1474
|
+
path: template.relativePath,
|
|
1475
|
+
error: "Path traversal detected - file path escapes target directory"
|
|
1476
|
+
});
|
|
1477
|
+
continue;
|
|
1478
|
+
}
|
|
1470
1479
|
if (existsSync3(fullPath)) {
|
|
1471
1480
|
skipped++;
|
|
1472
1481
|
continue;
|
|
@@ -1494,7 +1503,7 @@ var initCommand = new Command("init").description("Initialize AIGILE in current
|
|
|
1494
1503
|
"Module kind: library, service, ui, cli, other (for module profile)"
|
|
1495
1504
|
).option("--skip-templates", "Skip template file creation").option("-f, --force", "Reinitialize existing project").action(async (pathArg, options) => {
|
|
1496
1505
|
const opts = getOutputOptions(initCommand);
|
|
1497
|
-
const targetPath =
|
|
1506
|
+
const targetPath = resolve2(pathArg ?? process.cwd());
|
|
1498
1507
|
try {
|
|
1499
1508
|
await initProject(targetPath, options, opts);
|
|
1500
1509
|
} catch (err) {
|
|
@@ -7796,11 +7805,11 @@ uxJourneyCommand.command("delete").alias("rm").argument("<key>", "Journey key").
|
|
|
7796
7805
|
init_connection();
|
|
7797
7806
|
import { Command as Command19 } from "commander";
|
|
7798
7807
|
import { existsSync as existsSync7 } from "fs";
|
|
7799
|
-
import { resolve as
|
|
7808
|
+
import { resolve as resolve4, relative as relative4 } from "path";
|
|
7800
7809
|
|
|
7801
7810
|
// src/services/dependency-graph.ts
|
|
7802
7811
|
init_connection();
|
|
7803
|
-
import { resolve as
|
|
7812
|
+
import { resolve as resolve3, relative as relative3, dirname as dirname3 } from "path";
|
|
7804
7813
|
function buildDependencyGraph(projectId) {
|
|
7805
7814
|
const docs = queryAll(
|
|
7806
7815
|
`SELECT id, path, meta_status, last_approved_at, last_modified_at, meta_dependencies
|
|
@@ -7835,7 +7844,7 @@ function buildDependencyGraph(projectId) {
|
|
|
7835
7844
|
function resolveDocPath(fromPath, relativePath) {
|
|
7836
7845
|
if (relativePath.startsWith("./") || relativePath.startsWith("../")) {
|
|
7837
7846
|
const fromDir = dirname3(fromPath);
|
|
7838
|
-
const resolved =
|
|
7847
|
+
const resolved = resolve3(fromDir, relativePath);
|
|
7839
7848
|
return relative3(".", resolved);
|
|
7840
7849
|
}
|
|
7841
7850
|
return relativePath;
|
|
@@ -8139,7 +8148,7 @@ async function approveDocument(cwd, filePath, options, opts) {
|
|
|
8139
8148
|
if (!config?.project?.key) {
|
|
8140
8149
|
throw new Error("AIGILE not initialized in this directory");
|
|
8141
8150
|
}
|
|
8142
|
-
const absolutePath =
|
|
8151
|
+
const absolutePath = resolve4(cwd, filePath);
|
|
8143
8152
|
if (!existsSync7(absolutePath)) {
|
|
8144
8153
|
throw new Error(`File not found: ${filePath}`);
|
|
8145
8154
|
}
|
|
@@ -8173,7 +8182,7 @@ async function approveDocument(cwd, filePath, options, opts) {
|
|
|
8173
8182
|
blank();
|
|
8174
8183
|
info(`Cascade approving ${cascadeResult.affectedDocs.length} dependents...`, opts);
|
|
8175
8184
|
for (const depPath of cascadeResult.affectedDocs) {
|
|
8176
|
-
const depAbsolute =
|
|
8185
|
+
const depAbsolute = resolve4(cwd, depPath);
|
|
8177
8186
|
const depContent = readFileSync8(depAbsolute, "utf-8");
|
|
8178
8187
|
const updatedDep = updateFrontmatterContent(depContent, {
|
|
8179
8188
|
status: "APPROVED",
|
|
@@ -8200,7 +8209,7 @@ async function acknowledgeDocument(cwd, filePath, opts) {
|
|
|
8200
8209
|
if (!config?.project?.key) {
|
|
8201
8210
|
throw new Error("AIGILE not initialized in this directory");
|
|
8202
8211
|
}
|
|
8203
|
-
const absolutePath =
|
|
8212
|
+
const absolutePath = resolve4(cwd, filePath);
|
|
8204
8213
|
if (!existsSync7(absolutePath)) {
|
|
8205
8214
|
throw new Error(`File not found: ${filePath}`);
|
|
8206
8215
|
}
|
|
@@ -8223,7 +8232,7 @@ async function markReady(cwd, filePath, opts) {
|
|
|
8223
8232
|
if (!config?.project?.key) {
|
|
8224
8233
|
throw new Error("AIGILE not initialized in this directory");
|
|
8225
8234
|
}
|
|
8226
|
-
const absolutePath =
|
|
8235
|
+
const absolutePath = resolve4(cwd, filePath);
|
|
8227
8236
|
if (!existsSync7(absolutePath)) {
|
|
8228
8237
|
throw new Error(`File not found: ${filePath}`);
|
|
8229
8238
|
}
|
|
@@ -8251,7 +8260,7 @@ async function markException(cwd, filePath, reason, opts) {
|
|
|
8251
8260
|
if (!config?.project?.key) {
|
|
8252
8261
|
throw new Error("AIGILE not initialized in this directory");
|
|
8253
8262
|
}
|
|
8254
|
-
const absolutePath =
|
|
8263
|
+
const absolutePath = resolve4(cwd, filePath);
|
|
8255
8264
|
if (!existsSync7(absolutePath)) {
|
|
8256
8265
|
throw new Error(`File not found: ${filePath}`);
|
|
8257
8266
|
}
|
|
@@ -8277,7 +8286,7 @@ async function markRefactoring(cwd, filePath, opts) {
|
|
|
8277
8286
|
if (!config?.project?.key) {
|
|
8278
8287
|
throw new Error("AIGILE not initialized in this directory");
|
|
8279
8288
|
}
|
|
8280
|
-
const absolutePath =
|
|
8289
|
+
const absolutePath = resolve4(cwd, filePath);
|
|
8281
8290
|
if (!existsSync7(absolutePath)) {
|
|
8282
8291
|
throw new Error(`File not found: ${filePath}`);
|
|
8283
8292
|
}
|
|
@@ -8302,7 +8311,7 @@ async function archiveDocument(cwd, filePath, opts) {
|
|
|
8302
8311
|
if (!config?.project?.key) {
|
|
8303
8312
|
throw new Error("AIGILE not initialized in this directory");
|
|
8304
8313
|
}
|
|
8305
|
-
const absolutePath =
|
|
8314
|
+
const absolutePath = resolve4(cwd, filePath);
|
|
8306
8315
|
if (!existsSync7(absolutePath)) {
|
|
8307
8316
|
throw new Error(`File not found: ${filePath}`);
|
|
8308
8317
|
}
|
|
@@ -8512,10 +8521,19 @@ var docCommand = new Command19("doc").description("Document integrity and status
|
|
|
8512
8521
|
// src/commands/daemon.ts
|
|
8513
8522
|
init_connection();
|
|
8514
8523
|
import { Command as Command20 } from "commander";
|
|
8515
|
-
import {
|
|
8524
|
+
import {
|
|
8525
|
+
existsSync as existsSync11,
|
|
8526
|
+
writeFileSync as writeFileSync7,
|
|
8527
|
+
unlinkSync,
|
|
8528
|
+
readFileSync as readFileSync11,
|
|
8529
|
+
mkdirSync as mkdirSync5,
|
|
8530
|
+
statSync as statSync5,
|
|
8531
|
+
renameSync,
|
|
8532
|
+
readdirSync as readdirSync3
|
|
8533
|
+
} from "fs";
|
|
8516
8534
|
import { join as join12, dirname as dirname4 } from "path";
|
|
8517
8535
|
import { homedir as homedir2, platform } from "os";
|
|
8518
|
-
import { spawn, execSync as execSync2 } from "child_process";
|
|
8536
|
+
import { spawn, spawnSync, execSync as execSync2 } from "child_process";
|
|
8519
8537
|
init_config();
|
|
8520
8538
|
|
|
8521
8539
|
// src/services/daemon-manager.ts
|
|
@@ -8535,7 +8553,7 @@ init_config();
|
|
|
8535
8553
|
// src/services/document-status-transitions.ts
|
|
8536
8554
|
init_connection();
|
|
8537
8555
|
import { writeFileSync as writeFileSync6, readFileSync as readFileSync9, existsSync as existsSync8 } from "fs";
|
|
8538
|
-
import { resolve as
|
|
8556
|
+
import { resolve as resolve5 } from "path";
|
|
8539
8557
|
import { createHash as createHash2 } from "crypto";
|
|
8540
8558
|
async function handleDocumentEdit(projectId, docPath, absolutePath) {
|
|
8541
8559
|
if (!existsSync8(absolutePath)) {
|
|
@@ -8633,7 +8651,7 @@ async function onFileChanged(projectId, projectPath, relativeDocPath) {
|
|
|
8633
8651
|
if (!isAigileDoc(relativeDocPath)) {
|
|
8634
8652
|
return;
|
|
8635
8653
|
}
|
|
8636
|
-
const absolutePath =
|
|
8654
|
+
const absolutePath = resolve5(projectPath, relativeDocPath);
|
|
8637
8655
|
const transitioned = await handleDocumentEdit(
|
|
8638
8656
|
projectId,
|
|
8639
8657
|
relativeDocPath,
|
|
@@ -9441,7 +9459,11 @@ function cleanupOldLogs(logDir) {
|
|
|
9441
9459
|
function generateLaunchAgentPlist() {
|
|
9442
9460
|
const paths = getDaemonPaths();
|
|
9443
9461
|
const nodePath = process.execPath;
|
|
9444
|
-
const aigilePath = join12(
|
|
9462
|
+
const aigilePath = join12(
|
|
9463
|
+
dirname4(dirname4(import.meta.url.replace("file://", ""))),
|
|
9464
|
+
"bin",
|
|
9465
|
+
"aigile.js"
|
|
9466
|
+
);
|
|
9445
9467
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
9446
9468
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
9447
9469
|
<plist version="1.0">
|
|
@@ -9476,7 +9498,11 @@ function generateLaunchAgentPlist() {
|
|
|
9476
9498
|
function generateSystemdService() {
|
|
9477
9499
|
const paths = getDaemonPaths();
|
|
9478
9500
|
const nodePath = process.execPath;
|
|
9479
|
-
const aigilePath = join12(
|
|
9501
|
+
const aigilePath = join12(
|
|
9502
|
+
dirname4(dirname4(import.meta.url.replace("file://", ""))),
|
|
9503
|
+
"bin",
|
|
9504
|
+
"aigile.js"
|
|
9505
|
+
);
|
|
9480
9506
|
return `[Unit]
|
|
9481
9507
|
Description=AIGILE File Watcher Daemon
|
|
9482
9508
|
After=network.target
|
|
@@ -9495,7 +9521,9 @@ StandardError=append:${paths.logFile}
|
|
|
9495
9521
|
[Install]
|
|
9496
9522
|
WantedBy=default.target`;
|
|
9497
9523
|
}
|
|
9498
|
-
daemonCommand.command("install").description(
|
|
9524
|
+
daemonCommand.command("install").description(
|
|
9525
|
+
"Install daemon to start automatically on system boot (watches ALL registered projects)"
|
|
9526
|
+
).action(() => {
|
|
9499
9527
|
const opts = getOutputOptions(daemonCommand);
|
|
9500
9528
|
const paths = getDaemonPaths();
|
|
9501
9529
|
if (PLATFORM === "darwin") {
|
|
@@ -9660,12 +9688,15 @@ daemonCommand.command("status").description("Show daemon status for ALL register
|
|
|
9660
9688
|
let totalFiles = { allow: 0, unknown: 0, total: 0 };
|
|
9661
9689
|
for (const project of projects) {
|
|
9662
9690
|
const valid = existsSync11(project.path) && existsSync11(join12(project.path, ".aigile"));
|
|
9663
|
-
const counts = queryAll(
|
|
9691
|
+
const counts = queryAll(
|
|
9692
|
+
`
|
|
9664
9693
|
SELECT COALESCE(monitoring_category, 'unknown') as monitoring_category, COUNT(*) as count
|
|
9665
9694
|
FROM documents
|
|
9666
9695
|
WHERE project_id = ? AND status != 'deleted'
|
|
9667
9696
|
GROUP BY monitoring_category
|
|
9668
|
-
`,
|
|
9697
|
+
`,
|
|
9698
|
+
[project.id]
|
|
9699
|
+
);
|
|
9669
9700
|
let allow = 0;
|
|
9670
9701
|
let unknown = 0;
|
|
9671
9702
|
for (const row of counts) {
|
|
@@ -9689,28 +9720,32 @@ daemonCommand.command("status").description("Show daemon status for ALL register
|
|
|
9689
9720
|
}
|
|
9690
9721
|
const validCount = projectStats.filter((p) => p.valid).length;
|
|
9691
9722
|
if (opts.json) {
|
|
9692
|
-
console.log(
|
|
9693
|
-
|
|
9694
|
-
|
|
9695
|
-
|
|
9696
|
-
|
|
9697
|
-
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
9701
|
-
|
|
9702
|
-
|
|
9703
|
-
|
|
9704
|
-
|
|
9705
|
-
|
|
9706
|
-
|
|
9723
|
+
console.log(
|
|
9724
|
+
JSON.stringify({
|
|
9725
|
+
success: true,
|
|
9726
|
+
data: {
|
|
9727
|
+
running: status.running,
|
|
9728
|
+
pid: status.pid ?? null,
|
|
9729
|
+
platform: PLATFORM,
|
|
9730
|
+
installed: PLATFORM === "darwin" ? paths.plist && existsSync11(paths.plist) : PLATFORM === "linux" ? paths.service && existsSync11(paths.service) : false,
|
|
9731
|
+
projectCount: projects.length,
|
|
9732
|
+
validProjectCount: validCount,
|
|
9733
|
+
projects: projectStats,
|
|
9734
|
+
totalFiles,
|
|
9735
|
+
paths: {
|
|
9736
|
+
database: getDbPath(),
|
|
9737
|
+
pidFile: paths.pidFile,
|
|
9738
|
+
logFile: paths.logFile
|
|
9739
|
+
}
|
|
9707
9740
|
}
|
|
9708
|
-
}
|
|
9709
|
-
|
|
9741
|
+
})
|
|
9742
|
+
);
|
|
9710
9743
|
return;
|
|
9711
9744
|
}
|
|
9712
9745
|
console.log("\n\u{1F4CA} Daemon Status\n");
|
|
9713
|
-
console.log(
|
|
9746
|
+
console.log(
|
|
9747
|
+
`\u251C\u2500\u2500 Running: ${status.running ? "\u2705 Yes" : "\u274C No"}${status.pid ? ` (PID: ${status.pid})` : ""}`
|
|
9748
|
+
);
|
|
9714
9749
|
console.log(`\u251C\u2500\u2500 Platform: ${PLATFORM}`);
|
|
9715
9750
|
const installed = PLATFORM === "darwin" ? paths.plist && existsSync11(paths.plist) : PLATFORM === "linux" ? paths.service && existsSync11(paths.service) : false;
|
|
9716
9751
|
console.log(`\u251C\u2500\u2500 Installed: ${installed ? "\u2705 Yes" : "\u274C No"}`);
|
|
@@ -9733,7 +9768,9 @@ daemonCommand.command("status").description("Show daemon status for ALL register
|
|
|
9733
9768
|
console.log(` \u2514\u2500\u2500 Log File: ${paths.logFile}`);
|
|
9734
9769
|
console.log("");
|
|
9735
9770
|
if (projectStats.some((p) => !p.valid)) {
|
|
9736
|
-
console.log(
|
|
9771
|
+
console.log(
|
|
9772
|
+
'\u26A0\uFE0F Some projects have invalid paths. Run "aigile project cleanup" to remove them.\n'
|
|
9773
|
+
);
|
|
9737
9774
|
}
|
|
9738
9775
|
});
|
|
9739
9776
|
function getRelativeTime(isoDate) {
|
|
@@ -9782,25 +9819,35 @@ daemonCommand.command("run").option("--skip-resync", "Skip initial resync on sta
|
|
|
9782
9819
|
});
|
|
9783
9820
|
rotateLogIfNeeded();
|
|
9784
9821
|
writeFileSync7(paths.pidFile, String(process.pid));
|
|
9785
|
-
console.log(
|
|
9786
|
-
|
|
9822
|
+
console.log(
|
|
9823
|
+
`[${(/* @__PURE__ */ new Date()).toISOString()}] Starting AIGILE daemon for all registered projects...`
|
|
9824
|
+
);
|
|
9825
|
+
console.log(
|
|
9826
|
+
`[${(/* @__PURE__ */ new Date()).toISOString()}] PID: ${process.pid}, Node: ${process.version}, Platform: ${platform()}`
|
|
9827
|
+
);
|
|
9787
9828
|
const manager = getDaemonManager();
|
|
9788
9829
|
if (!options.skipResync) {
|
|
9789
9830
|
console.log(`[${(/* @__PURE__ */ new Date()).toISOString()}] Performing initial resync for all projects...`);
|
|
9790
9831
|
try {
|
|
9791
9832
|
const results = await manager.resyncAll();
|
|
9792
9833
|
const projectCount = Object.keys(results).length;
|
|
9793
|
-
console.log(
|
|
9834
|
+
console.log(
|
|
9835
|
+
`[${(/* @__PURE__ */ new Date()).toISOString()}] Resync complete: ${projectCount} projects synced`
|
|
9836
|
+
);
|
|
9794
9837
|
} catch (err) {
|
|
9795
9838
|
console.error(`[${(/* @__PURE__ */ new Date()).toISOString()}] Resync warning: ${err}`);
|
|
9796
9839
|
}
|
|
9797
9840
|
}
|
|
9798
9841
|
manager.on("sync", (event) => {
|
|
9799
9842
|
const categoryStr = event.category ? ` [${event.category}]` : "";
|
|
9800
|
-
console.log(
|
|
9843
|
+
console.log(
|
|
9844
|
+
`[${(/* @__PURE__ */ new Date()).toISOString()}] [${event.project}] Synced: ${event.type} ${event.path}${categoryStr}`
|
|
9845
|
+
);
|
|
9801
9846
|
});
|
|
9802
9847
|
manager.on("syncError", ({ project, event, error: err }) => {
|
|
9803
|
-
console.error(
|
|
9848
|
+
console.error(
|
|
9849
|
+
`[${(/* @__PURE__ */ new Date()).toISOString()}] [${project}] Sync error: ${event.type} ${event.path} - ${err}`
|
|
9850
|
+
);
|
|
9804
9851
|
});
|
|
9805
9852
|
manager.on("watcherError", ({ project, error: err }) => {
|
|
9806
9853
|
console.error(`[${(/* @__PURE__ */ new Date()).toISOString()}] [${project}] Watcher error: ${err}`);
|
|
@@ -9811,7 +9858,9 @@ daemonCommand.command("run").option("--skip-resync", "Skip initial resync on sta
|
|
|
9811
9858
|
isShuttingDown = true;
|
|
9812
9859
|
console.log(`[${(/* @__PURE__ */ new Date()).toISOString()}] Shutting down...`);
|
|
9813
9860
|
const forceExitTimeout = setTimeout(() => {
|
|
9814
|
-
console.error(
|
|
9861
|
+
console.error(
|
|
9862
|
+
`[${(/* @__PURE__ */ new Date()).toISOString()}] Shutdown timeout (${SHUTDOWN_TIMEOUT_MS}ms) - forcing exit`
|
|
9863
|
+
);
|
|
9815
9864
|
if (existsSync11(paths.pidFile)) {
|
|
9816
9865
|
try {
|
|
9817
9866
|
unlinkSync(paths.pidFile);
|
|
@@ -9834,15 +9883,20 @@ daemonCommand.command("run").option("--skip-resync", "Skip initial resync on sta
|
|
|
9834
9883
|
};
|
|
9835
9884
|
process.on("SIGTERM", shutdown);
|
|
9836
9885
|
process.on("SIGINT", shutdown);
|
|
9837
|
-
const logRotationInterval = setInterval(
|
|
9838
|
-
|
|
9839
|
-
|
|
9886
|
+
const logRotationInterval = setInterval(
|
|
9887
|
+
() => {
|
|
9888
|
+
rotateLogIfNeeded();
|
|
9889
|
+
},
|
|
9890
|
+
60 * 60 * 1e3
|
|
9891
|
+
);
|
|
9840
9892
|
process.on("exit", () => {
|
|
9841
9893
|
clearInterval(logRotationInterval);
|
|
9842
9894
|
});
|
|
9843
9895
|
try {
|
|
9844
9896
|
const status = await manager.start();
|
|
9845
|
-
console.log(
|
|
9897
|
+
console.log(
|
|
9898
|
+
`[${(/* @__PURE__ */ new Date()).toISOString()}] Daemon started - watching ${status.watchingCount} projects`
|
|
9899
|
+
);
|
|
9846
9900
|
for (const p of status.projects) {
|
|
9847
9901
|
if (p.watching) {
|
|
9848
9902
|
console.log(`[${(/* @__PURE__ */ new Date()).toISOString()}] \u2713 ${p.key}: ${p.path}`);
|
|
@@ -9863,6 +9917,11 @@ daemonCommand.command("logs").option("-n, --lines <number>", "Number of lines to
|
|
|
9863
9917
|
info("No log file found. Daemon may not have run yet.", opts);
|
|
9864
9918
|
return;
|
|
9865
9919
|
}
|
|
9920
|
+
const lines = parseInt(options.lines, 10);
|
|
9921
|
+
if (isNaN(lines) || lines < 1 || lines > 1e4) {
|
|
9922
|
+
error("Invalid lines parameter. Must be a number between 1 and 10000.", opts);
|
|
9923
|
+
return;
|
|
9924
|
+
}
|
|
9866
9925
|
if (options.follow) {
|
|
9867
9926
|
const tail = spawn("tail", ["-f", paths.logFile], {
|
|
9868
9927
|
stdio: "inherit"
|
|
@@ -9873,8 +9932,14 @@ daemonCommand.command("logs").option("-n, --lines <number>", "Number of lines to
|
|
|
9873
9932
|
});
|
|
9874
9933
|
} else {
|
|
9875
9934
|
try {
|
|
9876
|
-
const
|
|
9877
|
-
|
|
9935
|
+
const result = spawnSync("tail", ["-n", lines.toString(), paths.logFile], {
|
|
9936
|
+
encoding: "utf-8"
|
|
9937
|
+
});
|
|
9938
|
+
if (result.status === 0 && result.stdout) {
|
|
9939
|
+
console.log(result.stdout);
|
|
9940
|
+
} else {
|
|
9941
|
+
error("Failed to read log file", opts);
|
|
9942
|
+
}
|
|
9878
9943
|
} catch {
|
|
9879
9944
|
error("Failed to read log file", opts);
|
|
9880
9945
|
}
|
|
@@ -9892,13 +9957,15 @@ daemonCommand.command("resync").option("--project <key>", "Resync only a specifi
|
|
|
9892
9957
|
process.exit(1);
|
|
9893
9958
|
}
|
|
9894
9959
|
if (opts.json) {
|
|
9895
|
-
console.log(
|
|
9896
|
-
|
|
9897
|
-
|
|
9898
|
-
|
|
9899
|
-
|
|
9900
|
-
|
|
9901
|
-
|
|
9960
|
+
console.log(
|
|
9961
|
+
JSON.stringify({
|
|
9962
|
+
success: true,
|
|
9963
|
+
data: {
|
|
9964
|
+
project: options.project,
|
|
9965
|
+
...result
|
|
9966
|
+
}
|
|
9967
|
+
})
|
|
9968
|
+
);
|
|
9902
9969
|
} else {
|
|
9903
9970
|
success(`Resync complete for ${options.project}:`, opts);
|
|
9904
9971
|
console.log(` Allow: ${result.allow}`);
|
|
@@ -9917,13 +9984,15 @@ daemonCommand.command("resync").option("--project <key>", "Resync only a specifi
|
|
|
9917
9984
|
const results = await manager.resyncAll();
|
|
9918
9985
|
const projectKeys = Object.keys(results);
|
|
9919
9986
|
if (opts.json) {
|
|
9920
|
-
console.log(
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
|
|
9925
|
-
|
|
9926
|
-
|
|
9987
|
+
console.log(
|
|
9988
|
+
JSON.stringify({
|
|
9989
|
+
success: true,
|
|
9990
|
+
data: {
|
|
9991
|
+
projectCount: projectKeys.length,
|
|
9992
|
+
projects: results
|
|
9993
|
+
}
|
|
9994
|
+
})
|
|
9995
|
+
);
|
|
9927
9996
|
} else {
|
|
9928
9997
|
success(`Resync complete: ${projectKeys.length} projects`, opts);
|
|
9929
9998
|
for (const [key, result] of Object.entries(results)) {
|
|
@@ -9947,29 +10016,36 @@ daemonCommand.command("review").option("--list", "Just list unknown files withou
|
|
|
9947
10016
|
error("Could not load project config.", opts);
|
|
9948
10017
|
process.exit(1);
|
|
9949
10018
|
}
|
|
9950
|
-
const project = queryOne("SELECT id FROM projects WHERE key = ?", [
|
|
10019
|
+
const project = queryOne("SELECT id FROM projects WHERE key = ?", [
|
|
10020
|
+
config.project.key
|
|
10021
|
+
]);
|
|
9951
10022
|
if (!project) {
|
|
9952
10023
|
error(`Project "${config.project.key}" not found in database.`, opts);
|
|
9953
10024
|
process.exit(1);
|
|
9954
10025
|
}
|
|
9955
|
-
const unknownFiles = queryAll(
|
|
10026
|
+
const unknownFiles = queryAll(
|
|
10027
|
+
`
|
|
9956
10028
|
SELECT id, path, extension, size_bytes, updated_at
|
|
9957
10029
|
FROM documents
|
|
9958
10030
|
WHERE project_id = ? AND monitoring_category = 'unknown' AND status != 'deleted'
|
|
9959
10031
|
ORDER BY path
|
|
9960
|
-
`,
|
|
10032
|
+
`,
|
|
10033
|
+
[project.id]
|
|
10034
|
+
);
|
|
9961
10035
|
if (unknownFiles.length === 0) {
|
|
9962
10036
|
success("No unknown files to review! All files are classified.", opts);
|
|
9963
10037
|
return;
|
|
9964
10038
|
}
|
|
9965
10039
|
if (opts.json) {
|
|
9966
|
-
console.log(
|
|
9967
|
-
|
|
9968
|
-
|
|
9969
|
-
|
|
9970
|
-
|
|
9971
|
-
|
|
9972
|
-
|
|
10040
|
+
console.log(
|
|
10041
|
+
JSON.stringify({
|
|
10042
|
+
success: true,
|
|
10043
|
+
data: {
|
|
10044
|
+
count: unknownFiles.length,
|
|
10045
|
+
files: unknownFiles
|
|
10046
|
+
}
|
|
10047
|
+
})
|
|
10048
|
+
);
|
|
9973
10049
|
return;
|
|
9974
10050
|
}
|
|
9975
10051
|
if (options.list) {
|
|
@@ -9991,14 +10067,18 @@ daemonCommand.command("review").option("--list", "Just list unknown files withou
|
|
|
9991
10067
|
],
|
|
9992
10068
|
opts
|
|
9993
10069
|
);
|
|
9994
|
-
console.log(
|
|
10070
|
+
console.log(
|
|
10071
|
+
'\nUse "aigile daemon allow <pattern>" or "aigile daemon deny <pattern>" to classify files.'
|
|
10072
|
+
);
|
|
9995
10073
|
return;
|
|
9996
10074
|
}
|
|
9997
10075
|
console.log(`
|
|
9998
10076
|
\u{1F4CB} Unknown Files (${unknownFiles.length} total)
|
|
9999
10077
|
`);
|
|
10000
10078
|
console.log('Run "aigile daemon review --list" to see all files.');
|
|
10001
|
-
console.log(
|
|
10079
|
+
console.log(
|
|
10080
|
+
'Use "aigile daemon allow <pattern>" or "aigile daemon deny <pattern>" to classify.\n'
|
|
10081
|
+
);
|
|
10002
10082
|
const sample = unknownFiles.slice(0, 10);
|
|
10003
10083
|
for (const file of sample) {
|
|
10004
10084
|
console.log(` ${file.path} (.${file.extension || "no ext"})`);
|
|
@@ -10936,7 +11016,7 @@ init_connection();
|
|
|
10936
11016
|
init_connection();
|
|
10937
11017
|
import { Command as Command22 } from "commander";
|
|
10938
11018
|
import { glob as glob2 } from "glob";
|
|
10939
|
-
import { relative as relative7, resolve as
|
|
11019
|
+
import { relative as relative7, resolve as resolve6 } from "path";
|
|
10940
11020
|
init_config();
|
|
10941
11021
|
function safeParseArray(json) {
|
|
10942
11022
|
if (!json) return [];
|
|
@@ -10983,7 +11063,7 @@ chunkCommand.command("create").argument("<id>", "Chunk ID (e.g., chunk-001)").op
|
|
|
10983
11063
|
if (options.pattern) {
|
|
10984
11064
|
for (const pattern of options.pattern) {
|
|
10985
11065
|
const matches = await glob2(pattern, { cwd: projectRoot, nodir: true });
|
|
10986
|
-
assignedFiles.push(...matches.map((f) => relative7(projectRoot,
|
|
11066
|
+
assignedFiles.push(...matches.map((f) => relative7(projectRoot, resolve6(projectRoot, f))));
|
|
10987
11067
|
}
|
|
10988
11068
|
}
|
|
10989
11069
|
if (options.assign) {
|