@aurora-foundation/obsidian-next 0.4.7 → 0.4.9
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/CHANGELOG.md +23 -0
- package/LICENSE +628 -190
- package/README.md +23 -9
- package/dist/auditLog-6WDBDNYL.js +8 -0
- package/dist/auditLog-HGPVDSDC.js +8 -0
- package/dist/auditLog-TDIKFBM4.js +8 -0
- package/dist/auditLog-XC2KY3ZZ.js +8 -0
- package/dist/chunk-2I235WNB.js +133 -0
- package/dist/chunk-2JWDGXTR.js +42 -0
- package/dist/chunk-2NOB6W2B.js +133 -0
- package/dist/chunk-3LFKVKKL.js +7199 -0
- package/dist/chunk-3U6WHPDX.js +4695 -0
- package/dist/chunk-3UCL6RYE.js +7272 -0
- package/dist/chunk-4GN2UQLI.js +130 -0
- package/dist/chunk-4MW33MZD.js +516 -0
- package/dist/chunk-4PUJBUKZ.js +4716 -0
- package/dist/chunk-4QHK6H6O.js +130 -0
- package/dist/chunk-55CQIHCO.js +133 -0
- package/dist/chunk-5LWINFWI.js +676 -0
- package/dist/chunk-5OKGLNQW.js +439 -0
- package/dist/chunk-5T6ETZEO.js +6183 -0
- package/dist/chunk-5WGIFUVL.js +4234 -0
- package/dist/chunk-66EW47T3.js +4237 -0
- package/dist/chunk-6TXUOTT2.js +581 -0
- package/dist/chunk-6YUYSYDA.js +130 -0
- package/dist/chunk-74VPNFMX.js +133 -0
- package/dist/chunk-77CGJRGV.js +6188 -0
- package/dist/chunk-7DS3VT4C.js +7135 -0
- package/dist/chunk-7FHX3VBT.js +133 -0
- package/dist/chunk-7MHF56YU.js +6178 -0
- package/dist/chunk-ABLPMV7G.js +133 -0
- package/dist/chunk-B77K6OQZ.js +687 -0
- package/dist/chunk-BKOXH66O.js +133 -0
- package/dist/chunk-BPP76UN2.js +130 -0
- package/dist/chunk-C4D56GRC.js +5936 -0
- package/dist/chunk-CCDPY4WE.js +370 -0
- package/dist/chunk-CHNVBJN3.js +7272 -0
- package/dist/chunk-CKBZI576.js +7229 -0
- package/dist/chunk-CW5HBSJ2.js +7198 -0
- package/dist/chunk-DGHDJEY7.js +133 -0
- package/dist/chunk-DPNIQWKZ.js +439 -0
- package/dist/chunk-DU4T3V2T.js +214 -0
- package/dist/chunk-DV3WFKNB.js +4679 -0
- package/dist/chunk-DZI2OVN2.js +516 -0
- package/dist/chunk-E45VILML.js +7198 -0
- package/dist/chunk-ECEUUYXC.js +7199 -0
- package/dist/chunk-EJRRSHPW.js +685 -0
- package/dist/chunk-EMBMLZFE.js +370 -0
- package/dist/chunk-EPG5V5OO.js +285 -0
- package/dist/chunk-F2R4HXXW.js +130 -0
- package/dist/chunk-FK6N66ES.js +581 -0
- package/dist/chunk-G3CZKGYA.js +197 -0
- package/dist/chunk-GUUPG4A7.js +7111 -0
- package/dist/chunk-HBAAUGUN.js +7230 -0
- package/dist/chunk-HHFJMK2Q.js +6177 -0
- package/dist/chunk-HINRQTCZ.js +196 -0
- package/dist/chunk-HRKJ3R2U.js +288 -0
- package/dist/chunk-HWVK4CVE.js +439 -0
- package/dist/chunk-JEYSADNZ.js +581 -0
- package/dist/chunk-JNEIL7UN.js +4252 -0
- package/dist/chunk-JTWSK277.js +676 -0
- package/dist/chunk-K4CHTTCJ.js +942 -0
- package/dist/chunk-K7R5KUDS.js +4695 -0
- package/dist/chunk-KNJFOURE.js +7151 -0
- package/dist/chunk-KY22FIT3.js +7256 -0
- package/dist/chunk-L2OTIJSF.js +4228 -0
- package/dist/chunk-LEEBUHP6.js +4655 -0
- package/dist/chunk-LK7UP2T7.js +130 -0
- package/dist/chunk-LPGNO3PK.js +284 -0
- package/dist/chunk-LYQYJMWS.js +133 -0
- package/dist/chunk-MBYFJXR3.js +130 -0
- package/dist/chunk-N3WX44L3.js +130 -0
- package/dist/chunk-N6AQWES3.js +6197 -0
- package/dist/chunk-NW4XSTQZ.js +130 -0
- package/dist/chunk-NWG2XURH.js +130 -0
- package/dist/chunk-O3GF3LJD.js +6142 -0
- package/dist/chunk-OHP5LD3Y.js +6188 -0
- package/dist/chunk-P5PQSFZT.js +6182 -0
- package/dist/chunk-PAADOWNP.js +130 -0
- package/dist/chunk-PERGND7L.js +7213 -0
- package/dist/chunk-PWA7V4XX.js +179 -0
- package/dist/chunk-QGCWEP6L.js +7111 -0
- package/dist/chunk-QVT2IHNJ.js +175 -0
- package/dist/chunk-QZNGYPMS.js +6161 -0
- package/dist/chunk-R6P2E2ZQ.js +207 -0
- package/dist/chunk-ROSDMGIL.js +4679 -0
- package/dist/chunk-RQZP7IKG.js +196 -0
- package/dist/chunk-RUQSPX3U.js +133 -0
- package/dist/chunk-S3BYHP5M.js +130 -0
- package/dist/chunk-S6GNETVE.js +438 -0
- package/dist/chunk-SDT2ZE2R.js +133 -0
- package/dist/chunk-SHQBXJFC.js +6166 -0
- package/dist/chunk-TJNISYTE.js +42 -0
- package/dist/chunk-TJW74HFF.js +130 -0
- package/dist/chunk-TPP72DTK.js +7096 -0
- package/dist/chunk-UOESII6R.js +42 -0
- package/dist/chunk-UWEDGLYJ.js +6142 -0
- package/dist/chunk-V5FYNAFX.js +133 -0
- package/dist/chunk-VPURF6UT.js +7198 -0
- package/dist/chunk-VQH6LWIZ.js +6184 -0
- package/dist/chunk-VS22YVX6.js +7111 -0
- package/dist/chunk-VSF5KBW7.js +367 -0
- package/dist/chunk-VV3JMCKY.js +214 -0
- package/dist/chunk-W5L7HOE3.js +133 -0
- package/dist/chunk-WFEVQISK.js +676 -0
- package/dist/chunk-WJZPSCEP.js +516 -0
- package/dist/chunk-WLV4MKEF.js +16 -0
- package/dist/chunk-WSEVQFFI.js +5428 -0
- package/dist/chunk-X7N2RNR3.js +5428 -0
- package/dist/chunk-XKZNMRNO.js +133 -0
- package/dist/chunk-Y7BVEC36.js +130 -0
- package/dist/chunk-YG7YSNNU.js +4226 -0
- package/dist/chunk-YHM62466.js +261 -0
- package/dist/chunk-YLTYJLDZ.js +7208 -0
- package/dist/chunk-YPMJD4YE.js +56 -0
- package/dist/chunk-YTX3FU2A.js +7199 -0
- package/dist/chunk-ZEQ3EBBN.js +214 -0
- package/dist/chunk-ZIWLQSLK.js +42 -0
- package/dist/chunk-ZJELNTEO.js +516 -0
- package/dist/chunk-ZOSSVNGK.js +370 -0
- package/dist/config-EYK32F2E.js +10 -0
- package/dist/config-FJPPPYTY.js +10 -0
- package/dist/config-VAHPVILX.js +10 -0
- package/dist/context-2YGE4U75.js +10 -0
- package/dist/context-5UFVYKES.js +9 -0
- package/dist/context-ANZF4J72.js +10 -0
- package/dist/context-GLUNCUBQ.js +10 -0
- package/dist/context-M5ULPZKQ.js +10 -0
- package/dist/context-NYOIRZKV.js +10 -0
- package/dist/context-YP2REI6A.js +10 -0
- package/dist/database-MP2JBLMF.js +8 -0
- package/dist/index.js +6177 -4688
- package/dist/keyManager-P2SZONKE.js +8 -0
- package/dist/mcp/index.js +127 -47
- package/dist/memory-BPGJAL4J.js +13 -0
- package/dist/memory-FRQOUI6W.js +13 -0
- package/dist/memory-OAMK27IZ.js +13 -0
- package/dist/memory-OZ734ALL.js +13 -0
- package/dist/memory-PQ2EWRMU.js +13 -0
- package/dist/memory-PXL45M6W.js +13 -0
- package/dist/memory-QZTBTYPH.js +13 -0
- package/dist/migrations-TLJ3WRVW.js +188 -0
- package/dist/resume-2NHDK6EI.js +17 -0
- package/dist/resume-44L2PDB2.js +17 -0
- package/dist/resume-4MXIWUJO.js +7 -0
- package/dist/resume-72VJX66I.js +17 -0
- package/dist/resume-7ZW4XM3B.js +15 -0
- package/dist/resume-AZHYQ657.js +17 -0
- package/dist/resume-CNLXSYHV.js +17 -0
- package/dist/resume-DPN4Q777.js +16 -0
- package/dist/resume-DSFHVNPI.js +15 -0
- package/dist/resume-GHLQJJTO.js +17 -0
- package/dist/resume-HJ6SBWTF.js +17 -0
- package/dist/resume-HRLYHY2L.js +17 -0
- package/dist/resume-ISIQFKO6.js +17 -0
- package/dist/resume-JQDEA6PS.js +15 -0
- package/dist/resume-KP3Y3Y7P.js +17 -0
- package/dist/resume-M4KHR5OI.js +17 -0
- package/dist/resume-N62OAMBG.js +17 -0
- package/dist/resume-NNMA5POT.js +17 -0
- package/dist/resume-ODYT3J4H.js +17 -0
- package/dist/resume-PCFJXA5O.js +17 -0
- package/dist/resume-PLF4XGBD.js +15 -0
- package/dist/resume-Q2PFX57V.js +17 -0
- package/dist/resume-QB4XI2J5.js +17 -0
- package/dist/resume-R5MFTUPF.js +17 -0
- package/dist/resume-SVA7223Z.js +17 -0
- package/dist/resume-TYKKDJZI.js +17 -0
- package/dist/resume-XIS45HKV.js +17 -0
- package/dist/resume-YCSEJTU7.js +17 -0
- package/dist/resume-YD76GI2J.js +15 -0
- package/dist/resume-YDN7EL77.js +17 -0
- package/dist/resume-YE7DB4ZA.js +17 -0
- package/dist/resume-YKAKOXWV.js +15 -0
- package/dist/resume-ZHBCVFDY.js +17 -0
- package/dist/scheduler-2CK24A2Q.js +14 -0
- package/dist/scheduler-7OAF2XKX.js +14 -0
- package/dist/scheduler-AS23AAB5.js +14 -0
- package/dist/scheduler-PCOYQJA5.js +14 -0
- package/dist/scheduler-V2ECBQPK.js +14 -0
- package/dist/scheduler-VEWZ6L7V.js +13 -0
- package/dist/scheduler-W37QMGDQ.js +14 -0
- package/dist/session-2E2JKPD7.js +15 -0
- package/dist/session-2VSF257B.js +14 -0
- package/dist/session-4APFTDJU.js +14 -0
- package/dist/session-5YS5LNNL.js +16 -0
- package/dist/session-6MO5ZPOB.js +16 -0
- package/dist/session-6XMGPRTQ.js +14 -0
- package/dist/session-7DJR77R7.js +16 -0
- package/dist/session-7DQHPWTR.js +14 -0
- package/dist/session-ADKIQCR5.js +16 -0
- package/dist/session-AOGH2GGI.js +16 -0
- package/dist/session-C4W6GDYG.js +16 -0
- package/dist/session-DCGNGGMV.js +14 -0
- package/dist/session-F5JKZAN2.js +16 -0
- package/dist/session-G6F3O2FQ.js +16 -0
- package/dist/session-GFBSARRO.js +16 -0
- package/dist/session-H5IWAIUI.js +16 -0
- package/dist/session-IPFA6AHC.js +14 -0
- package/dist/session-IWG2UOAX.js +14 -0
- package/dist/session-KJ2K4Y4M.js +14 -0
- package/dist/session-KPXFBW6Q.js +14 -0
- package/dist/session-KR256UL5.js +16 -0
- package/dist/session-M72LJXPR.js +16 -0
- package/dist/session-MBK3FODN.js +14 -0
- package/dist/session-MOUFAU7G.js +16 -0
- package/dist/session-NRC6ZXFQ.js +16 -0
- package/dist/session-NRPQMV4K.js +16 -0
- package/dist/session-O5IFFJZQ.js +14 -0
- package/dist/session-OF5BGKDE.js +16 -0
- package/dist/session-OGRZMIM7.js +14 -0
- package/dist/session-OJOFAJG3.js +16 -0
- package/dist/session-OKU4N3SP.js +16 -0
- package/dist/session-P2VAOSFB.js +14 -0
- package/dist/session-PKOVZD4M.js +16 -0
- package/dist/session-POAIMUVN.js +16 -0
- package/dist/session-PSHFONFE.js +16 -0
- package/dist/session-QKYVVZFV.js +16 -0
- package/dist/session-QPWGBMUS.js +14 -0
- package/dist/session-R5UG5PZR.js +14 -0
- package/dist/session-RAY6BZRQ.js +16 -0
- package/dist/session-S3VATHMU.js +16 -0
- package/dist/session-SYTD7RHW.js +14 -0
- package/dist/session-UHMMVO4J.js +16 -0
- package/dist/session-WEX5K3ZY.js +14 -0
- package/dist/session-XFLOXGU3.js +14 -0
- package/dist/session-XV2A4HHG.js +14 -0
- package/dist/settings-3VPJYD4D.js +8 -0
- package/dist/settings-GZTJJTBK.js +8 -0
- package/dist/settings-YKJFSKMO.js +8 -0
- package/dist/shell-FM34624T.js +8 -0
- package/package.json +14 -4
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import {
|
|
2
|
+
config
|
|
3
|
+
} from "./chunk-PWA7V4XX.js";
|
|
4
|
+
import {
|
|
5
|
+
settings
|
|
6
|
+
} from "./chunk-EPG5V5OO.js";
|
|
7
|
+
import {
|
|
8
|
+
bus
|
|
9
|
+
} from "./chunk-WQM6FFSD.js";
|
|
10
|
+
import {
|
|
11
|
+
db
|
|
12
|
+
} from "./chunk-FNLWB54Z.js";
|
|
13
|
+
|
|
14
|
+
// src/core/context.ts
|
|
15
|
+
import path from "path";
|
|
16
|
+
var CONTEXT_CONFIG = {
|
|
17
|
+
DECAY_HALF_LIFE_MS: 36e5,
|
|
18
|
+
// 1 hour - files lose half their score every hour
|
|
19
|
+
MAX_WORKING_SET_SIZE: 50,
|
|
20
|
+
// Limit working set to prevent unbounded growth
|
|
21
|
+
IMPORTANCE_MODIFIED: 2,
|
|
22
|
+
// 2x weight for modified files
|
|
23
|
+
IMPORTANCE_ENTRY_POINT: 1.5,
|
|
24
|
+
// Higher weight for index.ts, main.ts, etc.
|
|
25
|
+
IMPORTANCE_RECENT_EDIT: 1.3,
|
|
26
|
+
// Files edited in last 5 interactions
|
|
27
|
+
TOKEN_ESTIMATE_PER_LINE: 4
|
|
28
|
+
// Rough estimate: 4 tokens per line
|
|
29
|
+
};
|
|
30
|
+
var ENTRY_POINT_PATTERNS = [
|
|
31
|
+
/^index\.(ts|tsx|js|jsx)$/,
|
|
32
|
+
/^main\.(ts|tsx|js|jsx)$/,
|
|
33
|
+
/^app\.(ts|tsx|js|jsx)$/,
|
|
34
|
+
/^server\.(ts|tsx|js|jsx)$/
|
|
35
|
+
];
|
|
36
|
+
function calculateRankScore(accessCount, lastAccessed, isModified, isEntryPoint) {
|
|
37
|
+
const ageMs = Date.now() - lastAccessed;
|
|
38
|
+
const decayFactor = Math.pow(0.5, ageMs / CONTEXT_CONFIG.DECAY_HALF_LIFE_MS);
|
|
39
|
+
let importanceMultiplier = 1;
|
|
40
|
+
if (isModified) importanceMultiplier *= CONTEXT_CONFIG.IMPORTANCE_MODIFIED;
|
|
41
|
+
if (isEntryPoint) importanceMultiplier *= CONTEXT_CONFIG.IMPORTANCE_ENTRY_POINT;
|
|
42
|
+
return accessCount * decayFactor * importanceMultiplier;
|
|
43
|
+
}
|
|
44
|
+
function isEntryPointFile(filePath) {
|
|
45
|
+
const filename = path.basename(filePath);
|
|
46
|
+
return ENTRY_POINT_PATTERNS.some((pattern) => pattern.test(filename));
|
|
47
|
+
}
|
|
48
|
+
function generateSessionId() {
|
|
49
|
+
return Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
|
|
50
|
+
}
|
|
51
|
+
function createEmptyContext() {
|
|
52
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
53
|
+
return {
|
|
54
|
+
session_id: generateSessionId(),
|
|
55
|
+
mode: "safe",
|
|
56
|
+
current_task: null,
|
|
57
|
+
files_read: [],
|
|
58
|
+
files_modified: [],
|
|
59
|
+
working_set: [],
|
|
60
|
+
last_action: null,
|
|
61
|
+
created_at: now,
|
|
62
|
+
updated_at: now
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
var ContextManager = class {
|
|
66
|
+
ctx = createEmptyContext();
|
|
67
|
+
constructor() {
|
|
68
|
+
}
|
|
69
|
+
async init() {
|
|
70
|
+
try {
|
|
71
|
+
const lastSession = db.getDb().prepare(`
|
|
72
|
+
SELECT id, created_at, source, permissions
|
|
73
|
+
FROM sessions
|
|
74
|
+
ORDER BY created_at DESC
|
|
75
|
+
LIMIT 1
|
|
76
|
+
`).get();
|
|
77
|
+
if (lastSession) {
|
|
78
|
+
await this.load(lastSession.id);
|
|
79
|
+
} else {
|
|
80
|
+
this.ctx = createEmptyContext();
|
|
81
|
+
await this.save();
|
|
82
|
+
}
|
|
83
|
+
} catch (e) {
|
|
84
|
+
bus.emitAgent({ type: "error", message: `[Context] Failed to init from DB: ${e instanceof Error ? e.message : String(e)}` });
|
|
85
|
+
this.ctx = createEmptyContext();
|
|
86
|
+
await this.save();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async load(sessionId) {
|
|
90
|
+
if (!sessionId) return;
|
|
91
|
+
try {
|
|
92
|
+
const session = db.getDb().prepare(`SELECT * FROM sessions WHERE id = ?`).get(sessionId);
|
|
93
|
+
if (!session) return;
|
|
94
|
+
const workingSetRows = db.getDb().prepare(`
|
|
95
|
+
SELECT file_path
|
|
96
|
+
FROM working_set
|
|
97
|
+
WHERE session_id = ?
|
|
98
|
+
ORDER BY rank_score DESC
|
|
99
|
+
`).all(sessionId);
|
|
100
|
+
this.ctx = {
|
|
101
|
+
session_id: session.id,
|
|
102
|
+
mode: "safe",
|
|
103
|
+
// Mode loaded from settings usually, but DB could store it if we added column
|
|
104
|
+
current_task: null,
|
|
105
|
+
// Tasks are now in 'tasks' table
|
|
106
|
+
files_read: [],
|
|
107
|
+
// Reset on load, or we could store this in DB if needed
|
|
108
|
+
files_modified: [],
|
|
109
|
+
working_set: workingSetRows.map((r) => r.file_path),
|
|
110
|
+
last_action: null,
|
|
111
|
+
created_at: new Date(session.created_at).toISOString(),
|
|
112
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
113
|
+
// Refreshed
|
|
114
|
+
};
|
|
115
|
+
await this.syncModeFromSettings();
|
|
116
|
+
} catch (e) {
|
|
117
|
+
bus.emitAgent({ type: "error", message: `[Context] Failed to load session: ${e instanceof Error ? e.message : String(e)}` });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async save() {
|
|
121
|
+
this.ctx.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
122
|
+
const cfg = await config.load();
|
|
123
|
+
try {
|
|
124
|
+
const timestamp = Date.now();
|
|
125
|
+
db.getDb().prepare(`
|
|
126
|
+
INSERT INTO sessions (id, created_at, workspace)
|
|
127
|
+
VALUES (?, ?, ?)
|
|
128
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
129
|
+
workspace = excluded.workspace,
|
|
130
|
+
created_at = excluded.created_at
|
|
131
|
+
`).run(this.ctx.session_id, timestamp, cfg.workspaceRoot);
|
|
132
|
+
const insertFile = db.getDb().prepare(`
|
|
133
|
+
INSERT INTO working_set (session_id, file_path, rank_score, last_accessed, access_count)
|
|
134
|
+
VALUES (?, ?, ?, ?, 1)
|
|
135
|
+
ON CONFLICT(session_id, file_path) DO UPDATE SET
|
|
136
|
+
access_count = access_count + 1,
|
|
137
|
+
last_accessed = ?
|
|
138
|
+
`);
|
|
139
|
+
const transaction = db.getDb().transaction(() => {
|
|
140
|
+
for (const file of this.ctx.working_set) {
|
|
141
|
+
insertFile.run(this.ctx.session_id, file, 1, timestamp, timestamp);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
transaction();
|
|
145
|
+
} catch (e) {
|
|
146
|
+
bus.emitAgent({ type: "error", message: `[Context] Failed to save: ${e instanceof Error ? e.message : String(e)}` });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async archive() {
|
|
150
|
+
}
|
|
151
|
+
async startNewSession() {
|
|
152
|
+
const oldMode = this.ctx.mode;
|
|
153
|
+
this.ctx = createEmptyContext();
|
|
154
|
+
this.ctx.mode = oldMode;
|
|
155
|
+
await this.save();
|
|
156
|
+
await settings.set("mode", this.ctx.mode);
|
|
157
|
+
}
|
|
158
|
+
// Getters
|
|
159
|
+
get() {
|
|
160
|
+
return { ...this.ctx };
|
|
161
|
+
}
|
|
162
|
+
getMode() {
|
|
163
|
+
return this.ctx.mode;
|
|
164
|
+
}
|
|
165
|
+
async syncModeFromSettings() {
|
|
166
|
+
const s = await settings.load();
|
|
167
|
+
this.ctx.mode = s.mode;
|
|
168
|
+
}
|
|
169
|
+
getCurrentTask() {
|
|
170
|
+
return this.ctx.current_task;
|
|
171
|
+
}
|
|
172
|
+
getWorkingSet() {
|
|
173
|
+
return [...this.ctx.working_set];
|
|
174
|
+
}
|
|
175
|
+
// Setters
|
|
176
|
+
async setMode(mode) {
|
|
177
|
+
this.ctx.mode = mode;
|
|
178
|
+
await settings.set("mode", mode);
|
|
179
|
+
}
|
|
180
|
+
async setTask(task) {
|
|
181
|
+
this.ctx.current_task = task;
|
|
182
|
+
}
|
|
183
|
+
// Tracking
|
|
184
|
+
async trackRead(filePath, tokenEstimate = 0) {
|
|
185
|
+
const cfg = await config.load();
|
|
186
|
+
const normalized = path.relative(cfg.workspaceRoot, path.resolve(filePath));
|
|
187
|
+
if (!this.ctx.files_read.includes(normalized)) {
|
|
188
|
+
this.ctx.files_read.push(normalized);
|
|
189
|
+
}
|
|
190
|
+
if (!this.ctx.working_set.includes(normalized)) {
|
|
191
|
+
this.ctx.working_set.push(normalized);
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
const timestamp = Date.now();
|
|
195
|
+
const isModified = this.ctx.files_modified.includes(normalized);
|
|
196
|
+
const isEntryPoint = isEntryPointFile(normalized);
|
|
197
|
+
const existing = db.getDb().prepare(`
|
|
198
|
+
SELECT access_count FROM working_set
|
|
199
|
+
WHERE session_id = ? AND file_path = ?
|
|
200
|
+
`).get(this.ctx.session_id, normalized);
|
|
201
|
+
const newAccessCount = (existing?.access_count || 0) + 1;
|
|
202
|
+
const rankScore = calculateRankScore(newAccessCount, timestamp, isModified, isEntryPoint);
|
|
203
|
+
db.getDb().prepare(`
|
|
204
|
+
INSERT INTO working_set (session_id, file_path, rank_score, last_accessed, access_count)
|
|
205
|
+
VALUES (?, ?, ?, ?, 1)
|
|
206
|
+
ON CONFLICT(session_id, file_path) DO UPDATE SET
|
|
207
|
+
access_count = access_count + 1,
|
|
208
|
+
last_accessed = ?,
|
|
209
|
+
rank_score = ?
|
|
210
|
+
`).run(this.ctx.session_id, normalized, rankScore, timestamp, timestamp, rankScore);
|
|
211
|
+
await this.pruneWorkingSet();
|
|
212
|
+
} catch (e) {
|
|
213
|
+
bus.emitAgent({ type: "thought", content: `[Context] Failed to track read for ${normalized}: ${e instanceof Error ? e.message : String(e)}`, hidden: true });
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
async trackModified(filePath, tokenEstimate = 0) {
|
|
217
|
+
const cfg = await config.load();
|
|
218
|
+
const normalized = path.relative(cfg.workspaceRoot, path.resolve(filePath));
|
|
219
|
+
if (!this.ctx.files_modified.includes(normalized)) {
|
|
220
|
+
this.ctx.files_modified.push(normalized);
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
const timestamp = Date.now();
|
|
224
|
+
const existing = db.getDb().prepare(`
|
|
225
|
+
SELECT access_count FROM working_set
|
|
226
|
+
WHERE session_id = ? AND file_path = ?
|
|
227
|
+
`).get(this.ctx.session_id, normalized);
|
|
228
|
+
const accessCount = existing?.access_count || 1;
|
|
229
|
+
const isEntryPoint = isEntryPointFile(normalized);
|
|
230
|
+
const rankScore = calculateRankScore(accessCount, timestamp, true, isEntryPoint);
|
|
231
|
+
db.getDb().prepare(`
|
|
232
|
+
UPDATE working_set SET rank_score = ?, last_accessed = ?
|
|
233
|
+
WHERE session_id = ? AND file_path = ?
|
|
234
|
+
`).run(rankScore, timestamp, this.ctx.session_id, normalized);
|
|
235
|
+
} catch (e) {
|
|
236
|
+
await this.trackRead(filePath, tokenEstimate);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Prune working set to prevent unbounded growth
|
|
241
|
+
* Keeps top N files by rank score
|
|
242
|
+
*/
|
|
243
|
+
async pruneWorkingSet() {
|
|
244
|
+
try {
|
|
245
|
+
const count = db.getDb().prepare(`
|
|
246
|
+
SELECT COUNT(*) as count FROM working_set WHERE session_id = ?
|
|
247
|
+
`).get(this.ctx.session_id);
|
|
248
|
+
if (count.count > CONTEXT_CONFIG.MAX_WORKING_SET_SIZE) {
|
|
249
|
+
db.getDb().prepare(`
|
|
250
|
+
DELETE FROM working_set
|
|
251
|
+
WHERE session_id = ? AND file_path NOT IN (
|
|
252
|
+
SELECT file_path FROM working_set
|
|
253
|
+
WHERE session_id = ?
|
|
254
|
+
ORDER BY rank_score DESC
|
|
255
|
+
LIMIT ?
|
|
256
|
+
)
|
|
257
|
+
`).run(this.ctx.session_id, this.ctx.session_id, CONTEXT_CONFIG.MAX_WORKING_SET_SIZE);
|
|
258
|
+
const remaining = db.getDb().prepare(`
|
|
259
|
+
SELECT file_path FROM working_set
|
|
260
|
+
WHERE session_id = ?
|
|
261
|
+
ORDER BY rank_score DESC
|
|
262
|
+
`).all(this.ctx.session_id);
|
|
263
|
+
this.ctx.working_set = remaining.map((r) => r.file_path);
|
|
264
|
+
}
|
|
265
|
+
} catch (e) {
|
|
266
|
+
bus.emitAgent({ type: "thought", content: `[Context] Working set pruning failed: ${e instanceof Error ? e.message : String(e)}`, hidden: true });
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Get working set entries with full metadata
|
|
271
|
+
*/
|
|
272
|
+
getWorkingSetWithMetadata() {
|
|
273
|
+
try {
|
|
274
|
+
const rows = db.getDb().prepare(`
|
|
275
|
+
SELECT file_path, access_count, last_accessed, rank_score
|
|
276
|
+
FROM working_set
|
|
277
|
+
WHERE session_id = ?
|
|
278
|
+
ORDER BY rank_score DESC
|
|
279
|
+
`).all(this.ctx.session_id);
|
|
280
|
+
return rows.map((r) => ({
|
|
281
|
+
filePath: r.file_path,
|
|
282
|
+
accessCount: r.access_count,
|
|
283
|
+
lastAccessed: r.last_accessed,
|
|
284
|
+
isModified: this.ctx.files_modified.includes(r.file_path),
|
|
285
|
+
tokenEstimate: 0
|
|
286
|
+
// Would need to read file to estimate
|
|
287
|
+
}));
|
|
288
|
+
} catch (e) {
|
|
289
|
+
return [];
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Recalculate all rank scores (useful for periodic refresh)
|
|
294
|
+
*/
|
|
295
|
+
async recalculateRankScores() {
|
|
296
|
+
try {
|
|
297
|
+
const rows = db.getDb().prepare(`
|
|
298
|
+
SELECT file_path, access_count, last_accessed
|
|
299
|
+
FROM working_set
|
|
300
|
+
WHERE session_id = ?
|
|
301
|
+
`).all(this.ctx.session_id);
|
|
302
|
+
const updateStmt = db.getDb().prepare(`
|
|
303
|
+
UPDATE working_set SET rank_score = ?
|
|
304
|
+
WHERE session_id = ? AND file_path = ?
|
|
305
|
+
`);
|
|
306
|
+
db.getDb().transaction(() => {
|
|
307
|
+
for (const row of rows) {
|
|
308
|
+
const isModified = this.ctx.files_modified.includes(row.file_path);
|
|
309
|
+
const isEntryPoint = isEntryPointFile(row.file_path);
|
|
310
|
+
const newScore = calculateRankScore(
|
|
311
|
+
row.access_count,
|
|
312
|
+
row.last_accessed,
|
|
313
|
+
isModified,
|
|
314
|
+
isEntryPoint
|
|
315
|
+
);
|
|
316
|
+
updateStmt.run(newScore, this.ctx.session_id, row.file_path);
|
|
317
|
+
}
|
|
318
|
+
})();
|
|
319
|
+
} catch (e) {
|
|
320
|
+
bus.emitAgent({ type: "thought", content: `[Context] Rank recalculation failed: ${e instanceof Error ? e.message : String(e)}`, hidden: true });
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
async setLastAction(action) {
|
|
324
|
+
this.ctx.last_action = action;
|
|
325
|
+
}
|
|
326
|
+
// Reset
|
|
327
|
+
async reset() {
|
|
328
|
+
this.ctx = createEmptyContext();
|
|
329
|
+
await this.save();
|
|
330
|
+
}
|
|
331
|
+
async clearWorkingSet() {
|
|
332
|
+
this.ctx.working_set = [];
|
|
333
|
+
db.getDb().prepare("DELETE FROM working_set WHERE session_id = ?").run(this.ctx.session_id);
|
|
334
|
+
}
|
|
335
|
+
// Summary for LLM
|
|
336
|
+
getSummary() {
|
|
337
|
+
const lines = [];
|
|
338
|
+
if (this.ctx.current_task) {
|
|
339
|
+
lines.push(`Task: ${this.ctx.current_task}`);
|
|
340
|
+
}
|
|
341
|
+
const topFiles = this.getWorkingSetWithMetadata().slice(0, 5);
|
|
342
|
+
if (topFiles.length > 0) {
|
|
343
|
+
const fileList = topFiles.map((f) => {
|
|
344
|
+
const modified = f.isModified ? "*" : "";
|
|
345
|
+
return `${modified}${f.filePath}`;
|
|
346
|
+
}).join(", ");
|
|
347
|
+
lines.push(`Working set (top 5): ${fileList}`);
|
|
348
|
+
}
|
|
349
|
+
if (this.ctx.files_modified.length > 0) {
|
|
350
|
+
lines.push(`Modified this session: ${this.ctx.files_modified.slice(-3).join(", ")}`);
|
|
351
|
+
}
|
|
352
|
+
return lines.join("\n");
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Get context statistics for monitoring
|
|
356
|
+
*/
|
|
357
|
+
getStats() {
|
|
358
|
+
return {
|
|
359
|
+
totalFilesRead: this.ctx.files_read.length,
|
|
360
|
+
totalFilesModified: this.ctx.files_modified.length,
|
|
361
|
+
workingSetSize: this.ctx.working_set.length,
|
|
362
|
+
sessionAge: Date.now() - new Date(this.ctx.created_at).getTime()
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
var context = new ContextManager();
|
|
367
|
+
|
|
368
|
+
export {
|
|
369
|
+
context
|
|
370
|
+
};
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
// src/core/settings.ts
|
|
2
|
+
import fs from "fs/promises";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import os from "os";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
var SETTINGS_DIR = ".obsidian-next";
|
|
7
|
+
var SETTINGS_FILE = "settings.json";
|
|
8
|
+
var SettingsSchema = z.object({
|
|
9
|
+
// Execution mode
|
|
10
|
+
mode: z.enum(["auto", "plan", "safe"]).default("safe"),
|
|
11
|
+
// Auto-accept settings
|
|
12
|
+
autoAccept: z.object({
|
|
13
|
+
enabled: z.boolean().default(false),
|
|
14
|
+
readOperations: z.boolean().default(true),
|
|
15
|
+
safeCommands: z.boolean().default(true)
|
|
16
|
+
}).default({}),
|
|
17
|
+
// Tool permissions
|
|
18
|
+
permissions: z.object({
|
|
19
|
+
// Patterns always allowed without prompt: "tool:pattern"
|
|
20
|
+
allow: z.array(z.string()).default([]),
|
|
21
|
+
// Patterns allowed without prompt AND without sandbox
|
|
22
|
+
allowUnsandboxed: z.array(z.string()).default([]),
|
|
23
|
+
// Patterns always blocked
|
|
24
|
+
deny: z.array(z.string()).default([])
|
|
25
|
+
}).default({}),
|
|
26
|
+
// Security settings
|
|
27
|
+
security: z.object({
|
|
28
|
+
// PII redaction before sending to LLM
|
|
29
|
+
piiRedaction: z.boolean().default(true),
|
|
30
|
+
// Audit logging of all commands
|
|
31
|
+
auditLogging: z.boolean().default(true),
|
|
32
|
+
// Key storage backend preference
|
|
33
|
+
keyBackend: z.enum(["auto", "keychain", "secret-tool", "encrypted-file", "env"]).default("auto"),
|
|
34
|
+
// Restrict filesystem access to sandbox directories
|
|
35
|
+
sandbox: z.boolean().default(false)
|
|
36
|
+
}).default({}),
|
|
37
|
+
// UI preferences
|
|
38
|
+
ui: z.object({
|
|
39
|
+
syntaxHighlight: z.boolean().default(true),
|
|
40
|
+
diffColors: z.boolean().default(true),
|
|
41
|
+
showLineNumbers: z.boolean().default(true),
|
|
42
|
+
// Owl animation settings
|
|
43
|
+
owlAnimation: z.object({
|
|
44
|
+
enabled: z.boolean().default(false),
|
|
45
|
+
flyWhenIdle: z.boolean().default(false),
|
|
46
|
+
idleTimeout: z.number().default(6e4),
|
|
47
|
+
// 60s before idle animation
|
|
48
|
+
sleepTimeout: z.number().default(3e5)
|
|
49
|
+
// 5m before sleep animation
|
|
50
|
+
}).default({})
|
|
51
|
+
}).default({}),
|
|
52
|
+
// Remote Gateway (Telegram)
|
|
53
|
+
telegram: z.object({
|
|
54
|
+
enabled: z.boolean().default(false),
|
|
55
|
+
botToken: z.string().optional(),
|
|
56
|
+
allowedUserIds: z.array(z.string()).default([])
|
|
57
|
+
}).default({})
|
|
58
|
+
});
|
|
59
|
+
var DEFAULT_SETTINGS = {
|
|
60
|
+
mode: "safe",
|
|
61
|
+
autoAccept: {
|
|
62
|
+
enabled: false,
|
|
63
|
+
readOperations: false,
|
|
64
|
+
safeCommands: false
|
|
65
|
+
},
|
|
66
|
+
permissions: {
|
|
67
|
+
allow: [],
|
|
68
|
+
// Empty - user builds their own allow list
|
|
69
|
+
allowUnsandboxed: [],
|
|
70
|
+
deny: []
|
|
71
|
+
},
|
|
72
|
+
security: {
|
|
73
|
+
piiRedaction: true,
|
|
74
|
+
// Enabled by default - protects user privacy
|
|
75
|
+
auditLogging: true,
|
|
76
|
+
// Enabled by default - for accountability
|
|
77
|
+
keyBackend: "auto",
|
|
78
|
+
// Auto-detect best available backend
|
|
79
|
+
sandbox: false
|
|
80
|
+
// Disabled by default
|
|
81
|
+
},
|
|
82
|
+
ui: {
|
|
83
|
+
syntaxHighlight: true,
|
|
84
|
+
diffColors: true,
|
|
85
|
+
showLineNumbers: true,
|
|
86
|
+
owlAnimation: {
|
|
87
|
+
enabled: false,
|
|
88
|
+
flyWhenIdle: false,
|
|
89
|
+
idleTimeout: 6e4,
|
|
90
|
+
// 60s before idle animation
|
|
91
|
+
sleepTimeout: 3e5
|
|
92
|
+
// 5m before sleep animation
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
telegram: {
|
|
96
|
+
enabled: false,
|
|
97
|
+
allowedUserIds: []
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
var SettingsManager = class {
|
|
101
|
+
settingsPath;
|
|
102
|
+
cache = null;
|
|
103
|
+
sessionAllow = /* @__PURE__ */ new Set();
|
|
104
|
+
sessionUnsandboxed = /* @__PURE__ */ new Set();
|
|
105
|
+
sessionDeny = /* @__PURE__ */ new Set();
|
|
106
|
+
constructor() {
|
|
107
|
+
this.settingsPath = path.join(os.homedir(), SETTINGS_DIR, SETTINGS_FILE);
|
|
108
|
+
}
|
|
109
|
+
async load() {
|
|
110
|
+
if (this.cache) return this.cache;
|
|
111
|
+
return this.reload();
|
|
112
|
+
}
|
|
113
|
+
async reload() {
|
|
114
|
+
try {
|
|
115
|
+
const data = await fs.readFile(this.settingsPath, "utf-8");
|
|
116
|
+
const parsed = JSON.parse(data);
|
|
117
|
+
this.cache = SettingsSchema.parse({ ...DEFAULT_SETTINGS, ...parsed });
|
|
118
|
+
} catch {
|
|
119
|
+
this.cache = DEFAULT_SETTINGS;
|
|
120
|
+
await this.save(DEFAULT_SETTINGS);
|
|
121
|
+
}
|
|
122
|
+
return this.cache;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Add a permission to the allow list (called when user approves a command)
|
|
126
|
+
*/
|
|
127
|
+
async addAllowedPermission(tool, command) {
|
|
128
|
+
const s = await this.load();
|
|
129
|
+
const pattern = `${tool}:${command}`;
|
|
130
|
+
if (!s.permissions.allow.includes(pattern)) {
|
|
131
|
+
s.permissions.allow.push(pattern);
|
|
132
|
+
await this.save({ permissions: s.permissions });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Add a permission to the unsandboxed allow list
|
|
137
|
+
*/
|
|
138
|
+
async addUnsandboxedPermission(tool, command) {
|
|
139
|
+
const s = await this.load();
|
|
140
|
+
const pattern = `${tool}:${command}`;
|
|
141
|
+
if (!s.permissions.allowUnsandboxed.includes(pattern)) {
|
|
142
|
+
s.permissions.allowUnsandboxed.push(pattern);
|
|
143
|
+
if (!s.permissions.allow.includes(pattern)) {
|
|
144
|
+
s.permissions.allow.push(pattern);
|
|
145
|
+
}
|
|
146
|
+
await this.save({ permissions: s.permissions });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Add a permission to the session-only allow/deny list
|
|
151
|
+
*/
|
|
152
|
+
async addSessionPermission(tool, command, approved, bypass = false) {
|
|
153
|
+
const pattern = `${tool}:${command}`;
|
|
154
|
+
if (approved) {
|
|
155
|
+
this.sessionAllow.add(pattern);
|
|
156
|
+
this.sessionDeny.delete(pattern);
|
|
157
|
+
if (bypass) {
|
|
158
|
+
this.sessionUnsandboxed.add(pattern);
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
this.sessionDeny.add(pattern);
|
|
162
|
+
this.sessionAllow.delete(pattern);
|
|
163
|
+
this.sessionUnsandboxed.delete(pattern);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Add a permission to the deny list
|
|
168
|
+
*/
|
|
169
|
+
async addDeniedPermission(tool, command) {
|
|
170
|
+
const s = await this.load();
|
|
171
|
+
const pattern = `${tool}:${command}`;
|
|
172
|
+
if (!s.permissions.deny.includes(pattern)) {
|
|
173
|
+
s.permissions.deny.push(pattern);
|
|
174
|
+
await this.save({ permissions: s.permissions });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
async save(newSettings) {
|
|
178
|
+
const current = await this.load();
|
|
179
|
+
const merged = { ...current, ...newSettings };
|
|
180
|
+
if (newSettings.autoAccept) {
|
|
181
|
+
merged.autoAccept = { ...current.autoAccept, ...newSettings.autoAccept };
|
|
182
|
+
}
|
|
183
|
+
if (newSettings.permissions) {
|
|
184
|
+
merged.permissions = { ...current.permissions, ...newSettings.permissions };
|
|
185
|
+
}
|
|
186
|
+
if (newSettings.security) {
|
|
187
|
+
merged.security = { ...current.security, ...newSettings.security };
|
|
188
|
+
}
|
|
189
|
+
if (newSettings.ui) {
|
|
190
|
+
merged.ui = { ...current.ui, ...newSettings.ui };
|
|
191
|
+
}
|
|
192
|
+
const validated = SettingsSchema.parse(merged);
|
|
193
|
+
const dir = path.dirname(this.settingsPath);
|
|
194
|
+
await fs.mkdir(dir, { recursive: true });
|
|
195
|
+
await fs.writeFile(this.settingsPath, JSON.stringify(validated, null, 2));
|
|
196
|
+
this.cache = validated;
|
|
197
|
+
}
|
|
198
|
+
async get(key) {
|
|
199
|
+
const s = await this.load();
|
|
200
|
+
return s[key];
|
|
201
|
+
}
|
|
202
|
+
async set(key, value) {
|
|
203
|
+
await this.save({ [key]: value });
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Check if a tool:command pattern is authorized for THIS SESSION only
|
|
207
|
+
*/
|
|
208
|
+
async isSessionAuthorized(tool, command) {
|
|
209
|
+
const pattern = `${tool}:${command}`;
|
|
210
|
+
return this.sessionAllow.has(pattern);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Check if a tool:command pattern is allowed (session or persistent)
|
|
214
|
+
*/
|
|
215
|
+
async isAllowed(tool, command) {
|
|
216
|
+
const pattern = `${tool}:${command}`;
|
|
217
|
+
if (this.sessionAllow.has(pattern)) {
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
const s = await this.load();
|
|
221
|
+
for (const deny of s.permissions.deny) {
|
|
222
|
+
if (this.matchPattern(pattern, deny)) {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
for (const allow of s.permissions.allow) {
|
|
227
|
+
if (this.matchPattern(pattern, allow)) {
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Check if a tool:command pattern is allowed to bypass sandbox
|
|
235
|
+
*/
|
|
236
|
+
async isUnsandboxed(tool, command) {
|
|
237
|
+
const pattern = `${tool}:${command}`;
|
|
238
|
+
if (this.sessionUnsandboxed.has(pattern)) {
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
const s = await this.load();
|
|
242
|
+
for (const allow of s.permissions.allowUnsandboxed) {
|
|
243
|
+
if (this.matchPattern(pattern, allow)) {
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Check if a tool:command pattern is explicitly denied
|
|
251
|
+
*/
|
|
252
|
+
async isDenied(tool, command) {
|
|
253
|
+
const pattern = `${tool}:${command}`;
|
|
254
|
+
if (this.sessionDeny.has(pattern)) {
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
const s = await this.load();
|
|
258
|
+
for (const deny of s.permissions.deny) {
|
|
259
|
+
if (this.matchPattern(pattern, deny)) {
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Simple glob-like pattern matching
|
|
267
|
+
* Supports * as wildcard
|
|
268
|
+
*/
|
|
269
|
+
matchPattern(value, pattern) {
|
|
270
|
+
const regex = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
271
|
+
return new RegExp(`^${regex}$`).test(value);
|
|
272
|
+
}
|
|
273
|
+
clearCache() {
|
|
274
|
+
this.cache = null;
|
|
275
|
+
}
|
|
276
|
+
getPath() {
|
|
277
|
+
return this.settingsPath;
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
var settings = new SettingsManager();
|
|
281
|
+
|
|
282
|
+
export {
|
|
283
|
+
SettingsSchema,
|
|
284
|
+
settings
|
|
285
|
+
};
|