caveat-cli 0.16.1 → 0.16.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/dist/{chunk-HCLEIAGO.js → chunk-PD5E6TFL.js} +686 -148
- package/dist/chunk-PD5E6TFL.js.map +1 -0
- package/dist/index.js +622 -218
- package/dist/index.js.map +1 -1
- package/dist/{server-EASKBCNK.js → server-ZMIRSFMH.js} +2 -2
- package/package.json +3 -3
- package/dist/chunk-HCLEIAGO.js.map +0 -1
- /package/dist/{server-EASKBCNK.js.map → server-ZMIRSFMH.js.map} +0 -0
|
@@ -2721,7 +2721,7 @@ var require_dumper = __commonJS({
|
|
|
2721
2721
|
var hasFoldableLine = false;
|
|
2722
2722
|
var shouldTrackWidth = lineWidth !== -1;
|
|
2723
2723
|
var previousLineBreak = -1;
|
|
2724
|
-
var
|
|
2724
|
+
var plain2 = isPlainSafeFirst2(string.charCodeAt(0)) && !isWhitespace2(string.charCodeAt(string.length - 1));
|
|
2725
2725
|
if (singleLineOnly) {
|
|
2726
2726
|
for (i2 = 0; i2 < string.length; i2++) {
|
|
2727
2727
|
char = string.charCodeAt(i2);
|
|
@@ -2729,7 +2729,7 @@ var require_dumper = __commonJS({
|
|
|
2729
2729
|
return STYLE_DOUBLE2;
|
|
2730
2730
|
}
|
|
2731
2731
|
prev_char = i2 > 0 ? string.charCodeAt(i2 - 1) : null;
|
|
2732
|
-
|
|
2732
|
+
plain2 = plain2 && isPlainSafe2(char, prev_char);
|
|
2733
2733
|
}
|
|
2734
2734
|
} else {
|
|
2735
2735
|
for (i2 = 0; i2 < string.length; i2++) {
|
|
@@ -2745,12 +2745,12 @@ var require_dumper = __commonJS({
|
|
|
2745
2745
|
return STYLE_DOUBLE2;
|
|
2746
2746
|
}
|
|
2747
2747
|
prev_char = i2 > 0 ? string.charCodeAt(i2 - 1) : null;
|
|
2748
|
-
|
|
2748
|
+
plain2 = plain2 && isPlainSafe2(char, prev_char);
|
|
2749
2749
|
}
|
|
2750
2750
|
hasFoldableLine = hasFoldableLine || shouldTrackWidth && (i2 - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ");
|
|
2751
2751
|
}
|
|
2752
2752
|
if (!hasLineBreak && !hasFoldableLine) {
|
|
2753
|
-
return
|
|
2753
|
+
return plain2 && !testAmbiguousType(string) ? STYLE_PLAIN2 : STYLE_SINGLE2;
|
|
2754
2754
|
}
|
|
2755
2755
|
if (indentPerLevel > 9 && needIndentIndicator2(string)) {
|
|
2756
2756
|
return STYLE_DOUBLE2;
|
|
@@ -6112,7 +6112,7 @@ var require_semver2 = __commonJS({
|
|
|
6112
6112
|
"../../node_modules/.pnpm/semver@7.7.4/node_modules/semver/index.js"(exports2, module2) {
|
|
6113
6113
|
"use strict";
|
|
6114
6114
|
var internalRe = require_re();
|
|
6115
|
-
var
|
|
6115
|
+
var constants2 = require_constants();
|
|
6116
6116
|
var SemVer = require_semver();
|
|
6117
6117
|
var identifiers = require_identifiers();
|
|
6118
6118
|
var parse2 = require_parse2();
|
|
@@ -6194,8 +6194,8 @@ var require_semver2 = __commonJS({
|
|
|
6194
6194
|
re: internalRe.re,
|
|
6195
6195
|
src: internalRe.src,
|
|
6196
6196
|
tokens: internalRe.t,
|
|
6197
|
-
SEMVER_SPEC_VERSION:
|
|
6198
|
-
RELEASE_TYPES:
|
|
6197
|
+
SEMVER_SPEC_VERSION: constants2.SEMVER_SPEC_VERSION,
|
|
6198
|
+
RELEASE_TYPES: constants2.RELEASE_TYPES,
|
|
6199
6199
|
compareIdentifiers: identifiers.compareIdentifiers,
|
|
6200
6200
|
rcompareIdentifiers: identifiers.rcompareIdentifiers
|
|
6201
6201
|
};
|
|
@@ -8367,14 +8367,14 @@ function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, te
|
|
|
8367
8367
|
var hasFoldableLine = false;
|
|
8368
8368
|
var shouldTrackWidth = lineWidth !== -1;
|
|
8369
8369
|
var previousLineBreak = -1;
|
|
8370
|
-
var
|
|
8370
|
+
var plain2 = isPlainSafeFirst(codePointAt(string, 0)) && isPlainSafeLast(codePointAt(string, string.length - 1));
|
|
8371
8371
|
if (singleLineOnly || forceQuotes) {
|
|
8372
8372
|
for (i2 = 0; i2 < string.length; char >= 65536 ? i2 += 2 : i2++) {
|
|
8373
8373
|
char = codePointAt(string, i2);
|
|
8374
8374
|
if (!isPrintable(char)) {
|
|
8375
8375
|
return STYLE_DOUBLE;
|
|
8376
8376
|
}
|
|
8377
|
-
|
|
8377
|
+
plain2 = plain2 && isPlainSafe(char, prevChar, inblock);
|
|
8378
8378
|
prevChar = char;
|
|
8379
8379
|
}
|
|
8380
8380
|
} else {
|
|
@@ -8390,13 +8390,13 @@ function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, te
|
|
|
8390
8390
|
} else if (!isPrintable(char)) {
|
|
8391
8391
|
return STYLE_DOUBLE;
|
|
8392
8392
|
}
|
|
8393
|
-
|
|
8393
|
+
plain2 = plain2 && isPlainSafe(char, prevChar, inblock);
|
|
8394
8394
|
prevChar = char;
|
|
8395
8395
|
}
|
|
8396
8396
|
hasFoldableLine = hasFoldableLine || shouldTrackWidth && (i2 - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ");
|
|
8397
8397
|
}
|
|
8398
8398
|
if (!hasLineBreak && !hasFoldableLine) {
|
|
8399
|
-
if (
|
|
8399
|
+
if (plain2 && !forceQuotes && !testAmbiguousType(string)) {
|
|
8400
8400
|
return STYLE_PLAIN;
|
|
8401
8401
|
}
|
|
8402
8402
|
return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
|
|
@@ -8963,7 +8963,7 @@ import { readFileSync as readFileSync2, readdirSync as readdirSync2, statSync, e
|
|
|
8963
8963
|
import { join as join2, relative } from "node:path";
|
|
8964
8964
|
function scanSource(opts) {
|
|
8965
8965
|
const { db, source, entriesRoot } = opts;
|
|
8966
|
-
const
|
|
8966
|
+
const now2 = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
8967
8967
|
db.exec("DROP TABLE IF EXISTS temp.touched");
|
|
8968
8968
|
db.exec("CREATE TEMP TABLE touched(rowid INTEGER PRIMARY KEY)");
|
|
8969
8969
|
const insertTouched = db.prepare("INSERT INTO touched (rowid) VALUES (?)");
|
|
@@ -8981,7 +8981,7 @@ function scanSource(opts) {
|
|
|
8981
8981
|
path: rel,
|
|
8982
8982
|
content: src,
|
|
8983
8983
|
file_mtime: mtime,
|
|
8984
|
-
indexed_at:
|
|
8984
|
+
indexed_at: now2()
|
|
8985
8985
|
});
|
|
8986
8986
|
const existing = db.prepare("SELECT rowid, file_mtime, path FROM entries WHERE source = ? AND id = ?").get(source, row.id);
|
|
8987
8987
|
if (existing && existing.file_mtime === mtime && existing.path === rel) {
|
|
@@ -9351,7 +9351,7 @@ async function prewarmSealedKeys(opts) {
|
|
|
9351
9351
|
return failures;
|
|
9352
9352
|
}
|
|
9353
9353
|
function scanSealedSource(opts) {
|
|
9354
|
-
const
|
|
9354
|
+
const now2 = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
9355
9355
|
const bundle = readFileSync3(opts.bundlePath);
|
|
9356
9356
|
const { header } = readSealedHeader(bundle);
|
|
9357
9357
|
const contentKey = opts.keyProvider.resolveContentKey(header.keyId, header.keyserverUrl);
|
|
@@ -9370,7 +9370,7 @@ function scanSealedSource(opts) {
|
|
|
9370
9370
|
path: file.relPath,
|
|
9371
9371
|
content: file.content.toString("utf-8"),
|
|
9372
9372
|
file_mtime: bundleMtime,
|
|
9373
|
-
indexed_at:
|
|
9373
|
+
indexed_at: now2()
|
|
9374
9374
|
});
|
|
9375
9375
|
const existing = opts.db.prepare("SELECT rowid FROM entries WHERE source = ? AND id = ?").get(opts.source, row.id);
|
|
9376
9376
|
const rowid = upsertEntry(opts.db, row);
|
|
@@ -9496,9 +9496,9 @@ function acquireFileLock(lockFilePath) {
|
|
|
9496
9496
|
}
|
|
9497
9497
|
return tryCreateLock(lockFilePath) ? { path: lockFilePath } : null;
|
|
9498
9498
|
}
|
|
9499
|
-
function releaseFileLock(
|
|
9499
|
+
function releaseFileLock(lock2) {
|
|
9500
9500
|
try {
|
|
9501
|
-
unlinkSync(
|
|
9501
|
+
unlinkSync(lock2.path);
|
|
9502
9502
|
} catch (err) {
|
|
9503
9503
|
if (err.code !== "ENOENT") throw err;
|
|
9504
9504
|
}
|
|
@@ -9506,8 +9506,8 @@ function releaseFileLock(lock) {
|
|
|
9506
9506
|
function acquireReindexLock(caveatHome) {
|
|
9507
9507
|
return acquireFileLock(lockPath(caveatHome));
|
|
9508
9508
|
}
|
|
9509
|
-
function releaseReindexLock(
|
|
9510
|
-
releaseFileLock(
|
|
9509
|
+
function releaseReindexLock(lock2) {
|
|
9510
|
+
releaseFileLock(lock2);
|
|
9511
9511
|
}
|
|
9512
9512
|
function reindexAllSources(opts) {
|
|
9513
9513
|
const { db, paths, logger, keyProvider } = opts;
|
|
@@ -14699,6 +14699,10 @@ import {
|
|
|
14699
14699
|
mkdirSync as mkdirSync3,
|
|
14700
14700
|
readdirSync as readdirSync6,
|
|
14701
14701
|
readFileSync as readFileSync5,
|
|
14702
|
+
linkSync,
|
|
14703
|
+
openSync,
|
|
14704
|
+
closeSync,
|
|
14705
|
+
chmodSync,
|
|
14702
14706
|
rmSync as rmSync2,
|
|
14703
14707
|
statSync as statSync5,
|
|
14704
14708
|
unlinkSync as unlinkSync2,
|
|
@@ -14706,21 +14710,182 @@ import {
|
|
|
14706
14710
|
} from "node:fs";
|
|
14707
14711
|
import { join as join6 } from "node:path";
|
|
14708
14712
|
import { randomBytes } from "node:crypto";
|
|
14713
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
14714
|
+
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
14709
14715
|
function sanitizeSessionId(raw) {
|
|
14710
14716
|
const clean = raw.replace(/[^A-Za-z0-9_-]/g, "");
|
|
14711
14717
|
return clean.length > 0 ? clean : "_unknown";
|
|
14712
14718
|
}
|
|
14713
14719
|
var GLOBAL_PENDING_SESSION = "_global";
|
|
14720
|
+
var PENDING_LOCK_BUSY_TIMEOUT_MS = 1e3;
|
|
14721
|
+
function withPendingQueueLock(caveatHome, operation) {
|
|
14722
|
+
const root = join6(caveatHome, "pending");
|
|
14723
|
+
mkdirSync3(root, { recursive: true, mode: 448 });
|
|
14724
|
+
const lockPath2 = join6(root, ".queue-lock.sqlite");
|
|
14725
|
+
const db = new DatabaseSync2(lockPath2);
|
|
14726
|
+
let transactionOpen = false;
|
|
14727
|
+
try {
|
|
14728
|
+
chmodSync(lockPath2, 384);
|
|
14729
|
+
db.exec(`PRAGMA busy_timeout = ${PENDING_LOCK_BUSY_TIMEOUT_MS}`);
|
|
14730
|
+
db.exec("BEGIN IMMEDIATE");
|
|
14731
|
+
transactionOpen = true;
|
|
14732
|
+
const result = operation();
|
|
14733
|
+
db.exec("COMMIT");
|
|
14734
|
+
transactionOpen = false;
|
|
14735
|
+
return result;
|
|
14736
|
+
} catch (error) {
|
|
14737
|
+
if (transactionOpen) {
|
|
14738
|
+
try {
|
|
14739
|
+
db.exec("ROLLBACK");
|
|
14740
|
+
} catch {
|
|
14741
|
+
}
|
|
14742
|
+
}
|
|
14743
|
+
throw error;
|
|
14744
|
+
} finally {
|
|
14745
|
+
db.close();
|
|
14746
|
+
}
|
|
14747
|
+
}
|
|
14714
14748
|
function pendingDirFor(caveatHome, sessionId) {
|
|
14715
14749
|
return join6(caveatHome, "pending", sanitizeSessionId(sessionId));
|
|
14716
14750
|
}
|
|
14717
14751
|
function appendPendingReminder(caveatHome, sessionId, text) {
|
|
14718
|
-
|
|
14719
|
-
|
|
14720
|
-
|
|
14721
|
-
|
|
14722
|
-
|
|
14723
|
-
|
|
14752
|
+
return withPendingQueueLock(caveatHome, () => {
|
|
14753
|
+
const dir = pendingDirFor(caveatHome, sessionId);
|
|
14754
|
+
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
14755
|
+
const name = `${Date.now()}-${randomBytes(4).toString("hex")}.txt`;
|
|
14756
|
+
const path = join6(dir, name);
|
|
14757
|
+
writeFileSync2(path, text, { encoding: "utf-8", mode: 384, flag: "wx" });
|
|
14758
|
+
return path;
|
|
14759
|
+
});
|
|
14760
|
+
}
|
|
14761
|
+
function buildPendingSemanticKey(input) {
|
|
14762
|
+
const refs = [...input.refs].map(({ source, id }) => ({ source, id })).sort((a, b2) => a.source.localeCompare(b2.source) || a.id.localeCompare(b2.id)).filter((ref, index, all) => index === 0 || ref.source !== all[index - 1].source || ref.id !== all[index - 1].id).map(({ source, id }) => [source, id]);
|
|
14763
|
+
return createHash2("sha256").update(JSON.stringify({
|
|
14764
|
+
agent: input.agent,
|
|
14765
|
+
surface: input.surface,
|
|
14766
|
+
refs,
|
|
14767
|
+
stopSignalDigest: input.stopSignalDigest ?? null
|
|
14768
|
+
})).digest("hex");
|
|
14769
|
+
}
|
|
14770
|
+
var CLAIM_TTL_MS = 5 * 60 * 1e3;
|
|
14771
|
+
function hasNonExpiredPendingClaim(sessionDir, nowMs) {
|
|
14772
|
+
const claimsDir = join6(sessionDir, ".claims");
|
|
14773
|
+
let claims;
|
|
14774
|
+
try {
|
|
14775
|
+
claims = readdirSync6(claimsDir).filter((entry) => entry.endsWith(".claim"));
|
|
14776
|
+
} catch (error) {
|
|
14777
|
+
if (error && typeof error === "object" && error.code === "ENOENT") return false;
|
|
14778
|
+
return true;
|
|
14779
|
+
}
|
|
14780
|
+
for (const claim of claims) {
|
|
14781
|
+
const path = join6(claimsDir, claim);
|
|
14782
|
+
try {
|
|
14783
|
+
let createdAt = statSync5(path).mtimeMs;
|
|
14784
|
+
try {
|
|
14785
|
+
const parsed = JSON.parse(readFileSync5(path, "utf-8"));
|
|
14786
|
+
if (typeof parsed.createdAt === "number") createdAt = parsed.createdAt;
|
|
14787
|
+
} catch {
|
|
14788
|
+
}
|
|
14789
|
+
if (nowMs - createdAt <= CLAIM_TTL_MS) return true;
|
|
14790
|
+
} catch {
|
|
14791
|
+
return true;
|
|
14792
|
+
}
|
|
14793
|
+
}
|
|
14794
|
+
return false;
|
|
14795
|
+
}
|
|
14796
|
+
function acquirePendingClaim(caveatHome, sessionId, key, options2 = {}) {
|
|
14797
|
+
return withPendingQueueLock(caveatHome, () => {
|
|
14798
|
+
if (!/^[a-f0-9]{64}$/.test(key)) throw new Error("pending semantic key is invalid");
|
|
14799
|
+
if (existsSync6(join6(pendingDirFor(caveatHome, sessionId), `${key}.ready`))) return null;
|
|
14800
|
+
const dir = join6(pendingDirFor(caveatHome, sessionId), ".claims");
|
|
14801
|
+
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
14802
|
+
const path = join6(dir, `${key}.claim`);
|
|
14803
|
+
const now2 = options2.now ?? Date.now();
|
|
14804
|
+
const ttlMs = options2.ttlMs ?? CLAIM_TTL_MS;
|
|
14805
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
14806
|
+
const ownerToken = randomBytes(16).toString("hex");
|
|
14807
|
+
try {
|
|
14808
|
+
const fd = openSync(path, "wx", 384);
|
|
14809
|
+
try {
|
|
14810
|
+
writeFileSync2(fd, JSON.stringify({ ownerToken, createdAt: now2 }), "utf-8");
|
|
14811
|
+
} finally {
|
|
14812
|
+
closeSync(fd);
|
|
14813
|
+
}
|
|
14814
|
+
if (existsSync6(join6(pendingDirFor(caveatHome, sessionId), `${key}.ready`))) {
|
|
14815
|
+
unlinkSync2(path);
|
|
14816
|
+
return null;
|
|
14817
|
+
}
|
|
14818
|
+
return { caveatHome, key, ownerToken, path };
|
|
14819
|
+
} catch (error) {
|
|
14820
|
+
if (!(error && typeof error === "object" && error.code === "EEXIST")) throw error;
|
|
14821
|
+
try {
|
|
14822
|
+
let createdAt = statSync5(path).mtimeMs;
|
|
14823
|
+
try {
|
|
14824
|
+
const parsed = JSON.parse(readFileSync5(path, "utf-8"));
|
|
14825
|
+
if (typeof parsed.createdAt === "number") createdAt = parsed.createdAt;
|
|
14826
|
+
} catch {
|
|
14827
|
+
}
|
|
14828
|
+
if (now2 - createdAt <= ttlMs) return null;
|
|
14829
|
+
unlinkSync2(path);
|
|
14830
|
+
} catch (retryError) {
|
|
14831
|
+
if (retryError && typeof retryError === "object" && retryError.code === "ENOENT") continue;
|
|
14832
|
+
return null;
|
|
14833
|
+
}
|
|
14834
|
+
}
|
|
14835
|
+
}
|
|
14836
|
+
return null;
|
|
14837
|
+
});
|
|
14838
|
+
}
|
|
14839
|
+
function releasePendingClaim(claim) {
|
|
14840
|
+
withPendingQueueLock(claim.caveatHome, () => {
|
|
14841
|
+
try {
|
|
14842
|
+
const parsed = JSON.parse(readFileSync5(claim.path, "utf-8"));
|
|
14843
|
+
if (parsed.ownerToken !== claim.ownerToken) return;
|
|
14844
|
+
unlinkSync2(claim.path);
|
|
14845
|
+
} catch (error) {
|
|
14846
|
+
if (error && typeof error === "object" && error.code === "ENOENT") return;
|
|
14847
|
+
throw error;
|
|
14848
|
+
}
|
|
14849
|
+
});
|
|
14850
|
+
}
|
|
14851
|
+
function publishPendingReminder(caveatHome, sessionId, semanticKey, text) {
|
|
14852
|
+
if (!/^[a-f0-9]{64}$/.test(semanticKey)) throw new Error("pending semantic key is invalid");
|
|
14853
|
+
const ready = join6(pendingDirFor(caveatHome, sessionId), `${semanticKey}.ready`);
|
|
14854
|
+
if (existsSync6(ready)) return { path: ready, published: false };
|
|
14855
|
+
try {
|
|
14856
|
+
return withPendingQueueLock(caveatHome, () => {
|
|
14857
|
+
const dir = pendingDirFor(caveatHome, sessionId);
|
|
14858
|
+
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
14859
|
+
const temp = join6(dir, `.${semanticKey}.${randomBytes(12).toString("hex")}.tmp`);
|
|
14860
|
+
writeFileSync2(temp, text, { encoding: "utf-8", mode: 384, flag: "wx" });
|
|
14861
|
+
try {
|
|
14862
|
+
linkSync(temp, ready);
|
|
14863
|
+
return { path: ready, published: true };
|
|
14864
|
+
} catch (error) {
|
|
14865
|
+
if (error && typeof error === "object" && error.code === "EEXIST") return { path: ready, published: false };
|
|
14866
|
+
throw error;
|
|
14867
|
+
} finally {
|
|
14868
|
+
try {
|
|
14869
|
+
unlinkSync2(temp);
|
|
14870
|
+
} catch (error) {
|
|
14871
|
+
if (!(error && typeof error === "object" && error.code === "ENOENT")) throw error;
|
|
14872
|
+
}
|
|
14873
|
+
}
|
|
14874
|
+
});
|
|
14875
|
+
} catch (error) {
|
|
14876
|
+
if (existsSync6(ready)) return { path: ready, published: false };
|
|
14877
|
+
throw error;
|
|
14878
|
+
}
|
|
14879
|
+
}
|
|
14880
|
+
function buildAndPublishPendingReminder(caveatHome, sessionId, semanticKey, build) {
|
|
14881
|
+
const claim = acquirePendingClaim(caveatHome, sessionId, semanticKey);
|
|
14882
|
+
if (!claim) return { ran: false, published: false };
|
|
14883
|
+
try {
|
|
14884
|
+
const result = publishPendingReminder(caveatHome, sessionId, claim.key, build());
|
|
14885
|
+
return { ran: true, published: result.published };
|
|
14886
|
+
} finally {
|
|
14887
|
+
releasePendingClaim(claim);
|
|
14888
|
+
}
|
|
14724
14889
|
}
|
|
14725
14890
|
function appendGlobalPendingReminder(caveatHome, text) {
|
|
14726
14891
|
return appendPendingReminder(caveatHome, GLOBAL_PENDING_SESSION, text);
|
|
@@ -14730,55 +14895,61 @@ function cleanupStalePendingDirs(caveatHome, options2 = {}) {
|
|
|
14730
14895
|
if (staleDays < 0) {
|
|
14731
14896
|
throw new Error(`cleanupStalePendingDirs: staleDays must be >= 0 (got ${staleDays})`);
|
|
14732
14897
|
}
|
|
14733
|
-
const
|
|
14734
|
-
const cutoffMs =
|
|
14898
|
+
const now2 = options2.now ?? /* @__PURE__ */ new Date();
|
|
14899
|
+
const cutoffMs = now2.getTime() - staleDays * 24 * 60 * 60 * 1e3;
|
|
14735
14900
|
const root = join6(caveatHome, "pending");
|
|
14736
14901
|
if (!existsSync6(root)) return { removed: [], kept: 0 };
|
|
14737
|
-
|
|
14738
|
-
|
|
14739
|
-
entries = readdirSync6(root);
|
|
14740
|
-
} catch {
|
|
14741
|
-
return { removed: [], kept: 0 };
|
|
14742
|
-
}
|
|
14743
|
-
const removed = [];
|
|
14744
|
-
let kept = 0;
|
|
14745
|
-
for (const entry of entries) {
|
|
14746
|
-
const sub = join6(root, entry);
|
|
14747
|
-
let subStat;
|
|
14902
|
+
return withPendingQueueLock(caveatHome, () => {
|
|
14903
|
+
let entries;
|
|
14748
14904
|
try {
|
|
14749
|
-
|
|
14905
|
+
entries = readdirSync6(root);
|
|
14750
14906
|
} catch {
|
|
14751
|
-
|
|
14907
|
+
return { removed: [], kept: 0 };
|
|
14752
14908
|
}
|
|
14753
|
-
|
|
14754
|
-
let
|
|
14755
|
-
|
|
14756
|
-
|
|
14757
|
-
|
|
14758
|
-
|
|
14759
|
-
|
|
14760
|
-
|
|
14761
|
-
|
|
14762
|
-
|
|
14763
|
-
|
|
14764
|
-
|
|
14909
|
+
const removed = [];
|
|
14910
|
+
let kept = 0;
|
|
14911
|
+
for (const entry of entries) {
|
|
14912
|
+
const sub = join6(root, entry);
|
|
14913
|
+
let subStat;
|
|
14914
|
+
try {
|
|
14915
|
+
subStat = statSync5(sub);
|
|
14916
|
+
} catch {
|
|
14917
|
+
continue;
|
|
14918
|
+
}
|
|
14919
|
+
if (!subStat.isDirectory()) continue;
|
|
14920
|
+
if (hasNonExpiredPendingClaim(sub, now2.getTime())) {
|
|
14921
|
+
kept++;
|
|
14922
|
+
continue;
|
|
14923
|
+
}
|
|
14924
|
+
let newest = subStat.mtimeMs;
|
|
14925
|
+
let scanFailed = false;
|
|
14926
|
+
try {
|
|
14927
|
+
for (const f of readdirSync6(sub)) {
|
|
14928
|
+
const fp = join6(sub, f);
|
|
14929
|
+
try {
|
|
14930
|
+
const fileStat = statSync5(fp);
|
|
14931
|
+
if (fileStat.mtimeMs > newest) newest = fileStat.mtimeMs;
|
|
14932
|
+
} catch {
|
|
14933
|
+
scanFailed = true;
|
|
14934
|
+
break;
|
|
14935
|
+
}
|
|
14765
14936
|
}
|
|
14937
|
+
} catch {
|
|
14938
|
+
scanFailed = true;
|
|
14939
|
+
}
|
|
14940
|
+
if (scanFailed || newest >= cutoffMs) {
|
|
14941
|
+
kept++;
|
|
14942
|
+
continue;
|
|
14943
|
+
}
|
|
14944
|
+
try {
|
|
14945
|
+
rmSync2(sub, { recursive: true, force: true });
|
|
14946
|
+
removed.push(sub);
|
|
14947
|
+
} catch {
|
|
14948
|
+
kept++;
|
|
14766
14949
|
}
|
|
14767
|
-
} catch {
|
|
14768
|
-
scanFailed = true;
|
|
14769
|
-
}
|
|
14770
|
-
if (scanFailed || newest >= cutoffMs) {
|
|
14771
|
-
kept++;
|
|
14772
|
-
continue;
|
|
14773
|
-
}
|
|
14774
|
-
try {
|
|
14775
|
-
rmSync2(sub, { recursive: true, force: true });
|
|
14776
|
-
removed.push(sub);
|
|
14777
|
-
} catch {
|
|
14778
|
-
kept++;
|
|
14779
14950
|
}
|
|
14780
|
-
|
|
14781
|
-
|
|
14951
|
+
return { removed, kept };
|
|
14952
|
+
});
|
|
14782
14953
|
}
|
|
14783
14954
|
function maybeSweepPendingDirs(caveatHome, options2 = {}) {
|
|
14784
14955
|
if (process.env.CAVEAT_PENDING_SWEEP === "off") {
|
|
@@ -14791,55 +14962,70 @@ function maybeSweepPendingDirs(caveatHome, options2 = {}) {
|
|
|
14791
14962
|
`maybeSweepPendingDirs: debounceDays must be >= 0 (got ${debounceDays})`
|
|
14792
14963
|
);
|
|
14793
14964
|
}
|
|
14794
|
-
const
|
|
14965
|
+
const now2 = options2.now ?? /* @__PURE__ */ new Date();
|
|
14795
14966
|
const pendingRoot = join6(caveatHome, "pending");
|
|
14796
14967
|
if (!existsSync6(pendingRoot)) return { skipped: "no_pending_dir" };
|
|
14797
14968
|
const marker = join6(pendingRoot, ".last-sweep");
|
|
14798
14969
|
try {
|
|
14799
14970
|
const m = statSync5(marker);
|
|
14800
|
-
const ageMs =
|
|
14971
|
+
const ageMs = now2.getTime() - m.mtimeMs;
|
|
14801
14972
|
if (ageMs < debounceDays * 24 * 60 * 60 * 1e3) {
|
|
14802
14973
|
return { skipped: "debounced" };
|
|
14803
14974
|
}
|
|
14804
14975
|
} catch {
|
|
14805
14976
|
}
|
|
14806
|
-
const result = cleanupStalePendingDirs(caveatHome, { staleDays, now });
|
|
14977
|
+
const result = cleanupStalePendingDirs(caveatHome, { staleDays, now: now2 });
|
|
14807
14978
|
try {
|
|
14808
14979
|
writeFileSync2(marker, "", "utf-8");
|
|
14809
14980
|
} catch {
|
|
14810
14981
|
}
|
|
14811
14982
|
return { swept: result };
|
|
14812
14983
|
}
|
|
14813
|
-
function
|
|
14984
|
+
function drainPendingRemindersDetailed(caveatHome, sessionId, fs = {}) {
|
|
14814
14985
|
const dir = pendingDirFor(caveatHome, sessionId);
|
|
14815
|
-
if (!existsSync6(dir)) return [];
|
|
14816
|
-
let entries;
|
|
14986
|
+
if (!existsSync6(dir)) return { reminders: [], cleanupFailures: [] };
|
|
14817
14987
|
try {
|
|
14818
|
-
|
|
14988
|
+
return withPendingQueueLock(caveatHome, () => {
|
|
14989
|
+
let entries;
|
|
14990
|
+
try {
|
|
14991
|
+
entries = readdirSync6(dir).filter((f) => f.endsWith(".txt") || f.endsWith(".ready"));
|
|
14992
|
+
} catch {
|
|
14993
|
+
return { reminders: [], cleanupFailures: ["pending directory read failed"] };
|
|
14994
|
+
}
|
|
14995
|
+
const cleanupFailures = [];
|
|
14996
|
+
entries.sort((a, b2) => {
|
|
14997
|
+
try {
|
|
14998
|
+
const diff = statSync5(join6(dir, a)).mtimeMs - statSync5(join6(dir, b2)).mtimeMs;
|
|
14999
|
+
return diff || a.localeCompare(b2);
|
|
15000
|
+
} catch {
|
|
15001
|
+
return a.localeCompare(b2);
|
|
15002
|
+
}
|
|
15003
|
+
});
|
|
15004
|
+
const reminders = [];
|
|
15005
|
+
for (const entry of entries) {
|
|
15006
|
+
const path = join6(dir, entry);
|
|
15007
|
+
try {
|
|
15008
|
+
reminders.push(fs.read ? fs.read(path) : readFileSync5(path, "utf-8"));
|
|
15009
|
+
} catch {
|
|
15010
|
+
cleanupFailures.push(entry);
|
|
15011
|
+
continue;
|
|
15012
|
+
}
|
|
15013
|
+
try {
|
|
15014
|
+
if (fs.unlink) fs.unlink(path);
|
|
15015
|
+
else unlinkSync2(path);
|
|
15016
|
+
} catch {
|
|
15017
|
+
cleanupFailures.push(entry);
|
|
15018
|
+
}
|
|
15019
|
+
}
|
|
15020
|
+
return { reminders, cleanupFailures };
|
|
15021
|
+
});
|
|
14819
15022
|
} catch {
|
|
14820
|
-
return [];
|
|
15023
|
+
return { reminders: [], cleanupFailures: ["pending queue lock unavailable"] };
|
|
14821
15024
|
}
|
|
14822
|
-
const out = [];
|
|
14823
|
-
for (const entry of entries) {
|
|
14824
|
-
const path = join6(dir, entry);
|
|
14825
|
-
try {
|
|
14826
|
-
out.push(readFileSync5(path, "utf-8"));
|
|
14827
|
-
} catch {
|
|
14828
|
-
continue;
|
|
14829
|
-
}
|
|
14830
|
-
try {
|
|
14831
|
-
unlinkSync2(path);
|
|
14832
|
-
} catch {
|
|
14833
|
-
}
|
|
14834
|
-
}
|
|
14835
|
-
return out;
|
|
14836
|
-
}
|
|
14837
|
-
function drainGlobalPendingReminders(caveatHome) {
|
|
14838
|
-
return drainPendingReminders(caveatHome, GLOBAL_PENDING_SESSION);
|
|
14839
15025
|
}
|
|
14840
15026
|
|
|
14841
15027
|
// ../../packages/core/dist/sealedKeys.js
|
|
14842
|
-
import { createHash as
|
|
15028
|
+
import { createHash as createHash3, randomBytes as randomBytes2 } from "node:crypto";
|
|
14843
15029
|
import {
|
|
14844
15030
|
existsSync as existsSync7,
|
|
14845
15031
|
mkdirSync as mkdirSync4,
|
|
@@ -14891,7 +15077,7 @@ function memoryKey(keyserverUrl, keyId) {
|
|
|
14891
15077
|
${keyId}`;
|
|
14892
15078
|
}
|
|
14893
15079
|
function cacheFilePath(caveatHome, keyserverUrl, keyId) {
|
|
14894
|
-
const digest =
|
|
15080
|
+
const digest = createHash3("sha256").update(`${keyserverUrl}
|
|
14895
15081
|
${keyId}`).digest("hex").slice(0, 32);
|
|
14896
15082
|
return join7(caveatHome, "keys", `${digest}.json`);
|
|
14897
15083
|
}
|
|
@@ -15248,7 +15434,7 @@ function errorMessage2(err) {
|
|
|
15248
15434
|
}
|
|
15249
15435
|
|
|
15250
15436
|
// ../../packages/core/dist/autoSync.js
|
|
15251
|
-
import { createHash as
|
|
15437
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
15252
15438
|
import { mkdirSync as mkdirSync6, readFileSync as readFileSync7, renameSync as renameSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
15253
15439
|
import { dirname as dirname5, join as join9 } from "node:path";
|
|
15254
15440
|
var AUTO_SYNC_DEBOUNCE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -15346,8 +15532,8 @@ function autoSyncNotification(outcome) {
|
|
|
15346
15532
|
}
|
|
15347
15533
|
async function runAutoSync(opts) {
|
|
15348
15534
|
if (process.env[CAVEAT_AUTO_SYNC_ENV] === "off") return { ran: false };
|
|
15349
|
-
const
|
|
15350
|
-
if (!
|
|
15535
|
+
const lock2 = acquireFileLock(autoSyncLockPath(opts.caveatHome));
|
|
15536
|
+
if (!lock2) return { ran: false };
|
|
15351
15537
|
let reindexLock = null;
|
|
15352
15538
|
try {
|
|
15353
15539
|
reindexLock = acquireReindexLock(opts.caveatHome);
|
|
@@ -15428,7 +15614,7 @@ async function runAutoSync(opts) {
|
|
|
15428
15614
|
}
|
|
15429
15615
|
}
|
|
15430
15616
|
try {
|
|
15431
|
-
releaseFileLock(
|
|
15617
|
+
releaseFileLock(lock2);
|
|
15432
15618
|
} catch (err) {
|
|
15433
15619
|
opts.logger.warn(`autosync lock release failed: ${errorMessage3(err)}`);
|
|
15434
15620
|
}
|
|
@@ -15450,7 +15636,7 @@ async function reindexAndMark2(opts) {
|
|
|
15450
15636
|
}
|
|
15451
15637
|
}
|
|
15452
15638
|
function sha256(input) {
|
|
15453
|
-
return
|
|
15639
|
+
return createHash4("sha256").update(input).digest("hex");
|
|
15454
15640
|
}
|
|
15455
15641
|
function errorMessage3(err) {
|
|
15456
15642
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -15707,7 +15893,40 @@ function toSearchResult2(row) {
|
|
|
15707
15893
|
environment: fm.environment ?? {}
|
|
15708
15894
|
};
|
|
15709
15895
|
}
|
|
15710
|
-
function
|
|
15896
|
+
function findCaveatsForHook(db, input, opts = {}) {
|
|
15897
|
+
if (input.surface === "user_prompt") {
|
|
15898
|
+
const prompt = input.topicText || input.failureText;
|
|
15899
|
+
return findCaveatsForText(db, prompt, opts);
|
|
15900
|
+
}
|
|
15901
|
+
if (input.surface === "stop") {
|
|
15902
|
+
return findCaveatsForText(db, input.failureText, opts);
|
|
15903
|
+
}
|
|
15904
|
+
const failureTokens = new Set(
|
|
15905
|
+
buildPromptCandidates(input.failureText).map((candidate) => candidate.token.toLowerCase())
|
|
15906
|
+
);
|
|
15907
|
+
return findCaveatsForText(
|
|
15908
|
+
db,
|
|
15909
|
+
[input.topicText, input.failureText].filter(Boolean).join("\n"),
|
|
15910
|
+
opts,
|
|
15911
|
+
failureTokens
|
|
15912
|
+
);
|
|
15913
|
+
}
|
|
15914
|
+
function findCaveatsForHookSegments(db, inputs, opts = {}) {
|
|
15915
|
+
const limit = opts.limit ?? DEFAULT_REMINDER_HIT_LIMIT;
|
|
15916
|
+
const out = [];
|
|
15917
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15918
|
+
for (const input of inputs) {
|
|
15919
|
+
for (const hit of findCaveatsForHook(db, input, { ...opts, limit })) {
|
|
15920
|
+
const key = `${hit.source}\0${hit.id}`;
|
|
15921
|
+
if (seen.has(key)) continue;
|
|
15922
|
+
seen.add(key);
|
|
15923
|
+
out.push(hit);
|
|
15924
|
+
if (out.length >= limit) return out;
|
|
15925
|
+
}
|
|
15926
|
+
}
|
|
15927
|
+
return out;
|
|
15928
|
+
}
|
|
15929
|
+
function findCaveatsForText(db, prompt, opts = {}, symptomEvidenceTokens) {
|
|
15711
15930
|
if (typeof prompt !== "string" || prompt.length === 0) return [];
|
|
15712
15931
|
const candidates = buildPromptCandidates(prompt);
|
|
15713
15932
|
if (candidates.length === 0) return [];
|
|
@@ -15746,7 +15965,7 @@ function findCaveatsForPrompt(db, prompt, opts = {}) {
|
|
|
15746
15965
|
perEntry.set(row.rowid, entry);
|
|
15747
15966
|
}
|
|
15748
15967
|
entry.groups.add(cand.group);
|
|
15749
|
-
if (entry.symptomLower !== null && tokenAppearsIn(tokLower, entry.symptomLower)) {
|
|
15968
|
+
if (entry.symptomLower !== null && (symptomEvidenceTokens === void 0 || symptomEvidenceTokens.has(tokLower)) && tokenAppearsIn(tokLower, entry.symptomLower)) {
|
|
15750
15969
|
entry.symptomTokens.add(tokLower);
|
|
15751
15970
|
}
|
|
15752
15971
|
if (entry.topicalLower !== null && tokenAppearsIn(tokLower, entry.topicalLower)) {
|
|
@@ -16152,9 +16371,9 @@ function readCodexSessionSignals(transcriptPath) {
|
|
|
16152
16371
|
}
|
|
16153
16372
|
|
|
16154
16373
|
// ../../packages/core/dist/markHit.js
|
|
16155
|
-
function markHit(db, keys,
|
|
16374
|
+
function markHit(db, keys, now2 = () => (/* @__PURE__ */ new Date()).toISOString()) {
|
|
16156
16375
|
if (keys.length === 0) return;
|
|
16157
|
-
const ts =
|
|
16376
|
+
const ts = now2();
|
|
16158
16377
|
const stmt = db.prepare(
|
|
16159
16378
|
"UPDATE entries SET last_hit_at = ? WHERE source = ? AND id = ?"
|
|
16160
16379
|
);
|
|
@@ -16164,14 +16383,14 @@ function markHit(db, keys, now = () => (/* @__PURE__ */ new Date()).toISOString(
|
|
|
16164
16383
|
}
|
|
16165
16384
|
|
|
16166
16385
|
// ../../packages/core/dist/hookQueryLog.js
|
|
16167
|
-
import { appendFileSync, chmodSync, mkdirSync as mkdirSync7, renameSync as renameSync4, statSync as statSync6, unlinkSync as unlinkSync3 } from "node:fs";
|
|
16386
|
+
import { appendFileSync, chmodSync as chmodSync2, mkdirSync as mkdirSync7, renameSync as renameSync4, statSync as statSync6, unlinkSync as unlinkSync3 } from "node:fs";
|
|
16168
16387
|
import { join as join11, resolve as resolve3 } from "node:path";
|
|
16169
16388
|
var CAVEAT_HOOK_QUERY_LOG_ENV = "CAVEAT_HOOK_QUERY_LOG";
|
|
16170
16389
|
var HOOK_QUERY_LOG_MAX_BYTES = 1024 * 1024;
|
|
16171
16390
|
var HOOK_QUERY_LOG_MAX_QUERY_CODE_UNITS = 1e3;
|
|
16172
16391
|
var fsDependencies = {
|
|
16173
16392
|
appendFileSync,
|
|
16174
|
-
chmodSync,
|
|
16393
|
+
chmodSync: chmodSync2,
|
|
16175
16394
|
mkdirSync: mkdirSync7,
|
|
16176
16395
|
renameSync: renameSync4,
|
|
16177
16396
|
statSync: statSync6,
|
|
@@ -16234,8 +16453,8 @@ function logHookQueryMiss(miss, dependencies = fsDependencies) {
|
|
|
16234
16453
|
function listStale(db, opts = {}) {
|
|
16235
16454
|
const days = opts.days ?? 90;
|
|
16236
16455
|
const limit = opts.limit ?? 50;
|
|
16237
|
-
const
|
|
16238
|
-
const cutoff = new Date(
|
|
16456
|
+
const now2 = (opts.now ?? (() => /* @__PURE__ */ new Date()))();
|
|
16457
|
+
const cutoff = new Date(now2.getTime() - days * 24 * 60 * 60 * 1e3).toISOString();
|
|
16239
16458
|
const conditions = ["(last_hit_at IS NULL OR last_hit_at < ?)"];
|
|
16240
16459
|
const params = [cutoff];
|
|
16241
16460
|
if (opts.visibility === "public" || opts.visibility === "private") {
|
|
@@ -16261,7 +16480,7 @@ function listStale(db, opts = {}) {
|
|
|
16261
16480
|
}
|
|
16262
16481
|
|
|
16263
16482
|
// ../../packages/core/dist/publishScan.js
|
|
16264
|
-
import { createHash as
|
|
16483
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
16265
16484
|
import { existsSync as existsSync13, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "node:fs";
|
|
16266
16485
|
import { join as join12, basename as basename2 } from "node:path";
|
|
16267
16486
|
import { homedir as homedir2, userInfo as userInfo2 } from "node:os";
|
|
@@ -16292,7 +16511,7 @@ var WIN_UNC_PATH_RE = /\\\\[^\\\s"'`<>()|]+\\[^\\\s"'`<>()|]+(?:\\[^\\\s"'`<>()|
|
|
|
16292
16511
|
var PRIVATE_IP_RE = /\b(?:10\.(?:\d{1,3}\.){2}\d{1,3}|172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}|169\.254\.\d{1,3}\.\d{1,3})\b/g;
|
|
16293
16512
|
var EMAIL_RE = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g;
|
|
16294
16513
|
function sha2562(raw) {
|
|
16295
|
-
return
|
|
16514
|
+
return createHash5("sha256").update(raw).digest("hex");
|
|
16296
16515
|
}
|
|
16297
16516
|
function findingDigest(opts) {
|
|
16298
16517
|
const pemContext = opts.rule === "pem-private-key" ? `\0${opts.fileDigest}\0${opts.lineNumber}\0${opts.index}` : "";
|
|
@@ -16522,7 +16741,7 @@ var PublishScanError = class extends Error {
|
|
|
16522
16741
|
};
|
|
16523
16742
|
|
|
16524
16743
|
// ../../packages/core/dist/publish.js
|
|
16525
|
-
import { createHash as
|
|
16744
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
16526
16745
|
import { existsSync as existsSync14, mkdirSync as mkdirSync8, readFileSync as readFileSync12, readdirSync as readdirSync8, rmSync as rmSync5, writeFileSync as writeFileSync8 } from "node:fs";
|
|
16527
16746
|
import { dirname as dirname7, join as join13, relative as relative3 } from "node:path";
|
|
16528
16747
|
|
|
@@ -16661,7 +16880,7 @@ ${bad.join("\n")}`);
|
|
|
16661
16880
|
return { fileCount: unsealed.files.length };
|
|
16662
16881
|
}
|
|
16663
16882
|
function sha2563(content) {
|
|
16664
|
-
return
|
|
16883
|
+
return createHash6("sha256").update(content).digest("hex");
|
|
16665
16884
|
}
|
|
16666
16885
|
function diffFiles(previous, next) {
|
|
16667
16886
|
const before = new Map(previous.map((file) => [file.relPath, sha2563(file.content)]));
|
|
@@ -17022,9 +17241,321 @@ function boundedCount(value) {
|
|
|
17022
17241
|
return Math.min(1e4, Math.max(0, Math.floor(value)));
|
|
17023
17242
|
}
|
|
17024
17243
|
|
|
17244
|
+
// ../../packages/core/dist/runtimeErrors.js
|
|
17245
|
+
import { spawnSync } from "node:child_process";
|
|
17246
|
+
import { createHash as createHash7, randomBytes as randomBytes3 } from "node:crypto";
|
|
17247
|
+
import { closeSync as closeSync2, constants, existsSync as existsSync15, fstatSync, lstatSync, mkdirSync as mkdirSync9, openSync as openSync2, readFileSync as readFileSync13, renameSync as renameSync5, rmSync as rmSync6, statSync as statSync7, writeFileSync as writeFileSync9 } from "node:fs";
|
|
17248
|
+
import { arch as hostArch, homedir as homedir3, platform as hostPlatform } from "node:os";
|
|
17249
|
+
import { dirname as dirname8, join as join14 } from "node:path";
|
|
17250
|
+
import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
|
|
17251
|
+
var RUNTIME_ERRORS_SCHEMA = "caveat.runtime_errors.v1";
|
|
17252
|
+
var STATE_VERSION = "1.0";
|
|
17253
|
+
var MAX_RECORDS = 256;
|
|
17254
|
+
var RETENTION_MS = 30 * 864e5;
|
|
17255
|
+
var MAX_CONFIG_BYTES = 64 * 1024;
|
|
17256
|
+
var definitions = {
|
|
17257
|
+
"CAVEAT.DATABASE_OPEN_FAILED": { component: "database", severity: "high", template: "Caveat database open failed" },
|
|
17258
|
+
"CAVEAT.INDEX_FAILED": { component: "index", severity: "high", template: "Caveat index operation failed" },
|
|
17259
|
+
"CAVEAT.SYNC_FAILED": { component: "sync", severity: "high", template: "Caveat own sync failed" },
|
|
17260
|
+
"CAVEAT.MCP_SERVER_FAILED": { component: "mcp", severity: "high", template: "Caveat MCP server failed" },
|
|
17261
|
+
"CAVEAT.MCP_TOOL_FAILED": { component: "mcp_tool", severity: "high", template: "Caveat MCP tool handler failed" },
|
|
17262
|
+
"CAVEAT.CLAUDE_HOOK_FAILED": { component: "claude_hook", severity: "high", template: "Caveat Claude hook failed" },
|
|
17263
|
+
"CAVEAT.CODEX_HOOK_FAILED": { component: "codex_hook", severity: "high", template: "Caveat Codex hook failed" }
|
|
17264
|
+
};
|
|
17265
|
+
function normalizeOptions(options2 = {}) {
|
|
17266
|
+
return "env" in options2 || "configPath" in options2 || "storePath" in options2 || "version" in options2 || "isWindows" in options2 ? options2 : { env: options2 };
|
|
17267
|
+
}
|
|
17268
|
+
var plain = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
17269
|
+
var exact = (v, keys) => Object.keys(v).length === keys.length && keys.every((key) => Object.hasOwn(v, key));
|
|
17270
|
+
var validTime = (v) => typeof v === "string" && Number.isFinite(Date.parse(v)) && new Date(v).toISOString() === v;
|
|
17271
|
+
var validVersion = (v) => typeof v === "string" && /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(v);
|
|
17272
|
+
var validOs = (v) => typeof v === "string" && ["darwin", "linux", "windows"].includes(v);
|
|
17273
|
+
var validArch = (v) => typeof v === "string" && ["x64", "arm64", "arm", "ia32"].includes(v);
|
|
17274
|
+
var windows = (env) => env.OS === "Windows_NT" || hostPlatform() === "win32";
|
|
17275
|
+
function defaultFactoryReporterConfigPath(env = process.env) {
|
|
17276
|
+
const home = env.HOME || env.USERPROFILE || homedir3();
|
|
17277
|
+
return windows(env) ? join14(env.LOCALAPPDATA || join14(home, "AppData", "Local"), "dotagents", "factory-reporter", "config.json") : join14(env.XDG_CONFIG_HOME || join14(home, ".config"), "dotagents", "factory-reporter.json");
|
|
17278
|
+
}
|
|
17279
|
+
function runtimeErrorsStatePath(env = process.env) {
|
|
17280
|
+
const home = env.HOME || env.USERPROFILE || homedir3();
|
|
17281
|
+
return windows(env) ? join14(env.LOCALAPPDATA || join14(home, "AppData", "Local"), "caveat", "runtime-errors.json") : join14(env.XDG_STATE_HOME || join14(home, ".local", "state"), "caveat", "runtime-errors.json");
|
|
17282
|
+
}
|
|
17283
|
+
function collectionEnabled(options2 = {}) {
|
|
17284
|
+
const env = options2.env ?? process.env;
|
|
17285
|
+
try {
|
|
17286
|
+
const path = options2.configPath ?? defaultFactoryReporterConfigPath(env);
|
|
17287
|
+
const isWin = (options2.isWindows ?? windows)(env);
|
|
17288
|
+
const before = lstatSync(path);
|
|
17289
|
+
if (!before.isFile() || before.isSymbolicLink() || before.size > MAX_CONFIG_BYTES) return false;
|
|
17290
|
+
if (isWin) secureWindowsAcl(path, options2.aclRunner);
|
|
17291
|
+
else assertPosix(before, 384);
|
|
17292
|
+
const fd = openSync2(path, constants.O_RDONLY | constants.O_NONBLOCK | (constants.O_NOFOLLOW ?? 0));
|
|
17293
|
+
let text;
|
|
17294
|
+
try {
|
|
17295
|
+
const after = fstatSync(fd);
|
|
17296
|
+
if (before.dev !== after.dev || before.ino !== after.ino || after.size > MAX_CONFIG_BYTES) return false;
|
|
17297
|
+
if (!isWin) assertPosix(after, 384);
|
|
17298
|
+
text = readFileSync13(fd, "utf8");
|
|
17299
|
+
} finally {
|
|
17300
|
+
closeSync2(fd);
|
|
17301
|
+
}
|
|
17302
|
+
const config = JSON.parse(text);
|
|
17303
|
+
return plain(config) && exact(config, ["schema_version", "host", "collection", "reporting"]) && config.schema_version === "1.0" && plain(config.host) && exact(config.host, ["id", "profile"]) && typeof config.host.id === "string" && /^[a-z0-9][a-z0-9._-]{0,63}$/.test(config.host.id) && ["server", "mac", "wsl", "windows-native"].includes(config.host.profile) && plain(config.collection) && exact(config.collection, ["enabled"]) && config.collection.enabled === true && canonicalReporting(config.reporting);
|
|
17304
|
+
} catch {
|
|
17305
|
+
return false;
|
|
17306
|
+
}
|
|
17307
|
+
}
|
|
17308
|
+
var empty = () => ({ schema: RUNTIME_ERRORS_SCHEMA, next_sequence: 1, acknowledged_through: 0, records: [] });
|
|
17309
|
+
function fingerprint(code) {
|
|
17310
|
+
const d = definitions[code];
|
|
17311
|
+
return createHash7("sha256").update(`caveat\0${d.component}\0${code}\0${d.template}`).digest("hex");
|
|
17312
|
+
}
|
|
17313
|
+
function ensureSafeDir(dir, isWin, options2 = {}) {
|
|
17314
|
+
const existed = existsSync15(dir);
|
|
17315
|
+
mkdirSync9(dir, { recursive: true, mode: 448 });
|
|
17316
|
+
const s = lstatSync(dir);
|
|
17317
|
+
if (!s.isDirectory() || s.isSymbolicLink()) throw Error("store_unsafe");
|
|
17318
|
+
if (isWin) secureWindowsAcl(dir, options2.aclRunner, true, !existed);
|
|
17319
|
+
else assertPosix(s, 448);
|
|
17320
|
+
}
|
|
17321
|
+
function canonicalReporting(value) {
|
|
17322
|
+
if (!plain(value) || !Object.keys(value).every((key) => ["enabled", "endpoint", "credential_file"].includes(key)) || typeof value.enabled !== "boolean") return false;
|
|
17323
|
+
if (value.endpoint !== void 0) {
|
|
17324
|
+
if (typeof value.endpoint !== "string" || value.endpoint.length > 2048) return false;
|
|
17325
|
+
try {
|
|
17326
|
+
if (!["http:", "https:"].includes(new URL(value.endpoint).protocol)) return false;
|
|
17327
|
+
} catch {
|
|
17328
|
+
return false;
|
|
17329
|
+
}
|
|
17330
|
+
}
|
|
17331
|
+
if (value.credential_file !== void 0 && (typeof value.credential_file !== "string" || value.credential_file.length < 1 || value.credential_file.length > 4096)) return false;
|
|
17332
|
+
return !value.enabled || value.endpoint !== void 0 && value.credential_file !== void 0;
|
|
17333
|
+
}
|
|
17334
|
+
var WINDOWS_ACL_VERIFY = String.raw`$p=$env:CAVEAT_ACL_PATH;$isDir=$env:CAVEAT_ACL_DIRECTORY -eq '1';$sid=[System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value;$acl=if($isDir){[System.IO.Directory]::GetAccessControl($p)}else{[System.IO.File]::GetAccessControl($p)};$owner=$acl.GetOwner([System.Security.Principal.SecurityIdentifier]).Value;if($owner -ne $sid){exit 41};$rules=@($acl.GetAccessRules($true,$true,[System.Security.Principal.SecurityIdentifier]));if($rules.Count -ne 1){exit 42};$r=$rules[0];if($r.IdentityReference.Value -ne $sid -or $r.AccessControlType -ne 'Allow' -or $r.IsInherited -or ($r.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::FullControl) -ne [System.Security.AccessControl.FileSystemRights]::FullControl){exit 43}`;
|
|
17335
|
+
var WINDOWS_ACL_APPLY = String.raw`$p=$env:CAVEAT_ACL_PATH;$isDir=$env:CAVEAT_ACL_DIRECTORY -eq '1';$sid=[System.Security.Principal.WindowsIdentity]::GetCurrent().User;$acl=if($isDir){New-Object System.Security.AccessControl.DirectorySecurity}else{New-Object System.Security.AccessControl.FileSecurity};$acl.SetAccessRuleProtection($true,$false);$flags=if($isDir){[System.Security.AccessControl.InheritanceFlags]'ContainerInherit, ObjectInherit'}else{[System.Security.AccessControl.InheritanceFlags]::None};$rule=New-Object System.Security.AccessControl.FileSystemAccessRule($sid,'FullControl',$flags,[System.Security.AccessControl.PropagationFlags]::None,[System.Security.AccessControl.AccessControlType]::Allow);$acl.SetOwner($sid);$acl.AddAccessRule($rule);if($isDir){[System.IO.Directory]::SetAccessControl($p,$acl)}else{[System.IO.File]::SetAccessControl($p,$acl)};` + WINDOWS_ACL_VERIFY;
|
|
17336
|
+
function runWindowsAcl(path, directory, apply) {
|
|
17337
|
+
const result = spawnSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", apply ? WINDOWS_ACL_APPLY : WINDOWS_ACL_VERIFY], { env: { ...process.env, CAVEAT_ACL_PATH: path, CAVEAT_ACL_DIRECTORY: directory ? "1" : "0" }, stdio: "ignore", timeout: 3e3, windowsHide: true });
|
|
17338
|
+
if (result.status !== 0) throw Error("store_unsafe");
|
|
17339
|
+
}
|
|
17340
|
+
function secureWindowsAcl(path, runner, directory = false, apply = false) {
|
|
17341
|
+
try {
|
|
17342
|
+
(runner ?? runWindowsAcl)(path, directory, apply);
|
|
17343
|
+
} catch {
|
|
17344
|
+
throw Error("store_unsafe");
|
|
17345
|
+
}
|
|
17346
|
+
}
|
|
17347
|
+
function assertPosix(info, mode) {
|
|
17348
|
+
if ((info.mode & 511) !== mode || typeof process.getuid === "function" && info.uid !== process.getuid()) throw Error("store_unsafe");
|
|
17349
|
+
}
|
|
17350
|
+
function ensureSafeFile(path, isWin, options2 = {}) {
|
|
17351
|
+
const s = lstatSync(path);
|
|
17352
|
+
if (!s.isFile() || s.isSymbolicLink()) throw Error("store_unsafe");
|
|
17353
|
+
if (isWin) secureWindowsAcl(path, options2.aclRunner);
|
|
17354
|
+
else assertPosix(statSync7(path), 384);
|
|
17355
|
+
}
|
|
17356
|
+
function validate(store) {
|
|
17357
|
+
if (!plain(store) || !exact(store, ["schema", "next_sequence", "acknowledged_through", "records"])) throw Error("state_invalid");
|
|
17358
|
+
const checked = store;
|
|
17359
|
+
if (checked.schema !== RUNTIME_ERRORS_SCHEMA || !Number.isSafeInteger(checked.next_sequence) || checked.next_sequence < 1 || !Number.isSafeInteger(checked.acknowledged_through) || checked.acknowledged_through < 0 || checked.acknowledged_through >= checked.next_sequence || !Array.isArray(checked.records) || checked.records.length > MAX_RECORDS) throw Error("state_invalid");
|
|
17360
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17361
|
+
let previous = 0;
|
|
17362
|
+
for (const record of checked.records) {
|
|
17363
|
+
if (!plain(record) || !exact(record, ["product", "product_version", "component", "error_code", "message_template", "severity", "fingerprint", "count", "first_seen", "last_seen", "state_schema_version", "os", "arch", "status", "resolved_at", "reason_code", "sequence"])) throw Error("state_invalid");
|
|
17364
|
+
const code = typeof record.error_code === "string" ? record.error_code : void 0;
|
|
17365
|
+
const d = code && definitions[code];
|
|
17366
|
+
if (!d || record.product !== "caveat" || !validVersion(record.product_version) || record.component !== d.component || record.message_template !== d.template || record.severity !== d.severity || record.fingerprint !== fingerprint(code) || seen.has(record.fingerprint) || !Number.isSafeInteger(record.count) || record.count < 1 || !validTime(record.first_seen) || !validTime(record.last_seen) || Date.parse(record.first_seen) > Date.parse(record.last_seen) || record.state_schema_version !== STATE_VERSION || !validOs(record.os) || !validArch(record.arch) || !Number.isSafeInteger(record.sequence) || record.sequence <= previous || record.sequence >= checked.next_sequence || !["open", "resolved"].includes(record.status) || record.status === "open" && (record.resolved_at !== null || record.reason_code !== null) || record.status === "resolved" && (typeof record.resolved_at !== "string" || !validTime(record.resolved_at) || Date.parse(record.resolved_at) < Date.parse(record.last_seen) || record.reason_code !== "operator_resolved")) throw Error("state_invalid");
|
|
17367
|
+
seen.add(record.fingerprint);
|
|
17368
|
+
previous = record.sequence;
|
|
17369
|
+
}
|
|
17370
|
+
}
|
|
17371
|
+
function readStore(path, isWin, options2 = {}) {
|
|
17372
|
+
if (!existsSync15(path)) return empty();
|
|
17373
|
+
ensureSafeFile(path, isWin, options2);
|
|
17374
|
+
const value = JSON.parse(readFileSync13(path, "utf8"));
|
|
17375
|
+
validate(value);
|
|
17376
|
+
return value;
|
|
17377
|
+
}
|
|
17378
|
+
function lock(path, isWin, fn, options2 = {}) {
|
|
17379
|
+
ensureSafeDir(dirname8(path), isWin, options2);
|
|
17380
|
+
const lockPath2 = `${path}.lock.sqlite`;
|
|
17381
|
+
let created = false;
|
|
17382
|
+
try {
|
|
17383
|
+
writeFileSync9(lockPath2, "", { mode: 384, flag: "wx" });
|
|
17384
|
+
created = true;
|
|
17385
|
+
} catch (error) {
|
|
17386
|
+
if (!plain(error) || error.code !== "EEXIST") throw error;
|
|
17387
|
+
}
|
|
17388
|
+
if (created) {
|
|
17389
|
+
if (isWin) secureWindowsAcl(lockPath2, options2.aclRunner, false, true);
|
|
17390
|
+
else assertPosix(statSync7(lockPath2), 384);
|
|
17391
|
+
} else ensureSafeFile(lockPath2, isWin, options2);
|
|
17392
|
+
const db = new DatabaseSync3(lockPath2);
|
|
17393
|
+
let begun = false;
|
|
17394
|
+
try {
|
|
17395
|
+
ensureSafeFile(lockPath2, isWin, options2);
|
|
17396
|
+
db.exec("PRAGMA busy_timeout=5000; PRAGMA synchronous=FULL; BEGIN IMMEDIATE");
|
|
17397
|
+
begun = true;
|
|
17398
|
+
const result = fn();
|
|
17399
|
+
db.exec("COMMIT");
|
|
17400
|
+
begun = false;
|
|
17401
|
+
return result;
|
|
17402
|
+
} finally {
|
|
17403
|
+
if (begun) try {
|
|
17404
|
+
db.exec("ROLLBACK");
|
|
17405
|
+
} catch {
|
|
17406
|
+
}
|
|
17407
|
+
db.close();
|
|
17408
|
+
}
|
|
17409
|
+
}
|
|
17410
|
+
function writeStore(path, store, isWin, options2 = {}) {
|
|
17411
|
+
validate(store);
|
|
17412
|
+
ensureSafeDir(dirname8(path), isWin, options2);
|
|
17413
|
+
const temporary = join14(dirname8(path), `.runtime-errors-${process.pid}-${randomBytes3(6).toString("hex")}`);
|
|
17414
|
+
try {
|
|
17415
|
+
writeFileSync9(temporary, `${JSON.stringify(store)}
|
|
17416
|
+
`, { mode: 384, flag: "wx" });
|
|
17417
|
+
if (isWin) secureWindowsAcl(temporary, options2.aclRunner, false, true);
|
|
17418
|
+
else assertPosix(statSync7(temporary), 384);
|
|
17419
|
+
renameSync5(temporary, path);
|
|
17420
|
+
ensureSafeFile(path, isWin, options2);
|
|
17421
|
+
} finally {
|
|
17422
|
+
rmSync6(temporary, { force: true });
|
|
17423
|
+
}
|
|
17424
|
+
}
|
|
17425
|
+
function now(options2) {
|
|
17426
|
+
const value = options2.now ? new Date(options2.now) : /* @__PURE__ */ new Date();
|
|
17427
|
+
if (Number.isNaN(value.valueOf())) throw Error("invalid_time");
|
|
17428
|
+
return value.toISOString();
|
|
17429
|
+
}
|
|
17430
|
+
function normalizeOs(value) {
|
|
17431
|
+
return value === "win32" ? "windows" : value;
|
|
17432
|
+
}
|
|
17433
|
+
function optionsFor(options2) {
|
|
17434
|
+
const env = options2.env ?? process.env;
|
|
17435
|
+
const isWin = (options2.isWindows ?? windows)(env);
|
|
17436
|
+
return { env, isWin, path: options2.storePath ?? runtimeErrorsStatePath(env) };
|
|
17437
|
+
}
|
|
17438
|
+
function requireCursor(value) {
|
|
17439
|
+
if (!Number.isSafeInteger(value) || value < 0) throw Error("invalid_cursor");
|
|
17440
|
+
}
|
|
17441
|
+
function requireLimit(value) {
|
|
17442
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > MAX_RECORDS) throw Error("invalid_limit");
|
|
17443
|
+
}
|
|
17444
|
+
function snapshot(options2 = {}) {
|
|
17445
|
+
const afterCursor = options2.afterCursor ?? 0, limit = options2.limit ?? MAX_RECORDS;
|
|
17446
|
+
requireCursor(afterCursor);
|
|
17447
|
+
requireLimit(limit);
|
|
17448
|
+
const enabled = collectionEnabled(options2);
|
|
17449
|
+
const { path, isWin } = optionsFor(options2);
|
|
17450
|
+
const store = enabled ? readStore(path, isWin, options2) : empty();
|
|
17451
|
+
if (afterCursor > store.next_sequence - 1) throw Error("invalid_cursor");
|
|
17452
|
+
const all = store.records.filter((r2) => r2.sequence > afterCursor);
|
|
17453
|
+
const rows = all.slice(0, limit);
|
|
17454
|
+
return { schema: RUNTIME_ERRORS_SCHEMA, product: "caveat", version: options2.version ?? "unknown", state_schema_version: STATE_VERSION, cursor: { high_watermark: store.next_sequence - 1, acknowledged_through: store.acknowledged_through, next: rows.at(-1)?.sequence ?? afterCursor }, runtime_errors: rows.filter((r2) => r2.status === "open").map(({ error_code, component, status, severity, fingerprint: fingerprint22, message_template, count, first_seen, last_seen, state_schema_version }) => ({ error_code, component, status, severity, fingerprint: fingerprint22, message_template, occurrence_count: count, first_seen, last_seen, state_schema_version })), resolutions: rows.filter((r2) => r2.status === "resolved").map(({ fingerprint: fingerprint22, resolved_at, reason_code }) => ({ fingerprint: fingerprint22, resolved_at, reason_code })), diagnostics: { collection: enabled ? "enabled" : "disabled", status: enabled ? "ready" : "not_applicable", total_count: store.records.length, pending_count: store.records.filter((r2) => r2.sequence > store.acknowledged_through).length, truncated: all.length > rows.length } };
|
|
17455
|
+
}
|
|
17456
|
+
function runtimeErrorsDiagnostics(options2 = {}) {
|
|
17457
|
+
if (!collectionEnabled(options2)) return { schema: "caveat.runtime_error_diagnostics.v1", collection: "disabled", status: "not_applicable", total_count: 0, open_count: 0, pending_count: 0, high_watermark: 0, acknowledged_through: 0 };
|
|
17458
|
+
try {
|
|
17459
|
+
const { path, isWin } = optionsFor(options2);
|
|
17460
|
+
const store = readStore(path, isWin, options2);
|
|
17461
|
+
return { schema: "caveat.runtime_error_diagnostics.v1", collection: "enabled", status: "ready", total_count: store.records.length, open_count: store.records.filter((record) => record.status === "open").length, pending_count: store.records.filter((record) => record.sequence > store.acknowledged_through).length, high_watermark: store.next_sequence - 1, acknowledged_through: store.acknowledged_through };
|
|
17462
|
+
} catch {
|
|
17463
|
+
return { schema: "caveat.runtime_error_diagnostics.v1", collection: "enabled", status: "unavailable", total_count: 0, open_count: 0, pending_count: 0, high_watermark: 0, acknowledged_through: 0 };
|
|
17464
|
+
}
|
|
17465
|
+
}
|
|
17466
|
+
function recordRuntimeError(code, options2 = {}) {
|
|
17467
|
+
if (!collectionEnabled(options2)) return { status: "disabled" };
|
|
17468
|
+
const { path, isWin } = optionsFor(options2);
|
|
17469
|
+
return lock(path, isWin, () => {
|
|
17470
|
+
const store = readStore(path, isWin, options2);
|
|
17471
|
+
const definition = definitions[code];
|
|
17472
|
+
if (!definition) throw Error("unknown_runtime_code");
|
|
17473
|
+
const key = fingerprint(code);
|
|
17474
|
+
const sequence = store.next_sequence++;
|
|
17475
|
+
const time = now(options2);
|
|
17476
|
+
const existing = store.records.find((r2) => r2.fingerprint === key);
|
|
17477
|
+
const version = options2.version ?? "0.0.0";
|
|
17478
|
+
const os = normalizeOs(options2.os ?? hostPlatform());
|
|
17479
|
+
const arch = options2.arch ?? hostArch();
|
|
17480
|
+
if (!validVersion(version) || !validOs(os) || !validArch(arch)) throw Error("invalid_runtime_metadata");
|
|
17481
|
+
if (existing) {
|
|
17482
|
+
existing.product_version = version;
|
|
17483
|
+
existing.os = os;
|
|
17484
|
+
existing.arch = arch;
|
|
17485
|
+
existing.count += 1;
|
|
17486
|
+
existing.last_seen = time;
|
|
17487
|
+
existing.sequence = sequence;
|
|
17488
|
+
existing.status = "open";
|
|
17489
|
+
existing.resolved_at = null;
|
|
17490
|
+
existing.reason_code = null;
|
|
17491
|
+
} else {
|
|
17492
|
+
if (store.records.length >= MAX_RECORDS) throw Error("store_overflow");
|
|
17493
|
+
store.records.push({ product: "caveat", product_version: version, component: definition.component, error_code: code, message_template: definition.template, severity: definition.severity, fingerprint: key, count: 1, first_seen: time, last_seen: time, state_schema_version: STATE_VERSION, os, arch, status: "open", resolved_at: null, reason_code: null, sequence });
|
|
17494
|
+
}
|
|
17495
|
+
store.records.sort((a, b2) => a.sequence - b2.sequence);
|
|
17496
|
+
writeStore(path, store, isWin, options2);
|
|
17497
|
+
return { status: "recorded", fingerprint: key, sequence };
|
|
17498
|
+
}, options2);
|
|
17499
|
+
}
|
|
17500
|
+
function observeRuntimeError(code, options2 = {}) {
|
|
17501
|
+
try {
|
|
17502
|
+
recordRuntimeError(code, options2);
|
|
17503
|
+
} catch {
|
|
17504
|
+
try {
|
|
17505
|
+
process.stderr.write("[caveat:runtime-errors] store_unavailable\n");
|
|
17506
|
+
} catch {
|
|
17507
|
+
}
|
|
17508
|
+
}
|
|
17509
|
+
}
|
|
17510
|
+
var runtimeErrorsSnapshot = (afterCursor = 0, limit = MAX_RECORDS, options2 = {}) => snapshot({ ...normalizeOptions(options2), afterCursor, limit });
|
|
17511
|
+
function acknowledgeRuntimeErrors(cursor, options2 = {}) {
|
|
17512
|
+
const normalized = normalizeOptions(options2);
|
|
17513
|
+
requireCursor(cursor);
|
|
17514
|
+
if (!collectionEnabled(normalized)) return snapshot({ ...normalized, afterCursor: cursor });
|
|
17515
|
+
const { path, isWin } = optionsFor(normalized);
|
|
17516
|
+
lock(path, isWin, () => {
|
|
17517
|
+
const store = readStore(path, isWin, normalized);
|
|
17518
|
+
if (cursor >= store.next_sequence) throw Error("invalid_cursor");
|
|
17519
|
+
store.acknowledged_through = Math.max(store.acknowledged_through, cursor);
|
|
17520
|
+
writeStore(path, store, isWin, normalized);
|
|
17521
|
+
}, normalized);
|
|
17522
|
+
return snapshot(normalized);
|
|
17523
|
+
}
|
|
17524
|
+
function setRuntimeErrorStatus(fingerprintValue, status, options2 = {}) {
|
|
17525
|
+
const normalized = normalizeOptions(options2);
|
|
17526
|
+
if (!/^[0-9a-f]{64}$/.test(fingerprintValue)) throw Error("invalid_fingerprint");
|
|
17527
|
+
if (!collectionEnabled(normalized)) return snapshot(normalized);
|
|
17528
|
+
const { path, isWin } = optionsFor(normalized);
|
|
17529
|
+
lock(path, isWin, () => {
|
|
17530
|
+
const store = readStore(path, isWin, normalized);
|
|
17531
|
+
const record = store.records.find((r2) => r2.fingerprint === fingerprintValue);
|
|
17532
|
+
if (!record) throw Error("fingerprint_not_found");
|
|
17533
|
+
if (record.status === status) return;
|
|
17534
|
+
record.status = status;
|
|
17535
|
+
record.resolved_at = status === "resolved" ? now(normalized) : null;
|
|
17536
|
+
record.reason_code = status === "resolved" ? "operator_resolved" : null;
|
|
17537
|
+
record.sequence = store.next_sequence++;
|
|
17538
|
+
store.records.sort((a, b2) => a.sequence - b2.sequence);
|
|
17539
|
+
writeStore(path, store, isWin, normalized);
|
|
17540
|
+
}, normalized);
|
|
17541
|
+
return snapshot(normalized);
|
|
17542
|
+
}
|
|
17543
|
+
function compactRuntimeErrors(options2 = {}) {
|
|
17544
|
+
const normalized = normalizeOptions(options2);
|
|
17545
|
+
if (!collectionEnabled(normalized)) return snapshot(normalized);
|
|
17546
|
+
const { path, isWin } = optionsFor(normalized);
|
|
17547
|
+
lock(path, isWin, () => {
|
|
17548
|
+
const store = readStore(path, isWin, normalized);
|
|
17549
|
+
const cutoff = Date.parse(now(normalized)) - RETENTION_MS;
|
|
17550
|
+
store.records = store.records.filter((record) => !(record.status === "resolved" && record.sequence <= store.acknowledged_through && record.resolved_at !== null && Date.parse(record.resolved_at) <= cutoff));
|
|
17551
|
+
writeStore(path, store, isWin, normalized);
|
|
17552
|
+
}, normalized);
|
|
17553
|
+
return snapshot(normalized);
|
|
17554
|
+
}
|
|
17555
|
+
|
|
17025
17556
|
// ../../packages/core/dist/env.js
|
|
17026
17557
|
var import_semver = __toESM(require_semver2(), 1);
|
|
17027
|
-
function
|
|
17558
|
+
function fingerprint2() {
|
|
17028
17559
|
return {
|
|
17029
17560
|
os: process.platform,
|
|
17030
17561
|
arch: process.arch,
|
|
@@ -17033,16 +17564,16 @@ function fingerprint() {
|
|
|
17033
17564
|
}
|
|
17034
17565
|
|
|
17035
17566
|
// ../../packages/core/dist/id.js
|
|
17036
|
-
import { randomBytes as
|
|
17567
|
+
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
17037
17568
|
function randomHex(hexChars) {
|
|
17038
17569
|
const bytes = Math.ceil(hexChars / 2);
|
|
17039
|
-
return
|
|
17570
|
+
return randomBytes4(bytes).toString("hex").slice(0, hexChars);
|
|
17040
17571
|
}
|
|
17041
|
-
function slugify(title,
|
|
17572
|
+
function slugify(title, now2 = () => /* @__PURE__ */ new Date()) {
|
|
17042
17573
|
const lowered = title.toLowerCase();
|
|
17043
17574
|
const sluggy = lowered.replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
17044
17575
|
if (!sluggy || !/^[a-z0-9]/.test(sluggy)) {
|
|
17045
|
-
const d =
|
|
17576
|
+
const d = now2();
|
|
17046
17577
|
const yyyy = d.getUTCFullYear().toString().padStart(4, "0");
|
|
17047
17578
|
const mm = (d.getUTCMonth() + 1).toString().padStart(2, "0");
|
|
17048
17579
|
const dd = d.getUTCDate().toString().padStart(2, "0");
|
|
@@ -17056,13 +17587,13 @@ function resolveCollision(baseId, exists2) {
|
|
|
17056
17587
|
while (exists2(`${baseId}-${n}`)) n++;
|
|
17057
17588
|
return `${baseId}-${n}`;
|
|
17058
17589
|
}
|
|
17059
|
-
function generateSourceSession(
|
|
17060
|
-
return `${
|
|
17590
|
+
function generateSourceSession(now2 = () => /* @__PURE__ */ new Date()) {
|
|
17591
|
+
return `${now2().toISOString()}/${randomHex(12)}`;
|
|
17061
17592
|
}
|
|
17062
17593
|
|
|
17063
17594
|
// ../../packages/core/dist/writer.js
|
|
17064
|
-
import { existsSync as
|
|
17065
|
-
import { dirname as
|
|
17595
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "node:fs";
|
|
17596
|
+
import { dirname as dirname9 } from "node:path";
|
|
17066
17597
|
function buildEntry(frontmatter, sections) {
|
|
17067
17598
|
const bodyParts = [];
|
|
17068
17599
|
for (const [heading, content2] of Object.entries(sections)) {
|
|
@@ -17080,24 +17611,24 @@ ${body}${body ? "\n" : ""}`;
|
|
|
17080
17611
|
return { content, body };
|
|
17081
17612
|
}
|
|
17082
17613
|
function writeEntryFile(filePath, content) {
|
|
17083
|
-
const dir =
|
|
17084
|
-
if (!
|
|
17085
|
-
|
|
17614
|
+
const dir = dirname9(filePath);
|
|
17615
|
+
if (!existsSync16(dir)) mkdirSync10(dir, { recursive: true });
|
|
17616
|
+
writeFileSync10(filePath, content, "utf-8");
|
|
17086
17617
|
}
|
|
17087
17618
|
|
|
17088
17619
|
// ../../packages/core/dist/record.js
|
|
17089
|
-
import { statSync as
|
|
17090
|
-
import { join as
|
|
17620
|
+
import { statSync as statSync8 } from "node:fs";
|
|
17621
|
+
import { join as join15 } from "node:path";
|
|
17091
17622
|
var DEFAULT_CATEGORY = "misc";
|
|
17092
17623
|
function recordEntry(input, opts) {
|
|
17093
|
-
const
|
|
17624
|
+
const now2 = opts.now ?? (() => /* @__PURE__ */ new Date());
|
|
17094
17625
|
const source = opts.source ?? "own";
|
|
17095
|
-
const nowDate =
|
|
17626
|
+
const nowDate = now2();
|
|
17096
17627
|
const ymd = formatYmd(nowDate);
|
|
17097
|
-
const baseId = input.id ?? slugify(input.title,
|
|
17628
|
+
const baseId = input.id ?? slugify(input.title, now2);
|
|
17098
17629
|
const id = resolveCollision(baseId, (candidate) => entryExists(opts.db, source, candidate));
|
|
17099
17630
|
const mergedEnv = {
|
|
17100
|
-
...
|
|
17631
|
+
...fingerprint2(),
|
|
17101
17632
|
...input.environment ?? {}
|
|
17102
17633
|
};
|
|
17103
17634
|
const frontmatter = {
|
|
@@ -17109,7 +17640,7 @@ function recordEntry(input, opts) {
|
|
|
17109
17640
|
tags: input.tags ?? [],
|
|
17110
17641
|
environment: mergedEnv,
|
|
17111
17642
|
source_project: null,
|
|
17112
|
-
source_session: generateSourceSession(
|
|
17643
|
+
source_session: generateSourceSession(now2),
|
|
17113
17644
|
created_at: ymd,
|
|
17114
17645
|
updated_at: ymd,
|
|
17115
17646
|
last_verified: ymd
|
|
@@ -17123,9 +17654,9 @@ function recordEntry(input, opts) {
|
|
|
17123
17654
|
const built = buildEntry(frontmatter, sections);
|
|
17124
17655
|
const category = input.category ?? DEFAULT_CATEGORY;
|
|
17125
17656
|
const relPath = `${category}/${id}.md`;
|
|
17126
|
-
const filePath =
|
|
17657
|
+
const filePath = join15(opts.entriesRoot, relPath);
|
|
17127
17658
|
writeEntryFile(filePath, built.content);
|
|
17128
|
-
const stat =
|
|
17659
|
+
const stat = statSync8(filePath);
|
|
17129
17660
|
upsertEntry(opts.db, {
|
|
17130
17661
|
id,
|
|
17131
17662
|
source,
|
|
@@ -17153,8 +17684,8 @@ function formatYmd(d) {
|
|
|
17153
17684
|
}
|
|
17154
17685
|
|
|
17155
17686
|
// ../../packages/core/dist/update.js
|
|
17156
|
-
import { readFileSync as
|
|
17157
|
-
import { join as
|
|
17687
|
+
import { readFileSync as readFileSync14, statSync as statSync9, writeFileSync as writeFileSync11 } from "node:fs";
|
|
17688
|
+
import { join as join16 } from "node:path";
|
|
17158
17689
|
var IMMUTABLE_KEYS = /* @__PURE__ */ new Set([
|
|
17159
17690
|
"id",
|
|
17160
17691
|
"created_at",
|
|
@@ -17166,15 +17697,15 @@ function updateEntry(id, patch, opts) {
|
|
|
17166
17697
|
if (source !== "own") {
|
|
17167
17698
|
throw new Error("community \u30A8\u30F3\u30C8\u30EA\u306F\u8CFC\u8AAD\u7269\u3067\u3059; \u7DE8\u96C6\u306F\u4E0A\u6D41\u3067\u884C\u3063\u3066\u304F\u3060\u3055\u3044");
|
|
17168
17699
|
}
|
|
17169
|
-
const
|
|
17170
|
-
const nowDate =
|
|
17700
|
+
const now2 = opts.now ?? (() => /* @__PURE__ */ new Date());
|
|
17701
|
+
const nowDate = now2();
|
|
17171
17702
|
const row = opts.db.prepare("SELECT path FROM entries WHERE source = ? AND id = ?").get(source, id);
|
|
17172
17703
|
if (!row) {
|
|
17173
17704
|
throw new Error(`caveat not found: id=${id} source=${source}`);
|
|
17174
17705
|
}
|
|
17175
17706
|
const relPath = row.path;
|
|
17176
|
-
const filePath =
|
|
17177
|
-
const raw =
|
|
17707
|
+
const filePath = join16(opts.entriesRoot, relPath);
|
|
17708
|
+
const raw = readFileSync14(filePath, "utf-8");
|
|
17178
17709
|
const parsed = parseMarkdown(raw);
|
|
17179
17710
|
if (patch.frontmatter) {
|
|
17180
17711
|
for (const key of Object.keys(patch.frontmatter)) {
|
|
@@ -17215,8 +17746,8 @@ function updateEntry(id, patch, opts) {
|
|
|
17215
17746
|
}
|
|
17216
17747
|
}
|
|
17217
17748
|
const built = buildEntry(mergedFrontmatter, mergedSections);
|
|
17218
|
-
|
|
17219
|
-
const stat =
|
|
17749
|
+
writeFileSync11(filePath, built.content, "utf-8");
|
|
17750
|
+
const stat = statSync9(filePath);
|
|
17220
17751
|
upsertEntry(opts.db, {
|
|
17221
17752
|
id,
|
|
17222
17753
|
source,
|
|
@@ -17240,15 +17771,15 @@ function formatYmd2(d) {
|
|
|
17240
17771
|
}
|
|
17241
17772
|
|
|
17242
17773
|
// ../../packages/core/dist/proposalEval.js
|
|
17243
|
-
import { createHash as
|
|
17774
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
17244
17775
|
import { isAbsolute as isAbsolute2, relative as relative4, resolve as resolve4, sep } from "node:path";
|
|
17245
17776
|
|
|
17246
17777
|
// ../../packages/core/dist/proposalExecution.js
|
|
17247
|
-
import { createHash as
|
|
17778
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
17248
17779
|
import { basename as basename3, isAbsolute as isAbsolute3 } from "node:path";
|
|
17249
17780
|
|
|
17250
17781
|
// ../../packages/core/dist/proposalExecutionCompiler.js
|
|
17251
|
-
import { createHash as
|
|
17782
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
17252
17783
|
|
|
17253
17784
|
export {
|
|
17254
17785
|
__commonJS,
|
|
@@ -17268,11 +17799,11 @@ export {
|
|
|
17268
17799
|
communityPull,
|
|
17269
17800
|
communityList,
|
|
17270
17801
|
communityRemove,
|
|
17271
|
-
|
|
17802
|
+
buildPendingSemanticKey,
|
|
17803
|
+
buildAndPublishPendingReminder,
|
|
17272
17804
|
cleanupStalePendingDirs,
|
|
17273
17805
|
maybeSweepPendingDirs,
|
|
17274
|
-
|
|
17275
|
-
drainGlobalPendingReminders,
|
|
17806
|
+
drainPendingRemindersDetailed,
|
|
17276
17807
|
createKeyserverKeyProvider,
|
|
17277
17808
|
SyncError,
|
|
17278
17809
|
syncOwn,
|
|
@@ -17293,7 +17824,8 @@ export {
|
|
|
17293
17824
|
ensureUserConfig,
|
|
17294
17825
|
writeUserConfigPatch,
|
|
17295
17826
|
defaultSelfIdentityTokens,
|
|
17296
|
-
|
|
17827
|
+
findCaveatsForHook,
|
|
17828
|
+
findCaveatsForHookSegments,
|
|
17297
17829
|
toolErrorReminderText,
|
|
17298
17830
|
userPromptSubmitReminderText,
|
|
17299
17831
|
stopReminderText,
|
|
@@ -17311,7 +17843,13 @@ export {
|
|
|
17311
17843
|
decideCodexSidecarExecution,
|
|
17312
17844
|
buildCodexSidecarDiagnosticsCommand,
|
|
17313
17845
|
buildCodexSidecarReadOnlySmokeCommand,
|
|
17314
|
-
buildCodexSidecarRunCommand
|
|
17846
|
+
buildCodexSidecarRunCommand,
|
|
17847
|
+
runtimeErrorsDiagnostics,
|
|
17848
|
+
observeRuntimeError,
|
|
17849
|
+
runtimeErrorsSnapshot,
|
|
17850
|
+
acknowledgeRuntimeErrors,
|
|
17851
|
+
setRuntimeErrorStatus,
|
|
17852
|
+
compactRuntimeErrors
|
|
17315
17853
|
};
|
|
17316
17854
|
/*! Bundled license information:
|
|
17317
17855
|
|
|
@@ -17334,4 +17872,4 @@ strip-bom-string/index.js:
|
|
|
17334
17872
|
js-yaml/dist/js-yaml.mjs:
|
|
17335
17873
|
(*! js-yaml 4.1.1 https://github.com/nodeca/js-yaml @license MIT *)
|
|
17336
17874
|
*/
|
|
17337
|
-
//# sourceMappingURL=chunk-
|
|
17875
|
+
//# sourceMappingURL=chunk-PD5E6TFL.js.map
|