@rashidee/co2 1.3.8 → 1.3.10
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/.co2-dat/app.db-shm +0 -0
- package/dist/.co2-dat/app.db-wal +0 -0
- package/dist/index.js +150 -81
- package/package.json +1 -1
- package/static/assets/{abnfDiagram-VRR7QNED-DP7zbvBZ.js → abnfDiagram-VRR7QNED-ChoWkBm-.js} +1 -1
- package/static/assets/{arc-Ckh0cqx_.js → arc-BOiutWhq.js} +1 -1
- package/static/assets/{architectureDiagram-ZJ3FMSHR-EpVuCwzS.js → architectureDiagram-ZJ3FMSHR-Dn4YKYfM.js} +1 -1
- package/static/assets/{blockDiagram-677ZJIJ3-DsgBkX_g.js → blockDiagram-677ZJIJ3-BrXEfs29.js} +1 -1
- package/static/assets/{c4Diagram-LMCZKHZV-CR04rrP-.js → c4Diagram-LMCZKHZV-ChaIzrlx.js} +1 -1
- package/static/assets/channel-CKovdojM.js +1 -0
- package/static/assets/{chunk-2Q5K7J3B-DeQC-sio.js → chunk-2Q5K7J3B-BOlnmyI2.js} +1 -1
- package/static/assets/{chunk-32BRIVSS-Qbam-XOV.js → chunk-32BRIVSS-BYtO1gsq.js} +1 -1
- package/static/assets/{chunk-5VM5RSS4-CH-IX0uh.js → chunk-5VM5RSS4-Cmx4Morj.js} +1 -1
- package/static/assets/{chunk-EX3LRPZG-6gUCPZ6x.js → chunk-EX3LRPZG-BcgUofmA.js} +1 -1
- package/static/assets/{chunk-JWPE2WC7-DSNEXnbo.js → chunk-JWPE2WC7-CnNRXdvN.js} +1 -1
- package/static/assets/{chunk-MOJQB5TN-BVmlLOXk.js → chunk-MOJQB5TN-DGG6Q3Wn.js} +1 -1
- package/static/assets/{chunk-RYQCIY6F-2pIZN6PI.js → chunk-RYQCIY6F-C8erKHls.js} +1 -1
- package/static/assets/{chunk-V7JOEXUC-Dj8a39S7.js → chunk-V7JOEXUC-BNkIJqzu.js} +1 -1
- package/static/assets/{chunk-VR4S4FIN-D2kLoVlo.js → chunk-VR4S4FIN-CGq-RseS.js} +1 -1
- package/static/assets/{chunk-XXDRQBXY-x3SQWIAg.js → chunk-XXDRQBXY-DOVfEC7j.js} +1 -1
- package/static/assets/classDiagram-OUVF2IWQ-BRxqfb0_.js +1 -0
- package/static/assets/classDiagram-v2-EOCWNBFH-BRxqfb0_.js +1 -0
- package/static/assets/{cose-bilkent-JH36ORCC-ltgQwU4R.js → cose-bilkent-JH36ORCC-BrK3gCzK.js} +1 -1
- package/static/assets/{cynefin-VYW2F7L2-BwJnOy5O.js → cynefin-VYW2F7L2-BTMYzKLg.js} +1 -1
- package/static/assets/{cynefinDiagram-TSTJHNR4-Bi47Fvnv.js → cynefinDiagram-TSTJHNR4-Df4k0_Hb.js} +1 -1
- package/static/assets/{dagre-VKFMJZFB-5_l7QdUh.js → dagre-VKFMJZFB-0LnYnEqq.js} +1 -1
- package/static/assets/{diagram-FQU43EPY-HKDyXOzo.js → diagram-FQU43EPY-B5nIVD5g.js} +1 -1
- package/static/assets/{diagram-G47NLZAW-xHHInyx1.js → diagram-G47NLZAW-B2YLBzdb.js} +1 -1
- package/static/assets/{diagram-NH7WQ7WH-nftmRdjw.js → diagram-NH7WQ7WH-DPVumXIF.js} +1 -1
- package/static/assets/{diagram-OA4YK3LP-CX8gIXu7.js → diagram-OA4YK3LP-Da20vcLJ.js} +1 -1
- package/static/assets/{diagram-WEI45ONY-BaT3ur6a.js → diagram-WEI45ONY-DQbTpuRZ.js} +1 -1
- package/static/assets/{ebnfDiagram-CCIWWBDH-CM9hwJSh.js → ebnfDiagram-CCIWWBDH-BEn1vEyb.js} +1 -1
- package/static/assets/{erDiagram-Q63AITRT-C9cK36a5.js → erDiagram-Q63AITRT-Ccg0DVBG.js} +1 -1
- package/static/assets/{flowDiagram-23GEKE2U-BQw_JFaW.js → flowDiagram-23GEKE2U-B2dMjEpa.js} +1 -1
- package/static/assets/{ganttDiagram-NO4QXBWP-Cgg9ZbM9.js → ganttDiagram-NO4QXBWP-Kp1UsG59.js} +1 -1
- package/static/assets/{gitGraphDiagram-IHSO6WYX-SciNAnN3.js → gitGraphDiagram-IHSO6WYX-D6RB8sPf.js} +1 -1
- package/static/assets/{index-HUEMwsDE.js → index-GEUFVo96.js} +58 -58
- package/static/assets/{infoDiagram-FWYZ7A6U-BPCKxKmJ.js → infoDiagram-FWYZ7A6U-C4ILACOF.js} +1 -1
- package/static/assets/{ishikawaDiagram-FXEZZL3T-C0eQKvpo.js → ishikawaDiagram-FXEZZL3T-Q2Ef9fW7.js} +1 -1
- package/static/assets/{journeyDiagram-5HDEW3XC-DgrJ90BU.js → journeyDiagram-5HDEW3XC-B7ZV1i0L.js} +1 -1
- package/static/assets/{kanban-definition-HUTT4EX6-ISgFrxBl.js → kanban-definition-HUTT4EX6-CjaPV_vw.js} +1 -1
- package/static/assets/{linear-CaPqviiq.js → linear-BELpVz92.js} +1 -1
- package/static/assets/{mindmap-definition-LN4V7U3C-DTpJ3Okf.js → mindmap-definition-LN4V7U3C-COhl-GrE.js} +1 -1
- package/static/assets/{pegDiagram-2B236MQR-D0EbYB8X.js → pegDiagram-2B236MQR-3FlTtWva.js} +1 -1
- package/static/assets/{pieDiagram-ENE6RG2P-lAwviOjS.js → pieDiagram-ENE6RG2P-CLeOh_sh.js} +1 -1
- package/static/assets/{quadrantDiagram-ABIIQ3AL-Dn8yVCWJ.js → quadrantDiagram-ABIIQ3AL-D2MnobFS.js} +1 -1
- package/static/assets/{railroadDiagram-RFXS5EU6-BVLcNBsS.js → railroadDiagram-RFXS5EU6-FjtL4fEj.js} +1 -1
- package/static/assets/{requirementDiagram-TGXJPOKE-Bmjsh1uy.js → requirementDiagram-TGXJPOKE-C5Y2uWRV.js} +1 -1
- package/static/assets/{sankeyDiagram-HTMAVEWB-tdNqcgyd.js → sankeyDiagram-HTMAVEWB-ITj9bISn.js} +1 -1
- package/static/assets/{sequenceDiagram-DBY2YBRQ-ChtQkNW9.js → sequenceDiagram-DBY2YBRQ-Ct2xTSbI.js} +1 -1
- package/static/assets/{sizeCapture-X5ZJPWSS-BAnRJGV8.js → sizeCapture-X5ZJPWSS-w9hGRpov.js} +1 -1
- package/static/assets/{stateDiagram-2N3HPSRC-CI7wmYAe.js → stateDiagram-2N3HPSRC-BlxDF1qr.js} +1 -1
- package/static/assets/stateDiagram-v2-6OUMAXLB-CQVgnOlz.js +1 -0
- package/static/assets/{swimlanes-5IMT3BWC-k6NGsb3p.js → swimlanes-5IMT3BWC-DFYm_SCW.js} +2 -2
- package/static/assets/swimlanesDiagram-G3AALYLV-DubMPSZe.js +8 -0
- package/static/assets/{timeline-definition-FHXFAJF6-CweEa8iU.js → timeline-definition-FHXFAJF6-johIMUxt.js} +1 -1
- package/static/assets/{vennDiagram-L72KCM5P-DDPbV_sp.js → vennDiagram-L72KCM5P-BFk2-H5y.js} +1 -1
- package/static/assets/{wardleyDiagram-EHGQE667-IP4J8kqe.js → wardleyDiagram-EHGQE667-T7509MWq.js} +1 -1
- package/static/assets/{xychartDiagram-FW5EYKEG-CMfWLoM8.js → xychartDiagram-FW5EYKEG-DskgQ7uq.js} +1 -1
- package/static/index.html +1 -1
- package/static/assets/channel-DfxyTZ0M.js +0 -1
- package/static/assets/classDiagram-OUVF2IWQ-DPLLyb_P.js +0 -1
- package/static/assets/classDiagram-v2-EOCWNBFH-DPLLyb_P.js +0 -1
- package/static/assets/stateDiagram-v2-6OUMAXLB-BJrR07NX.js +0 -1
- package/static/assets/swimlanesDiagram-G3AALYLV-B0-5v6_-.js +0 -8
package/dist/index.js
CHANGED
|
@@ -6809,7 +6809,7 @@ var {
|
|
|
6809
6809
|
// package.json
|
|
6810
6810
|
var package_default = {
|
|
6811
6811
|
name: "@rashidee/co2",
|
|
6812
|
-
version: "1.3.
|
|
6812
|
+
version: "1.3.10",
|
|
6813
6813
|
description: "Compound Context Studio \u2014 self-hosted team context authoring for CO2 projects",
|
|
6814
6814
|
type: "module",
|
|
6815
6815
|
license: "MIT",
|
|
@@ -6937,7 +6937,7 @@ ${install.output}`));
|
|
|
6937
6937
|
}
|
|
6938
6938
|
|
|
6939
6939
|
// src/commands/start.ts
|
|
6940
|
-
import { existsSync as
|
|
6940
|
+
import { existsSync as existsSync26 } from "fs";
|
|
6941
6941
|
import { networkInterfaces } from "os";
|
|
6942
6942
|
import { dirname as dirname3, join as join29 } from "path";
|
|
6943
6943
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -22666,11 +22666,11 @@ function cicdGuardRoutes(db, workspacePath) {
|
|
|
22666
22666
|
}
|
|
22667
22667
|
|
|
22668
22668
|
// ../server/src/features/project/service.ts
|
|
22669
|
-
import { existsSync as
|
|
22669
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
|
|
22670
22670
|
import { join as join16 } from "path";
|
|
22671
22671
|
|
|
22672
22672
|
// ../server/src/features/project-config/service.ts
|
|
22673
|
-
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync7 } from "fs";
|
|
22673
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
22674
22674
|
import { join as join15 } from "path";
|
|
22675
22675
|
function svcError9(code, status) {
|
|
22676
22676
|
return Object.assign(new Error(code), { code, status });
|
|
@@ -22742,6 +22742,27 @@ function importProjectDevtool(db, workspacePath, projectId, content, importedBy)
|
|
|
22742
22742
|
writeProjectFile(workspacePath, folder, "DEVTOOL.md", content);
|
|
22743
22743
|
return toDto5(db, updated, "devtoolMd");
|
|
22744
22744
|
}
|
|
22745
|
+
function reloadProjectConfigFromFile(db, workspacePath, projectId, fileName, field) {
|
|
22746
|
+
const { folder } = requireProject2(db, projectId);
|
|
22747
|
+
const filePath = join15(workspacePath, folder, fileName);
|
|
22748
|
+
if (!existsSync14(filePath)) throw svcError9("FILE_NOT_FOUND", 404);
|
|
22749
|
+
const content = readFileSync9(filePath, "utf8");
|
|
22750
|
+
const row = getOrCreate(db, projectId);
|
|
22751
|
+
const updated = db.update(projectConfigs).set({ [field]: content, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq(projectConfigs.id, row.id)).returning().get();
|
|
22752
|
+
return toDto5(db, updated, field);
|
|
22753
|
+
}
|
|
22754
|
+
function reloadProjectEnvironment(db, workspacePath, projectId) {
|
|
22755
|
+
return reloadProjectConfigFromFile(
|
|
22756
|
+
db,
|
|
22757
|
+
workspacePath,
|
|
22758
|
+
projectId,
|
|
22759
|
+
"ENVIRONMENT.md",
|
|
22760
|
+
"environmentMd"
|
|
22761
|
+
);
|
|
22762
|
+
}
|
|
22763
|
+
function reloadProjectDevtool(db, workspacePath, projectId) {
|
|
22764
|
+
return reloadProjectConfigFromFile(db, workspacePath, projectId, "DEVTOOL.md", "devtoolMd");
|
|
22765
|
+
}
|
|
22745
22766
|
function adoptProjectConfig(db, projectId, content, importedBy) {
|
|
22746
22767
|
if (content.environmentMd === void 0 && content.devtoolMd === void 0) return;
|
|
22747
22768
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -22868,8 +22889,8 @@ function getBrainstormMd(db, workspacePath, projectId) {
|
|
|
22868
22889
|
project.workspaceFolderName,
|
|
22869
22890
|
`${project.workspaceFolderName}.brainstorm.md`
|
|
22870
22891
|
);
|
|
22871
|
-
if (!
|
|
22872
|
-
return { content:
|
|
22892
|
+
if (!existsSync15(filePath)) throw svcError10("BRAINSTORM_MD_MISSING", 404);
|
|
22893
|
+
return { content: readFileSync10(filePath, "utf8"), filePath };
|
|
22873
22894
|
}
|
|
22874
22895
|
function updateBrainstormMd(db, workspacePath, projectId, content) {
|
|
22875
22896
|
const project = db.select().from(projects).where(eq(projects.id, projectId)).limit(1).get();
|
|
@@ -22922,7 +22943,7 @@ function getProjectDetail(db, workspacePath, projectId) {
|
|
|
22922
22943
|
project.workspaceFolderName,
|
|
22923
22944
|
`${project.workspaceFolderName}.brainstorm.md`
|
|
22924
22945
|
);
|
|
22925
|
-
if (
|
|
22946
|
+
if (existsSync15(brainstormMdPath) && isBrainstormSessionCompleted(readFileSync10(brainstormMdPath, "utf8"))) {
|
|
22926
22947
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22927
22948
|
db.update(projects).set({ creationStatus: "fully_created", updatedAt: now }).where(eq(projects.id, projectId)).run();
|
|
22928
22949
|
creationStatus = "fully_created";
|
|
@@ -23078,9 +23099,9 @@ function rescanClaudeMd(db, workspacePath, projectId) {
|
|
|
23078
23099
|
const claudeMdPath = [
|
|
23079
23100
|
join16(projectDir2, "CLAUDE.md"),
|
|
23080
23101
|
join16(projectDir2, "source", "CLAUDE.md")
|
|
23081
|
-
].find((p) =>
|
|
23102
|
+
].find((p) => existsSync15(p));
|
|
23082
23103
|
if (!claudeMdPath) throw svcError10("CLAUDE_MD_MISSING", 404);
|
|
23083
|
-
const content =
|
|
23104
|
+
const content = readFileSync10(claudeMdPath, "utf8");
|
|
23084
23105
|
const names = parseApplicationNames(content);
|
|
23085
23106
|
const known = new Set(
|
|
23086
23107
|
db.select({ name: applications.name }).from(applications).where(eq(applications.projectId, projectId)).all().map((r) => toKebabCase(r.name))
|
|
@@ -23412,7 +23433,7 @@ function dashboardRoutes(db) {
|
|
|
23412
23433
|
}
|
|
23413
23434
|
|
|
23414
23435
|
// ../server/src/features/defect/service.ts
|
|
23415
|
-
import { existsSync as
|
|
23436
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync7, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
23416
23437
|
import { join as join17 } from "path";
|
|
23417
23438
|
|
|
23418
23439
|
// ../server/src/features/project-import/bug-md.ts
|
|
@@ -23848,10 +23869,10 @@ function writeBugMdFile(db, workspacePath, app, projectFolderName) {
|
|
|
23848
23869
|
return { content, bugCount: bugs.length };
|
|
23849
23870
|
}
|
|
23850
23871
|
function syncBugStatusesFromMaster(db, trackingFilePath, applicationId) {
|
|
23851
|
-
if (!
|
|
23872
|
+
if (!existsSync16(trackingFilePath)) return 0;
|
|
23852
23873
|
let entries;
|
|
23853
23874
|
try {
|
|
23854
|
-
entries = parseBugMaster(
|
|
23875
|
+
entries = parseBugMaster(readFileSync11(trackingFilePath, "utf8"));
|
|
23855
23876
|
} catch {
|
|
23856
23877
|
return 0;
|
|
23857
23878
|
}
|
|
@@ -23879,14 +23900,14 @@ function syncBugMdToDisk(db, workspacePath, applicationId, bugId, mode = "replac
|
|
|
23879
23900
|
if (bugId !== void 0) {
|
|
23880
23901
|
const projectDir2 = join17(workspacePath, project.workspaceFolderName);
|
|
23881
23902
|
const file = join17(projectDir2, resolveAppFolderName(projectDir2, app.name), "context", "BUG.md");
|
|
23882
|
-
if (
|
|
23903
|
+
if (existsSync16(file)) {
|
|
23883
23904
|
const bug = db.select().from(bugReports).where(and(eq(bugReports.id, bugId), eq(bugReports.isDeleted, 0))).get();
|
|
23884
23905
|
if (bug) {
|
|
23885
23906
|
const semver = (bug.prdVersionId !== null ? db.select({ semver: prdVersions.semver }).from(prdVersions).where(eq(prdVersions.id, bug.prdVersionId)).get()?.semver : void 0) ?? "v1.0.0";
|
|
23886
23907
|
const category = (bug.module ? db.select({ name: projectModules.name, category: projectModules.category }).from(projectModules).where(
|
|
23887
23908
|
and(eq(projectModules.applicationId, app.id), eq(projectModules.isDeleted, 0))
|
|
23888
23909
|
).all().find((m) => m.name.toLowerCase() === bug.module?.toLowerCase())?.category : void 0) ?? null;
|
|
23889
|
-
const merged = mergeBugIntoBugMd(
|
|
23910
|
+
const merged = mergeBugIntoBugMd(readFileSync11(file, "utf8"), bug, semver, category, mode);
|
|
23890
23911
|
if (merged !== null) {
|
|
23891
23912
|
writeFileSync9(file, merged, "utf8");
|
|
23892
23913
|
return;
|
|
@@ -24022,7 +24043,7 @@ function defectRoutes(db, workspacePath) {
|
|
|
24022
24043
|
}
|
|
24023
24044
|
|
|
24024
24045
|
// ../server/src/features/document/service.ts
|
|
24025
|
-
import { existsSync as
|
|
24046
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync8, readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
|
|
24026
24047
|
import { join as join18 } from "path";
|
|
24027
24048
|
function svcError12(code, status) {
|
|
24028
24049
|
return Object.assign(new Error(code), { code, status });
|
|
@@ -24053,8 +24074,8 @@ function getDocumentContent(db, dataDir, documentId) {
|
|
|
24053
24074
|
const doc = db.select().from(documents).where(and(eq(documents.id, documentId), eq(documents.isDeleted, 0))).limit(1).get();
|
|
24054
24075
|
if (!doc) throw svcError12("NOT_FOUND", 404);
|
|
24055
24076
|
const fullPath = join18(dataDir, "files", doc.relativePath);
|
|
24056
|
-
if (!
|
|
24057
|
-
return { mimeType: doc.mimeType, bytes:
|
|
24077
|
+
if (!existsSync17(fullPath)) throw svcError12("FILE_MISSING", 404);
|
|
24078
|
+
return { mimeType: doc.mimeType, bytes: readFileSync12(fullPath), name: doc.name };
|
|
24058
24079
|
}
|
|
24059
24080
|
function listProjectDocuments(db, projectId) {
|
|
24060
24081
|
return db.select({
|
|
@@ -24122,7 +24143,7 @@ function documentRoutes(db, dataDir) {
|
|
|
24122
24143
|
|
|
24123
24144
|
// ../server/src/features/git/service.ts
|
|
24124
24145
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
24125
|
-
import { existsSync as
|
|
24146
|
+
import { existsSync as existsSync18, readFileSync as readFileSync13, rmSync, writeFileSync as writeFileSync11 } from "fs";
|
|
24126
24147
|
import { join as join19 } from "path";
|
|
24127
24148
|
var GitServiceError = class extends Error {
|
|
24128
24149
|
code;
|
|
@@ -24161,7 +24182,7 @@ function projectDir(db, workspacePath, projectId) {
|
|
|
24161
24182
|
return join19(workspacePath, project.folder);
|
|
24162
24183
|
}
|
|
24163
24184
|
function isGitRepo(dir) {
|
|
24164
|
-
return
|
|
24185
|
+
return existsSync18(join19(dir, ".git"));
|
|
24165
24186
|
}
|
|
24166
24187
|
function classifyStatus(x, y) {
|
|
24167
24188
|
const conflictPairs = /* @__PURE__ */ new Set(["DD", "AU", "UD", "UA", "DU", "AA", "UU"]);
|
|
@@ -24225,7 +24246,7 @@ function getGitStatus(db, workspacePath, projectId) {
|
|
|
24225
24246
|
files: [],
|
|
24226
24247
|
changedCount: 0
|
|
24227
24248
|
};
|
|
24228
|
-
if (!
|
|
24249
|
+
if (!existsSync18(dir) || !isGitRepo(dir)) return empty;
|
|
24229
24250
|
let raw2;
|
|
24230
24251
|
try {
|
|
24231
24252
|
raw2 = execFileSync3("git", ["status", "--porcelain=v1", "-b", "-z"], {
|
|
@@ -24256,7 +24277,7 @@ function looksBinary(s) {
|
|
|
24256
24277
|
}
|
|
24257
24278
|
function getFileDiff(db, workspacePath, projectId, path) {
|
|
24258
24279
|
const dir = projectDir(db, workspacePath, projectId);
|
|
24259
|
-
if (!
|
|
24280
|
+
if (!existsSync18(dir) || !isGitRepo(dir)) {
|
|
24260
24281
|
throw new GitServiceError("NO_GIT_REPO", 404, "No git repository for this project");
|
|
24261
24282
|
}
|
|
24262
24283
|
const status = getGitStatus(db, workspacePath, projectId);
|
|
@@ -24299,16 +24320,27 @@ function getFileDiff(db, workspacePath, projectId, path) {
|
|
|
24299
24320
|
}
|
|
24300
24321
|
function readWorking(dir, path) {
|
|
24301
24322
|
const abs = join19(dir, path);
|
|
24302
|
-
if (!
|
|
24323
|
+
if (!existsSync18(abs)) return null;
|
|
24303
24324
|
try {
|
|
24304
|
-
return
|
|
24325
|
+
return readFileSync13(abs, "utf8");
|
|
24305
24326
|
} catch {
|
|
24306
24327
|
return null;
|
|
24307
24328
|
}
|
|
24308
24329
|
}
|
|
24309
|
-
function
|
|
24330
|
+
function identityArgs(db, userId) {
|
|
24331
|
+
if (!userId) return [];
|
|
24332
|
+
const user = db.select({ gitName: users.gitName, gitEmail: users.gitEmail }).from(users).where(eq(users.id, userId)).get();
|
|
24333
|
+
const args = [];
|
|
24334
|
+
if (user?.gitName) args.push("-c", `user.name=${user.gitName}`);
|
|
24335
|
+
if (user?.gitEmail) args.push("-c", `user.email=${user.gitEmail}`);
|
|
24336
|
+
return args;
|
|
24337
|
+
}
|
|
24338
|
+
function withIdentityHint(message) {
|
|
24339
|
+
return /Author identity unknown|Please tell me who you are|empty ident name/i.test(message) ? `${message} \u2014 set your Git name/email on your co2 Profile page, or configure git user.name/user.email for the service account on this host.` : message;
|
|
24340
|
+
}
|
|
24341
|
+
function commitChanges(db, workspacePath, projectId, input, userId) {
|
|
24310
24342
|
const dir = projectDir(db, workspacePath, projectId);
|
|
24311
|
-
if (!
|
|
24343
|
+
if (!existsSync18(dir) || !isGitRepo(dir)) {
|
|
24312
24344
|
throw new GitServiceError("NO_GIT_REPO", 404, "No git repository for this project");
|
|
24313
24345
|
}
|
|
24314
24346
|
try {
|
|
@@ -24324,9 +24356,9 @@ function commitChanges(db, workspacePath, projectId, input) {
|
|
|
24324
24356
|
if (e instanceof GitServiceError) throw e;
|
|
24325
24357
|
}
|
|
24326
24358
|
try {
|
|
24327
|
-
git3(dir, ["commit", "-m", input.message]);
|
|
24359
|
+
git3(dir, [...identityArgs(db, userId), "commit", "-m", input.message]);
|
|
24328
24360
|
} catch (e) {
|
|
24329
|
-
throw new GitServiceError("GIT_COMMIT_FAILED", 409, detail(e));
|
|
24361
|
+
throw new GitServiceError("GIT_COMMIT_FAILED", 409, withIdentityHint(detail(e)));
|
|
24330
24362
|
}
|
|
24331
24363
|
const branch = safe(() => git3(dir, ["branch", "--show-current"])) ?? "";
|
|
24332
24364
|
const commitHash = safe(() => git3(dir, ["rev-parse", "--short", "HEAD"])) ?? "";
|
|
@@ -24334,7 +24366,7 @@ function commitChanges(db, workspacePath, projectId, input) {
|
|
|
24334
24366
|
}
|
|
24335
24367
|
function discardChanges(db, workspacePath, projectId, paths) {
|
|
24336
24368
|
const dir = projectDir(db, workspacePath, projectId);
|
|
24337
|
-
if (!
|
|
24369
|
+
if (!existsSync18(dir) || !isGitRepo(dir)) {
|
|
24338
24370
|
throw new GitServiceError("NO_GIT_REPO", 404, "No git repository for this project");
|
|
24339
24371
|
}
|
|
24340
24372
|
for (const path of paths) {
|
|
@@ -24348,13 +24380,13 @@ function discardChanges(db, workspacePath, projectId, paths) {
|
|
|
24348
24380
|
}
|
|
24349
24381
|
} else {
|
|
24350
24382
|
const abs = join19(dir, path);
|
|
24351
|
-
if (
|
|
24383
|
+
if (existsSync18(abs)) rmSync(abs, { force: true });
|
|
24352
24384
|
}
|
|
24353
24385
|
}
|
|
24354
24386
|
}
|
|
24355
24387
|
function resolveConflict(db, workspacePath, projectId, input) {
|
|
24356
24388
|
const dir = projectDir(db, workspacePath, projectId);
|
|
24357
|
-
if (!
|
|
24389
|
+
if (!existsSync18(dir) || !isGitRepo(dir)) {
|
|
24358
24390
|
throw new GitServiceError("NO_GIT_REPO", 404, "No git repository for this project");
|
|
24359
24391
|
}
|
|
24360
24392
|
try {
|
|
@@ -24388,7 +24420,7 @@ function safe(fn) {
|
|
|
24388
24420
|
function errorResponse7(c, e) {
|
|
24389
24421
|
const err = e;
|
|
24390
24422
|
const status = err.status ?? 500;
|
|
24391
|
-
return c.json({ code: err.code ?? "INTERNAL_ERROR" }, status);
|
|
24423
|
+
return c.json({ code: err.code ?? "INTERNAL_ERROR", message: err.message }, status);
|
|
24392
24424
|
}
|
|
24393
24425
|
function gitRoutes(db, workspacePath) {
|
|
24394
24426
|
const app = new Hono2();
|
|
@@ -24417,7 +24449,7 @@ function gitRoutes(db, workspacePath) {
|
|
|
24417
24449
|
if (Number.isNaN(projectId)) return c.json({ code: "INVALID_ID" }, 400);
|
|
24418
24450
|
try {
|
|
24419
24451
|
const body = c.req.valid("json");
|
|
24420
|
-
return c.json(commitChanges(db, workspacePath, projectId, body));
|
|
24452
|
+
return c.json(commitChanges(db, workspacePath, projectId, body, c.get("user")?.id));
|
|
24421
24453
|
} catch (e) {
|
|
24422
24454
|
return errorResponse7(c, e);
|
|
24423
24455
|
}
|
|
@@ -24579,6 +24611,15 @@ function projectConfigRoutes(db, workspacePath) {
|
|
|
24579
24611
|
}
|
|
24580
24612
|
}
|
|
24581
24613
|
);
|
|
24614
|
+
app.post("/:projectId/environment/reload", (c) => {
|
|
24615
|
+
const projectId = parseProjectId2(c);
|
|
24616
|
+
if (projectId === null) return c.json({ code: "INVALID_ID" }, 400);
|
|
24617
|
+
try {
|
|
24618
|
+
return c.json(reloadProjectEnvironment(db, workspacePath, projectId));
|
|
24619
|
+
} catch (e) {
|
|
24620
|
+
return errorResponse9(c, e);
|
|
24621
|
+
}
|
|
24622
|
+
});
|
|
24582
24623
|
app.get("/:projectId/devtool", (c) => {
|
|
24583
24624
|
const projectId = parseProjectId2(c);
|
|
24584
24625
|
if (projectId === null) return c.json({ code: "INVALID_ID" }, 400);
|
|
@@ -24615,11 +24656,20 @@ function projectConfigRoutes(db, workspacePath) {
|
|
|
24615
24656
|
}
|
|
24616
24657
|
}
|
|
24617
24658
|
);
|
|
24659
|
+
app.post("/:projectId/devtool/reload", (c) => {
|
|
24660
|
+
const projectId = parseProjectId2(c);
|
|
24661
|
+
if (projectId === null) return c.json({ code: "INVALID_ID" }, 400);
|
|
24662
|
+
try {
|
|
24663
|
+
return c.json(reloadProjectDevtool(db, workspacePath, projectId));
|
|
24664
|
+
} catch (e) {
|
|
24665
|
+
return errorResponse9(c, e);
|
|
24666
|
+
}
|
|
24667
|
+
});
|
|
24618
24668
|
return app;
|
|
24619
24669
|
}
|
|
24620
24670
|
|
|
24621
24671
|
// ../server/src/features/project-import/scanner.ts
|
|
24622
|
-
import { existsSync as
|
|
24672
|
+
import { existsSync as existsSync19, readFileSync as readFileSync14, readdirSync as readdirSync3, statSync as statSync5 } from "fs";
|
|
24623
24673
|
import { join as join20 } from "path";
|
|
24624
24674
|
|
|
24625
24675
|
// ../server/src/features/project-import/changelog-md.ts
|
|
@@ -24768,7 +24818,7 @@ function svcError13(code, status) {
|
|
|
24768
24818
|
return Object.assign(new Error(code), { code, status });
|
|
24769
24819
|
}
|
|
24770
24820
|
function readIfExists(path) {
|
|
24771
|
-
return
|
|
24821
|
+
return existsSync19(path) ? readFileSync14(path, "utf8") : null;
|
|
24772
24822
|
}
|
|
24773
24823
|
function emptyArtifactCounts() {
|
|
24774
24824
|
return { erd: 0, data_model: 0, mockup: 0, technical_spec: 0, test_spec: 0, source_code: 0 };
|
|
@@ -24777,18 +24827,18 @@ function countArtifacts(appDir) {
|
|
|
24777
24827
|
const counts = emptyArtifactCounts();
|
|
24778
24828
|
const contextDir = join20(appDir, "context");
|
|
24779
24829
|
const modelDir = join20(contextDir, "model");
|
|
24780
|
-
if (
|
|
24830
|
+
if (existsSync19(modelDir)) {
|
|
24781
24831
|
for (const slug of readdirSync3(modelDir)) {
|
|
24782
24832
|
try {
|
|
24783
24833
|
if (!statSync5(join20(modelDir, slug)).isDirectory()) continue;
|
|
24784
24834
|
} catch {
|
|
24785
24835
|
continue;
|
|
24786
24836
|
}
|
|
24787
|
-
if (
|
|
24837
|
+
if (existsSync19(join20(modelDir, slug, "erd.mermaid")) || existsSync19(join20(modelDir, slug, "document-model.mermaid")))
|
|
24788
24838
|
counts.erd++;
|
|
24789
|
-
if (
|
|
24790
|
-
if (
|
|
24791
|
-
if (
|
|
24839
|
+
if (existsSync19(join20(modelDir, slug, "model.md"))) counts.data_model++;
|
|
24840
|
+
if (existsSync19(join20(contextDir, "specification", slug, "SPEC.md"))) counts.technical_spec++;
|
|
24841
|
+
if (existsSync19(join20(contextDir, "test", slug, "TEST_SPEC.md"))) counts.test_spec++;
|
|
24792
24842
|
}
|
|
24793
24843
|
}
|
|
24794
24844
|
for (const [sub, key, file] of [
|
|
@@ -24796,29 +24846,29 @@ function countArtifacts(appDir) {
|
|
|
24796
24846
|
["test", "test_spec", "TEST_SPEC.md"]
|
|
24797
24847
|
]) {
|
|
24798
24848
|
const dir = join20(contextDir, sub);
|
|
24799
|
-
if (!
|
|
24849
|
+
if (!existsSync19(dir)) continue;
|
|
24800
24850
|
let total = 0;
|
|
24801
24851
|
for (const slug of readdirSync3(dir)) {
|
|
24802
24852
|
try {
|
|
24803
|
-
if (statSync5(join20(dir, slug)).isDirectory() &&
|
|
24853
|
+
if (statSync5(join20(dir, slug)).isDirectory() && existsSync19(join20(dir, slug, file))) total++;
|
|
24804
24854
|
} catch {
|
|
24805
24855
|
}
|
|
24806
24856
|
}
|
|
24807
24857
|
counts[key] = Math.max(counts[key], total);
|
|
24808
24858
|
}
|
|
24809
|
-
if (
|
|
24859
|
+
if (existsSync19(join20(contextDir, "mockup", "MOCKUP.html")) || existsSync19(join20(contextDir, "mockup", "index.html")))
|
|
24810
24860
|
counts.mockup = 1;
|
|
24811
24861
|
counts.source_code = sweepSourceFiles(appDir).length;
|
|
24812
24862
|
return counts;
|
|
24813
24863
|
}
|
|
24814
24864
|
function findClaudeMd(folderDir) {
|
|
24815
|
-
if (
|
|
24816
|
-
if (
|
|
24865
|
+
if (existsSync19(join20(folderDir, "CLAUDE.md"))) return { relPath: "CLAUDE.md", prefix: "" };
|
|
24866
|
+
if (existsSync19(join20(folderDir, "source", "CLAUDE.md")))
|
|
24817
24867
|
return { relPath: "source/CLAUDE.md", prefix: "source" };
|
|
24818
24868
|
return null;
|
|
24819
24869
|
}
|
|
24820
24870
|
function listImportCandidates(db, workspacePath) {
|
|
24821
|
-
if (!
|
|
24871
|
+
if (!existsSync19(workspacePath)) return [];
|
|
24822
24872
|
const registered = new Set(
|
|
24823
24873
|
db.select({ folder: projects.workspaceFolderName }).from(projects).all().map((r) => r.folder)
|
|
24824
24874
|
);
|
|
@@ -24834,7 +24884,7 @@ function listImportCandidates(db, workspacePath) {
|
|
|
24834
24884
|
const found = findClaudeMd(dir);
|
|
24835
24885
|
if (!found) continue;
|
|
24836
24886
|
const detail2 = parseProjectDetail(
|
|
24837
|
-
|
|
24887
|
+
readFileSync14(join20(workspacePath, entry, found.relPath), "utf8")
|
|
24838
24888
|
);
|
|
24839
24889
|
candidates.push({
|
|
24840
24890
|
folderName: entry,
|
|
@@ -24849,10 +24899,10 @@ function scanRepo(db, workspacePath, folderName) {
|
|
|
24849
24899
|
const registered = db.select({ id: projects.id }).from(projects).where(eq(projects.workspaceFolderName, folderName)).limit(1).get();
|
|
24850
24900
|
if (registered) throw svcError13("FOLDER_ALREADY_IMPORTED", 409);
|
|
24851
24901
|
const folderDir = join20(workspacePath, folderName);
|
|
24852
|
-
const found =
|
|
24902
|
+
const found = existsSync19(folderDir) ? findClaudeMd(folderDir) : null;
|
|
24853
24903
|
if (!found) throw svcError13("CLAUDE_MD_MISSING", 404);
|
|
24854
24904
|
const repoRoot = found.prefix ? join20(folderDir, found.prefix) : folderDir;
|
|
24855
|
-
const claudeMdRaw =
|
|
24905
|
+
const claudeMdRaw = readFileSync14(join20(folderDir, found.relPath), "utf8");
|
|
24856
24906
|
const detail2 = parseProjectDetail(claudeMdRaw);
|
|
24857
24907
|
const claudeApps = parseClaudeMdApplications(claudeMdRaw);
|
|
24858
24908
|
const claudeModules = new Set(parseModuleNames(claudeMdRaw).map((m) => m.name));
|
|
@@ -24875,7 +24925,7 @@ function scanRepo(db, workspacePath, folderName) {
|
|
|
24875
24925
|
for (const claude of claudeApps) {
|
|
24876
24926
|
const name = toKebabCase(claude.heading);
|
|
24877
24927
|
const resolvedInRoot = resolveAppFolderName(repoRoot, name);
|
|
24878
|
-
const folderExists =
|
|
24928
|
+
const folderExists = existsSync19(join20(repoRoot, resolvedInRoot));
|
|
24879
24929
|
const folderRel = folderExists ? found.prefix ? `${found.prefix}/${resolvedInRoot}` : resolvedInRoot : null;
|
|
24880
24930
|
const appDir = folderRel ? join20(folderDir, folderRel) : null;
|
|
24881
24931
|
const prdRaw = appDir ? readIfExists(join20(appDir, "context", "PRD.md")) : null;
|
|
@@ -24897,8 +24947,8 @@ function scanRepo(db, workspacePath, folderName) {
|
|
|
24897
24947
|
for (const [, m] of bugMaster) if (m.semver) semverUnion.add(m.semver);
|
|
24898
24948
|
const preparePath = appDir ? join20(appDir, "context", "prepare", "PREPARE_MASTER.md") : "";
|
|
24899
24949
|
const developPath = appDir ? join20(appDir, "context", "develop", "IMPLEMENTATION_MASTER.md") : "";
|
|
24900
|
-
const prepareMasterExists = !!appDir &&
|
|
24901
|
-
const developMasterExists = !!appDir &&
|
|
24950
|
+
const prepareMasterExists = !!appDir && existsSync19(preparePath);
|
|
24951
|
+
const developMasterExists = !!appDir && existsSync19(developPath);
|
|
24902
24952
|
const prepareCompleted = prepareMasterExists && parseTrackingStatus(preparePath) === "COMPLETED";
|
|
24903
24953
|
const developCompleted = developMasterExists && parseTrackingStatus(developPath) === "COMPLETED";
|
|
24904
24954
|
const changelogRaw = appDir ? readIfExists(join20(appDir, "CHANGELOG.md")) : null;
|
|
@@ -24987,7 +25037,7 @@ function scanRepo(db, workspacePath, folderName) {
|
|
|
24987
25037
|
const devtoolMd = readIfExists(join20(repoRoot, "DEVTOOL.md")) ?? readIfExists(join20(folderDir, "DEVTOOL.md"));
|
|
24988
25038
|
const origin = readOriginUrl(folderDir);
|
|
24989
25039
|
const gitRemoteUrl = origin ? stripHttpsCredentials(origin) : origin;
|
|
24990
|
-
const defaultBranch =
|
|
25040
|
+
const defaultBranch = existsSync19(join20(folderDir, ".git")) ? detectTrunkBranch(folderDir, readCurrentBranch(folderDir)) : "main";
|
|
24991
25041
|
const gitProvider = /gitlab/i.test(gitRemoteUrl ?? "") ? "gitlab" : "github";
|
|
24992
25042
|
return {
|
|
24993
25043
|
folderName,
|
|
@@ -25046,7 +25096,7 @@ function scanProject(db, workspacePath, folderName) {
|
|
|
25046
25096
|
import { join as join22, relative as relative2 } from "path";
|
|
25047
25097
|
|
|
25048
25098
|
// ../server/src/features/workflow/service.ts
|
|
25049
|
-
import { existsSync as
|
|
25099
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "fs";
|
|
25050
25100
|
import { join as join21, relative, resolve as resolve2, sep } from "path";
|
|
25051
25101
|
var ACTIVE_RUN_STATUSES = ["pending", "in_progress"];
|
|
25052
25102
|
function svcError14(code, status) {
|
|
@@ -25357,8 +25407,8 @@ function backfillWorkflowHistoryFromChangelogs(db, workspacePath, projectId) {
|
|
|
25357
25407
|
for (const app of apps) {
|
|
25358
25408
|
const appRel = resolveAppFolderName(projectDir2, app.name);
|
|
25359
25409
|
const changelogPath = join21(projectDir2, appRel, "CHANGELOG.md");
|
|
25360
|
-
if (!
|
|
25361
|
-
for (const entry of parseChangelogConductorEntries(
|
|
25410
|
+
if (!existsSync20(changelogPath)) continue;
|
|
25411
|
+
for (const entry of parseChangelogConductorEntries(readFileSync15(changelogPath, "utf8"))) {
|
|
25362
25412
|
collected.push({ appName: app.name, appRel, entry });
|
|
25363
25413
|
}
|
|
25364
25414
|
}
|
|
@@ -25519,8 +25569,8 @@ function getWorkflowRunFileContent(db, workspacePath, workflowMarkdownId) {
|
|
|
25519
25569
|
const absolute = resolve2(projectDir2, wfm.filePath);
|
|
25520
25570
|
if (absolute !== projectDir2 && !absolute.startsWith(projectDir2 + sep))
|
|
25521
25571
|
throw svcError14("INVALID_PATH", 400);
|
|
25522
|
-
if (!
|
|
25523
|
-
return { filePath: wfm.filePath, content:
|
|
25572
|
+
if (!existsSync20(absolute)) throw svcError14("FILE_NOT_FOUND", 404);
|
|
25573
|
+
return { filePath: wfm.filePath, content: readFileSync15(absolute, "utf-8") };
|
|
25524
25574
|
}
|
|
25525
25575
|
function getRunApplicationChangelog(db, workspacePath, workflowMarkdownId, appName) {
|
|
25526
25576
|
const wfm = db.select().from(workflowMarkdowns).where(eq(workflowMarkdowns.id, workflowMarkdownId)).get();
|
|
@@ -25540,11 +25590,11 @@ function getRunApplicationChangelog(db, workspacePath, workflowMarkdownId, appNa
|
|
|
25540
25590
|
const absolute = resolve2(projectDir2, appFolder, "CHANGELOG.md");
|
|
25541
25591
|
if (absolute !== projectDir2 && !absolute.startsWith(projectDir2 + sep))
|
|
25542
25592
|
throw svcError14("INVALID_PATH", 400);
|
|
25543
|
-
if (!
|
|
25593
|
+
if (!existsSync20(absolute)) throw svcError14("CHANGELOG_NOT_FOUND", 404);
|
|
25544
25594
|
return {
|
|
25545
25595
|
applicationName: appName,
|
|
25546
25596
|
filePath: relative(workspacePath, absolute).replace(/\\/g, "/"),
|
|
25547
|
-
content:
|
|
25597
|
+
content: readFileSync15(absolute, "utf-8")
|
|
25548
25598
|
};
|
|
25549
25599
|
}
|
|
25550
25600
|
function toDetail(db, projectFolder, wfm, workspacePath) {
|
|
@@ -25586,7 +25636,7 @@ function toDetail(db, projectFolder, wfm, workspacePath) {
|
|
|
25586
25636
|
return {
|
|
25587
25637
|
applicationName: appName,
|
|
25588
25638
|
status: r.status,
|
|
25589
|
-
trackingFileExists:
|
|
25639
|
+
trackingFileExists: existsSync20(trackingPath),
|
|
25590
25640
|
trackingFilePath: relative(workspacePath, trackingPath).replace(/\\/g, "/")
|
|
25591
25641
|
};
|
|
25592
25642
|
});
|
|
@@ -26117,7 +26167,7 @@ function projectRoutes(db, workspacePath) {
|
|
|
26117
26167
|
}
|
|
26118
26168
|
|
|
26119
26169
|
// ../server/src/features/shared-context/service.ts
|
|
26120
|
-
import { existsSync as
|
|
26170
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync16, readdirSync as readdirSync4, statSync as statSync6, writeFileSync as writeFileSync13 } from "fs";
|
|
26121
26171
|
import { join as join23, resolve as resolve3, sep as sep2 } from "path";
|
|
26122
26172
|
function svcError16(code, status) {
|
|
26123
26173
|
return Object.assign(new Error(code), { code, status });
|
|
@@ -26206,7 +26256,7 @@ function uploadFile(db, workspacePath, projectId, folder, file) {
|
|
|
26206
26256
|
if (file.bytes.length > MAX_DOCUMENT_BYTES) throw svcError16("FILE_TOO_LARGE", 413);
|
|
26207
26257
|
const root = resolveSharedRoot(db, workspacePath, projectId);
|
|
26208
26258
|
const dir = folder ? safeResolve(root, folder) : root;
|
|
26209
|
-
if (folder && !
|
|
26259
|
+
if (folder && !existsSync21(dir)) throw svcError16("FOLDER_NOT_FOUND", 404);
|
|
26210
26260
|
const safeName = sanitizeSegment(file.name);
|
|
26211
26261
|
writeFileSync13(join23(dir, safeName), file.bytes);
|
|
26212
26262
|
return { path: folder ? `${folder}/${safeName}` : safeName };
|
|
@@ -26214,15 +26264,15 @@ function uploadFile(db, workspacePath, projectId, folder, file) {
|
|
|
26214
26264
|
function getFileContent(db, workspacePath, projectId, relPath) {
|
|
26215
26265
|
const root = resolveSharedRoot(db, workspacePath, projectId);
|
|
26216
26266
|
const full = safeResolve(root, relPath);
|
|
26217
|
-
if (!
|
|
26267
|
+
if (!existsSync21(full) || !statSync6(full).isFile()) throw svcError16("NOT_FOUND", 404);
|
|
26218
26268
|
const name = relPath.split("/").pop() ?? relPath;
|
|
26219
|
-
return { mimeType: mimeForName(name), bytes:
|
|
26269
|
+
return { mimeType: mimeForName(name), bytes: readFileSync16(full), name };
|
|
26220
26270
|
}
|
|
26221
26271
|
function saveMarkdown(db, workspacePath, projectId, relPath, content) {
|
|
26222
26272
|
if (mimeForName(relPath) !== "text/markdown") throw svcError16("NOT_MARKDOWN", 400);
|
|
26223
26273
|
const root = resolveSharedRoot(db, workspacePath, projectId);
|
|
26224
26274
|
const full = safeResolve(root, relPath);
|
|
26225
|
-
if (!
|
|
26275
|
+
if (!existsSync21(full) || !statSync6(full).isFile()) throw svcError16("NOT_FOUND", 404);
|
|
26226
26276
|
writeFileSync13(full, content, "utf8");
|
|
26227
26277
|
}
|
|
26228
26278
|
|
|
@@ -27136,7 +27186,7 @@ function terminalRoutes(db) {
|
|
|
27136
27186
|
import { execSync } from "child_process";
|
|
27137
27187
|
|
|
27138
27188
|
// ../server/src/lib/claude-plugin.ts
|
|
27139
|
-
import { existsSync as
|
|
27189
|
+
import { existsSync as existsSync22, readFileSync as readFileSync17, readdirSync as readdirSync5 } from "fs";
|
|
27140
27190
|
import { homedir } from "os";
|
|
27141
27191
|
import { join as join24 } from "path";
|
|
27142
27192
|
var PLUGIN_NAME = "co2-skills";
|
|
@@ -27145,7 +27195,7 @@ function detectCo2SkillsPlugin(claudeDir = join24(homedir(), ".claude")) {
|
|
|
27145
27195
|
}
|
|
27146
27196
|
function readRegistry(claudeDir) {
|
|
27147
27197
|
try {
|
|
27148
|
-
const raw2 =
|
|
27198
|
+
const raw2 = readFileSync17(join24(claudeDir, "plugins", "installed_plugins.json"), "utf8");
|
|
27149
27199
|
const json = JSON.parse(raw2);
|
|
27150
27200
|
for (const [key, entries] of Object.entries(json.plugins ?? {})) {
|
|
27151
27201
|
if (!key.startsWith(`${PLUGIN_NAME}@`)) continue;
|
|
@@ -27159,7 +27209,7 @@ function readRegistry(claudeDir) {
|
|
|
27159
27209
|
}
|
|
27160
27210
|
function readCacheDir(claudeDir) {
|
|
27161
27211
|
const base = join24(claudeDir, "plugins", "cache", "co2", PLUGIN_NAME);
|
|
27162
|
-
if (!
|
|
27212
|
+
if (!existsSync22(base)) return { installed: false };
|
|
27163
27213
|
try {
|
|
27164
27214
|
const versions = readdirSync5(base).filter((d) => /^\d+\.\d+/.test(d)).sort();
|
|
27165
27215
|
return { installed: true, version: versions.at(-1) };
|
|
@@ -27213,7 +27263,7 @@ function workspaceRoutes(_db, config, port, host, workspacePath) {
|
|
|
27213
27263
|
}
|
|
27214
27264
|
|
|
27215
27265
|
// ../server/src/lib/config.ts
|
|
27216
|
-
import { existsSync as
|
|
27266
|
+
import { existsSync as existsSync23, readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "fs";
|
|
27217
27267
|
import { join as join25 } from "path";
|
|
27218
27268
|
var configSchema = external_exports.object({
|
|
27219
27269
|
port: external_exports.number().int().min(1).max(65535).optional(),
|
|
@@ -27223,9 +27273,9 @@ var configSchema = external_exports.object({
|
|
|
27223
27273
|
});
|
|
27224
27274
|
function loadConfig(dataDir) {
|
|
27225
27275
|
const file = join25(dataDir, "config.json");
|
|
27226
|
-
if (!
|
|
27276
|
+
if (!existsSync23(file)) return {};
|
|
27227
27277
|
try {
|
|
27228
|
-
return configSchema.parse(JSON.parse(
|
|
27278
|
+
return configSchema.parse(JSON.parse(readFileSync18(file, "utf8")));
|
|
27229
27279
|
} catch {
|
|
27230
27280
|
return {};
|
|
27231
27281
|
}
|
|
@@ -27236,6 +27286,16 @@ function saveConfig(dataDir, config) {
|
|
|
27236
27286
|
|
|
27237
27287
|
// ../server/src/lib/logger.ts
|
|
27238
27288
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
27289
|
+
async function readErrorBody(res) {
|
|
27290
|
+
try {
|
|
27291
|
+
const body = await res.clone().json();
|
|
27292
|
+
const code = typeof body.code === "string" ? body.code : void 0;
|
|
27293
|
+
const message = typeof body.message === "string" ? body.message : void 0;
|
|
27294
|
+
return code || message ? { code, message } : void 0;
|
|
27295
|
+
} catch {
|
|
27296
|
+
return void 0;
|
|
27297
|
+
}
|
|
27298
|
+
}
|
|
27239
27299
|
function loggerMiddleware() {
|
|
27240
27300
|
return async (c, next) => {
|
|
27241
27301
|
const start = Date.now();
|
|
@@ -27244,14 +27304,23 @@ function loggerMiddleware() {
|
|
|
27244
27304
|
const { method } = c.req;
|
|
27245
27305
|
const path = c.req.path;
|
|
27246
27306
|
const status = c.res.status;
|
|
27307
|
+
const error = status >= 400 ? await readErrorBody(c.res) : void 0;
|
|
27247
27308
|
if (process.stdout.isTTY) {
|
|
27248
27309
|
const col = status >= 400 ? import_picocolors2.default.red : status >= 300 ? import_picocolors2.default.yellow : import_picocolors2.default.green;
|
|
27310
|
+
const errorSuffix = error ? ` ${import_picocolors2.default.red(error.code ?? "ERROR")}${error.message ? import_picocolors2.default.dim(` ${error.message}`) : ""}` : "";
|
|
27249
27311
|
console.log(
|
|
27250
|
-
`${import_picocolors2.default.dim((/* @__PURE__ */ new Date()).toISOString())} ${import_picocolors2.default.bold(method.padEnd(6))} ${col(String(status))} ${path} ${import_picocolors2.default.dim(`${ms}ms`)}`
|
|
27312
|
+
`${import_picocolors2.default.dim((/* @__PURE__ */ new Date()).toISOString())} ${import_picocolors2.default.bold(method.padEnd(6))} ${col(String(status))} ${path} ${import_picocolors2.default.dim(`${ms}ms`)}${errorSuffix}`
|
|
27251
27313
|
);
|
|
27252
27314
|
} else {
|
|
27253
27315
|
process.stdout.write(
|
|
27254
|
-
`${JSON.stringify({
|
|
27316
|
+
`${JSON.stringify({
|
|
27317
|
+
time: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27318
|
+
method,
|
|
27319
|
+
path,
|
|
27320
|
+
status,
|
|
27321
|
+
ms,
|
|
27322
|
+
...error ? { error: error.code, errorMessage: error.message } : {}
|
|
27323
|
+
})}
|
|
27255
27324
|
`
|
|
27256
27325
|
);
|
|
27257
27326
|
}
|
|
@@ -27259,7 +27328,7 @@ function loggerMiddleware() {
|
|
|
27259
27328
|
}
|
|
27260
27329
|
|
|
27261
27330
|
// ../server/src/lib/static.ts
|
|
27262
|
-
import { existsSync as
|
|
27331
|
+
import { existsSync as existsSync24, readFileSync as readFileSync19, statSync as statSync7 } from "fs";
|
|
27263
27332
|
import { extname, join as join26, normalize, resolve as resolve4, sep as sep3 } from "path";
|
|
27264
27333
|
var MIME = {
|
|
27265
27334
|
".html": "text/html; charset=utf-8",
|
|
@@ -27297,14 +27366,14 @@ function serveSpa(staticDir) {
|
|
|
27297
27366
|
}
|
|
27298
27367
|
const rel = path === "/" ? "/index.html" : decodeURIComponent(path);
|
|
27299
27368
|
const filePath = safeResolve2(staticDir, rel);
|
|
27300
|
-
if (filePath &&
|
|
27301
|
-
const body =
|
|
27369
|
+
if (filePath && existsSync24(filePath) && statSync7(filePath).isFile()) {
|
|
27370
|
+
const body = readFileSync19(filePath);
|
|
27302
27371
|
return c.body(body, 200, {
|
|
27303
27372
|
"Content-Type": MIME[extname(filePath)] ?? "application/octet-stream"
|
|
27304
27373
|
});
|
|
27305
27374
|
}
|
|
27306
|
-
if (
|
|
27307
|
-
return c.body(
|
|
27375
|
+
if (existsSync24(indexPath)) {
|
|
27376
|
+
return c.body(readFileSync19(indexPath), 200, { "Content-Type": "text/html; charset=utf-8" });
|
|
27308
27377
|
}
|
|
27309
27378
|
await next();
|
|
27310
27379
|
};
|
|
@@ -27357,7 +27426,7 @@ function createApp(db, opts) {
|
|
|
27357
27426
|
}
|
|
27358
27427
|
|
|
27359
27428
|
// ../server/src/db/index.ts
|
|
27360
|
-
import { existsSync as
|
|
27429
|
+
import { existsSync as existsSync25 } from "fs";
|
|
27361
27430
|
import { dirname as dirname2, join as join27 } from "path";
|
|
27362
27431
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
27363
27432
|
import Database from "better-sqlite3";
|
|
@@ -27569,7 +27638,7 @@ function resolveMigrationsFolder() {
|
|
|
27569
27638
|
join27(here, "drizzle")
|
|
27570
27639
|
].filter((c) => Boolean(c));
|
|
27571
27640
|
for (const c of candidates) {
|
|
27572
|
-
if (
|
|
27641
|
+
if (existsSync25(join27(c, "meta", "_journal.json"))) return c;
|
|
27573
27642
|
}
|
|
27574
27643
|
return join27(here, "../../drizzle");
|
|
27575
27644
|
}
|
|
@@ -28273,7 +28342,7 @@ var startOptionsSchema = external_exports.object({
|
|
|
28273
28342
|
});
|
|
28274
28343
|
function resolveStaticDir() {
|
|
28275
28344
|
const dir = join29(dirname3(fileURLToPath3(import.meta.url)), "../static");
|
|
28276
|
-
return
|
|
28345
|
+
return existsSync26(join29(dir, "index.html")) ? dir : void 0;
|
|
28277
28346
|
}
|
|
28278
28347
|
function registerStart(program3, version2) {
|
|
28279
28348
|
program3.command("start").description("Start the co2-cli web application (foreground)").option("-p, --port <n>", "Listen port (default: 3001)").option("-H, --host <addr>", "Listen host (default: 0.0.0.0 for LAN access)").option("-d, --data-dir <path>", "Override the data directory").option("-w, --workspace-path <path>", "Override the Workspace root folder").action(async (rawOpts) => {
|