@xerg/cli 0.5.2 → 0.5.3
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/README.md +1 -1
- package/dist/browser.js +3 -0
- package/dist/browser.js.map +1 -0
- package/dist/index.js +92 -394
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
- package/skills/xerg/SKILL.md +2 -2
package/README.md
CHANGED
|
@@ -214,7 +214,7 @@ Xerg v0 stores economic metadata and audit summaries locally. It does not store
|
|
|
214
214
|
|
|
215
215
|
## Troubleshooting
|
|
216
216
|
|
|
217
|
-
-
|
|
217
|
+
- If install fails with an unsupported engine warning, retry with Node 22 or 24.
|
|
218
218
|
- `xerg init` is interactive in v1. Use direct `doctor` / `audit` commands when you need non-interactive control.
|
|
219
219
|
- `--verbose` prints progress updates to stderr for `xerg doctor` and `xerg audit`, which helps distinguish package install time from CLI runtime.
|
|
220
220
|
- If `xerg audit --remote ...` fails before pulling files, verify that both `ssh` and `rsync` are installed and reachable on your `PATH`.
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/browser.ts"],"sourcesContent":["throw new Error('@xerg/cli is a Node.js CLI and cannot run in browser bundles.');\n"],"mappings":";AAAA,MAAM,IAAI,MAAM,+DAA+D;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -122,23 +122,6 @@ import { closeSync, openSync, readSync } from "fs";
|
|
|
122
122
|
function sha1(input) {
|
|
123
123
|
return createHash("sha1").update(input).digest("hex");
|
|
124
124
|
}
|
|
125
|
-
function sha1File(path) {
|
|
126
|
-
const hash = createHash("sha1");
|
|
127
|
-
const fd = openSync(path, "r");
|
|
128
|
-
const buffer = Buffer.allocUnsafe(64 * 1024);
|
|
129
|
-
try {
|
|
130
|
-
let bytesRead = 0;
|
|
131
|
-
do {
|
|
132
|
-
bytesRead = readSync(fd, buffer, 0, buffer.length, null);
|
|
133
|
-
if (bytesRead > 0) {
|
|
134
|
-
hash.update(buffer.subarray(0, bytesRead));
|
|
135
|
-
}
|
|
136
|
-
} while (bytesRead > 0);
|
|
137
|
-
} finally {
|
|
138
|
-
closeSync(fd);
|
|
139
|
-
}
|
|
140
|
-
return hash.digest("hex");
|
|
141
|
-
}
|
|
142
125
|
|
|
143
126
|
// ../core/src/utils/time.ts
|
|
144
127
|
function parseSince(value) {
|
|
@@ -736,354 +719,80 @@ async function inspectCursorUsageCsv(options) {
|
|
|
736
719
|
}
|
|
737
720
|
|
|
738
721
|
// ../core/src/db/client.ts
|
|
739
|
-
import { mkdirSync } from "fs";
|
|
722
|
+
import { existsSync, mkdirSync, readFileSync as readFileSync2, renameSync, writeFileSync } from "fs";
|
|
740
723
|
import { dirname } from "path";
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
kind TEXT NOT NULL,
|
|
750
|
-
file_hash TEXT NOT NULL,
|
|
751
|
-
mtime_ms INTEGER NOT NULL,
|
|
752
|
-
size_bytes INTEGER NOT NULL,
|
|
753
|
-
imported_at TEXT NOT NULL
|
|
754
|
-
);
|
|
755
|
-
|
|
756
|
-
CREATE TABLE IF NOT EXISTS runs (
|
|
757
|
-
id TEXT PRIMARY KEY,
|
|
758
|
-
source_path TEXT NOT NULL,
|
|
759
|
-
source_kind TEXT NOT NULL,
|
|
760
|
-
timestamp TEXT NOT NULL,
|
|
761
|
-
workflow TEXT NOT NULL,
|
|
762
|
-
environment TEXT NOT NULL,
|
|
763
|
-
tags_json TEXT NOT NULL,
|
|
764
|
-
total_cost_usd REAL NOT NULL,
|
|
765
|
-
total_tokens INTEGER NOT NULL,
|
|
766
|
-
observed_cost_usd REAL NOT NULL,
|
|
767
|
-
estimated_cost_usd REAL NOT NULL
|
|
768
|
-
);
|
|
769
|
-
|
|
770
|
-
CREATE TABLE IF NOT EXISTS calls (
|
|
771
|
-
id TEXT PRIMARY KEY,
|
|
772
|
-
run_id TEXT NOT NULL,
|
|
773
|
-
timestamp TEXT NOT NULL,
|
|
774
|
-
provider TEXT NOT NULL,
|
|
775
|
-
model TEXT NOT NULL,
|
|
776
|
-
input_tokens INTEGER NOT NULL,
|
|
777
|
-
output_tokens INTEGER NOT NULL,
|
|
778
|
-
cost_usd REAL NOT NULL,
|
|
779
|
-
cost_source TEXT NOT NULL,
|
|
780
|
-
latency_ms INTEGER,
|
|
781
|
-
tool_calls INTEGER NOT NULL,
|
|
782
|
-
retries INTEGER NOT NULL,
|
|
783
|
-
attempt INTEGER,
|
|
784
|
-
iteration INTEGER,
|
|
785
|
-
status TEXT,
|
|
786
|
-
task_class TEXT,
|
|
787
|
-
cache_hit INTEGER NOT NULL,
|
|
788
|
-
cache_cost_usd REAL,
|
|
789
|
-
metadata_json TEXT NOT NULL
|
|
790
|
-
);
|
|
791
|
-
|
|
792
|
-
CREATE TABLE IF NOT EXISTS findings (
|
|
793
|
-
id TEXT PRIMARY KEY,
|
|
794
|
-
audit_id TEXT NOT NULL,
|
|
795
|
-
classification TEXT NOT NULL,
|
|
796
|
-
confidence TEXT NOT NULL,
|
|
797
|
-
kind TEXT NOT NULL,
|
|
798
|
-
title TEXT NOT NULL,
|
|
799
|
-
summary TEXT NOT NULL,
|
|
800
|
-
scope TEXT NOT NULL,
|
|
801
|
-
scope_id TEXT NOT NULL,
|
|
802
|
-
cost_impact_usd REAL NOT NULL,
|
|
803
|
-
details_json TEXT NOT NULL
|
|
804
|
-
);
|
|
805
|
-
|
|
806
|
-
CREATE TABLE IF NOT EXISTS pricing_catalog (
|
|
807
|
-
id TEXT PRIMARY KEY,
|
|
808
|
-
provider TEXT NOT NULL,
|
|
809
|
-
model TEXT NOT NULL,
|
|
810
|
-
effective_date TEXT NOT NULL,
|
|
811
|
-
input_per_1m REAL NOT NULL,
|
|
812
|
-
output_per_1m REAL NOT NULL,
|
|
813
|
-
cached_input_per_1m REAL
|
|
814
|
-
);
|
|
815
|
-
|
|
816
|
-
CREATE TABLE IF NOT EXISTS audit_snapshots (
|
|
817
|
-
id TEXT PRIMARY KEY,
|
|
818
|
-
created_at TEXT NOT NULL,
|
|
819
|
-
summary_json TEXT NOT NULL
|
|
820
|
-
);
|
|
821
|
-
`;
|
|
822
|
-
|
|
823
|
-
// ../core/src/db/client.ts
|
|
824
|
-
function createDb(path) {
|
|
825
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
826
|
-
const sqlite = new Database(path);
|
|
827
|
-
const currentVersion = sqlite.pragma("user_version", { simple: true });
|
|
828
|
-
if (currentVersion > SCHEMA_VERSION) {
|
|
829
|
-
sqlite.close();
|
|
830
|
-
throw new Error(
|
|
831
|
-
`Unsupported Xerg database schema version ${currentVersion}. This build supports up to ${SCHEMA_VERSION}.`
|
|
724
|
+
var SNAPSHOT_STORE_VERSION = 1;
|
|
725
|
+
function readStoredSnapshotRows(path) {
|
|
726
|
+
if (!existsSync(path)) {
|
|
727
|
+
return [];
|
|
728
|
+
}
|
|
729
|
+
try {
|
|
730
|
+
return normalizeStore(JSON.parse(readFileSync2(path, "utf8"))).auditSnapshots.sort(
|
|
731
|
+
(left, right) => right.createdAt.localeCompare(left.createdAt)
|
|
832
732
|
);
|
|
733
|
+
} catch (error) {
|
|
734
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
735
|
+
process.stderr.write(`Warning: skipping unreadable local snapshot store ${path}: ${message}
|
|
736
|
+
`);
|
|
737
|
+
return [];
|
|
833
738
|
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
739
|
+
}
|
|
740
|
+
function writeStoredSnapshotRows(path, rows) {
|
|
741
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
742
|
+
const store = {
|
|
743
|
+
version: SNAPSHOT_STORE_VERSION,
|
|
744
|
+
auditSnapshots: rows.sort((left, right) => right.createdAt.localeCompare(left.createdAt))
|
|
745
|
+
};
|
|
746
|
+
const tempPath = `${path}.tmp-${process.pid}-${Date.now()}`;
|
|
747
|
+
writeFileSync(tempPath, `${JSON.stringify(store, null, 2)}
|
|
748
|
+
`, "utf8");
|
|
749
|
+
renameSync(tempPath, path);
|
|
750
|
+
}
|
|
751
|
+
function upsertStoredAuditSnapshot(path, row) {
|
|
752
|
+
const rows = readStoredSnapshotRows(path);
|
|
753
|
+
if (rows.some((existing) => existing.id === row.id)) {
|
|
754
|
+
return;
|
|
837
755
|
}
|
|
838
|
-
|
|
756
|
+
writeStoredSnapshotRows(path, [...rows, row]);
|
|
839
757
|
}
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
const
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
id: sha1(`${file.path}:${file.mtimeMs}:${file.sizeBytes}`),
|
|
851
|
-
path: file.path,
|
|
852
|
-
kind: file.kind,
|
|
853
|
-
fileHash: sha1File(file.path),
|
|
854
|
-
mtimeMs: Math.trunc(file.mtimeMs),
|
|
855
|
-
sizeBytes: file.sizeBytes,
|
|
856
|
-
importedAt
|
|
857
|
-
}));
|
|
858
|
-
const runRows = audit.runs.map((run2) => ({
|
|
859
|
-
id: run2.id,
|
|
860
|
-
sourcePath: run2.sourcePath,
|
|
861
|
-
sourceKind: run2.sourceKind,
|
|
862
|
-
timestamp: run2.timestamp,
|
|
863
|
-
workflow: run2.workflow,
|
|
864
|
-
environment: run2.environment,
|
|
865
|
-
tagsJson: JSON.stringify(run2.tags),
|
|
866
|
-
totalCostUsd: run2.totalCostUsd,
|
|
867
|
-
totalTokens: run2.totalTokens,
|
|
868
|
-
observedCostUsd: run2.observedCostUsd,
|
|
869
|
-
estimatedCostUsd: run2.estimatedCostUsd
|
|
870
|
-
}));
|
|
871
|
-
const callRows = audit.runs.flatMap(
|
|
872
|
-
(run2) => run2.calls.map((call) => ({
|
|
873
|
-
id: call.id,
|
|
874
|
-
runId: call.runId,
|
|
875
|
-
timestamp: call.timestamp,
|
|
876
|
-
provider: call.provider,
|
|
877
|
-
model: call.model,
|
|
878
|
-
inputTokens: call.inputTokens,
|
|
879
|
-
outputTokens: call.outputTokens,
|
|
880
|
-
costUsd: call.costUsd,
|
|
881
|
-
costSource: call.costSource,
|
|
882
|
-
latencyMs: call.latencyMs,
|
|
883
|
-
toolCalls: call.toolCalls,
|
|
884
|
-
retries: call.retries,
|
|
885
|
-
attempt: call.attempt,
|
|
886
|
-
iteration: call.iteration,
|
|
887
|
-
status: call.status,
|
|
888
|
-
taskClass: call.taskClass,
|
|
889
|
-
cacheHit: call.cacheHit,
|
|
890
|
-
cacheCostUsd: call.cacheCostUsd,
|
|
891
|
-
metadataJson: JSON.stringify(call.metadata)
|
|
892
|
-
}))
|
|
893
|
-
);
|
|
894
|
-
const findingRows = audit.summary.findings.map((finding) => ({
|
|
895
|
-
id: finding.id,
|
|
896
|
-
auditId: audit.summary.auditId,
|
|
897
|
-
classification: finding.classification,
|
|
898
|
-
confidence: finding.confidence,
|
|
899
|
-
kind: finding.kind,
|
|
900
|
-
title: finding.title,
|
|
901
|
-
summary: finding.summary,
|
|
902
|
-
scope: finding.scope,
|
|
903
|
-
scopeId: finding.scopeId,
|
|
904
|
-
costImpactUsd: finding.costImpactUsd,
|
|
905
|
-
detailsJson: JSON.stringify(finding.details)
|
|
906
|
-
}));
|
|
907
|
-
const persistTransaction = sqlite.transaction(() => {
|
|
908
|
-
insertMany(
|
|
909
|
-
sqlite,
|
|
910
|
-
`
|
|
911
|
-
INSERT OR IGNORE INTO pricing_catalog (
|
|
912
|
-
id,
|
|
913
|
-
provider,
|
|
914
|
-
model,
|
|
915
|
-
effective_date,
|
|
916
|
-
input_per_1m,
|
|
917
|
-
output_per_1m,
|
|
918
|
-
cached_input_per_1m
|
|
919
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
920
|
-
`,
|
|
921
|
-
pricingRows.map((row) => [
|
|
922
|
-
row.id,
|
|
923
|
-
row.provider,
|
|
924
|
-
row.model,
|
|
925
|
-
row.effectiveDate,
|
|
926
|
-
row.inputPer1m,
|
|
927
|
-
row.outputPer1m,
|
|
928
|
-
row.cachedInputPer1m
|
|
929
|
-
])
|
|
930
|
-
);
|
|
931
|
-
insertMany(
|
|
932
|
-
sqlite,
|
|
933
|
-
`
|
|
934
|
-
INSERT OR IGNORE INTO source_files (
|
|
935
|
-
id,
|
|
936
|
-
path,
|
|
937
|
-
kind,
|
|
938
|
-
file_hash,
|
|
939
|
-
mtime_ms,
|
|
940
|
-
size_bytes,
|
|
941
|
-
imported_at
|
|
942
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
943
|
-
`,
|
|
944
|
-
sourceFileRows.map((row) => [
|
|
945
|
-
row.id,
|
|
946
|
-
row.path,
|
|
947
|
-
row.kind,
|
|
948
|
-
row.fileHash,
|
|
949
|
-
row.mtimeMs,
|
|
950
|
-
row.sizeBytes,
|
|
951
|
-
row.importedAt
|
|
952
|
-
])
|
|
953
|
-
);
|
|
954
|
-
insertMany(
|
|
955
|
-
sqlite,
|
|
956
|
-
`
|
|
957
|
-
INSERT OR IGNORE INTO runs (
|
|
958
|
-
id,
|
|
959
|
-
source_path,
|
|
960
|
-
source_kind,
|
|
961
|
-
timestamp,
|
|
962
|
-
workflow,
|
|
963
|
-
environment,
|
|
964
|
-
tags_json,
|
|
965
|
-
total_cost_usd,
|
|
966
|
-
total_tokens,
|
|
967
|
-
observed_cost_usd,
|
|
968
|
-
estimated_cost_usd
|
|
969
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
970
|
-
`,
|
|
971
|
-
runRows.map((row) => [
|
|
972
|
-
row.id,
|
|
973
|
-
row.sourcePath,
|
|
974
|
-
row.sourceKind,
|
|
975
|
-
row.timestamp,
|
|
976
|
-
row.workflow,
|
|
977
|
-
row.environment,
|
|
978
|
-
row.tagsJson,
|
|
979
|
-
row.totalCostUsd,
|
|
980
|
-
row.totalTokens,
|
|
981
|
-
row.observedCostUsd,
|
|
982
|
-
row.estimatedCostUsd
|
|
983
|
-
])
|
|
984
|
-
);
|
|
985
|
-
insertMany(
|
|
986
|
-
sqlite,
|
|
987
|
-
`
|
|
988
|
-
INSERT OR IGNORE INTO calls (
|
|
989
|
-
id,
|
|
990
|
-
run_id,
|
|
991
|
-
timestamp,
|
|
992
|
-
provider,
|
|
993
|
-
model,
|
|
994
|
-
input_tokens,
|
|
995
|
-
output_tokens,
|
|
996
|
-
cost_usd,
|
|
997
|
-
cost_source,
|
|
998
|
-
latency_ms,
|
|
999
|
-
tool_calls,
|
|
1000
|
-
retries,
|
|
1001
|
-
attempt,
|
|
1002
|
-
iteration,
|
|
1003
|
-
status,
|
|
1004
|
-
task_class,
|
|
1005
|
-
cache_hit,
|
|
1006
|
-
cache_cost_usd,
|
|
1007
|
-
metadata_json
|
|
1008
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1009
|
-
`,
|
|
1010
|
-
callRows.map((row) => [
|
|
1011
|
-
row.id,
|
|
1012
|
-
row.runId,
|
|
1013
|
-
row.timestamp,
|
|
1014
|
-
row.provider,
|
|
1015
|
-
row.model,
|
|
1016
|
-
row.inputTokens,
|
|
1017
|
-
row.outputTokens,
|
|
1018
|
-
row.costUsd,
|
|
1019
|
-
row.costSource,
|
|
1020
|
-
row.latencyMs ?? null,
|
|
1021
|
-
row.toolCalls,
|
|
1022
|
-
row.retries,
|
|
1023
|
-
row.attempt ?? null,
|
|
1024
|
-
row.iteration ?? null,
|
|
1025
|
-
row.status ?? null,
|
|
1026
|
-
row.taskClass ?? null,
|
|
1027
|
-
row.cacheHit ? 1 : 0,
|
|
1028
|
-
row.cacheCostUsd ?? null,
|
|
1029
|
-
row.metadataJson
|
|
1030
|
-
])
|
|
1031
|
-
);
|
|
1032
|
-
insertMany(
|
|
1033
|
-
sqlite,
|
|
1034
|
-
`
|
|
1035
|
-
INSERT OR IGNORE INTO findings (
|
|
1036
|
-
id,
|
|
1037
|
-
audit_id,
|
|
1038
|
-
classification,
|
|
1039
|
-
confidence,
|
|
1040
|
-
kind,
|
|
1041
|
-
title,
|
|
1042
|
-
summary,
|
|
1043
|
-
scope,
|
|
1044
|
-
scope_id,
|
|
1045
|
-
cost_impact_usd,
|
|
1046
|
-
details_json
|
|
1047
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1048
|
-
`,
|
|
1049
|
-
findingRows.map((row) => [
|
|
1050
|
-
row.id,
|
|
1051
|
-
row.auditId,
|
|
1052
|
-
row.classification,
|
|
1053
|
-
row.confidence,
|
|
1054
|
-
row.kind,
|
|
1055
|
-
row.title,
|
|
1056
|
-
row.summary,
|
|
1057
|
-
row.scope,
|
|
1058
|
-
row.scopeId,
|
|
1059
|
-
row.costImpactUsd,
|
|
1060
|
-
row.detailsJson
|
|
1061
|
-
])
|
|
1062
|
-
);
|
|
1063
|
-
sqlite.prepare(
|
|
1064
|
-
`
|
|
1065
|
-
INSERT OR IGNORE INTO audit_snapshots (
|
|
1066
|
-
id,
|
|
1067
|
-
created_at,
|
|
1068
|
-
summary_json
|
|
1069
|
-
) VALUES (?, ?, ?)
|
|
1070
|
-
`
|
|
1071
|
-
).run(audit.summary.auditId, audit.summary.generatedAt, JSON.stringify(audit.summary));
|
|
1072
|
-
});
|
|
1073
|
-
try {
|
|
1074
|
-
persistTransaction();
|
|
1075
|
-
} finally {
|
|
1076
|
-
sqlite.close();
|
|
758
|
+
function normalizeStore(input) {
|
|
759
|
+
if (!input || typeof input !== "object") {
|
|
760
|
+
throw new Error("Snapshot store is not an object.");
|
|
761
|
+
}
|
|
762
|
+
const store = input;
|
|
763
|
+
if (store.version !== SNAPSHOT_STORE_VERSION) {
|
|
764
|
+
throw new Error(`Unsupported snapshot store version ${String(store.version)}.`);
|
|
765
|
+
}
|
|
766
|
+
if (!Array.isArray(store.auditSnapshots)) {
|
|
767
|
+
throw new Error("Snapshot store auditSnapshots field is missing or invalid.");
|
|
1077
768
|
}
|
|
769
|
+
return {
|
|
770
|
+
version: SNAPSHOT_STORE_VERSION,
|
|
771
|
+
auditSnapshots: store.auditSnapshots.map(normalizeSnapshotRow)
|
|
772
|
+
};
|
|
1078
773
|
}
|
|
1079
|
-
function
|
|
1080
|
-
if (
|
|
1081
|
-
|
|
774
|
+
function normalizeSnapshotRow(input) {
|
|
775
|
+
if (!input || typeof input !== "object") {
|
|
776
|
+
throw new Error("Snapshot row is not an object.");
|
|
1082
777
|
}
|
|
1083
|
-
const
|
|
1084
|
-
|
|
1085
|
-
|
|
778
|
+
const row = input;
|
|
779
|
+
if (typeof row.id !== "string" || typeof row.createdAt !== "string" || typeof row.summaryJson !== "string") {
|
|
780
|
+
throw new Error("Snapshot row is missing id, createdAt, or summaryJson.");
|
|
1086
781
|
}
|
|
782
|
+
return {
|
|
783
|
+
id: row.id,
|
|
784
|
+
createdAt: row.createdAt,
|
|
785
|
+
summaryJson: row.summaryJson
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// ../core/src/db/persist.ts
|
|
790
|
+
function persistAudit(audit, dbPath) {
|
|
791
|
+
upsertStoredAuditSnapshot(dbPath, {
|
|
792
|
+
id: audit.summary.auditId,
|
|
793
|
+
createdAt: audit.summary.generatedAt,
|
|
794
|
+
summaryJson: JSON.stringify(audit.summary)
|
|
795
|
+
});
|
|
1087
796
|
}
|
|
1088
797
|
|
|
1089
798
|
// ../core/src/report/comparison.ts
|
|
@@ -1358,19 +1067,7 @@ function parseAuditSummary(row) {
|
|
|
1358
1067
|
}
|
|
1359
1068
|
}
|
|
1360
1069
|
function listStoredAuditSummaries(dbPath) {
|
|
1361
|
-
|
|
1362
|
-
try {
|
|
1363
|
-
const rows = sqlite.prepare(
|
|
1364
|
-
`
|
|
1365
|
-
SELECT id, summary_json AS summaryJson
|
|
1366
|
-
FROM audit_snapshots
|
|
1367
|
-
ORDER BY created_at DESC
|
|
1368
|
-
`
|
|
1369
|
-
).all();
|
|
1370
|
-
return rows.map((row) => parseAuditSummary(row)).filter((summary) => summary !== null);
|
|
1371
|
-
} finally {
|
|
1372
|
-
sqlite.close();
|
|
1373
|
-
}
|
|
1070
|
+
return readStoredSnapshotRows(dbPath).map((row) => parseAuditSummary(row)).filter((summary) => summary !== null);
|
|
1374
1071
|
}
|
|
1375
1072
|
function readLatestComparableAuditSummary(input) {
|
|
1376
1073
|
return listStoredAuditSummaries(input.dbPath).find((summary) => {
|
|
@@ -2368,7 +2065,7 @@ import { homedir as homedir2 } from "os";
|
|
|
2368
2065
|
import { basename as basename2, join as join3 } from "path";
|
|
2369
2066
|
|
|
2370
2067
|
// ../core/src/normalize/hermes.ts
|
|
2371
|
-
import { readFileSync as
|
|
2068
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
2372
2069
|
import { basename } from "path";
|
|
2373
2070
|
|
|
2374
2071
|
// ../core/src/utils/records.ts
|
|
@@ -2454,7 +2151,7 @@ function parseJsonLine(line) {
|
|
|
2454
2151
|
}
|
|
2455
2152
|
}
|
|
2456
2153
|
function parseJsonLines(path) {
|
|
2457
|
-
const content =
|
|
2154
|
+
const content = readFileSync3(path, "utf8");
|
|
2458
2155
|
const lines = content.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
2459
2156
|
const records = [];
|
|
2460
2157
|
for (const line of lines) {
|
|
@@ -2807,7 +2504,7 @@ function getAppPaths() {
|
|
|
2807
2504
|
};
|
|
2808
2505
|
}
|
|
2809
2506
|
function getDefaultDbPath() {
|
|
2810
|
-
return join(getAppPaths().data, "xerg.
|
|
2507
|
+
return join(getAppPaths().data, "xerg-snapshots.json");
|
|
2811
2508
|
}
|
|
2812
2509
|
function getDefaultOpenClawSessionsPattern() {
|
|
2813
2510
|
return join(getUserHome(), ".openclaw", "agents", "*", "sessions", "*.jsonl");
|
|
@@ -2998,10 +2695,10 @@ async function detectOpenClawSources(options) {
|
|
|
2998
2695
|
}
|
|
2999
2696
|
|
|
3000
2697
|
// ../core/src/normalize/openclaw.ts
|
|
3001
|
-
import { readFileSync as
|
|
2698
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
3002
2699
|
import { basename as basename3 } from "path";
|
|
3003
2700
|
function parseJsonLines2(path) {
|
|
3004
|
-
const content =
|
|
2701
|
+
const content = readFileSync4(path, "utf8");
|
|
3005
2702
|
const lines = content.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
3006
2703
|
const records = [];
|
|
3007
2704
|
for (const line of lines) {
|
|
@@ -4226,12 +3923,12 @@ async function pushAudit(payload, config) {
|
|
|
4226
3923
|
}
|
|
4227
3924
|
|
|
4228
3925
|
// src/push/config.ts
|
|
4229
|
-
import { readFileSync as
|
|
3926
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
4230
3927
|
import { homedir as homedir4 } from "os";
|
|
4231
3928
|
import { join as join5 } from "path";
|
|
4232
3929
|
|
|
4233
3930
|
// src/auth/credentials.ts
|
|
4234
|
-
import { existsSync, mkdirSync as mkdirSync3, readFileSync as
|
|
3931
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync5, rmSync, writeFileSync as writeFileSync2 } from "fs";
|
|
4235
3932
|
import { homedir as homedir3 } from "os";
|
|
4236
3933
|
import { dirname as dirname2, join as join4 } from "path";
|
|
4237
3934
|
function getCredentialsPath() {
|
|
@@ -4243,13 +3940,13 @@ function storeCredentials(token) {
|
|
|
4243
3940
|
const dir = dirname2(credPath);
|
|
4244
3941
|
mkdirSync3(dir, { recursive: true });
|
|
4245
3942
|
const data = { token, storedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
4246
|
-
|
|
3943
|
+
writeFileSync2(credPath, JSON.stringify(data, null, 2), { mode: 384 });
|
|
4247
3944
|
}
|
|
4248
3945
|
function loadStoredCredentials() {
|
|
4249
3946
|
const credPath = getCredentialsPath();
|
|
4250
3947
|
try {
|
|
4251
|
-
if (!
|
|
4252
|
-
const raw =
|
|
3948
|
+
if (!existsSync2(credPath)) return null;
|
|
3949
|
+
const raw = readFileSync5(credPath, "utf8");
|
|
4253
3950
|
const parsed = JSON.parse(raw);
|
|
4254
3951
|
return parsed.token || null;
|
|
4255
3952
|
} catch {
|
|
@@ -4259,7 +3956,7 @@ function loadStoredCredentials() {
|
|
|
4259
3956
|
function clearCredentials() {
|
|
4260
3957
|
const credPath = getCredentialsPath();
|
|
4261
3958
|
try {
|
|
4262
|
-
if (!
|
|
3959
|
+
if (!existsSync2(credPath)) return false;
|
|
4263
3960
|
rmSync(credPath);
|
|
4264
3961
|
return true;
|
|
4265
3962
|
} catch {
|
|
@@ -4281,7 +3978,7 @@ function loadPushConfig() {
|
|
|
4281
3978
|
};
|
|
4282
3979
|
}
|
|
4283
3980
|
try {
|
|
4284
|
-
const raw =
|
|
3981
|
+
const raw = readFileSync6(CONFIG_PATH, "utf8");
|
|
4285
3982
|
const parsed = JSON.parse(raw);
|
|
4286
3983
|
if (parsed.apiKey) {
|
|
4287
3984
|
return {
|
|
@@ -5100,13 +4797,13 @@ function formatBytes2(bytes) {
|
|
|
5100
4797
|
}
|
|
5101
4798
|
|
|
5102
4799
|
// src/transport/config.ts
|
|
5103
|
-
import { readFileSync as
|
|
4800
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
5104
4801
|
import { resolve as resolve3 } from "path";
|
|
5105
4802
|
function loadRemoteConfig(configPath) {
|
|
5106
4803
|
const resolved = resolve3(configPath);
|
|
5107
4804
|
let raw;
|
|
5108
4805
|
try {
|
|
5109
|
-
raw =
|
|
4806
|
+
raw = readFileSync7(resolved, "utf8");
|
|
5110
4807
|
} catch {
|
|
5111
4808
|
throw new Error(`Cannot read remote config at ${resolved}`);
|
|
5112
4809
|
}
|
|
@@ -5253,11 +4950,11 @@ function resolveRemoteHost(target) {
|
|
|
5253
4950
|
}
|
|
5254
4951
|
|
|
5255
4952
|
// src/version.ts
|
|
5256
|
-
import { readFileSync as
|
|
4953
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
5257
4954
|
function getCliVersion() {
|
|
5258
4955
|
try {
|
|
5259
4956
|
const packageJsonPath = new URL("../package.json", import.meta.url);
|
|
5260
|
-
const packageJson = JSON.parse(
|
|
4957
|
+
const packageJson = JSON.parse(readFileSync8(packageJsonPath, "utf8"));
|
|
5261
4958
|
return packageJson.version ?? "0.0.0";
|
|
5262
4959
|
} catch {
|
|
5263
4960
|
return "0.0.0";
|
|
@@ -5793,7 +5490,8 @@ function renderMcpCredentialSourceMessage(config) {
|
|
|
5793
5490
|
}
|
|
5794
5491
|
|
|
5795
5492
|
// src/prompts.ts
|
|
5796
|
-
import
|
|
5493
|
+
import confirm from "@inquirer/confirm";
|
|
5494
|
+
import select from "@inquirer/select";
|
|
5797
5495
|
function hasPromptTty() {
|
|
5798
5496
|
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
5799
5497
|
}
|
|
@@ -5811,7 +5509,7 @@ async function promptSelect(message, choices) {
|
|
|
5811
5509
|
}
|
|
5812
5510
|
|
|
5813
5511
|
// src/commands/push.ts
|
|
5814
|
-
import { readFileSync as
|
|
5512
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
5815
5513
|
async function runPushCommand(options) {
|
|
5816
5514
|
const payload = options.file ? loadPayloadFromFile(options.file) : loadLatestCachedAuditPayload();
|
|
5817
5515
|
if (options.dryRun) {
|
|
@@ -5835,7 +5533,7 @@ async function runPushCommand(options) {
|
|
|
5835
5533
|
function loadPayloadFromFile(filePath) {
|
|
5836
5534
|
let raw;
|
|
5837
5535
|
try {
|
|
5838
|
-
raw =
|
|
5536
|
+
raw = readFileSync9(filePath, "utf8");
|
|
5839
5537
|
} catch {
|
|
5840
5538
|
throw new Error(`Cannot read file: ${filePath}`);
|
|
5841
5539
|
}
|
|
@@ -6206,7 +5904,7 @@ function renderRailwayDoctorReport(report) {
|
|
|
6206
5904
|
}
|
|
6207
5905
|
|
|
6208
5906
|
// src/commands/mcp-setup.ts
|
|
6209
|
-
import { existsSync as
|
|
5907
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync3 } from "fs";
|
|
6210
5908
|
import { dirname as dirname3, join as join8 } from "path";
|
|
6211
5909
|
var HOSTED_MCP_URL = "https://mcp.xerg.ai/mcp";
|
|
6212
5910
|
var MCP_SERVER_NAME = "xerg";
|
|
@@ -6292,7 +5990,7 @@ async function runMcpSetupFlow() {
|
|
|
6292
5990
|
async function handleCursorSetup(snippet, config) {
|
|
6293
5991
|
const cursorDir = join8(process.cwd(), ".cursor");
|
|
6294
5992
|
const cursorConfigPath = join8(cursorDir, "mcp.json");
|
|
6295
|
-
if (
|
|
5993
|
+
if (existsSync3(cursorDir)) {
|
|
6296
5994
|
const shouldWrite = await promptConfirm(
|
|
6297
5995
|
"Write a project-scoped Cursor MCP config to .cursor/mcp.json?",
|
|
6298
5996
|
true
|
|
@@ -6339,9 +6037,9 @@ function tomlString(value) {
|
|
|
6339
6037
|
function writeCursorConfig(filePath, config) {
|
|
6340
6038
|
mkdirSync6(dirname3(filePath), { recursive: true });
|
|
6341
6039
|
let parsed = {};
|
|
6342
|
-
if (
|
|
6040
|
+
if (existsSync3(filePath)) {
|
|
6343
6041
|
try {
|
|
6344
|
-
parsed = JSON.parse(
|
|
6042
|
+
parsed = JSON.parse(readFileSync10(filePath, "utf8"));
|
|
6345
6043
|
} catch {
|
|
6346
6044
|
throw new Error(`Cursor config is not valid JSON: ${filePath}`);
|
|
6347
6045
|
}
|
|
@@ -6354,7 +6052,7 @@ function writeCursorConfig(filePath, config) {
|
|
|
6354
6052
|
...existingServers ?? {},
|
|
6355
6053
|
xerg: buildHostedMcpConfig(config).mcpServers.xerg
|
|
6356
6054
|
};
|
|
6357
|
-
|
|
6055
|
+
writeFileSync3(filePath, `${JSON.stringify(parsed, null, 2)}
|
|
6358
6056
|
`);
|
|
6359
6057
|
}
|
|
6360
6058
|
|
|
@@ -6566,7 +6264,7 @@ Options:
|
|
|
6566
6264
|
--compare Compare this audit to the newest compatible prior local snapshot
|
|
6567
6265
|
--json Render the report as JSON
|
|
6568
6266
|
--markdown Render the report as Markdown
|
|
6569
|
-
--db <path> Custom
|
|
6267
|
+
--db <path> Custom JSON snapshot path
|
|
6570
6268
|
--no-db Skip local persistence
|
|
6571
6269
|
|
|
6572
6270
|
Remote options (SSH, OpenClaw only):
|