@triedotdev/mcp 1.0.166 → 1.0.167
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 +337 -801
- package/dist/chunk-2HF65EHQ.js +311 -0
- package/dist/chunk-2HF65EHQ.js.map +1 -0
- package/dist/{chunk-JNUOW2JS.js → chunk-4MXH2ZPT.js} +12 -12
- package/dist/chunk-4MXH2ZPT.js.map +1 -0
- package/dist/{chunk-LR5M4RTN.js → chunk-575YT2SD.js} +1 -1
- package/dist/chunk-575YT2SD.js.map +1 -0
- package/dist/{chunk-ZKKKLRZZ.js → chunk-5BRRRTN6.js} +4 -4
- package/dist/{chunk-TQOO6A4G.js → chunk-7WITSO22.js} +3 -3
- package/dist/{chunk-ACU2RJUJ.js → chunk-F6WFNUAY.js} +2 -2
- package/dist/{chunk-VR4VWXXU.js → chunk-G2TGF6TR.js} +9 -2
- package/dist/chunk-G2TGF6TR.js.map +1 -0
- package/dist/{chunk-ZBXW244P.js → chunk-HVCDY3AK.js} +3 -3
- package/dist/chunk-HVCDY3AK.js.map +1 -0
- package/dist/{chunk-HOGKPDZA.js → chunk-LQIMKE3P.js} +678 -151
- package/dist/chunk-LQIMKE3P.js.map +1 -0
- package/dist/{chunk-2Z3TQNNK.js → chunk-MRHKX5M5.js} +3 -3
- package/dist/{chunk-OLNZJ3XV.js → chunk-Q63FFI6D.js} +2 -2
- package/dist/{chunk-S36IO3EE.js → chunk-XE6KQRKZ.js} +9 -8
- package/dist/chunk-XE6KQRKZ.js.map +1 -0
- package/dist/{chunk-GDWA3CH3.js → chunk-XPZZFPBZ.js} +30 -6
- package/dist/chunk-XPZZFPBZ.js.map +1 -0
- package/dist/{chunk-JEZ7XJQN.js → chunk-XTFWT2XM.js} +2 -2
- package/dist/{chunk-UXRW2YSP.js → chunk-YDHUCDHM.js} +18 -112
- package/dist/chunk-YDHUCDHM.js.map +1 -0
- package/dist/{chunk-LG5CBK6A.js → chunk-YZ6Y2H3P.js} +21 -196
- package/dist/chunk-YZ6Y2H3P.js.map +1 -0
- package/dist/{chunk-MVVPJ73K.js → chunk-ZJF5FTBX.js} +126 -358
- package/dist/chunk-ZJF5FTBX.js.map +1 -0
- package/dist/cli/create-agent.js +1 -1
- package/dist/cli/create-agent.js.map +1 -1
- package/dist/cli/main.js +194 -849
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +15 -14
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/{fast-analyzer-NJQO3TFD.js → fast-analyzer-XXYMOXRK.js} +3 -3
- package/dist/git-EO5SRFMN.js +28 -0
- package/dist/{github-ingester-TFBDUDIY.js → github-ingester-ZOKK6GRS.js} +3 -3
- package/dist/{goal-manager-DVX24UPZ.js → goal-manager-YOB7VWK7.js} +5 -4
- package/dist/{goal-validator-6Y5CDEMJ.js → goal-validator-ULKIBDPX.js} +5 -4
- package/dist/{hypothesis-UKPGOYY2.js → hypothesis-7BFFT5JY.js} +5 -4
- package/dist/index.js +19 -18
- package/dist/index.js.map +1 -1
- package/dist/{issue-store-UZAPI5DU.js → issue-store-ZIRP23EP.js} +4 -3
- package/dist/{ledger-CNFCJKHX.js → ledger-TWZTGDFA.js} +3 -2
- package/dist/{linear-ingester-PLES2BRS.js → linear-ingester-XXPAZZRW.js} +3 -3
- package/dist/{output-manager-JNMEAXFO.js → output-manager-RVJ37XKA.js} +2 -2
- package/dist/server/mcp-server.js +19 -18
- package/dist/{tiered-storage-OP74NPJY.js → tiered-storage-Z3YCR465.js} +2 -2
- package/dist/{trie-agent-6SWUHCVO.js → trie-agent-3YDPEGHJ.js} +9 -8
- package/dist/trie-agent-3YDPEGHJ.js.map +1 -0
- package/package.json +3 -2
- package/dist/chunk-GDWA3CH3.js.map +0 -1
- package/dist/chunk-HOGKPDZA.js.map +0 -1
- package/dist/chunk-JNUOW2JS.js.map +0 -1
- package/dist/chunk-LG5CBK6A.js.map +0 -1
- package/dist/chunk-LR5M4RTN.js.map +0 -1
- package/dist/chunk-MVVPJ73K.js.map +0 -1
- package/dist/chunk-S36IO3EE.js.map +0 -1
- package/dist/chunk-UXRW2YSP.js.map +0 -1
- package/dist/chunk-VR4VWXXU.js.map +0 -1
- package/dist/chunk-ZBXW244P.js.map +0 -1
- /package/dist/{chunk-ZKKKLRZZ.js.map → chunk-5BRRRTN6.js.map} +0 -0
- /package/dist/{chunk-TQOO6A4G.js.map → chunk-7WITSO22.js.map} +0 -0
- /package/dist/{chunk-ACU2RJUJ.js.map → chunk-F6WFNUAY.js.map} +0 -0
- /package/dist/{chunk-2Z3TQNNK.js.map → chunk-MRHKX5M5.js.map} +0 -0
- /package/dist/{chunk-OLNZJ3XV.js.map → chunk-Q63FFI6D.js.map} +0 -0
- /package/dist/{chunk-JEZ7XJQN.js.map → chunk-XTFWT2XM.js.map} +0 -0
- /package/dist/{fast-analyzer-NJQO3TFD.js.map → fast-analyzer-XXYMOXRK.js.map} +0 -0
- /package/dist/{github-ingester-TFBDUDIY.js.map → git-EO5SRFMN.js.map} +0 -0
- /package/dist/{goal-manager-DVX24UPZ.js.map → github-ingester-ZOKK6GRS.js.map} +0 -0
- /package/dist/{goal-validator-6Y5CDEMJ.js.map → goal-manager-YOB7VWK7.js.map} +0 -0
- /package/dist/{hypothesis-UKPGOYY2.js.map → goal-validator-ULKIBDPX.js.map} +0 -0
- /package/dist/{issue-store-UZAPI5DU.js.map → hypothesis-7BFFT5JY.js.map} +0 -0
- /package/dist/{ledger-CNFCJKHX.js.map → issue-store-ZIRP23EP.js.map} +0 -0
- /package/dist/{linear-ingester-PLES2BRS.js.map → ledger-TWZTGDFA.js.map} +0 -0
- /package/dist/{output-manager-JNMEAXFO.js.map → linear-ingester-XXPAZZRW.js.map} +0 -0
- /package/dist/{tiered-storage-OP74NPJY.js.map → output-manager-RVJ37XKA.js.map} +0 -0
- /package/dist/{trie-agent-6SWUHCVO.js.map → tiered-storage-Z3YCR465.js.map} +0 -0
|
@@ -5,6 +5,10 @@ import {
|
|
|
5
5
|
getTrieDirectory,
|
|
6
6
|
getWorkingDirectory
|
|
7
7
|
} from "./chunk-VVITXIHN.js";
|
|
8
|
+
import {
|
|
9
|
+
getLastCommit,
|
|
10
|
+
isGitRepo
|
|
11
|
+
} from "./chunk-2HF65EHQ.js";
|
|
8
12
|
import {
|
|
9
13
|
__require
|
|
10
14
|
} from "./chunk-DGUM43GV.js";
|
|
@@ -12,7 +16,7 @@ import {
|
|
|
12
16
|
// src/memory/ledger.ts
|
|
13
17
|
import { createHash } from "crypto";
|
|
14
18
|
import { mkdir as mkdir2, readFile as readFile2, writeFile, stat as stat2, unlink as unlink2 } from "fs/promises";
|
|
15
|
-
import { existsSync as
|
|
19
|
+
import { existsSync as existsSync4 } from "fs";
|
|
16
20
|
import { createGzip, createGunzip } from "zlib";
|
|
17
21
|
import { pipeline } from "stream/promises";
|
|
18
22
|
import { createReadStream, createWriteStream } from "fs";
|
|
@@ -143,311 +147,10 @@ function isProcessRunning(pid) {
|
|
|
143
147
|
}
|
|
144
148
|
}
|
|
145
149
|
|
|
146
|
-
// src/agent/git.ts
|
|
147
|
-
import { existsSync as existsSync2 } from "fs";
|
|
148
|
-
import path from "path";
|
|
149
|
-
|
|
150
|
-
// src/utils/command-runner.ts
|
|
151
|
-
import { exec, execFile, execSync } from "child_process";
|
|
152
|
-
import { promisify } from "util";
|
|
153
|
-
|
|
154
|
-
// src/utils/audit-logger.ts
|
|
155
|
-
function formatAuditLog(_entry) {
|
|
156
|
-
return "Audit logging has been integrated into the decision ledger";
|
|
157
|
-
}
|
|
158
|
-
function getAuditStatistics() {
|
|
159
|
-
return {
|
|
160
|
-
totalScans: 0,
|
|
161
|
-
totalIssues: 0,
|
|
162
|
-
criticalCount: 0,
|
|
163
|
-
seriousCount: 0,
|
|
164
|
-
moderateCount: 0,
|
|
165
|
-
lowCount: 0,
|
|
166
|
-
totalExecutions: 0,
|
|
167
|
-
successfulExecutions: 0,
|
|
168
|
-
failedExecutions: 0,
|
|
169
|
-
uniqueSkills: 0,
|
|
170
|
-
totalCommands: 0,
|
|
171
|
-
blockedCommands: 0,
|
|
172
|
-
totalNetworkCalls: 0,
|
|
173
|
-
blockedNetworkCalls: 0
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
function createAuditEntry(skillName, skillSource, triggeredBy, targetPath) {
|
|
177
|
-
return {
|
|
178
|
-
skillName,
|
|
179
|
-
skillSource,
|
|
180
|
-
triggeredBy,
|
|
181
|
-
targetPath,
|
|
182
|
-
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
183
|
-
commands: []
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
function completeAuditEntry(entry, success, error) {
|
|
187
|
-
const result = {
|
|
188
|
-
...entry,
|
|
189
|
-
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
190
|
-
success
|
|
191
|
-
};
|
|
192
|
-
if (error !== void 0) {
|
|
193
|
-
result.error = error;
|
|
194
|
-
}
|
|
195
|
-
return result;
|
|
196
|
-
}
|
|
197
|
-
async function logSkillExecution(_execution) {
|
|
198
|
-
}
|
|
199
|
-
async function getRecentAuditLogs(_limit = 10) {
|
|
200
|
-
return [];
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// src/utils/command-runner.ts
|
|
204
|
-
var execAsync = promisify(exec);
|
|
205
|
-
var execFileAsync = promisify(execFile);
|
|
206
|
-
function redact(text) {
|
|
207
|
-
return text.replace(/\b(AWS|ANTHROPIC|OPENAI|GITHUB)_[A-Z0-9_]*\s*=\s*([^\s"'`]+)/gi, "$1_<REDACTED>=<REDACTED>").replace(/\bBearer\s+[A-Za-z0-9\-._~+/]+=*\b/g, "Bearer <REDACTED>").replace(/\bghp_[A-Za-z0-9]{20,}\b/g, "ghp_<REDACTED>").replace(/\b(?:xox[baprs]-)[A-Za-z0-9-]{10,}\b/g, "<REDACTED_SLACK_TOKEN>").replace(/\bAKIA[0-9A-Z]{16}\b/g, "AKIA<REDACTED>");
|
|
208
|
-
}
|
|
209
|
-
function clampOutput(text, maxChars) {
|
|
210
|
-
if (text.length <= maxChars) return text;
|
|
211
|
-
return text.slice(0, maxChars) + `
|
|
212
|
-
\u2026(truncated ${text.length - maxChars} chars)`;
|
|
213
|
-
}
|
|
214
|
-
function buildCommandRecord(command) {
|
|
215
|
-
return {
|
|
216
|
-
command,
|
|
217
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
async function finalizeAndWrite(entry, cmd, outcome, options) {
|
|
221
|
-
const duration = Date.now() - outcome.startedAt;
|
|
222
|
-
cmd.duration = duration;
|
|
223
|
-
if (outcome.exitCode !== void 0) {
|
|
224
|
-
cmd.exitCode = outcome.exitCode;
|
|
225
|
-
}
|
|
226
|
-
const captureOutput = options?.captureOutput ?? false;
|
|
227
|
-
const redactOutput = options?.redactOutput ?? true;
|
|
228
|
-
const maxOutputChars = options?.maxOutputChars ?? 2e3;
|
|
229
|
-
if (captureOutput) {
|
|
230
|
-
const out = outcome.stdout ?? "";
|
|
231
|
-
const err = outcome.stderr ?? "";
|
|
232
|
-
cmd.stdout = redactOutput ? redact(clampOutput(out, maxOutputChars)) : clampOutput(out, maxOutputChars);
|
|
233
|
-
cmd.stderr = redactOutput ? redact(clampOutput(err, maxOutputChars)) : clampOutput(err, maxOutputChars);
|
|
234
|
-
}
|
|
235
|
-
const completed = completeAuditEntry(entry, outcome.success, outcome.error);
|
|
236
|
-
await logSkillExecution(completed);
|
|
237
|
-
}
|
|
238
|
-
function runShellCommandSync(command, audit, options) {
|
|
239
|
-
const startedAt = Date.now();
|
|
240
|
-
const entry = createAuditEntry(audit.actor, audit.source ?? "trie", audit.triggeredBy, audit.targetPath);
|
|
241
|
-
const cmd = buildCommandRecord(command);
|
|
242
|
-
entry.commands?.push(cmd);
|
|
243
|
-
try {
|
|
244
|
-
const stdout = execSync(command, {
|
|
245
|
-
cwd: options?.cwd,
|
|
246
|
-
timeout: options?.timeoutMs,
|
|
247
|
-
maxBuffer: options?.maxBuffer,
|
|
248
|
-
encoding: "utf-8",
|
|
249
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
250
|
-
});
|
|
251
|
-
void finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout, stderr: "", startedAt }, options);
|
|
252
|
-
return { stdout: stdout ?? "", exitCode: 0 };
|
|
253
|
-
} catch (e) {
|
|
254
|
-
const err = e;
|
|
255
|
-
const stdout = typeof err.stdout === "string" ? err.stdout : "";
|
|
256
|
-
const stderr = typeof err.stderr === "string" ? err.stderr : "";
|
|
257
|
-
const exitCode = typeof err.status === "number" ? err.status : 1;
|
|
258
|
-
void finalizeAndWrite(
|
|
259
|
-
entry,
|
|
260
|
-
cmd,
|
|
261
|
-
{ success: false, exitCode, stdout, stderr, error: err.message, startedAt },
|
|
262
|
-
{ ...options, captureOutput: options?.captureOutput ?? true }
|
|
263
|
-
);
|
|
264
|
-
return { stdout, exitCode };
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
async function runExecFile(file, args, audit, options) {
|
|
268
|
-
const startedAt = Date.now();
|
|
269
|
-
const command = [file, ...args].join(" ");
|
|
270
|
-
const entry = createAuditEntry(audit.actor, audit.source ?? "trie", audit.triggeredBy, audit.targetPath);
|
|
271
|
-
const cmd = buildCommandRecord(command);
|
|
272
|
-
entry.commands?.push(cmd);
|
|
273
|
-
try {
|
|
274
|
-
const { stdout, stderr } = await execFileAsync(file, args, {
|
|
275
|
-
cwd: options?.cwd,
|
|
276
|
-
timeout: options?.timeoutMs,
|
|
277
|
-
maxBuffer: options?.maxBuffer
|
|
278
|
-
});
|
|
279
|
-
await finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout: String(stdout ?? ""), stderr: String(stderr ?? ""), startedAt }, options);
|
|
280
|
-
return { stdout: String(stdout ?? ""), stderr: String(stderr ?? ""), exitCode: 0 };
|
|
281
|
-
} catch (e) {
|
|
282
|
-
const err = e;
|
|
283
|
-
const stdout = typeof err.stdout === "string" ? err.stdout : "";
|
|
284
|
-
const stderr = typeof err.stderr === "string" ? err.stderr : "";
|
|
285
|
-
const exitCode = typeof err.code === "number" ? err.code : 1;
|
|
286
|
-
await finalizeAndWrite(
|
|
287
|
-
entry,
|
|
288
|
-
cmd,
|
|
289
|
-
{ success: false, exitCode, stdout, stderr, error: err.message, startedAt },
|
|
290
|
-
{ ...options, captureOutput: options?.captureOutput ?? true }
|
|
291
|
-
);
|
|
292
|
-
return { stdout, stderr, exitCode };
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// src/agent/git.ts
|
|
297
|
-
async function execGit(args, cwd) {
|
|
298
|
-
try {
|
|
299
|
-
const { stdout } = await runExecFile(
|
|
300
|
-
"git",
|
|
301
|
-
["-C", cwd, ...args],
|
|
302
|
-
{ actor: "internal:git", triggeredBy: "manual", targetPath: cwd },
|
|
303
|
-
{ maxBuffer: 10 * 1024 * 1024, captureOutput: false }
|
|
304
|
-
);
|
|
305
|
-
return stdout.trim();
|
|
306
|
-
} catch (error) {
|
|
307
|
-
const stderr = error?.stderr?.toString();
|
|
308
|
-
if (stderr?.includes("not a git repository") || stderr?.includes("does not have any commits")) {
|
|
309
|
-
return null;
|
|
310
|
-
}
|
|
311
|
-
throw error;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
async function ensureRepo(projectPath) {
|
|
315
|
-
const result = await execGit(["rev-parse", "--is-inside-work-tree"], projectPath);
|
|
316
|
-
return result === "true";
|
|
317
|
-
}
|
|
318
|
-
function parseNameStatus(output) {
|
|
319
|
-
return output.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => {
|
|
320
|
-
const parts = line.split(" ");
|
|
321
|
-
const status = parts[0] ?? "";
|
|
322
|
-
const filePath = parts[1] ?? "";
|
|
323
|
-
const oldPath = parts[2];
|
|
324
|
-
const change = { status, path: filePath };
|
|
325
|
-
if (oldPath) change.oldPath = oldPath;
|
|
326
|
-
return change;
|
|
327
|
-
}).filter((entry) => entry.path.length > 0);
|
|
328
|
-
}
|
|
329
|
-
async function getRecentCommits(projectPath, limit) {
|
|
330
|
-
const isRepo = await ensureRepo(projectPath);
|
|
331
|
-
if (!isRepo) return [];
|
|
332
|
-
const output = await execGit(
|
|
333
|
-
["log", `-n`, String(limit), "--pretty=format:%H%x09%an%x09%ad%x09%s", "--date=iso"],
|
|
334
|
-
projectPath
|
|
335
|
-
);
|
|
336
|
-
if (!output) return [];
|
|
337
|
-
return output.split("\n").map((line) => {
|
|
338
|
-
const [hash, author, date, message] = line.split(" ");
|
|
339
|
-
return { hash, author, date, message };
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
async function getLastCommit(projectPath) {
|
|
343
|
-
const commits = await getRecentCommits(projectPath, 1);
|
|
344
|
-
return commits[0] ?? null;
|
|
345
|
-
}
|
|
346
|
-
async function getStagedChanges(projectPath) {
|
|
347
|
-
const isRepo = await ensureRepo(projectPath);
|
|
348
|
-
if (!isRepo) return [];
|
|
349
|
-
const output = await execGit(["diff", "--cached", "--name-status"], projectPath);
|
|
350
|
-
if (!output) return [];
|
|
351
|
-
return parseNameStatus(output);
|
|
352
|
-
}
|
|
353
|
-
async function getUncommittedChanges(projectPath) {
|
|
354
|
-
const isRepo = await ensureRepo(projectPath);
|
|
355
|
-
if (!isRepo) return [];
|
|
356
|
-
const changes = [];
|
|
357
|
-
const unstaged = await execGit(["diff", "--name-status"], projectPath);
|
|
358
|
-
if (unstaged) {
|
|
359
|
-
changes.push(...parseNameStatus(unstaged));
|
|
360
|
-
}
|
|
361
|
-
const untracked = await execGit(["ls-files", "--others", "--exclude-standard"], projectPath);
|
|
362
|
-
if (untracked) {
|
|
363
|
-
changes.push(
|
|
364
|
-
...untracked.split("\n").map((p) => p.trim()).filter(Boolean).map((p) => ({ status: "??", path: p }))
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
return changes;
|
|
368
|
-
}
|
|
369
|
-
async function getGitChangedFiles(projectPath) {
|
|
370
|
-
const isRepo = await ensureRepo(projectPath);
|
|
371
|
-
if (!isRepo) return null;
|
|
372
|
-
const [staged, uncommitted] = await Promise.all([
|
|
373
|
-
getStagedChanges(projectPath).catch(() => []),
|
|
374
|
-
getUncommittedChanges(projectPath).catch(() => [])
|
|
375
|
-
]);
|
|
376
|
-
const paths = /* @__PURE__ */ new Set();
|
|
377
|
-
for (const change of [...staged, ...uncommitted]) {
|
|
378
|
-
if (change.path) paths.add(change.path);
|
|
379
|
-
if (change.oldPath) paths.add(change.oldPath);
|
|
380
|
-
}
|
|
381
|
-
return [...paths];
|
|
382
|
-
}
|
|
383
|
-
async function getDiff(projectPath, commitHash) {
|
|
384
|
-
const isRepo = await ensureRepo(projectPath);
|
|
385
|
-
if (!isRepo) return "";
|
|
386
|
-
const diff = await execGit(["show", commitHash, "--unified=3", "--no-color"], projectPath);
|
|
387
|
-
return diff ?? "";
|
|
388
|
-
}
|
|
389
|
-
async function getWorkingTreeDiff(projectPath, stagedOnly = false) {
|
|
390
|
-
const isRepo = await ensureRepo(projectPath);
|
|
391
|
-
if (!isRepo) return "";
|
|
392
|
-
const args = stagedOnly ? ["diff", "--cached", "--unified=3", "--no-color"] : ["diff", "--unified=3", "--no-color"];
|
|
393
|
-
const diff = await execGit(args, projectPath);
|
|
394
|
-
return diff ?? "";
|
|
395
|
-
}
|
|
396
|
-
async function isGitRepo(projectPath) {
|
|
397
|
-
const result = await execGit(["rev-parse", "--is-inside-work-tree"], projectPath);
|
|
398
|
-
return result === "true";
|
|
399
|
-
}
|
|
400
|
-
async function getChangedFilesSinceTimestamp(projectPath, timestamp) {
|
|
401
|
-
const isRepo = await isGitRepo(projectPath);
|
|
402
|
-
if (!isRepo) return null;
|
|
403
|
-
try {
|
|
404
|
-
const sinceDate = new Date(timestamp).toISOString();
|
|
405
|
-
const GIT_TIMEOUT_MS = 5e3;
|
|
406
|
-
const startTime = Date.now();
|
|
407
|
-
const committedChangesPromise = execGit(
|
|
408
|
-
["log", `--since=${sinceDate}`, "--name-only", "--pretty=format:"],
|
|
409
|
-
projectPath
|
|
410
|
-
);
|
|
411
|
-
const committedChangesTimeout = new Promise((resolve) => {
|
|
412
|
-
setTimeout(() => resolve(null), GIT_TIMEOUT_MS);
|
|
413
|
-
});
|
|
414
|
-
const committedChanges = await Promise.race([committedChangesPromise, committedChangesTimeout]);
|
|
415
|
-
if (Date.now() - startTime > GIT_TIMEOUT_MS) {
|
|
416
|
-
return null;
|
|
417
|
-
}
|
|
418
|
-
const stagedPromise = execGit(["diff", "--cached", "--name-only"], projectPath);
|
|
419
|
-
const unstagedPromise = execGit(["diff", "--name-only"], projectPath);
|
|
420
|
-
const untrackedPromise = execGit(
|
|
421
|
-
["ls-files", "--others", "--exclude-standard"],
|
|
422
|
-
projectPath
|
|
423
|
-
);
|
|
424
|
-
const timeoutPromise = new Promise((resolve) => {
|
|
425
|
-
setTimeout(() => resolve(null), Math.max(0, GIT_TIMEOUT_MS - (Date.now() - startTime)));
|
|
426
|
-
});
|
|
427
|
-
const [stagedChanges, unstagedChanges, untrackedFiles] = await Promise.race([
|
|
428
|
-
Promise.all([stagedPromise, unstagedPromise, untrackedPromise]),
|
|
429
|
-
timeoutPromise.then(() => [null, null, null])
|
|
430
|
-
]);
|
|
431
|
-
const changedFiles = /* @__PURE__ */ new Set();
|
|
432
|
-
const addFiles = (output) => {
|
|
433
|
-
if (output) {
|
|
434
|
-
output.split("\n").map((f) => f.trim()).filter(Boolean).forEach((f) => changedFiles.add(path.join(projectPath, f)));
|
|
435
|
-
}
|
|
436
|
-
};
|
|
437
|
-
addFiles(committedChanges);
|
|
438
|
-
addFiles(stagedChanges);
|
|
439
|
-
addFiles(unstagedChanges);
|
|
440
|
-
addFiles(untrackedFiles);
|
|
441
|
-
return Array.from(changedFiles);
|
|
442
|
-
} catch {
|
|
443
|
-
return null;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
150
|
// src/memory/crypto-keys.ts
|
|
448
151
|
import * as ed25519 from "@noble/ed25519";
|
|
449
152
|
import { randomBytes } from "crypto";
|
|
450
|
-
import { existsSync as
|
|
153
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
451
154
|
import { join } from "path";
|
|
452
155
|
function getKeysDirectory(workDir) {
|
|
453
156
|
const trieDir = getTrieDirectory(workDir || process.cwd());
|
|
@@ -466,7 +169,7 @@ async function generateKeyPair() {
|
|
|
466
169
|
}
|
|
467
170
|
function saveKeyPair(keyPair, workDir) {
|
|
468
171
|
const keysDir = getKeysDirectory(workDir);
|
|
469
|
-
if (!
|
|
172
|
+
if (!existsSync2(keysDir)) {
|
|
470
173
|
mkdirSync(keysDir, { recursive: true });
|
|
471
174
|
}
|
|
472
175
|
const keyPath = getDefaultKeyPath(workDir);
|
|
@@ -481,7 +184,7 @@ function saveKeyPair(keyPair, workDir) {
|
|
|
481
184
|
}
|
|
482
185
|
function loadKeyPair(workDir) {
|
|
483
186
|
const keyPath = getDefaultKeyPath(workDir);
|
|
484
|
-
if (!
|
|
187
|
+
if (!existsSync2(keyPath)) {
|
|
485
188
|
return null;
|
|
486
189
|
}
|
|
487
190
|
try {
|
|
@@ -544,23 +247,23 @@ function getPublicKey(workDir) {
|
|
|
544
247
|
}
|
|
545
248
|
function hasSigningKey(workDir) {
|
|
546
249
|
const keyPath = getDefaultKeyPath(workDir);
|
|
547
|
-
return
|
|
250
|
+
return existsSync2(keyPath);
|
|
548
251
|
}
|
|
549
252
|
|
|
550
253
|
// src/memory/git-integration.ts
|
|
551
|
-
import { exec
|
|
552
|
-
import { promisify
|
|
553
|
-
import { existsSync as
|
|
254
|
+
import { exec } from "child_process";
|
|
255
|
+
import { promisify } from "util";
|
|
256
|
+
import { existsSync as existsSync3 } from "fs";
|
|
554
257
|
import { join as join2 } from "path";
|
|
555
|
-
var
|
|
258
|
+
var execAsync = promisify(exec);
|
|
556
259
|
async function isGitIntegrationEnabled(workDir) {
|
|
557
260
|
try {
|
|
558
261
|
const gitDir = join2(workDir, ".git");
|
|
559
|
-
if (!
|
|
262
|
+
if (!existsSync3(gitDir)) {
|
|
560
263
|
return false;
|
|
561
264
|
}
|
|
562
265
|
const configPath = join2(getTrieDirectory(workDir), "config.json");
|
|
563
|
-
if (!
|
|
266
|
+
if (!existsSync3(configPath)) {
|
|
564
267
|
return true;
|
|
565
268
|
}
|
|
566
269
|
const config = JSON.parse(await import("fs/promises").then((fs) => fs.readFile(configPath, "utf-8")));
|
|
@@ -576,18 +279,18 @@ async function autoCommitLedger(workDir, message) {
|
|
|
576
279
|
return { committed: false, error: "Git integration disabled" };
|
|
577
280
|
}
|
|
578
281
|
const ledgerPath = join2(getTrieDirectory(workDir), "memory", "ledger.json");
|
|
579
|
-
const { stdout: statusOutput } = await
|
|
282
|
+
const { stdout: statusOutput } = await execAsync("git status --porcelain", { cwd: workDir });
|
|
580
283
|
const hasLedgerChanges = statusOutput.includes("ledger.json");
|
|
581
284
|
if (!hasLedgerChanges) {
|
|
582
285
|
return { committed: false, error: "No ledger changes to commit" };
|
|
583
286
|
}
|
|
584
|
-
await
|
|
287
|
+
await execAsync(`git add ${ledgerPath}`, { cwd: workDir });
|
|
585
288
|
const commitMessage = message || "ledger: append entries";
|
|
586
|
-
await
|
|
289
|
+
await execAsync(
|
|
587
290
|
`git commit -m "${commitMessage}"`,
|
|
588
291
|
{ cwd: workDir }
|
|
589
292
|
);
|
|
590
|
-
const { stdout: hashOutput } = await
|
|
293
|
+
const { stdout: hashOutput } = await execAsync("git rev-parse HEAD", { cwd: workDir });
|
|
591
294
|
const commitHash = hashOutput.trim();
|
|
592
295
|
return {
|
|
593
296
|
committed: true,
|
|
@@ -605,7 +308,7 @@ async function ensureKeysIgnored(workDir) {
|
|
|
605
308
|
const gitignorePath = join2(workDir, ".gitignore");
|
|
606
309
|
const fs = await import("fs/promises");
|
|
607
310
|
let gitignore = "";
|
|
608
|
-
if (
|
|
311
|
+
if (existsSync3(gitignorePath)) {
|
|
609
312
|
gitignore = await fs.readFile(gitignorePath, "utf-8");
|
|
610
313
|
}
|
|
611
314
|
if (gitignore.includes(".trie/keys/")) {
|
|
@@ -689,23 +392,73 @@ async function appendIssuesToLedger(issues, workDir, author) {
|
|
|
689
392
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
690
393
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
691
394
|
const shouldSign = hasSigningKey(projectDir);
|
|
692
|
-
let entries = issues.map((issue) =>
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
395
|
+
let entries = await Promise.all(issues.map(async (issue) => {
|
|
396
|
+
const context = {
|
|
397
|
+
detectionMethod: "automated-scan",
|
|
398
|
+
confidence: issue.confidence || 80,
|
|
399
|
+
ruleId: issue.agent,
|
|
400
|
+
exposureScope: "repository",
|
|
401
|
+
riskFactors: [],
|
|
402
|
+
escalatedTo: blockAuthor
|
|
403
|
+
};
|
|
404
|
+
if (issue.line !== void 0) {
|
|
405
|
+
context.line = issue.line;
|
|
406
|
+
}
|
|
407
|
+
if (lastCommit?.hash) {
|
|
408
|
+
context.gitCommit = lastCommit.hash;
|
|
409
|
+
}
|
|
410
|
+
if (lastCommit?.branch) {
|
|
411
|
+
context.gitBranch = lastCommit.branch;
|
|
412
|
+
}
|
|
413
|
+
if (issue.category === "security") {
|
|
414
|
+
context.complianceViolations = ["security-policy"];
|
|
415
|
+
context.requiresNotification = issue.severity === "critical";
|
|
416
|
+
}
|
|
417
|
+
if (issue.category === "pii" || issue.issue?.toLowerCase().includes("personal")) {
|
|
418
|
+
context.complianceViolations = ["GDPR", "privacy-policy"];
|
|
419
|
+
context.requiresNotification = true;
|
|
420
|
+
context.exposureScope = "public";
|
|
421
|
+
context.riskFactors.push("data-exposure", "privacy-violation");
|
|
422
|
+
}
|
|
423
|
+
try {
|
|
424
|
+
const filePath = join3(projectDir, issue.file);
|
|
425
|
+
if (existsSync4(filePath)) {
|
|
426
|
+
const { readFile: readFile3, stat: stat3 } = await import("fs/promises");
|
|
427
|
+
const stats = await stat3(filePath);
|
|
428
|
+
context.fileSize = stats.size;
|
|
429
|
+
context.fileModified = stats.mtime.toISOString();
|
|
430
|
+
if (issue.line && issue.line > 0) {
|
|
431
|
+
const content = await readFile3(filePath, "utf-8");
|
|
432
|
+
const lines = content.split("\n");
|
|
433
|
+
const startLine = Math.max(0, issue.line - 3);
|
|
434
|
+
const endLine = Math.min(lines.length, issue.line + 2);
|
|
435
|
+
const snippet = lines.slice(startLine, endLine).join("\n");
|
|
436
|
+
context.codeSnippet = snippet.length > 500 ? snippet.slice(0, 500) + "..." : snippet;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
} catch (error) {
|
|
440
|
+
console.debug("Failed to collect file metadata:", error);
|
|
441
|
+
}
|
|
442
|
+
return {
|
|
443
|
+
id: issue.id,
|
|
444
|
+
hash: issue.hash,
|
|
445
|
+
severity: issue.severity,
|
|
446
|
+
file: issue.file,
|
|
447
|
+
agent: issue.agent,
|
|
448
|
+
timestamp: issue.timestamp,
|
|
449
|
+
status: "active",
|
|
450
|
+
// Include semantic content for ambient awareness
|
|
451
|
+
issue: issue.issue,
|
|
452
|
+
fix: issue.fix,
|
|
453
|
+
// Enhanced forensic context
|
|
454
|
+
context
|
|
455
|
+
};
|
|
703
456
|
}));
|
|
704
457
|
if (shouldSign) {
|
|
705
458
|
entries = await Promise.all(entries.map((entry) => signLedgerEntry(entry, projectDir)));
|
|
706
459
|
}
|
|
707
460
|
const previousBlock = blocks[blocks.length - 1];
|
|
708
|
-
const block = previousBlock && previousBlock.date === today ? previousBlock : createSyncableBlock(today, now, previousBlock?.blockHash ?? GENESIS_HASH, blockAuthor, lastCommit?.hash, blocks.length);
|
|
461
|
+
const block = previousBlock && previousBlock.date === today ? previousBlock : await createSyncableBlock(today, now, previousBlock?.blockHash ?? GENESIS_HASH, blockAuthor, projectDir, lastCommit?.hash, blocks.length);
|
|
709
462
|
if (block !== previousBlock) {
|
|
710
463
|
blocks.push(block);
|
|
711
464
|
}
|
|
@@ -777,7 +530,30 @@ function computeMerkleRoot(hashes) {
|
|
|
777
530
|
function computeBlockHash(previousHash, merkleRoot, date, version) {
|
|
778
531
|
return sha256(`${version}:${date}:${previousHash}:${merkleRoot}`);
|
|
779
532
|
}
|
|
780
|
-
function createSyncableBlock(date, now, previousHash, author, gitCommit, chainHeight = 0) {
|
|
533
|
+
async function createSyncableBlock(date, now, previousHash, author, projectDir, gitCommit, chainHeight = 0) {
|
|
534
|
+
const metadata = {};
|
|
535
|
+
try {
|
|
536
|
+
metadata.hostname = __require("os").hostname();
|
|
537
|
+
metadata.workingDirectory = projectDir;
|
|
538
|
+
metadata.scanId = `scan-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
539
|
+
metadata.toolVersion = process.env.npm_package_version || "unknown";
|
|
540
|
+
if (await isGitRepo(projectDir)) {
|
|
541
|
+
const { getLastCommit: getLastCommit2 } = await import("./git-EO5SRFMN.js");
|
|
542
|
+
const lastCommit = await getLastCommit2(projectDir);
|
|
543
|
+
if (lastCommit?.hash) {
|
|
544
|
+
metadata.gitHeadCommit = lastCommit.hash;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
metadata.summary = {
|
|
548
|
+
totalIssues: 0,
|
|
549
|
+
issuesBySeverity: {},
|
|
550
|
+
issuesByAgent: {},
|
|
551
|
+
newIssues: 0,
|
|
552
|
+
resolvedIssues: 0
|
|
553
|
+
};
|
|
554
|
+
} catch (error) {
|
|
555
|
+
console.debug("Failed to collect block metadata:", error);
|
|
556
|
+
}
|
|
781
557
|
return {
|
|
782
558
|
version: LEDGER_VERSION,
|
|
783
559
|
date,
|
|
@@ -789,6 +565,7 @@ function createSyncableBlock(date, now, previousHash, author, gitCommit, chainHe
|
|
|
789
565
|
updatedAt: now,
|
|
790
566
|
author,
|
|
791
567
|
chainHeight,
|
|
568
|
+
metadata,
|
|
792
569
|
...gitCommit && { gitCommit }
|
|
793
570
|
};
|
|
794
571
|
}
|
|
@@ -799,7 +576,7 @@ async function loadLedger(projectDir) {
|
|
|
799
576
|
async function loadLedgerWithHash(projectDir) {
|
|
800
577
|
const ledgerPath = join3(getTrieDirectory(projectDir), "memory", LEDGER_FILENAME);
|
|
801
578
|
try {
|
|
802
|
-
if (!
|
|
579
|
+
if (!existsSync4(ledgerPath)) {
|
|
803
580
|
return { blocks: [], contentHash: sha256("[]") };
|
|
804
581
|
}
|
|
805
582
|
const content = await readFile2(ledgerPath, "utf-8");
|
|
@@ -897,7 +674,7 @@ async function ensureSharedStorageStructure(projectDir) {
|
|
|
897
674
|
async function loadManifest(projectDir) {
|
|
898
675
|
const manifestPath = getManifestPath(projectDir);
|
|
899
676
|
try {
|
|
900
|
-
if (!
|
|
677
|
+
if (!existsSync4(manifestPath)) return null;
|
|
901
678
|
const content = await readFile2(manifestPath, "utf-8");
|
|
902
679
|
return JSON.parse(content);
|
|
903
680
|
} catch {
|
|
@@ -935,7 +712,7 @@ async function createDefaultManifest(_projectDir) {
|
|
|
935
712
|
async function loadSyncState(projectDir) {
|
|
936
713
|
const syncStatePath = getSyncStatePath(projectDir);
|
|
937
714
|
try {
|
|
938
|
-
if (!
|
|
715
|
+
if (!existsSync4(syncStatePath)) return null;
|
|
939
716
|
const content = await readFile2(syncStatePath, "utf-8");
|
|
940
717
|
return JSON.parse(content);
|
|
941
718
|
} catch {
|
|
@@ -1004,7 +781,7 @@ async function pushLedgerToShared(workDir) {
|
|
|
1004
781
|
for (const block of localBlocks) {
|
|
1005
782
|
const blockFilename = `${block.date}.json`;
|
|
1006
783
|
const blockPath = join3(activeDir, blockFilename);
|
|
1007
|
-
if (!
|
|
784
|
+
if (!existsSync4(blockPath) || block.updatedAt > manifest.lastSync) {
|
|
1008
785
|
await atomicWriteJSON(blockPath, block);
|
|
1009
786
|
manifest.index.byDate[block.date] = `active/${blockFilename}`;
|
|
1010
787
|
const blockAuthor = block.author;
|
|
@@ -1035,7 +812,7 @@ async function loadSharedBlocks(projectDir) {
|
|
|
1035
812
|
for (const filename of manifest.activeBlocks) {
|
|
1036
813
|
const blockPath = join3(activeDir, filename);
|
|
1037
814
|
try {
|
|
1038
|
-
if (
|
|
815
|
+
if (existsSync4(blockPath)) {
|
|
1039
816
|
const content = await readFile2(blockPath, "utf-8");
|
|
1040
817
|
const block = JSON.parse(content);
|
|
1041
818
|
blocks.push(block);
|
|
@@ -1063,8 +840,11 @@ async function mergeChains(localBlocks, remoteBlocks, strategy = "timestamp") {
|
|
|
1063
840
|
for (const block of remoteBlocks) {
|
|
1064
841
|
remoteByDate.set(block.date, block);
|
|
1065
842
|
}
|
|
1066
|
-
const allDates = /* @__PURE__ */ new Set([
|
|
1067
|
-
|
|
843
|
+
const allDates = /* @__PURE__ */ new Set([
|
|
844
|
+
...Array.from(localByDate.keys()),
|
|
845
|
+
...Array.from(remoteByDate.keys())
|
|
846
|
+
]);
|
|
847
|
+
for (const date of Array.from(allDates)) {
|
|
1068
848
|
const localBlock = localByDate.get(date);
|
|
1069
849
|
const remoteBlock = remoteByDate.get(date);
|
|
1070
850
|
if (localBlock && remoteBlock) {
|
|
@@ -1180,7 +960,7 @@ function mergeBlockEntries(localBlock, remoteBlock) {
|
|
|
1180
960
|
async function migrateLegacyLedger(workDir) {
|
|
1181
961
|
const projectDir = workDir || getWorkingDirectory(void 0, true);
|
|
1182
962
|
const legacyLedgerPath = join3(getTrieDirectory(projectDir), "memory", LEDGER_FILENAME);
|
|
1183
|
-
if (!
|
|
963
|
+
if (!existsSync4(legacyLedgerPath)) {
|
|
1184
964
|
return false;
|
|
1185
965
|
}
|
|
1186
966
|
try {
|
|
@@ -1215,7 +995,7 @@ async function migrateLegacyLedger(workDir) {
|
|
|
1215
995
|
async function detectLegacyLedger(workDir) {
|
|
1216
996
|
const projectDir = workDir || getWorkingDirectory(void 0, true);
|
|
1217
997
|
const legacyLedgerPath = join3(getTrieDirectory(projectDir), "memory", LEDGER_FILENAME);
|
|
1218
|
-
if (!
|
|
998
|
+
if (!existsSync4(legacyLedgerPath)) {
|
|
1219
999
|
return false;
|
|
1220
1000
|
}
|
|
1221
1001
|
try {
|
|
@@ -1266,9 +1046,9 @@ async function compressOldBlocks(workDir) {
|
|
|
1266
1046
|
blocksByMonth.get(monthKey).push(blockFile);
|
|
1267
1047
|
}
|
|
1268
1048
|
}
|
|
1269
|
-
for (const [monthKey, blockFiles] of blocksByMonth) {
|
|
1049
|
+
for (const [monthKey, blockFiles] of Array.from(blocksByMonth.entries())) {
|
|
1270
1050
|
const archivePath = join3(archivedDir, `${monthKey}.tar.gz`);
|
|
1271
|
-
if (
|
|
1051
|
+
if (existsSync4(archivePath)) {
|
|
1272
1052
|
continue;
|
|
1273
1053
|
}
|
|
1274
1054
|
console.log(`Archiving ${blockFiles.length} blocks for ${monthKey}...`);
|
|
@@ -1320,7 +1100,7 @@ async function compressOldBlocks(workDir) {
|
|
|
1320
1100
|
async function loadArchivedBlocks(projectDir, monthKey) {
|
|
1321
1101
|
const archivedDir = getArchivedBlocksDir(projectDir);
|
|
1322
1102
|
const archivePath = join3(archivedDir, `${monthKey}.tar.gz`);
|
|
1323
|
-
if (!
|
|
1103
|
+
if (!existsSync4(archivePath)) {
|
|
1324
1104
|
return [];
|
|
1325
1105
|
}
|
|
1326
1106
|
try {
|
|
@@ -1362,7 +1142,7 @@ async function getStorageStats(workDir) {
|
|
|
1362
1142
|
for (const blockFile of manifest.activeBlocks) {
|
|
1363
1143
|
const blockPath = join3(activeDir, blockFile);
|
|
1364
1144
|
try {
|
|
1365
|
-
if (
|
|
1145
|
+
if (existsSync4(blockPath)) {
|
|
1366
1146
|
const stats = await stat2(blockPath);
|
|
1367
1147
|
activeSize += stats.size;
|
|
1368
1148
|
}
|
|
@@ -1372,7 +1152,7 @@ async function getStorageStats(workDir) {
|
|
|
1372
1152
|
for (const archiveFile of manifest.archivedBlocks) {
|
|
1373
1153
|
const archivePath = join3(archivedDir, archiveFile);
|
|
1374
1154
|
try {
|
|
1375
|
-
if (
|
|
1155
|
+
if (existsSync4(archivePath)) {
|
|
1376
1156
|
const stats = await stat2(archivePath);
|
|
1377
1157
|
archivedSize += stats.size;
|
|
1378
1158
|
}
|
|
@@ -1506,7 +1286,7 @@ async function appendCorrectionEntries(correctionEntries, projectDir, author) {
|
|
|
1506
1286
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1507
1287
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1508
1288
|
const previousBlock = blocks[blocks.length - 1];
|
|
1509
|
-
const block = previousBlock && previousBlock.date === today ? previousBlock : createSyncableBlock(today, now, previousBlock?.blockHash ?? GENESIS_HASH, author, void 0, blocks.length);
|
|
1289
|
+
const block = previousBlock && previousBlock.date === today ? previousBlock : await createSyncableBlock(today, now, previousBlock?.blockHash ?? GENESIS_HASH, author, projectDir, void 0, blocks.length);
|
|
1510
1290
|
if (block !== previousBlock) {
|
|
1511
1291
|
blocks.push(block);
|
|
1512
1292
|
}
|
|
@@ -1583,18 +1363,6 @@ async function getCorrectionStats(workDir) {
|
|
|
1583
1363
|
|
|
1584
1364
|
export {
|
|
1585
1365
|
withFileLock,
|
|
1586
|
-
formatAuditLog,
|
|
1587
|
-
getAuditStatistics,
|
|
1588
|
-
getRecentAuditLogs,
|
|
1589
|
-
runShellCommandSync,
|
|
1590
|
-
getRecentCommits,
|
|
1591
|
-
getStagedChanges,
|
|
1592
|
-
getUncommittedChanges,
|
|
1593
|
-
getGitChangedFiles,
|
|
1594
|
-
getDiff,
|
|
1595
|
-
getWorkingTreeDiff,
|
|
1596
|
-
isGitRepo,
|
|
1597
|
-
getChangedFilesSinceTimestamp,
|
|
1598
1366
|
generateKeyPair,
|
|
1599
1367
|
saveKeyPair,
|
|
1600
1368
|
loadKeyPair,
|
|
@@ -1625,4 +1393,4 @@ export {
|
|
|
1625
1393
|
getEntryCorrectionHistory,
|
|
1626
1394
|
getCorrectionStats
|
|
1627
1395
|
};
|
|
1628
|
-
//# sourceMappingURL=chunk-
|
|
1396
|
+
//# sourceMappingURL=chunk-ZJF5FTBX.js.map
|