@wrongstack/core 0.270.0 → 0.272.0
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/{agent-bridge-PcHQl_UQ.d.ts → agent-bridge-jVSZiygR.d.ts} +1 -1
- package/dist/{agent-subagent-runner-SHJW7t8q.d.ts → agent-subagent-runner-DOLIwBRo.d.ts} +7 -7
- package/dist/{brain-BYcK__Ym.d.ts → brain-CdbbJWi3.d.ts} +71 -1
- package/dist/{compactor-C2RKEBtC.d.ts → compactor-72ug-ZRB.d.ts} +1 -1
- package/dist/{config-C_ae2k86.d.ts → config-D2DGoGSQ.d.ts} +29 -2
- package/dist/{context-Dp87Bcaq.d.ts → context-Dw55zZ_Q.d.ts} +110 -1
- package/dist/coordination/index.d.ts +121 -17
- package/dist/coordination/index.js +738 -74
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +25 -25
- package/dist/defaults/index.js +599 -86
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +23 -18
- package/dist/execution/index.js +136 -41
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/prompt-enhancer.d.ts +36 -6
- package/dist/execution/prompt-enhancer.js +35 -9
- package/dist/execution/prompt-enhancer.js.map +1 -1
- package/dist/extension/index.d.ts +6 -6
- package/dist/{global-mailbox-Bvrz1P3f.d.ts → global-mailbox-CQj_C9Dp.d.ts} +139 -3
- package/dist/{goal-preamble-CA_4yiGQ.d.ts → goal-preamble-ZXDjjR1y.d.ts} +9 -9
- package/dist/{goal-store-DhuJoUNG.d.ts → goal-store-CcJBd-g1.d.ts} +1 -1
- package/dist/hq/index.d.ts +93 -6
- package/dist/hq/index.js +616 -46
- package/dist/hq/index.js.map +1 -1
- package/dist/{index-whDfTANu.d.ts → index-2Lhk5v0o.d.ts} +2 -2
- package/dist/{index-CZQ6Pwbs.d.ts → index-BL7BAx0p.d.ts} +8 -8
- package/dist/{index-W4VJCzHa.d.ts → index-Qo4kTzgw.d.ts} +5 -5
- package/dist/index.d.ts +96 -56
- package/dist/index.js +1938 -349
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +6 -6
- package/dist/infrastructure/index.js +5 -3
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +9 -9
- package/dist/kernel/index.js.map +1 -1
- package/dist/{mcp-servers-DJdZiRcv.d.ts → mcp-servers-DS-YUXvF.d.ts} +3 -3
- package/dist/models/index.d.ts +5 -5
- package/dist/models/index.js +28 -5
- package/dist/models/index.js.map +1 -1
- package/dist/{models-registry-C3a-2-Yd.d.ts → models-registry-DP6pGHet.d.ts} +1 -1
- package/dist/{multi-agent-coordinator-CJSpTe5O.d.ts → multi-agent-coordinator-BvbdNQ14.d.ts} +1 -1
- package/dist/{null-fleet-bus-QVshIsDx.d.ts → null-fleet-bus-BxTfXBKo.d.ts} +6 -6
- package/dist/observability/index.d.ts +2 -2
- package/dist/{parallel-eternal-engine-D9y5Pkcc.d.ts → parallel-eternal-engine-Cf-GTegR.d.ts} +9 -9
- package/dist/{path-resolver-CnQ8SIfh.d.ts → path-resolver-DztfnFcv.d.ts} +3 -3
- package/dist/{permission-CvYQNUqZ.d.ts → permission-CC7XFYWG.d.ts} +1 -1
- package/dist/{permission-policy-D5Ss8j4B.d.ts → permission-policy-cYR4RJmw.d.ts} +2 -2
- package/dist/{pipeline-l_zzFRh3.d.ts → pipeline-sNIkhXeB.d.ts} +2 -2
- package/dist/{plan-templates-NtPgyeJA.d.ts → plan-templates-DYiKFmEb.d.ts} +11 -5
- package/dist/{provider-model-resolve-d5poT5y0.d.ts → provider-model-resolve-dYAbTs_i.d.ts} +3 -3
- package/dist/{provider-runner-gkctlQV_.d.ts → provider-runner-Dw8x0F7u.d.ts} +3 -3
- package/dist/{retry-policy-CtFhfwa8.d.ts → retry-policy-BV7nzeAd.d.ts} +1 -1
- package/dist/sdd/index.d.ts +8 -8
- package/dist/sdd/index.js +2 -0
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-vault-BLsVmTIK.d.ts → secret-vault-eMBKfheR.d.ts} +9 -1
- package/dist/security/index.d.ts +5 -5
- package/dist/security/index.js +137 -10
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-CXl2_y9W.d.ts → selector-C4ORTOid.d.ts} +1 -1
- package/dist/{session-event-bridge-Ccud20CC.d.ts → session-event-bridge-CeNpUL9w.d.ts} +1 -1
- package/dist/{session-reader-ZeXQmsmE.d.ts → session-reader-BepLSnGL.d.ts} +1 -1
- package/dist/storage/index.d.ts +45 -13
- package/dist/storage/index.js +374 -113
- package/dist/storage/index.js.map +1 -1
- package/dist/tools/index.d.ts +2 -2
- package/dist/tools/index.js +9 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/types/index.d.ts +19 -19
- package/dist/types/index.js +202 -41
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +17 -4
- package/dist/utils/index.js +48 -9
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
package/dist/storage/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createReadStream } from 'fs';
|
|
2
2
|
import * as fsp from 'fs/promises';
|
|
3
3
|
import * as path2 from 'path';
|
|
4
|
+
import { createInterface } from 'readline';
|
|
5
|
+
import { randomBytes, randomUUID, createHash } from 'crypto';
|
|
4
6
|
import * as os from 'os';
|
|
5
7
|
import { hostname } from 'os';
|
|
6
|
-
import 'fs';
|
|
7
8
|
|
|
8
9
|
// src/storage/session-store.ts
|
|
9
10
|
async function atomicWrite(targetPath, content, opts = {}) {
|
|
@@ -430,8 +431,6 @@ function resolveWstackPaths(opts) {
|
|
|
430
431
|
projectStatus: (projectHash2) => path2.join(globalRoot, "projects", projectHash2, "status.json")
|
|
431
432
|
};
|
|
432
433
|
}
|
|
433
|
-
|
|
434
|
-
// src/storage/session-store.ts
|
|
435
434
|
function sanitizeModel(model) {
|
|
436
435
|
return model.replace(/[^a-zA-Z0-9_-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
|
|
437
436
|
}
|
|
@@ -442,6 +441,8 @@ function generateSessionId(startedAt, model) {
|
|
|
442
441
|
const modelPart = model ? `_${sanitizeModel(model)}` : "";
|
|
443
442
|
return `${date}/${time}Z${modelPart}_${suffix}`;
|
|
444
443
|
}
|
|
444
|
+
|
|
445
|
+
// src/storage/session-store.ts
|
|
445
446
|
var DefaultSessionStore = class _DefaultSessionStore {
|
|
446
447
|
dir;
|
|
447
448
|
events;
|
|
@@ -459,6 +460,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
459
460
|
_loadCache = /* @__PURE__ */ new Map();
|
|
460
461
|
_indexCache = null;
|
|
461
462
|
static LOAD_CACHE_MAX_ENTRIES = 50;
|
|
463
|
+
static LIST_SCAN_CONCURRENCY = 32;
|
|
462
464
|
constructor(opts) {
|
|
463
465
|
this.dir = opts.dir;
|
|
464
466
|
this.events = opts.events;
|
|
@@ -681,15 +683,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
681
683
|
});
|
|
682
684
|
return indexed.slice(0, limit);
|
|
683
685
|
}
|
|
684
|
-
|
|
685
|
-
const sessions = await Promise.all(ids.map((id) => this.summaryFor(id).catch(() => null)));
|
|
686
|
-
const out = sessions.filter((s) => s !== null);
|
|
687
|
-
out.sort((a, b) => {
|
|
688
|
-
if (a.startedAt < b.startedAt) return 1;
|
|
689
|
-
if (a.startedAt > b.startedAt) return -1;
|
|
690
|
-
return a.id.localeCompare(b.id);
|
|
691
|
-
});
|
|
692
|
-
return out.slice(0, limit);
|
|
686
|
+
return await this.listFromDirectoryScan(limit);
|
|
693
687
|
} catch {
|
|
694
688
|
return [];
|
|
695
689
|
}
|
|
@@ -814,43 +808,102 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
814
808
|
this._indexCache = null;
|
|
815
809
|
return valid.length;
|
|
816
810
|
}
|
|
811
|
+
async listFromDirectoryScan(limit) {
|
|
812
|
+
const refs = await this.collectSessionFiles(this.dir);
|
|
813
|
+
const candidates = await mapWithConcurrency(
|
|
814
|
+
refs,
|
|
815
|
+
_DefaultSessionStore.LIST_SCAN_CONCURRENCY,
|
|
816
|
+
async (ref) => {
|
|
817
|
+
const manifest = await this.readSummaryManifest(ref.id);
|
|
818
|
+
if (manifest) return { summary: manifest, needsBackfill: false };
|
|
819
|
+
const summary = await this.summaryHeaderFor(ref);
|
|
820
|
+
return summary ? { summary, needsBackfill: true } : null;
|
|
821
|
+
}
|
|
822
|
+
);
|
|
823
|
+
const out = candidates.filter((s) => s !== null);
|
|
824
|
+
out.sort((a, b) => compareSessionSummaries(a.summary, b.summary));
|
|
825
|
+
const selected = out.slice(0, limit);
|
|
826
|
+
const summaries = await mapWithConcurrency(
|
|
827
|
+
selected,
|
|
828
|
+
Math.min(_DefaultSessionStore.LIST_SCAN_CONCURRENCY, Math.max(1, limit)),
|
|
829
|
+
async (candidate) => {
|
|
830
|
+
if (!candidate.needsBackfill) return candidate.summary;
|
|
831
|
+
return await this.summaryFor(candidate.summary.id).catch(() => candidate.summary);
|
|
832
|
+
}
|
|
833
|
+
);
|
|
834
|
+
return summaries.filter((s) => s !== null);
|
|
835
|
+
}
|
|
836
|
+
async collectSessionFiles(dir, prefix = "", depth = 0) {
|
|
837
|
+
let entries;
|
|
838
|
+
try {
|
|
839
|
+
entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
840
|
+
} catch {
|
|
841
|
+
return [];
|
|
842
|
+
}
|
|
843
|
+
const dirEntries = [];
|
|
844
|
+
const files = [];
|
|
845
|
+
for (const entry of entries) {
|
|
846
|
+
if (entry.name.startsWith(".") && entry.name !== ".wrongstack") continue;
|
|
847
|
+
if (entry.name === "shared" || entry.name === "subagents" || entry.name === "attachments")
|
|
848
|
+
continue;
|
|
849
|
+
if (entry.isDirectory()) {
|
|
850
|
+
dirEntries.push(entry);
|
|
851
|
+
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
852
|
+
if (entry.name === "_index.jsonl") continue;
|
|
853
|
+
const base = entry.name.replace(/\.jsonl$/, "");
|
|
854
|
+
const id = prefix ? `${prefix}/${base}` : base;
|
|
855
|
+
files.push({ id, filePath: path2.join(dir, entry.name) });
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
const childFileArrays = await Promise.all(
|
|
859
|
+
dirEntries.map((entry) => {
|
|
860
|
+
const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
861
|
+
return this.collectSessionFiles(path2.join(dir, entry.name), childPrefix, depth + 1);
|
|
862
|
+
})
|
|
863
|
+
);
|
|
864
|
+
return [...childFileArrays.flat(), ...files];
|
|
865
|
+
}
|
|
817
866
|
/** Recursively collect session IDs from date-shard subdirectories.
|
|
818
867
|
* IDs include the date-prefix path (e.g. "2026-06-06/17-46-57Z_…").
|
|
819
868
|
* Skips `.jsonl`/`.summary.json` root files, dot-files, and
|
|
820
869
|
* sub-directories that belong to fleet/subagent sessions. */
|
|
821
870
|
async collectSessionIds(dir, prefix = "", depth = 0) {
|
|
822
|
-
const ids = [];
|
|
823
871
|
let entries;
|
|
824
872
|
try {
|
|
825
873
|
entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
826
874
|
} catch {
|
|
827
|
-
return
|
|
875
|
+
return [];
|
|
828
876
|
}
|
|
877
|
+
const dirEntries = [];
|
|
878
|
+
const fileIds = [];
|
|
829
879
|
for (const entry of entries) {
|
|
830
880
|
if (entry.name.startsWith(".") && entry.name !== ".wrongstack") continue;
|
|
831
881
|
if (entry.name === "shared" || entry.name === "subagents" || entry.name === "attachments")
|
|
832
882
|
continue;
|
|
833
883
|
if (entry.isDirectory()) {
|
|
834
|
-
|
|
835
|
-
ids.push(...await this.collectSessionIds(path2.join(dir, entry.name), childPrefix, depth + 1));
|
|
884
|
+
dirEntries.push(entry);
|
|
836
885
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
837
886
|
if (entry.name === "_index.jsonl") continue;
|
|
838
887
|
const base = entry.name.replace(/\.jsonl$/, "");
|
|
839
|
-
|
|
888
|
+
fileIds.push(prefix ? `${prefix}/${base}` : base);
|
|
840
889
|
}
|
|
841
890
|
}
|
|
842
|
-
|
|
891
|
+
const childIdArrays = await Promise.all(
|
|
892
|
+
dirEntries.map((entry) => {
|
|
893
|
+
const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
894
|
+
return this.collectSessionIds(path2.join(dir, entry.name), childPrefix, depth + 1);
|
|
895
|
+
})
|
|
896
|
+
);
|
|
897
|
+
return [...childIdArrays.flat(), ...fileIds];
|
|
843
898
|
}
|
|
844
899
|
async summaryFor(id) {
|
|
845
900
|
const manifest = this.sessionPath(id, ".summary.json");
|
|
846
901
|
const t0 = Date.now();
|
|
847
902
|
let outcome = "success";
|
|
848
903
|
let errorMsg;
|
|
904
|
+
const fromManifest = await this.readSummaryManifest(id, t0);
|
|
905
|
+
if (fromManifest) return fromManifest;
|
|
849
906
|
try {
|
|
850
|
-
const raw = await fsp.readFile(manifest, "utf8");
|
|
851
|
-
this.emitRead(id, manifest, "summary", "success", Date.now() - t0);
|
|
852
|
-
return JSON.parse(raw);
|
|
853
|
-
} catch {
|
|
854
907
|
const full = this.sessionPath(id, ".jsonl");
|
|
855
908
|
const stat7 = await fsp.stat(full);
|
|
856
909
|
const summary = await this.summarize(id, stat7.mtime.toISOString());
|
|
@@ -869,6 +922,78 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
869
922
|
errorMsg = "summary fallback \u2014 manifest rebuilt";
|
|
870
923
|
this.emitRead(id, manifest, "summary", outcome, Date.now() - t0, errorMsg);
|
|
871
924
|
return summary;
|
|
925
|
+
} catch (err) {
|
|
926
|
+
outcome = "failure";
|
|
927
|
+
errorMsg = toErrorMessage(err);
|
|
928
|
+
this.emitRead(id, manifest, "summary", outcome, Date.now() - t0, errorMsg);
|
|
929
|
+
return {
|
|
930
|
+
id,
|
|
931
|
+
title: "(damaged)",
|
|
932
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
933
|
+
model: "unknown",
|
|
934
|
+
provider: "unknown",
|
|
935
|
+
tokenTotal: 0
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
async readSummaryManifest(id, startTime = Date.now()) {
|
|
940
|
+
const manifest = this.sessionPath(id, ".summary.json");
|
|
941
|
+
try {
|
|
942
|
+
const raw = await fsp.readFile(manifest, "utf8");
|
|
943
|
+
this.emitRead(id, manifest, "summary", "success", Date.now() - startTime);
|
|
944
|
+
return JSON.parse(raw);
|
|
945
|
+
} catch {
|
|
946
|
+
return null;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
async summaryHeaderFor(ref) {
|
|
950
|
+
let mtime = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
951
|
+
try {
|
|
952
|
+
const stat7 = await fsp.stat(ref.filePath);
|
|
953
|
+
if (!stat7.isFile()) {
|
|
954
|
+
return {
|
|
955
|
+
id: ref.id,
|
|
956
|
+
title: "(damaged)",
|
|
957
|
+
startedAt: stat7.mtime.toISOString(),
|
|
958
|
+
model: "unknown",
|
|
959
|
+
provider: "unknown",
|
|
960
|
+
tokenTotal: 0
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
mtime = stat7.mtime.toISOString();
|
|
964
|
+
} catch {
|
|
965
|
+
return null;
|
|
966
|
+
}
|
|
967
|
+
try {
|
|
968
|
+
for await (const event of this.iterSessionEvents(ref.filePath)) {
|
|
969
|
+
if (event.type === "session_start") {
|
|
970
|
+
return {
|
|
971
|
+
id: ref.id,
|
|
972
|
+
title: "(empty session)",
|
|
973
|
+
startedAt: event.ts,
|
|
974
|
+
model: event.model ?? "unknown",
|
|
975
|
+
provider: event.provider ?? "unknown",
|
|
976
|
+
tokenTotal: 0
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
return {
|
|
981
|
+
id: ref.id,
|
|
982
|
+
title: "(empty session)",
|
|
983
|
+
startedAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
984
|
+
model: "unknown",
|
|
985
|
+
provider: "unknown",
|
|
986
|
+
tokenTotal: 0
|
|
987
|
+
};
|
|
988
|
+
} catch {
|
|
989
|
+
return {
|
|
990
|
+
id: ref.id,
|
|
991
|
+
title: "(damaged)",
|
|
992
|
+
startedAt: mtime,
|
|
993
|
+
model: "unknown",
|
|
994
|
+
provider: "unknown",
|
|
995
|
+
tokenTotal: 0
|
|
996
|
+
};
|
|
872
997
|
}
|
|
873
998
|
}
|
|
874
999
|
/**
|
|
@@ -993,39 +1118,62 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
993
1118
|
}
|
|
994
1119
|
async summarize(id, mtime) {
|
|
995
1120
|
try {
|
|
996
|
-
const
|
|
997
|
-
|
|
998
|
-
|
|
1121
|
+
const file = this.sessionPath(id, ".jsonl");
|
|
1122
|
+
let title = "(empty session)";
|
|
1123
|
+
let startedAt = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
1124
|
+
let endedAt;
|
|
1125
|
+
let model = "unknown";
|
|
1126
|
+
let provider = "unknown";
|
|
1127
|
+
let tokenIn = 0;
|
|
1128
|
+
let tokenOut = 0;
|
|
999
1129
|
let iterationCount = 0;
|
|
1000
1130
|
let toolCallCount = 0;
|
|
1001
1131
|
let toolErrorCount = 0;
|
|
1002
1132
|
let fileChangeCount = 0;
|
|
1003
1133
|
const toolBreakdown = {};
|
|
1004
1134
|
let outcome;
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1135
|
+
let lastEventType;
|
|
1136
|
+
let hasError = false;
|
|
1137
|
+
let sawStart = false;
|
|
1138
|
+
for await (const e of this.iterSessionEvents(file)) {
|
|
1139
|
+
lastEventType = e.type;
|
|
1140
|
+
if (e.type === "session_start") {
|
|
1141
|
+
if (!sawStart) {
|
|
1142
|
+
sawStart = true;
|
|
1143
|
+
startedAt = e.ts;
|
|
1144
|
+
model = e.model ?? "unknown";
|
|
1145
|
+
provider = e.provider ?? "unknown";
|
|
1146
|
+
}
|
|
1147
|
+
} else if (e.type === "session_end") {
|
|
1148
|
+
endedAt = e.ts;
|
|
1149
|
+
} else if (e.type === "user_input") {
|
|
1150
|
+
if (title === "(empty session)") title = userInputTitle(e.content);
|
|
1151
|
+
} else if (e.type === "llm_response") {
|
|
1152
|
+
tokenIn += e.usage.input ?? 0;
|
|
1153
|
+
tokenOut += e.usage.output ?? 0;
|
|
1154
|
+
} else if (e.type === "in_flight_start") iterationCount++;
|
|
1008
1155
|
else if (e.type === "tool_call_start") {
|
|
1009
1156
|
toolCallCount++;
|
|
1010
1157
|
toolBreakdown[e.name] = (toolBreakdown[e.name] ?? 0) + 1;
|
|
1011
1158
|
} else if (e.type === "tool_result" && e.isError) toolErrorCount++;
|
|
1012
1159
|
else if (e.type === "file_snapshot") fileChangeCount += e.files.length;
|
|
1160
|
+
else if (e.type === "error" || e.type === "provider_error") hasError = true;
|
|
1013
1161
|
}
|
|
1014
|
-
if (
|
|
1162
|
+
if (lastEventType === "session_end") {
|
|
1015
1163
|
outcome = "completed";
|
|
1016
|
-
} else if (
|
|
1164
|
+
} else if (lastEventType === "in_flight_start") {
|
|
1017
1165
|
outcome = "aborted";
|
|
1018
|
-
} else if (
|
|
1166
|
+
} else if (hasError) {
|
|
1019
1167
|
outcome = "error";
|
|
1020
1168
|
}
|
|
1021
1169
|
return {
|
|
1022
1170
|
id,
|
|
1023
1171
|
title,
|
|
1024
|
-
startedAt
|
|
1025
|
-
endedAt
|
|
1026
|
-
model
|
|
1027
|
-
provider
|
|
1028
|
-
tokenTotal:
|
|
1172
|
+
startedAt,
|
|
1173
|
+
endedAt,
|
|
1174
|
+
model,
|
|
1175
|
+
provider,
|
|
1176
|
+
tokenTotal: tokenIn + tokenOut,
|
|
1029
1177
|
iterationCount: iterationCount > 0 ? iterationCount : void 0,
|
|
1030
1178
|
toolCallCount: toolCallCount > 0 ? toolCallCount : void 0,
|
|
1031
1179
|
toolErrorCount: toolErrorCount > 0 ? toolErrorCount : void 0,
|
|
@@ -1044,6 +1192,25 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
1044
1192
|
};
|
|
1045
1193
|
}
|
|
1046
1194
|
}
|
|
1195
|
+
async *iterSessionEvents(file) {
|
|
1196
|
+
const stream = createReadStream(file, { encoding: "utf8" });
|
|
1197
|
+
const lines = createInterface({ input: stream, crlfDelay: Infinity });
|
|
1198
|
+
try {
|
|
1199
|
+
for await (const line of lines) {
|
|
1200
|
+
if (!line.trim()) continue;
|
|
1201
|
+
try {
|
|
1202
|
+
const parsed = JSON.parse(line);
|
|
1203
|
+
if (parsed !== null && typeof parsed === "object" && typeof parsed.type === "string" && typeof parsed.ts === "string") {
|
|
1204
|
+
yield parsed;
|
|
1205
|
+
}
|
|
1206
|
+
} catch {
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
} finally {
|
|
1210
|
+
lines.close();
|
|
1211
|
+
stream.destroy();
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1047
1214
|
metaFromEvents(id, events) {
|
|
1048
1215
|
const start = events.find((e) => e.type === "session_start");
|
|
1049
1216
|
const end = events.findLast((e) => e.type === "session_end");
|
|
@@ -1707,6 +1874,27 @@ function userInputTitle(content) {
|
|
|
1707
1874
|
const text = typeof content === "string" ? content : content.filter((b) => b.type === "text").map((b) => b.text).join(" ");
|
|
1708
1875
|
return (text || "(non-text input)").slice(0, 60);
|
|
1709
1876
|
}
|
|
1877
|
+
function compareSessionSummaries(a, b) {
|
|
1878
|
+
if (a.startedAt < b.startedAt) return 1;
|
|
1879
|
+
if (a.startedAt > b.startedAt) return -1;
|
|
1880
|
+
return a.id.localeCompare(b.id);
|
|
1881
|
+
}
|
|
1882
|
+
async function mapWithConcurrency(items, concurrency, fn) {
|
|
1883
|
+
if (items.length === 0) return [];
|
|
1884
|
+
const out = new Array(items.length);
|
|
1885
|
+
let next = 0;
|
|
1886
|
+
const workerCount = Math.min(Math.max(1, concurrency), items.length);
|
|
1887
|
+
const workers = Array.from({ length: workerCount }, async () => {
|
|
1888
|
+
for (; ; ) {
|
|
1889
|
+
const idx = next++;
|
|
1890
|
+
if (idx >= items.length) return;
|
|
1891
|
+
const item = items[idx];
|
|
1892
|
+
if (item !== void 0) out[idx] = await fn(item);
|
|
1893
|
+
}
|
|
1894
|
+
});
|
|
1895
|
+
await Promise.all(workers);
|
|
1896
|
+
return out;
|
|
1897
|
+
}
|
|
1710
1898
|
var QueueStore = class {
|
|
1711
1899
|
file;
|
|
1712
1900
|
// Use `| undefined` (not `?`) so exactOptionalPropertyTypes doesn't
|
|
@@ -2767,6 +2955,12 @@ var GraphMemoryBackend = class {
|
|
|
2767
2955
|
edges = [];
|
|
2768
2956
|
loadedScope = null;
|
|
2769
2957
|
loaded = false;
|
|
2958
|
+
/**
|
|
2959
|
+
* Promise that resolves when the current in-flight _saveGraph completes.
|
|
2960
|
+
* Tests call flush() to await this before deleting the backend or its temp dir.
|
|
2961
|
+
* Each save operation chains onto the previous one so concurrent saves are serialised.
|
|
2962
|
+
*/
|
|
2963
|
+
_saveDone = Promise.resolve();
|
|
2770
2964
|
constructor(opts) {
|
|
2771
2965
|
this.file = new FileMemoryBackend({ paths: opts.paths });
|
|
2772
2966
|
this.graphFile = opts.graphPath ?? `${opts.paths.projectDir}/memory-graph.json`;
|
|
@@ -2793,7 +2987,8 @@ var GraphMemoryBackend = class {
|
|
|
2793
2987
|
tags: entry.tags,
|
|
2794
2988
|
priority: entry.priority
|
|
2795
2989
|
});
|
|
2796
|
-
|
|
2990
|
+
const recentNodes = [...this.nodes.values()].slice(-100);
|
|
2991
|
+
for (const other of recentNodes) {
|
|
2797
2992
|
if (other.id === nodeId) continue;
|
|
2798
2993
|
const sim = wordOverlap(entry.text, other.entry.text);
|
|
2799
2994
|
const tagSim = sharedTags(entry.tags ?? [], other.tags ?? []);
|
|
@@ -2809,7 +3004,8 @@ var GraphMemoryBackend = class {
|
|
|
2809
3004
|
}
|
|
2810
3005
|
}
|
|
2811
3006
|
}
|
|
2812
|
-
|
|
3007
|
+
this._saveDone = this._saveGraph(scope);
|
|
3008
|
+
await this._saveDone;
|
|
2813
3009
|
}
|
|
2814
3010
|
async forget(scope, query, filePath) {
|
|
2815
3011
|
const removed = await this.file.forget(scope, query, filePath);
|
|
@@ -2824,7 +3020,8 @@ var GraphMemoryBackend = class {
|
|
|
2824
3020
|
}
|
|
2825
3021
|
for (const id of toRemove) this.nodes.delete(id);
|
|
2826
3022
|
this.edges = this.edges.filter((e) => !toRemove.includes(e.from) && !toRemove.includes(e.to));
|
|
2827
|
-
|
|
3023
|
+
this._saveDone = this._saveGraph(scope);
|
|
3024
|
+
await this._saveDone;
|
|
2828
3025
|
}
|
|
2829
3026
|
return removed;
|
|
2830
3027
|
}
|
|
@@ -2936,7 +3133,8 @@ var GraphMemoryBackend = class {
|
|
|
2936
3133
|
this.loadedScope = scope;
|
|
2937
3134
|
this.loaded = true;
|
|
2938
3135
|
}
|
|
2939
|
-
|
|
3136
|
+
/** Fire-and-forget graph persistence. Named _saveGraph to signal it must not be awaited. */
|
|
3137
|
+
async _saveGraph(scope) {
|
|
2940
3138
|
this.loadedScope = scope;
|
|
2941
3139
|
this.loaded = true;
|
|
2942
3140
|
try {
|
|
@@ -2944,16 +3142,21 @@ var GraphMemoryBackend = class {
|
|
|
2944
3142
|
nodes: [...this.nodes.entries()],
|
|
2945
3143
|
edges: this.edges
|
|
2946
3144
|
};
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
{ recursive: true }
|
|
2950
|
-
);
|
|
3145
|
+
const dir = this.graphFile.substring(0, this.graphFile.lastIndexOf("/"));
|
|
3146
|
+
await fsp.mkdir(dir, { recursive: true });
|
|
2951
3147
|
const tmp = `${this.graphFile}.tmp`;
|
|
2952
3148
|
await fsp.writeFile(tmp, JSON.stringify(data));
|
|
2953
3149
|
await fsp.rename(tmp, this.graphFile);
|
|
2954
3150
|
} catch {
|
|
2955
3151
|
}
|
|
2956
3152
|
}
|
|
3153
|
+
/**
|
|
3154
|
+
* Wait for all in-flight _saveGraph operations to complete.
|
|
3155
|
+
* Call this before deleting the backend or its temp directory.
|
|
3156
|
+
*/
|
|
3157
|
+
async flush() {
|
|
3158
|
+
await this._saveDone;
|
|
3159
|
+
}
|
|
2957
3160
|
};
|
|
2958
3161
|
function wordOverlap(a, b) {
|
|
2959
3162
|
const wordsA = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
@@ -3054,84 +3257,89 @@ var SessionMemoryConsolidator = class {
|
|
|
3054
3257
|
this.minIterations = opts.minIterations ?? 2;
|
|
3055
3258
|
this.maxExistingEntries = opts.maxExistingEntries ?? 15;
|
|
3056
3259
|
}
|
|
3057
|
-
afterRun =
|
|
3260
|
+
afterRun = (ctx, result) => {
|
|
3058
3261
|
if (result.status !== "done") return;
|
|
3059
3262
|
if (!result.finalText || result.finalText.trim().length < 20) return;
|
|
3060
3263
|
if (result.iterations < this.minIterations) return;
|
|
3061
3264
|
const provider = this.provider ?? ctx.provider;
|
|
3062
3265
|
if (!provider?.complete) return;
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
existingEntries
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3266
|
+
const _finalText = result.finalText;
|
|
3267
|
+
const _iterations = result.iterations;
|
|
3268
|
+
const _model = this.model ?? ctx.model;
|
|
3269
|
+
void (async () => {
|
|
3270
|
+
try {
|
|
3271
|
+
const existingEntries = await this.memoryStore.list("project-memory", this.maxExistingEntries);
|
|
3272
|
+
const prompt = buildConsolidationPrompt(
|
|
3273
|
+
_finalText,
|
|
3274
|
+
_iterations,
|
|
3275
|
+
existingEntries
|
|
3276
|
+
);
|
|
3277
|
+
const signal = AbortSignal.timeout(15e3);
|
|
3278
|
+
const response = await provider.complete(
|
|
3279
|
+
{
|
|
3280
|
+
model: _model,
|
|
3281
|
+
system: [{ type: "text", text: prompt }],
|
|
3282
|
+
messages: [
|
|
3283
|
+
{ role: "user", content: "Review the session and return memory operations as JSON." }
|
|
3284
|
+
],
|
|
3285
|
+
maxTokens: 500
|
|
3286
|
+
},
|
|
3287
|
+
{ signal }
|
|
3288
|
+
);
|
|
3289
|
+
const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("").trim();
|
|
3290
|
+
if (!text) return;
|
|
3291
|
+
const jsonMatch = text.match(/\{[\s\S]*\}/);
|
|
3292
|
+
if (!jsonMatch) return;
|
|
3293
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
3294
|
+
if (!Array.isArray(parsed.operations) || parsed.operations.length === 0) return;
|
|
3295
|
+
let added = 0;
|
|
3296
|
+
let edited = 0;
|
|
3297
|
+
let deleted = 0;
|
|
3298
|
+
for (const op of parsed.operations) {
|
|
3299
|
+
switch (op.action) {
|
|
3300
|
+
case "add": {
|
|
3301
|
+
if (op.text?.trim()) {
|
|
3302
|
+
await this.memoryStore.remember(op.text.trim(), void 0, {
|
|
3303
|
+
type: op.type,
|
|
3304
|
+
tags: op.tags,
|
|
3305
|
+
priority: op.priority
|
|
3306
|
+
});
|
|
3307
|
+
added++;
|
|
3308
|
+
}
|
|
3309
|
+
break;
|
|
3101
3310
|
}
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
}
|
|
3112
|
-
|
|
3311
|
+
case "edit": {
|
|
3312
|
+
if (op.query && op.text?.trim()) {
|
|
3313
|
+
await this.memoryStore.forget(op.query);
|
|
3314
|
+
await this.memoryStore.remember(op.text.trim(), void 0, {
|
|
3315
|
+
type: op.type,
|
|
3316
|
+
tags: op.tags,
|
|
3317
|
+
priority: op.priority
|
|
3318
|
+
});
|
|
3319
|
+
edited++;
|
|
3320
|
+
}
|
|
3321
|
+
break;
|
|
3113
3322
|
}
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3323
|
+
case "delete": {
|
|
3324
|
+
if (op.query) {
|
|
3325
|
+
const n = await this.memoryStore.forget(op.query);
|
|
3326
|
+
deleted += n;
|
|
3327
|
+
}
|
|
3328
|
+
break;
|
|
3120
3329
|
}
|
|
3121
|
-
break;
|
|
3122
3330
|
}
|
|
3123
3331
|
}
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
process.stderr.write(`[memory] Session consolidation: ${parts.join(", ")}
|
|
3332
|
+
if (added > 0 || edited > 0 || deleted > 0) {
|
|
3333
|
+
const parts = [];
|
|
3334
|
+
if (added) parts.push(`${added} added`);
|
|
3335
|
+
if (edited) parts.push(`${edited} edited`);
|
|
3336
|
+
if (deleted) parts.push(`${deleted} deleted`);
|
|
3337
|
+
process.stderr.write(`[memory] Session consolidation: ${parts.join(", ")}
|
|
3131
3338
|
`);
|
|
3339
|
+
}
|
|
3340
|
+
} catch {
|
|
3132
3341
|
}
|
|
3133
|
-
}
|
|
3134
|
-
}
|
|
3342
|
+
})();
|
|
3135
3343
|
};
|
|
3136
3344
|
};
|
|
3137
3345
|
|
|
@@ -3297,8 +3505,13 @@ function deepFreeze(obj) {
|
|
|
3297
3505
|
return Object.freeze(obj);
|
|
3298
3506
|
}
|
|
3299
3507
|
var KEY_BYTES = 32;
|
|
3508
|
+
var IV_BYTES = 12;
|
|
3509
|
+
var TAG_BYTES = 16;
|
|
3300
3510
|
var KEY_FILE_MAGIC = Buffer.from("WSKV", "ascii");
|
|
3301
3511
|
KEY_FILE_MAGIC.length + 1 + KEY_BYTES;
|
|
3512
|
+
var KEK_MAGIC = Buffer.from("WSKW", "ascii");
|
|
3513
|
+
var KEK_SALT_BYTES = 16;
|
|
3514
|
+
KEK_MAGIC.length + 1 + KEK_SALT_BYTES + IV_BYTES + TAG_BYTES + KEY_BYTES;
|
|
3302
3515
|
function decryptConfigSecrets(cfg, vault, opts) {
|
|
3303
3516
|
const warn = ((msg) => console.warn(msg));
|
|
3304
3517
|
return walk(cfg, vault, (v, key) => {
|
|
@@ -3514,6 +3727,42 @@ var defaultIndexing = {
|
|
|
3514
3727
|
watchExternal: true,
|
|
3515
3728
|
debounceMs: 400
|
|
3516
3729
|
};
|
|
3730
|
+
var IN_PROJECT_FORBIDDEN_KEYS = /* @__PURE__ */ new Set([
|
|
3731
|
+
"provider",
|
|
3732
|
+
"apiKey",
|
|
3733
|
+
"baseUrl",
|
|
3734
|
+
"providers",
|
|
3735
|
+
"mcpServers",
|
|
3736
|
+
"hooks",
|
|
3737
|
+
"plugins",
|
|
3738
|
+
"sync",
|
|
3739
|
+
"yolo",
|
|
3740
|
+
"extensions"
|
|
3741
|
+
]);
|
|
3742
|
+
function stripUnsafeInProjectFields(inProject, sourcePath, warn = (msg) => console.warn(msg)) {
|
|
3743
|
+
const stripped = [];
|
|
3744
|
+
const out = {};
|
|
3745
|
+
for (const [k, v] of Object.entries(inProject)) {
|
|
3746
|
+
if (IN_PROJECT_FORBIDDEN_KEYS.has(k)) {
|
|
3747
|
+
stripped.push(k);
|
|
3748
|
+
continue;
|
|
3749
|
+
}
|
|
3750
|
+
out[k] = v;
|
|
3751
|
+
}
|
|
3752
|
+
if (stripped.length > 0) {
|
|
3753
|
+
warn(
|
|
3754
|
+
JSON.stringify({
|
|
3755
|
+
level: "warn",
|
|
3756
|
+
event: "config.in_project_unsafe_fields_ignored",
|
|
3757
|
+
path: sourcePath,
|
|
3758
|
+
ignoredKeys: stripped,
|
|
3759
|
+
message: `Ignored ${stripped.length} unsafe field(s) from the repo-committed config "${sourcePath}": ${stripped.join(", ")}. These can only be set in your personal ~/.wrongstack/config.json, not in a project-committed file.`,
|
|
3760
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3761
|
+
})
|
|
3762
|
+
);
|
|
3763
|
+
}
|
|
3764
|
+
return out;
|
|
3765
|
+
}
|
|
3517
3766
|
function deepMerge2(base, patch) {
|
|
3518
3767
|
const opts = { arrayMode: "concat-primitives" };
|
|
3519
3768
|
if (envBoolOptional(process.env.WRONGSTACK_DEBUG_CONFIG)) {
|
|
@@ -3549,7 +3798,7 @@ var DefaultConfigLoader = class {
|
|
|
3549
3798
|
]);
|
|
3550
3799
|
cfg = deepMerge2(cfg, global);
|
|
3551
3800
|
cfg = deepMerge2(cfg, local);
|
|
3552
|
-
cfg = deepMerge2(cfg, inProject);
|
|
3801
|
+
cfg = deepMerge2(cfg, stripUnsafeInProjectFields(inProject, this.paths.inProjectConfig));
|
|
3553
3802
|
for (const [key, fn] of Object.entries(ENV_MAP)) {
|
|
3554
3803
|
const v = process.env[key];
|
|
3555
3804
|
if (v) fn(cfg, v);
|
|
@@ -5814,6 +6063,9 @@ var AgentStatusTracker = class {
|
|
|
5814
6063
|
leaderName;
|
|
5815
6064
|
// Live agent map: agentId → AgentEntry
|
|
5816
6065
|
agents = /* @__PURE__ */ new Map();
|
|
6066
|
+
// Last full agent list flushed (leader + subagents). Lets external consumers
|
|
6067
|
+
// read the current state synchronously without re-deriving it.
|
|
6068
|
+
lastAgents = [];
|
|
5817
6069
|
// Leader tracking
|
|
5818
6070
|
leaderStatus = "idle";
|
|
5819
6071
|
leaderCurrentTool;
|
|
@@ -5835,6 +6087,10 @@ var AgentStatusTracker = class {
|
|
|
5835
6087
|
this.leaderName = opts.leaderName ?? "leader";
|
|
5836
6088
|
this.onUpdate = opts.onUpdate;
|
|
5837
6089
|
}
|
|
6090
|
+
/** Current full agent list (leader + subagents) as of the last flush. */
|
|
6091
|
+
getAgents() {
|
|
6092
|
+
return this.lastAgents.length > 0 ? [...this.lastAgents] : [];
|
|
6093
|
+
}
|
|
5838
6094
|
start() {
|
|
5839
6095
|
this.unsubscribers.push(
|
|
5840
6096
|
this.events.onPattern("agent.run.started", () => {
|
|
@@ -6076,6 +6332,11 @@ var AgentStatusTracker = class {
|
|
|
6076
6332
|
lastActivityAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6077
6333
|
};
|
|
6078
6334
|
const allAgents = [leaderEntry, ...this.agents.values()];
|
|
6335
|
+
this.lastAgents = allAgents;
|
|
6336
|
+
try {
|
|
6337
|
+
this.events.emit("session.agents_updated", { agents: allAgents });
|
|
6338
|
+
} catch {
|
|
6339
|
+
}
|
|
6079
6340
|
this.registry.updateAgents(allAgents).then(() => {
|
|
6080
6341
|
try {
|
|
6081
6342
|
this.onUpdate?.();
|
|
@@ -7831,6 +8092,6 @@ function resolveSessionLoggingConfig(cfg) {
|
|
|
7831
8092
|
};
|
|
7832
8093
|
}
|
|
7833
8094
|
|
|
7834
|
-
export { ALL_SYNC_CATEGORIES, AgentStatusTracker, AnnotationsStore, CORE_RECONSTRUCT_EVENTS, CloudSync, ConfigMigrationError, DEFAULT_CONFIG_MIGRATIONS, DefaultAttachmentStore, DefaultConfigLoader, DefaultConfigStore, DefaultMemoryStore, DefaultPromptStore, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, DirectorStateCheckpoint, FileMemoryBackend, FleetNotifier, GraphMemoryBackend, MAX_JOURNAL_ENTRIES, MAX_PROGRESS_HISTORY, QueueStore, RecoveryLock, ReplayLogStore, STANDARD_AUDIT_EVENTS, SessionAnalyzer, SessionMemoryConsolidator, SessionRecovery, SessionRegistry, ToolAuditLog, addPlanItem, appendJournal, attachPlanCheckpoint, attachTodosCheckpoint, clearPlan, createSessionEventBridge, deriveTodosFromPlanItem, emptyGoal, emptyPlan, emptyTaskFile, formatGoal, formatPlan, formatPlanTemplates, getPlanTemplate, getSessionRegistry, goalFilePath, hasSessionRegistry, listPlanTemplates, loadDirectorState, loadGoal, loadPlan, loadTasks, loadTodosCheckpoint, mutatePlan, mutateTasks, parseEntries, parseProgressFromText, recordProgress, removePlanItem, resolveAuditLevel, resolveSessionLoggingConfig, runConfigMigrations, saveGoal, savePlan, saveTasks, saveTodosCheckpoint, setPlanItemStatus, setProgress, summarizeUsage };
|
|
8095
|
+
export { ALL_SYNC_CATEGORIES, AgentStatusTracker, AnnotationsStore, CORE_RECONSTRUCT_EVENTS, CloudSync, ConfigMigrationError, DEFAULT_CONFIG_MIGRATIONS, DefaultAttachmentStore, DefaultConfigLoader, DefaultConfigStore, DefaultMemoryStore, DefaultPromptStore, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, DirectorStateCheckpoint, FileMemoryBackend, FleetNotifier, GraphMemoryBackend, MAX_JOURNAL_ENTRIES, MAX_PROGRESS_HISTORY, QueueStore, RecoveryLock, ReplayLogStore, STANDARD_AUDIT_EVENTS, SessionAnalyzer, SessionMemoryConsolidator, SessionRecovery, SessionRegistry, ToolAuditLog, addPlanItem, appendJournal, attachPlanCheckpoint, attachTodosCheckpoint, clearPlan, createSessionEventBridge, deriveTodosFromPlanItem, emptyGoal, emptyPlan, emptyTaskFile, formatGoal, formatPlan, formatPlanTemplates, generateSessionId, getPlanTemplate, getSessionRegistry, goalFilePath, hasSessionRegistry, listPlanTemplates, loadDirectorState, loadGoal, loadPlan, loadTasks, loadTodosCheckpoint, mutatePlan, mutateTasks, parseEntries, parseProgressFromText, recordProgress, removePlanItem, resolveAuditLevel, resolveSessionLoggingConfig, runConfigMigrations, sanitizeModel, saveGoal, savePlan, saveTasks, saveTodosCheckpoint, setPlanItemStatus, setProgress, summarizeUsage };
|
|
7835
8096
|
//# sourceMappingURL=index.js.map
|
|
7836
8097
|
//# sourceMappingURL=index.js.map
|