opencroc 1.8.0 → 1.8.1
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/cli/index.js +354 -43
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/web/index-studio.html +886 -46
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -6324,8 +6324,222 @@ var init_insight = __esm({
|
|
|
6324
6324
|
}
|
|
6325
6325
|
});
|
|
6326
6326
|
|
|
6327
|
+
// src/server/studio-store.ts
|
|
6328
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync11, readFileSync as readFileSync6, writeFileSync as writeFileSync10 } from "fs";
|
|
6329
|
+
import { dirname as dirname6 } from "path";
|
|
6330
|
+
function isSerializedSnapshotFile(value) {
|
|
6331
|
+
return "snapshots" in value && Array.isArray(value.snapshots);
|
|
6332
|
+
}
|
|
6333
|
+
var EMPTY_STUDIO_STORE, FileStudioSnapshotStore;
|
|
6334
|
+
var init_studio_store = __esm({
|
|
6335
|
+
"src/server/studio-store.ts"() {
|
|
6336
|
+
"use strict";
|
|
6337
|
+
init_esm_shims();
|
|
6338
|
+
EMPTY_STUDIO_STORE = {
|
|
6339
|
+
graph: null,
|
|
6340
|
+
risks: [],
|
|
6341
|
+
scanTime: 0,
|
|
6342
|
+
source: ""
|
|
6343
|
+
};
|
|
6344
|
+
FileStudioSnapshotStore = class {
|
|
6345
|
+
filePath;
|
|
6346
|
+
maxSnapshots;
|
|
6347
|
+
constructor(filePath, maxSnapshots = 12) {
|
|
6348
|
+
this.filePath = filePath;
|
|
6349
|
+
this.maxSnapshots = maxSnapshots;
|
|
6350
|
+
}
|
|
6351
|
+
load() {
|
|
6352
|
+
const data = this.readFile();
|
|
6353
|
+
if (!data || !data.currentSnapshotId) return null;
|
|
6354
|
+
const current = data.snapshots.find((snapshot) => snapshot.id === data.currentSnapshotId);
|
|
6355
|
+
return current ? this.toProjectStore(current) : null;
|
|
6356
|
+
}
|
|
6357
|
+
save(snapshot) {
|
|
6358
|
+
const data = this.readFile() ?? { version: 2, currentSnapshotId: null, snapshots: [] };
|
|
6359
|
+
const record = this.toSnapshotRecord(snapshot);
|
|
6360
|
+
data.currentSnapshotId = record.id;
|
|
6361
|
+
data.snapshots = [record, ...data.snapshots].slice(0, this.maxSnapshots);
|
|
6362
|
+
mkdirSync11(dirname6(this.filePath), { recursive: true });
|
|
6363
|
+
writeFileSync10(this.filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
6364
|
+
}
|
|
6365
|
+
list() {
|
|
6366
|
+
const data = this.readFile();
|
|
6367
|
+
if (!data) return [];
|
|
6368
|
+
return data.snapshots.map((snapshot) => ({
|
|
6369
|
+
id: snapshot.id,
|
|
6370
|
+
name: snapshot.name,
|
|
6371
|
+
source: snapshot.source,
|
|
6372
|
+
scanTime: snapshot.scanTime,
|
|
6373
|
+
nodeCount: snapshot.graph?.nodes.length ?? 0,
|
|
6374
|
+
riskCount: snapshot.risks.length,
|
|
6375
|
+
current: snapshot.id === data.currentSnapshotId,
|
|
6376
|
+
pinned: Boolean(snapshot.pinned),
|
|
6377
|
+
tags: Array.isArray(snapshot.tags) ? snapshot.tags : []
|
|
6378
|
+
})).sort((left, right) => {
|
|
6379
|
+
if (left.pinned !== right.pinned) return left.pinned ? -1 : 1;
|
|
6380
|
+
return right.scanTime - left.scanTime;
|
|
6381
|
+
});
|
|
6382
|
+
}
|
|
6383
|
+
loadById(id) {
|
|
6384
|
+
const data = this.readFile();
|
|
6385
|
+
if (!data) return null;
|
|
6386
|
+
const record = data.snapshots.find((snapshot) => snapshot.id === id);
|
|
6387
|
+
if (!record) return null;
|
|
6388
|
+
data.currentSnapshotId = record.id;
|
|
6389
|
+
mkdirSync11(dirname6(this.filePath), { recursive: true });
|
|
6390
|
+
writeFileSync10(this.filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
6391
|
+
return this.toProjectStore(record);
|
|
6392
|
+
}
|
|
6393
|
+
rename(id, name) {
|
|
6394
|
+
const nextName = name.trim();
|
|
6395
|
+
if (!nextName) return false;
|
|
6396
|
+
const data = this.readFile();
|
|
6397
|
+
if (!data) return false;
|
|
6398
|
+
const record = data.snapshots.find((snapshot) => snapshot.id === id);
|
|
6399
|
+
if (!record) return false;
|
|
6400
|
+
record.name = nextName;
|
|
6401
|
+
mkdirSync11(dirname6(this.filePath), { recursive: true });
|
|
6402
|
+
writeFileSync10(this.filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
6403
|
+
return true;
|
|
6404
|
+
}
|
|
6405
|
+
delete(id) {
|
|
6406
|
+
const data = this.readFile();
|
|
6407
|
+
if (!data) return false;
|
|
6408
|
+
const nextSnapshots = data.snapshots.filter((snapshot) => snapshot.id !== id);
|
|
6409
|
+
if (nextSnapshots.length === data.snapshots.length) return false;
|
|
6410
|
+
data.snapshots = nextSnapshots;
|
|
6411
|
+
if (data.currentSnapshotId === id) {
|
|
6412
|
+
data.currentSnapshotId = nextSnapshots[0]?.id ?? null;
|
|
6413
|
+
}
|
|
6414
|
+
mkdirSync11(dirname6(this.filePath), { recursive: true });
|
|
6415
|
+
writeFileSync10(this.filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
6416
|
+
return true;
|
|
6417
|
+
}
|
|
6418
|
+
pin(id, pinned) {
|
|
6419
|
+
const data = this.readFile();
|
|
6420
|
+
if (!data) return false;
|
|
6421
|
+
const record = data.snapshots.find((snapshot) => snapshot.id === id);
|
|
6422
|
+
if (!record) return false;
|
|
6423
|
+
record.pinned = pinned;
|
|
6424
|
+
mkdirSync11(dirname6(this.filePath), { recursive: true });
|
|
6425
|
+
writeFileSync10(this.filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
6426
|
+
return true;
|
|
6427
|
+
}
|
|
6428
|
+
updateTags(id, tags) {
|
|
6429
|
+
const data = this.readFile();
|
|
6430
|
+
if (!data) return false;
|
|
6431
|
+
const record = data.snapshots.find((snapshot) => snapshot.id === id);
|
|
6432
|
+
if (!record) return false;
|
|
6433
|
+
record.tags = this.normalizeTags(tags);
|
|
6434
|
+
mkdirSync11(dirname6(this.filePath), { recursive: true });
|
|
6435
|
+
writeFileSync10(this.filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
6436
|
+
return true;
|
|
6437
|
+
}
|
|
6438
|
+
readFile() {
|
|
6439
|
+
if (!existsSync18(this.filePath)) return null;
|
|
6440
|
+
try {
|
|
6441
|
+
const raw = readFileSync6(this.filePath, "utf-8");
|
|
6442
|
+
const parsed = JSON.parse(raw);
|
|
6443
|
+
return this.normalize(parsed);
|
|
6444
|
+
} catch {
|
|
6445
|
+
return null;
|
|
6446
|
+
}
|
|
6447
|
+
}
|
|
6448
|
+
normalize(parsed) {
|
|
6449
|
+
if (isSerializedSnapshotFile(parsed)) {
|
|
6450
|
+
return {
|
|
6451
|
+
version: 2,
|
|
6452
|
+
currentSnapshotId: typeof parsed.currentSnapshotId === "string" ? parsed.currentSnapshotId : null,
|
|
6453
|
+
snapshots: parsed.snapshots.map((snapshot) => ({
|
|
6454
|
+
id: snapshot.id,
|
|
6455
|
+
name: snapshot.name,
|
|
6456
|
+
pinned: Boolean(snapshot.pinned),
|
|
6457
|
+
tags: this.normalizeTags(snapshot.tags),
|
|
6458
|
+
graph: snapshot.graph ?? null,
|
|
6459
|
+
risks: Array.isArray(snapshot.risks) ? snapshot.risks : [],
|
|
6460
|
+
scanTime: typeof snapshot.scanTime === "number" ? snapshot.scanTime : 0,
|
|
6461
|
+
source: typeof snapshot.source === "string" ? snapshot.source : ""
|
|
6462
|
+
}))
|
|
6463
|
+
};
|
|
6464
|
+
}
|
|
6465
|
+
const legacyStore = parsed;
|
|
6466
|
+
const legacy = this.toSnapshotRecord({
|
|
6467
|
+
graph: legacyStore.graph ?? null,
|
|
6468
|
+
risks: Array.isArray(legacyStore.risks) ? legacyStore.risks : [],
|
|
6469
|
+
scanTime: typeof legacyStore.scanTime === "number" ? legacyStore.scanTime : 0,
|
|
6470
|
+
source: typeof legacyStore.source === "string" ? legacyStore.source : ""
|
|
6471
|
+
});
|
|
6472
|
+
return {
|
|
6473
|
+
version: 2,
|
|
6474
|
+
currentSnapshotId: legacy.id,
|
|
6475
|
+
snapshots: [legacy]
|
|
6476
|
+
};
|
|
6477
|
+
}
|
|
6478
|
+
toSnapshotRecord(snapshot) {
|
|
6479
|
+
const name = snapshot.graph?.projectInfo?.name || this.deriveName(snapshot.source);
|
|
6480
|
+
return {
|
|
6481
|
+
id: `${snapshot.scanTime || Date.now()}-${Math.random().toString(16).slice(2, 8)}`,
|
|
6482
|
+
name,
|
|
6483
|
+
pinned: false,
|
|
6484
|
+
tags: [],
|
|
6485
|
+
graph: snapshot.graph ?? null,
|
|
6486
|
+
risks: Array.isArray(snapshot.risks) ? snapshot.risks : [],
|
|
6487
|
+
scanTime: typeof snapshot.scanTime === "number" ? snapshot.scanTime : Date.now(),
|
|
6488
|
+
source: typeof snapshot.source === "string" ? snapshot.source : ""
|
|
6489
|
+
};
|
|
6490
|
+
}
|
|
6491
|
+
toProjectStore(snapshot) {
|
|
6492
|
+
return {
|
|
6493
|
+
graph: snapshot.graph ?? null,
|
|
6494
|
+
risks: Array.isArray(snapshot.risks) ? snapshot.risks : [],
|
|
6495
|
+
scanTime: typeof snapshot.scanTime === "number" ? snapshot.scanTime : 0,
|
|
6496
|
+
source: typeof snapshot.source === "string" ? snapshot.source : ""
|
|
6497
|
+
};
|
|
6498
|
+
}
|
|
6499
|
+
deriveName(source) {
|
|
6500
|
+
if (!source) return "unknown-project";
|
|
6501
|
+
const parts = source.split(/[\\/]/).filter(Boolean);
|
|
6502
|
+
return parts[parts.length - 1] || source;
|
|
6503
|
+
}
|
|
6504
|
+
normalizeTags(tags) {
|
|
6505
|
+
if (!Array.isArray(tags)) return [];
|
|
6506
|
+
return [...new Set(
|
|
6507
|
+
tags.map((tag) => typeof tag === "string" ? tag.trim() : "").filter(Boolean)
|
|
6508
|
+
)];
|
|
6509
|
+
}
|
|
6510
|
+
};
|
|
6511
|
+
}
|
|
6512
|
+
});
|
|
6513
|
+
|
|
6327
6514
|
// src/server/routes/studio.ts
|
|
6328
|
-
function
|
|
6515
|
+
function restoreStore(snapshotStore) {
|
|
6516
|
+
return snapshotStore?.load() ?? { ...EMPTY_STUDIO_STORE };
|
|
6517
|
+
}
|
|
6518
|
+
function registerStudioRoutes(app, office, snapshotStore) {
|
|
6519
|
+
const store = restoreStore(snapshotStore);
|
|
6520
|
+
if (store.graph) {
|
|
6521
|
+
office.log(`\u267B\uFE0F Restored Studio snapshot: ${store.graph.nodes.length} nodes, ${store.risks.length} risks`, "info");
|
|
6522
|
+
}
|
|
6523
|
+
const persistStore = () => {
|
|
6524
|
+
snapshotStore?.save(store);
|
|
6525
|
+
};
|
|
6526
|
+
const broadcastGraph = () => {
|
|
6527
|
+
if (!store.graph) return;
|
|
6528
|
+
office.broadcast("graph:update", {
|
|
6529
|
+
nodes: store.graph.nodes.map((n) => ({
|
|
6530
|
+
id: n.id,
|
|
6531
|
+
label: n.label,
|
|
6532
|
+
type: n.type,
|
|
6533
|
+
module: n.module,
|
|
6534
|
+
status: n.status
|
|
6535
|
+
})),
|
|
6536
|
+
edges: store.graph.edges.map((e) => ({
|
|
6537
|
+
source: e.source,
|
|
6538
|
+
target: e.target,
|
|
6539
|
+
relation: e.relation
|
|
6540
|
+
}))
|
|
6541
|
+
});
|
|
6542
|
+
};
|
|
6329
6543
|
app.post("/api/studio/scan", async (req, reply) => {
|
|
6330
6544
|
const { target, branch, useLlm } = req.body || {};
|
|
6331
6545
|
if (!target || typeof target !== "string") {
|
|
@@ -6364,20 +6578,8 @@ function registerStudioRoutes(app, office) {
|
|
|
6364
6578
|
store.risks = risks;
|
|
6365
6579
|
store.scanTime = Date.now();
|
|
6366
6580
|
store.source = target;
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
id: n.id,
|
|
6370
|
-
label: n.label,
|
|
6371
|
-
type: n.type,
|
|
6372
|
-
module: n.module,
|
|
6373
|
-
status: n.status
|
|
6374
|
-
})),
|
|
6375
|
-
edges: graph.edges.map((e) => ({
|
|
6376
|
-
source: e.source,
|
|
6377
|
-
target: e.target,
|
|
6378
|
-
relation: e.relation
|
|
6379
|
-
}))
|
|
6380
|
-
});
|
|
6581
|
+
persistStore();
|
|
6582
|
+
broadcastGraph();
|
|
6381
6583
|
return {
|
|
6382
6584
|
ok: true,
|
|
6383
6585
|
project: graph.projectInfo,
|
|
@@ -6511,8 +6713,120 @@ function registerStudioRoutes(app, office) {
|
|
|
6511
6713
|
source: store.source
|
|
6512
6714
|
};
|
|
6513
6715
|
});
|
|
6716
|
+
app.get("/api/studio/snapshots", async () => {
|
|
6717
|
+
const snapshots = snapshotStore?.list() ?? [];
|
|
6718
|
+
return {
|
|
6719
|
+
total: snapshots.length,
|
|
6720
|
+
snapshots
|
|
6721
|
+
};
|
|
6722
|
+
});
|
|
6723
|
+
app.post("/api/studio/snapshots/:id/load", async (req, reply) => {
|
|
6724
|
+
if (!snapshotStore) {
|
|
6725
|
+
reply.code(501).send({ error: "Snapshot persistence is not configured." });
|
|
6726
|
+
return;
|
|
6727
|
+
}
|
|
6728
|
+
const restored = snapshotStore.loadById(req.params.id);
|
|
6729
|
+
if (!restored) {
|
|
6730
|
+
reply.code(404).send({ error: "Snapshot not found." });
|
|
6731
|
+
return;
|
|
6732
|
+
}
|
|
6733
|
+
store.graph = restored.graph;
|
|
6734
|
+
store.risks = restored.risks;
|
|
6735
|
+
store.scanTime = restored.scanTime;
|
|
6736
|
+
store.source = restored.source;
|
|
6737
|
+
office.log(`\u267B\uFE0F Restored snapshot: ${store.source || "unknown source"}`, "info");
|
|
6738
|
+
broadcastGraph();
|
|
6739
|
+
return {
|
|
6740
|
+
ok: true,
|
|
6741
|
+
source: store.source,
|
|
6742
|
+
scanTime: store.scanTime,
|
|
6743
|
+
graph: store.graph ? {
|
|
6744
|
+
nodeCount: store.graph.nodes.length,
|
|
6745
|
+
edgeCount: store.graph.edges.length
|
|
6746
|
+
} : null,
|
|
6747
|
+
risks: store.risks.length
|
|
6748
|
+
};
|
|
6749
|
+
});
|
|
6750
|
+
app.post("/api/studio/snapshots/:id/rename", async (req, reply) => {
|
|
6751
|
+
if (!snapshotStore) {
|
|
6752
|
+
reply.code(501).send({ error: "Snapshot persistence is not configured." });
|
|
6753
|
+
return;
|
|
6754
|
+
}
|
|
6755
|
+
const name = req.body?.name?.trim();
|
|
6756
|
+
if (!name) {
|
|
6757
|
+
reply.code(400).send({ error: "Snapshot name is required." });
|
|
6758
|
+
return;
|
|
6759
|
+
}
|
|
6760
|
+
const renamed = snapshotStore.rename(req.params.id, name);
|
|
6761
|
+
if (!renamed) {
|
|
6762
|
+
reply.code(404).send({ error: "Snapshot not found." });
|
|
6763
|
+
return;
|
|
6764
|
+
}
|
|
6765
|
+
return {
|
|
6766
|
+
ok: true,
|
|
6767
|
+
snapshots: snapshotStore.list()
|
|
6768
|
+
};
|
|
6769
|
+
});
|
|
6770
|
+
app.post("/api/studio/snapshots/:id/pin", async (req, reply) => {
|
|
6771
|
+
if (!snapshotStore) {
|
|
6772
|
+
reply.code(501).send({ error: "Snapshot persistence is not configured." });
|
|
6773
|
+
return;
|
|
6774
|
+
}
|
|
6775
|
+
const pinned = Boolean(req.body?.pinned);
|
|
6776
|
+
const updated = snapshotStore.pin(req.params.id, pinned);
|
|
6777
|
+
if (!updated) {
|
|
6778
|
+
reply.code(404).send({ error: "Snapshot not found." });
|
|
6779
|
+
return;
|
|
6780
|
+
}
|
|
6781
|
+
return {
|
|
6782
|
+
ok: true,
|
|
6783
|
+
snapshots: snapshotStore.list()
|
|
6784
|
+
};
|
|
6785
|
+
});
|
|
6786
|
+
app.post("/api/studio/snapshots/:id/tags", async (req, reply) => {
|
|
6787
|
+
if (!snapshotStore) {
|
|
6788
|
+
reply.code(501).send({ error: "Snapshot persistence is not configured." });
|
|
6789
|
+
return;
|
|
6790
|
+
}
|
|
6791
|
+
const rawTags = Array.isArray(req.body?.tags) ? req.body.tags : [];
|
|
6792
|
+
const tags = [...new Set(
|
|
6793
|
+
rawTags.map((tag) => typeof tag === "string" ? tag.trim() : "").filter(Boolean)
|
|
6794
|
+
)];
|
|
6795
|
+
const updated = snapshotStore.updateTags(req.params.id, tags);
|
|
6796
|
+
if (!updated) {
|
|
6797
|
+
reply.code(404).send({ error: "Snapshot not found." });
|
|
6798
|
+
return;
|
|
6799
|
+
}
|
|
6800
|
+
return {
|
|
6801
|
+
ok: true,
|
|
6802
|
+
snapshots: snapshotStore.list()
|
|
6803
|
+
};
|
|
6804
|
+
});
|
|
6805
|
+
app.post("/api/studio/snapshots/:id/delete", async (req, reply) => {
|
|
6806
|
+
if (!snapshotStore) {
|
|
6807
|
+
reply.code(501).send({ error: "Snapshot persistence is not configured." });
|
|
6808
|
+
return;
|
|
6809
|
+
}
|
|
6810
|
+
const deleted = snapshotStore.delete(req.params.id);
|
|
6811
|
+
if (!deleted) {
|
|
6812
|
+
reply.code(404).send({ error: "Snapshot not found." });
|
|
6813
|
+
return;
|
|
6814
|
+
}
|
|
6815
|
+
const current = snapshotStore.load();
|
|
6816
|
+
store.graph = current?.graph ?? null;
|
|
6817
|
+
store.risks = current?.risks ?? [];
|
|
6818
|
+
store.scanTime = current?.scanTime ?? 0;
|
|
6819
|
+
store.source = current?.source ?? "";
|
|
6820
|
+
if (store.graph) {
|
|
6821
|
+
broadcastGraph();
|
|
6822
|
+
}
|
|
6823
|
+
return {
|
|
6824
|
+
ok: true,
|
|
6825
|
+
hasCurrent: Boolean(current?.graph),
|
|
6826
|
+
snapshots: snapshotStore.list()
|
|
6827
|
+
};
|
|
6828
|
+
});
|
|
6514
6829
|
}
|
|
6515
|
-
var store;
|
|
6516
6830
|
var init_studio = __esm({
|
|
6517
6831
|
"src/server/routes/studio.ts"() {
|
|
6518
6832
|
"use strict";
|
|
@@ -6520,12 +6834,7 @@ var init_studio = __esm({
|
|
|
6520
6834
|
init_github_cloner();
|
|
6521
6835
|
init_graph();
|
|
6522
6836
|
init_insight();
|
|
6523
|
-
|
|
6524
|
-
graph: null,
|
|
6525
|
-
risks: [],
|
|
6526
|
-
scanTime: 0,
|
|
6527
|
-
source: ""
|
|
6528
|
-
};
|
|
6837
|
+
init_studio_store();
|
|
6529
6838
|
}
|
|
6530
6839
|
});
|
|
6531
6840
|
|
|
@@ -6728,14 +7037,14 @@ var runtime_bootstrap_exports = {};
|
|
|
6728
7037
|
__export(runtime_bootstrap_exports, {
|
|
6729
7038
|
createRuntimeBootstrap: () => createRuntimeBootstrap
|
|
6730
7039
|
});
|
|
6731
|
-
import { existsSync as
|
|
6732
|
-
import { dirname as
|
|
7040
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync12, writeFileSync as writeFileSync11 } from "fs";
|
|
7041
|
+
import { dirname as dirname7, join as join16 } from "path";
|
|
6733
7042
|
function ensureFile(filePath, content, force) {
|
|
6734
|
-
if (
|
|
7043
|
+
if (existsSync19(filePath) && !force) {
|
|
6735
7044
|
return false;
|
|
6736
7045
|
}
|
|
6737
|
-
|
|
6738
|
-
|
|
7046
|
+
mkdirSync12(dirname7(filePath), { recursive: true });
|
|
7047
|
+
writeFileSync11(filePath, content, "utf-8");
|
|
6739
7048
|
return true;
|
|
6740
7049
|
}
|
|
6741
7050
|
function createRuntimeBootstrap(config) {
|
|
@@ -7034,13 +7343,13 @@ var init_croc_office = __esm({
|
|
|
7034
7343
|
const fullResult = await pipeline.run(["scan", "er-diagram", "api-chain", "plan", "codegen"]);
|
|
7035
7344
|
this.lastPipelineResult = fullResult;
|
|
7036
7345
|
this.lastGeneratedFiles = fullResult.generatedFiles;
|
|
7037
|
-
const { writeFileSync:
|
|
7038
|
-
const { dirname:
|
|
7346
|
+
const { writeFileSync: writeFileSync14, mkdirSync: mkdirSync15 } = await import("fs");
|
|
7347
|
+
const { dirname: dirname9 } = await import("path");
|
|
7039
7348
|
let filesWritten = 0;
|
|
7040
7349
|
for (const file of fullResult.generatedFiles) {
|
|
7041
7350
|
const fullPath = resolvePath(this.cwd, file.filePath);
|
|
7042
|
-
|
|
7043
|
-
|
|
7351
|
+
mkdirSync15(dirname9(fullPath), { recursive: true });
|
|
7352
|
+
writeFileSync14(fullPath, file.content, "utf-8");
|
|
7044
7353
|
filesWritten++;
|
|
7045
7354
|
}
|
|
7046
7355
|
this.updateNodeStatus("controller", "passed");
|
|
@@ -7124,14 +7433,14 @@ var init_croc_office = __esm({
|
|
|
7124
7433
|
let backendStatus;
|
|
7125
7434
|
try {
|
|
7126
7435
|
const { resolve: resolvePath } = await import("path");
|
|
7127
|
-
const { existsSync:
|
|
7436
|
+
const { existsSync: existsSync22 } = await import("fs");
|
|
7128
7437
|
const { createExecutionCoordinator: createExecutionCoordinator2 } = await Promise.resolve().then(() => (init_coordinator(), coordinator_exports));
|
|
7129
7438
|
const { createBackendManager: createBackendManager2 } = await Promise.resolve().then(() => (init_backend_manager(), backend_manager_exports));
|
|
7130
7439
|
const { createRuntimeBootstrap: createRuntimeBootstrap2 } = await Promise.resolve().then(() => (init_runtime_bootstrap(), runtime_bootstrap_exports));
|
|
7131
7440
|
const { createAuthProvisioner: createAuthProvisioner2 } = await Promise.resolve().then(() => (init_auth_provisioner(), auth_provisioner_exports));
|
|
7132
7441
|
const { buildExecutionQualityGate: buildExecutionQualityGate2 } = await Promise.resolve().then(() => (init_quality_gate(), quality_gate_exports));
|
|
7133
7442
|
const { categorizeFailure: categorizeFailure2 } = await Promise.resolve().then(() => (init_self_healing(), self_healing_exports));
|
|
7134
|
-
const testFiles = this.lastGeneratedFiles.map((f) => resolvePath(this.cwd, f.filePath)).filter((f) =>
|
|
7443
|
+
const testFiles = this.lastGeneratedFiles.map((f) => resolvePath(this.cwd, f.filePath)).filter((f) => existsSync22(f));
|
|
7135
7444
|
if (testFiles.length === 0) {
|
|
7136
7445
|
this.log("\u26A0\uFE0F No test files found on disk", "warn");
|
|
7137
7446
|
return { ok: false, task: "execute", duration: Date.now() - start, error: "No test files found on disk" };
|
|
@@ -7258,12 +7567,12 @@ var init_croc_office = __esm({
|
|
|
7258
7567
|
});
|
|
7259
7568
|
this.lastReports = reports;
|
|
7260
7569
|
const { resolve: resolvePath } = await import("path");
|
|
7261
|
-
const { writeFileSync:
|
|
7570
|
+
const { writeFileSync: writeFileSync14, mkdirSync: mkdirSync15 } = await import("fs");
|
|
7262
7571
|
const outDir = resolvePath(this.cwd, this.config.outDir || "./opencroc-output");
|
|
7263
|
-
|
|
7572
|
+
mkdirSync15(outDir, { recursive: true });
|
|
7264
7573
|
for (const report2 of reports) {
|
|
7265
7574
|
const fullPath = resolvePath(outDir, report2.filename);
|
|
7266
|
-
|
|
7575
|
+
writeFileSync14(fullPath, report2.content, "utf-8");
|
|
7267
7576
|
this.log(`\u{1F4C4} Generated ${report2.format} report: ${report2.filename}`);
|
|
7268
7577
|
}
|
|
7269
7578
|
this.updateAgent("reporter-croc", { status: "done", currentTask: `${reports.length} reports generated`, progress: 100 });
|
|
@@ -7508,13 +7817,13 @@ import Fastify from "fastify";
|
|
|
7508
7817
|
import fastifyStatic from "@fastify/static";
|
|
7509
7818
|
import fastifyWebsocket from "@fastify/websocket";
|
|
7510
7819
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7511
|
-
import { dirname as
|
|
7512
|
-
import { existsSync as
|
|
7820
|
+
import { dirname as dirname8, join as join17, resolve as resolve11 } from "path";
|
|
7821
|
+
import { existsSync as existsSync20 } from "fs";
|
|
7513
7822
|
async function startServer(opts) {
|
|
7514
7823
|
const app = Fastify({ logger: false });
|
|
7515
7824
|
await app.register(fastifyWebsocket);
|
|
7516
7825
|
const webDir = resolve11(__dirname2, "../web");
|
|
7517
|
-
if (
|
|
7826
|
+
if (existsSync20(webDir)) {
|
|
7518
7827
|
await app.register(fastifyStatic, {
|
|
7519
7828
|
root: webDir,
|
|
7520
7829
|
prefix: "/",
|
|
@@ -7522,9 +7831,10 @@ async function startServer(opts) {
|
|
|
7522
7831
|
});
|
|
7523
7832
|
}
|
|
7524
7833
|
const office = new CrocOffice(opts.config, opts.cwd);
|
|
7834
|
+
const snapshotStore = new FileStudioSnapshotStore(resolve11(opts.cwd, ".opencroc/studio-snapshot.json"));
|
|
7525
7835
|
registerProjectRoutes(app, office);
|
|
7526
7836
|
registerAgentRoutes(app, office);
|
|
7527
|
-
registerStudioRoutes(app, office);
|
|
7837
|
+
registerStudioRoutes(app, office, snapshotStore);
|
|
7528
7838
|
app.register(async (fastify) => {
|
|
7529
7839
|
fastify.get("/ws", { websocket: true }, (socket) => {
|
|
7530
7840
|
office.addClient(socket);
|
|
@@ -7538,9 +7848,9 @@ async function startServer(opts) {
|
|
|
7538
7848
|
}
|
|
7539
7849
|
const studioPath = join17(webDir, "index-studio.html");
|
|
7540
7850
|
const indexPath = join17(webDir, "index.html");
|
|
7541
|
-
if (
|
|
7851
|
+
if (existsSync20(studioPath)) {
|
|
7542
7852
|
reply.sendFile("index-studio.html");
|
|
7543
|
-
} else if (
|
|
7853
|
+
} else if (existsSync20(indexPath)) {
|
|
7544
7854
|
reply.sendFile("index.html");
|
|
7545
7855
|
} else {
|
|
7546
7856
|
reply.code(200).header("content-type", "text/html").send(getEmbeddedHtml());
|
|
@@ -7691,8 +8001,9 @@ var init_server = __esm({
|
|
|
7691
8001
|
init_agents();
|
|
7692
8002
|
init_studio();
|
|
7693
8003
|
init_croc_office();
|
|
8004
|
+
init_studio_store();
|
|
7694
8005
|
__filename2 = fileURLToPath2(import.meta.url);
|
|
7695
|
-
__dirname2 =
|
|
8006
|
+
__dirname2 = dirname8(__filename2);
|
|
7696
8007
|
}
|
|
7697
8008
|
});
|
|
7698
8009
|
|