@aurora-foundation/obsidian-next 0.4.8 → 0.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-2JWDGXTR.js +42 -0
- package/dist/chunk-3UCL6RYE.js +7272 -0
- package/dist/chunk-3VZGPA3N.js +42 -0
- package/dist/chunk-3XR3GZLX.js +7809 -0
- package/dist/chunk-6YJSTQKN.js +7817 -0
- package/dist/chunk-7XFP3ZUD.js +42 -0
- package/dist/chunk-ASDVTRIQ.js +7805 -0
- package/dist/chunk-BAKREPY2.js +439 -0
- package/dist/chunk-BFRO5BO2.js +42 -0
- package/dist/chunk-CHNVBJN3.js +7272 -0
- package/dist/chunk-DAR45YDV.js +42 -0
- package/dist/chunk-FNXAI27K.js +7812 -0
- package/dist/chunk-HKPL675M.js +42 -0
- package/dist/chunk-INEXRRON.js +42 -0
- package/dist/chunk-ISO6GNIB.js +429 -0
- package/dist/chunk-MGDY5JUY.js +581 -0
- package/dist/chunk-OFTKVOQ2.js +7828 -0
- package/dist/chunk-PD4ZKYTJ.js +7838 -0
- package/dist/chunk-PQSPCOJ7.js +7616 -0
- package/dist/chunk-QSEH5NXV.js +7807 -0
- package/dist/chunk-RUEIA6Z5.js +42 -0
- package/dist/chunk-S5IDXE2L.js +42 -0
- package/dist/chunk-UG3HWGIO.js +42 -0
- package/dist/chunk-UOESII6R.js +42 -0
- package/dist/chunk-VWMT4HCP.js +7668 -0
- package/dist/chunk-YFQI44IA.js +42 -0
- package/dist/chunk-ZR7MEF3B.js +7605 -0
- package/dist/context-NI6N46WG.js +10 -0
- package/dist/index.js +585 -345
- package/dist/memory-GXW2OA2T.js +13 -0
- package/dist/resume-EA6ISWW2.js +15 -0
- package/dist/resume-EIM5FN42.js +15 -0
- package/dist/resume-FBVK6NAI.js +15 -0
- package/dist/resume-H6J5PQIA.js +15 -0
- package/dist/resume-JDDVTMM4.js +15 -0
- package/dist/resume-JFYYR7DJ.js +15 -0
- package/dist/resume-KGFAZY34.js +15 -0
- package/dist/resume-MF5TM2ZB.js +15 -0
- package/dist/resume-O6PLICAA.js +15 -0
- package/dist/resume-PZU3PWCJ.js +15 -0
- package/dist/resume-YD76GI2J.js +15 -0
- package/dist/resume-YKAKOXWV.js +15 -0
- package/dist/session-37MDDCWV.js +14 -0
- package/dist/session-56ZI3GZV.js +14 -0
- package/dist/session-5OFIDWGU.js +14 -0
- package/dist/session-7LPACLRV.js +14 -0
- package/dist/session-CJ6HSKDI.js +14 -0
- package/dist/session-CUXGN26I.js +14 -0
- package/dist/session-DCGNGGMV.js +14 -0
- package/dist/session-LEVSW6JH.js +14 -0
- package/dist/session-MHZAYMLC.js +14 -0
- package/dist/session-NNU7OW5K.js +14 -0
- package/dist/session-R5UG5PZR.js +14 -0
- package/dist/session-T64DMDAU.js +14 -0
- package/dist/settings-4ALCRT5S.js +8 -0
- package/dist/skills/defaults/clipboard.mjs +46 -0
- package/dist/skills/defaults/notify.mjs +36 -0
- package/dist/skills/defaults/open_app.mjs +53 -0
- package/dist/skills/defaults/speak.mjs +47 -0
- package/dist/skills/defaults/spotify_control.mjs +187 -0
- package/package.json +7 -4
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
session
|
|
3
|
+
} from "./chunk-FNXAI27K.js";
|
|
4
|
+
import {
|
|
5
|
+
bus
|
|
6
|
+
} from "./chunk-WQM6FFSD.js";
|
|
7
|
+
|
|
8
|
+
// src/commands/resume.ts
|
|
9
|
+
async function resumeCommand(args) {
|
|
10
|
+
if (args.length > 0) {
|
|
11
|
+
const sessionId = args[0];
|
|
12
|
+
try {
|
|
13
|
+
const result = await session.restore(sessionId);
|
|
14
|
+
if (result.success) {
|
|
15
|
+
bus.emitAgent({
|
|
16
|
+
type: "thought",
|
|
17
|
+
content: `Resumed session: ${sessionId}`
|
|
18
|
+
});
|
|
19
|
+
} else {
|
|
20
|
+
bus.emitAgent({
|
|
21
|
+
type: "error",
|
|
22
|
+
message: `Failed to resume session: ${result.error}`
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
} catch (err) {
|
|
26
|
+
bus.emitAgent({
|
|
27
|
+
type: "error",
|
|
28
|
+
message: `Error resuming session: ${err}`
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
bus.emitAgent({
|
|
34
|
+
type: "view_request",
|
|
35
|
+
viewId: "sessions",
|
|
36
|
+
command: "resume"
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export {
|
|
41
|
+
resumeCommand
|
|
42
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
session
|
|
3
|
+
} from "./chunk-VWMT4HCP.js";
|
|
4
|
+
import {
|
|
5
|
+
bus
|
|
6
|
+
} from "./chunk-WQM6FFSD.js";
|
|
7
|
+
|
|
8
|
+
// src/commands/resume.ts
|
|
9
|
+
async function resumeCommand(args) {
|
|
10
|
+
if (args.length > 0) {
|
|
11
|
+
const sessionId = args[0];
|
|
12
|
+
try {
|
|
13
|
+
const result = await session.restore(sessionId);
|
|
14
|
+
if (result.success) {
|
|
15
|
+
bus.emitAgent({
|
|
16
|
+
type: "thought",
|
|
17
|
+
content: `Resumed session: ${sessionId}`
|
|
18
|
+
});
|
|
19
|
+
} else {
|
|
20
|
+
bus.emitAgent({
|
|
21
|
+
type: "error",
|
|
22
|
+
message: `Failed to resume session: ${result.error}`
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
} catch (err) {
|
|
26
|
+
bus.emitAgent({
|
|
27
|
+
type: "error",
|
|
28
|
+
message: `Error resuming session: ${err}`
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
bus.emitAgent({
|
|
34
|
+
type: "view_request",
|
|
35
|
+
viewId: "sessions",
|
|
36
|
+
command: "resume"
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export {
|
|
41
|
+
resumeCommand
|
|
42
|
+
};
|
|
@@ -0,0 +1,429 @@
|
|
|
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
|
+
|
|
7
|
+
// src/core/settings-cache.ts
|
|
8
|
+
import { EventEmitter } from "events";
|
|
9
|
+
var DEFAULT_CACHE_OPTIONS = {
|
|
10
|
+
ttl: 5e3,
|
|
11
|
+
// 5 seconds (balance freshness vs performance)
|
|
12
|
+
maxSize: 100,
|
|
13
|
+
// 100 entries max
|
|
14
|
+
enabled: true
|
|
15
|
+
// Cache enabled by default
|
|
16
|
+
};
|
|
17
|
+
var SettingsCache = class extends EventEmitter {
|
|
18
|
+
cache = /* @__PURE__ */ new Map();
|
|
19
|
+
options;
|
|
20
|
+
hits = 0;
|
|
21
|
+
misses = 0;
|
|
22
|
+
constructor(options = {}) {
|
|
23
|
+
super();
|
|
24
|
+
this.options = { ...DEFAULT_CACHE_OPTIONS, ...options };
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get cached value or execute loader if miss/expired
|
|
28
|
+
*/
|
|
29
|
+
async get(key, loader, ttl) {
|
|
30
|
+
if (!this.options.enabled) {
|
|
31
|
+
return await loader();
|
|
32
|
+
}
|
|
33
|
+
const cached = this.cache.get(key);
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
const effectiveTtl = ttl ?? this.options.ttl;
|
|
36
|
+
if (cached && now - cached.timestamp < effectiveTtl) {
|
|
37
|
+
this.hits++;
|
|
38
|
+
cached.hits++;
|
|
39
|
+
this.emit("hit", { key, hits: cached.hits });
|
|
40
|
+
return cached.value;
|
|
41
|
+
}
|
|
42
|
+
this.misses++;
|
|
43
|
+
this.emit("miss", { key });
|
|
44
|
+
const value = await loader();
|
|
45
|
+
this.set(key, value, effectiveTtl);
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Set cache entry (internal use)
|
|
50
|
+
*/
|
|
51
|
+
set(key, value, ttl = this.options.ttl) {
|
|
52
|
+
if (this.cache.size >= this.options.maxSize) {
|
|
53
|
+
this.evictLRU();
|
|
54
|
+
}
|
|
55
|
+
this.cache.set(key, {
|
|
56
|
+
value,
|
|
57
|
+
timestamp: Date.now(),
|
|
58
|
+
hits: 0
|
|
59
|
+
});
|
|
60
|
+
this.emit("set", { key, size: this.cache.size });
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Invalidate specific key or pattern
|
|
64
|
+
*/
|
|
65
|
+
invalidate(keyOrPattern) {
|
|
66
|
+
if (typeof keyOrPattern === "string") {
|
|
67
|
+
this.cache.delete(keyOrPattern);
|
|
68
|
+
this.emit("invalidate", { key: keyOrPattern });
|
|
69
|
+
} else {
|
|
70
|
+
const keysToDelete = [];
|
|
71
|
+
for (const key of this.cache.keys()) {
|
|
72
|
+
if (keyOrPattern.test(key)) {
|
|
73
|
+
keysToDelete.push(key);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
keysToDelete.forEach((k) => this.cache.delete(k));
|
|
77
|
+
this.emit("invalidate", { pattern: keyOrPattern.source, count: keysToDelete.length });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Clear entire cache
|
|
82
|
+
*/
|
|
83
|
+
clear() {
|
|
84
|
+
const size = this.cache.size;
|
|
85
|
+
this.cache.clear();
|
|
86
|
+
this.hits = 0;
|
|
87
|
+
this.misses = 0;
|
|
88
|
+
this.emit("clear", { size });
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Evict least-recently-used entry (lowest hit count)
|
|
92
|
+
*/
|
|
93
|
+
evictLRU() {
|
|
94
|
+
let lruKey = null;
|
|
95
|
+
let minHits = Infinity;
|
|
96
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
97
|
+
if (entry.hits < minHits) {
|
|
98
|
+
minHits = entry.hits;
|
|
99
|
+
lruKey = key;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (lruKey) {
|
|
103
|
+
this.cache.delete(lruKey);
|
|
104
|
+
this.emit("evict", { key: lruKey, hits: minHits });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get cache statistics (for monitoring/debugging)
|
|
109
|
+
*/
|
|
110
|
+
getStats() {
|
|
111
|
+
const total = this.hits + this.misses;
|
|
112
|
+
const hitRate = total > 0 ? this.hits / total * 100 : 0;
|
|
113
|
+
return {
|
|
114
|
+
hits: this.hits,
|
|
115
|
+
misses: this.misses,
|
|
116
|
+
hitRate: hitRate.toFixed(2) + "%",
|
|
117
|
+
size: this.cache.size,
|
|
118
|
+
maxSize: this.options.maxSize,
|
|
119
|
+
enabled: this.options.enabled
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Enable/disable cache dynamically
|
|
124
|
+
*/
|
|
125
|
+
setEnabled(enabled) {
|
|
126
|
+
this.options.enabled = enabled;
|
|
127
|
+
if (!enabled) {
|
|
128
|
+
this.clear();
|
|
129
|
+
}
|
|
130
|
+
this.emit("toggle", { enabled });
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
var settingsCache = new SettingsCache({
|
|
134
|
+
ttl: 5e3,
|
|
135
|
+
// 5 seconds TTL
|
|
136
|
+
maxSize: 100,
|
|
137
|
+
// 100 entries
|
|
138
|
+
enabled: true
|
|
139
|
+
// Enabled by default
|
|
140
|
+
});
|
|
141
|
+
async function cachedSettings(key, loader, ttl) {
|
|
142
|
+
return settingsCache.get(key, loader, ttl);
|
|
143
|
+
}
|
|
144
|
+
function invalidateSettingsCache() {
|
|
145
|
+
settingsCache.invalidate(/^settings:/);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// src/core/settings.ts
|
|
149
|
+
var SETTINGS_DIR = ".obsidian-next";
|
|
150
|
+
var SETTINGS_FILE = "settings.json";
|
|
151
|
+
var SettingsSchema = z.object({
|
|
152
|
+
// Execution mode
|
|
153
|
+
mode: z.enum(["auto", "plan", "safe"]).default("safe"),
|
|
154
|
+
// Auto-accept settings
|
|
155
|
+
autoAccept: z.object({
|
|
156
|
+
enabled: z.boolean().default(false),
|
|
157
|
+
readOperations: z.boolean().default(true),
|
|
158
|
+
safeCommands: z.boolean().default(true)
|
|
159
|
+
}).default({}),
|
|
160
|
+
// Tool permissions
|
|
161
|
+
permissions: z.object({
|
|
162
|
+
// Patterns always allowed without prompt: "tool:pattern"
|
|
163
|
+
allow: z.array(z.string()).default([]),
|
|
164
|
+
// Patterns allowed without prompt AND without sandbox
|
|
165
|
+
allowUnsandboxed: z.array(z.string()).default([]),
|
|
166
|
+
// Patterns always blocked
|
|
167
|
+
deny: z.array(z.string()).default([])
|
|
168
|
+
}).default({}),
|
|
169
|
+
// Security settings
|
|
170
|
+
security: z.object({
|
|
171
|
+
// PII redaction before sending to LLM
|
|
172
|
+
piiRedaction: z.boolean().default(true),
|
|
173
|
+
// Audit logging of all commands
|
|
174
|
+
auditLogging: z.boolean().default(true),
|
|
175
|
+
// Key storage backend preference
|
|
176
|
+
keyBackend: z.enum(["auto", "keychain", "secret-tool", "encrypted-file", "env"]).default("auto")
|
|
177
|
+
}).default({}),
|
|
178
|
+
// UI preferences
|
|
179
|
+
ui: z.object({
|
|
180
|
+
syntaxHighlight: z.boolean().default(true),
|
|
181
|
+
diffColors: z.boolean().default(true),
|
|
182
|
+
showLineNumbers: z.boolean().default(true),
|
|
183
|
+
// Owl animation settings
|
|
184
|
+
owlAnimation: z.object({
|
|
185
|
+
enabled: z.boolean().default(false),
|
|
186
|
+
flyWhenIdle: z.boolean().default(false),
|
|
187
|
+
idleTimeout: z.number().default(6e4),
|
|
188
|
+
// 60s before idle animation
|
|
189
|
+
sleepTimeout: z.number().default(3e5)
|
|
190
|
+
// 5m before sleep animation
|
|
191
|
+
}).default({})
|
|
192
|
+
}).default({}),
|
|
193
|
+
// Remote Gateway (Telegram)
|
|
194
|
+
telegram: z.object({
|
|
195
|
+
enabled: z.boolean().default(false),
|
|
196
|
+
botToken: z.string().optional(),
|
|
197
|
+
allowedUserIds: z.array(z.string()).default([])
|
|
198
|
+
}).default({})
|
|
199
|
+
});
|
|
200
|
+
var DEFAULT_SETTINGS = {
|
|
201
|
+
mode: "safe",
|
|
202
|
+
autoAccept: {
|
|
203
|
+
enabled: false,
|
|
204
|
+
readOperations: false,
|
|
205
|
+
safeCommands: false
|
|
206
|
+
},
|
|
207
|
+
permissions: {
|
|
208
|
+
allow: [],
|
|
209
|
+
// Empty - user builds their own allow list
|
|
210
|
+
allowUnsandboxed: [],
|
|
211
|
+
deny: []
|
|
212
|
+
},
|
|
213
|
+
security: {
|
|
214
|
+
piiRedaction: true,
|
|
215
|
+
// Enabled by default - protects user privacy
|
|
216
|
+
auditLogging: true,
|
|
217
|
+
// Enabled by default - for accountability
|
|
218
|
+
keyBackend: "auto"
|
|
219
|
+
// Auto-detect best available backend
|
|
220
|
+
},
|
|
221
|
+
ui: {
|
|
222
|
+
syntaxHighlight: true,
|
|
223
|
+
diffColors: true,
|
|
224
|
+
showLineNumbers: true,
|
|
225
|
+
owlAnimation: {
|
|
226
|
+
enabled: false,
|
|
227
|
+
flyWhenIdle: false,
|
|
228
|
+
idleTimeout: 6e4,
|
|
229
|
+
// 60s before idle animation
|
|
230
|
+
sleepTimeout: 3e5
|
|
231
|
+
// 5m before sleep animation
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
telegram: {
|
|
235
|
+
enabled: false,
|
|
236
|
+
allowedUserIds: []
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
var SettingsManager = class {
|
|
240
|
+
settingsPath;
|
|
241
|
+
cache = null;
|
|
242
|
+
sessionAllow = /* @__PURE__ */ new Set();
|
|
243
|
+
sessionUnsandboxed = /* @__PURE__ */ new Set();
|
|
244
|
+
sessionDeny = /* @__PURE__ */ new Set();
|
|
245
|
+
constructor() {
|
|
246
|
+
this.settingsPath = path.join(os.homedir(), SETTINGS_DIR, SETTINGS_FILE);
|
|
247
|
+
}
|
|
248
|
+
async load() {
|
|
249
|
+
if (this.cache) return this.cache;
|
|
250
|
+
return this.reload();
|
|
251
|
+
}
|
|
252
|
+
async reload() {
|
|
253
|
+
try {
|
|
254
|
+
const data = await fs.readFile(this.settingsPath, "utf-8");
|
|
255
|
+
const parsed = JSON.parse(data);
|
|
256
|
+
this.cache = SettingsSchema.parse({ ...DEFAULT_SETTINGS, ...parsed });
|
|
257
|
+
} catch {
|
|
258
|
+
this.cache = DEFAULT_SETTINGS;
|
|
259
|
+
await this.save(DEFAULT_SETTINGS);
|
|
260
|
+
}
|
|
261
|
+
return this.cache;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Add a permission to the allow list (called when user approves a command)
|
|
265
|
+
*/
|
|
266
|
+
async addAllowedPermission(tool, command) {
|
|
267
|
+
const s = await this.load();
|
|
268
|
+
const pattern = `${tool}:${command}`;
|
|
269
|
+
if (!s.permissions.allow.includes(pattern)) {
|
|
270
|
+
s.permissions.allow.push(pattern);
|
|
271
|
+
await this.save({ permissions: s.permissions });
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Add a permission to the unsandboxed allow list
|
|
276
|
+
*/
|
|
277
|
+
async addUnsandboxedPermission(tool, command) {
|
|
278
|
+
const s = await this.load();
|
|
279
|
+
const pattern = `${tool}:${command}`;
|
|
280
|
+
if (!s.permissions.allowUnsandboxed.includes(pattern)) {
|
|
281
|
+
s.permissions.allowUnsandboxed.push(pattern);
|
|
282
|
+
if (!s.permissions.allow.includes(pattern)) {
|
|
283
|
+
s.permissions.allow.push(pattern);
|
|
284
|
+
}
|
|
285
|
+
await this.save({ permissions: s.permissions });
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Add a permission to the session-only allow/deny list
|
|
290
|
+
*/
|
|
291
|
+
async addSessionPermission(tool, command, approved, bypass = false) {
|
|
292
|
+
const pattern = `${tool}:${command}`;
|
|
293
|
+
if (approved) {
|
|
294
|
+
this.sessionAllow.add(pattern);
|
|
295
|
+
this.sessionDeny.delete(pattern);
|
|
296
|
+
if (bypass) {
|
|
297
|
+
this.sessionUnsandboxed.add(pattern);
|
|
298
|
+
}
|
|
299
|
+
} else {
|
|
300
|
+
this.sessionDeny.add(pattern);
|
|
301
|
+
this.sessionAllow.delete(pattern);
|
|
302
|
+
this.sessionUnsandboxed.delete(pattern);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Add a permission to the deny list
|
|
307
|
+
*/
|
|
308
|
+
async addDeniedPermission(tool, command) {
|
|
309
|
+
const s = await this.load();
|
|
310
|
+
const pattern = `${tool}:${command}`;
|
|
311
|
+
if (!s.permissions.deny.includes(pattern)) {
|
|
312
|
+
s.permissions.deny.push(pattern);
|
|
313
|
+
await this.save({ permissions: s.permissions });
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
async save(newSettings) {
|
|
317
|
+
const current = await this.load();
|
|
318
|
+
const merged = { ...current, ...newSettings };
|
|
319
|
+
if (newSettings.autoAccept) {
|
|
320
|
+
merged.autoAccept = { ...current.autoAccept, ...newSettings.autoAccept };
|
|
321
|
+
}
|
|
322
|
+
if (newSettings.permissions) {
|
|
323
|
+
merged.permissions = {
|
|
324
|
+
...current.permissions,
|
|
325
|
+
...newSettings.permissions
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
if (newSettings.security) {
|
|
329
|
+
merged.security = { ...current.security, ...newSettings.security };
|
|
330
|
+
}
|
|
331
|
+
if (newSettings.ui) {
|
|
332
|
+
merged.ui = { ...current.ui, ...newSettings.ui };
|
|
333
|
+
}
|
|
334
|
+
const validated = SettingsSchema.parse(merged);
|
|
335
|
+
const dir = path.dirname(this.settingsPath);
|
|
336
|
+
await fs.mkdir(dir, { recursive: true });
|
|
337
|
+
await fs.writeFile(this.settingsPath, JSON.stringify(validated, null, 2));
|
|
338
|
+
this.cache = validated;
|
|
339
|
+
invalidateSettingsCache();
|
|
340
|
+
}
|
|
341
|
+
async get(key) {
|
|
342
|
+
const s = await this.load();
|
|
343
|
+
return s[key];
|
|
344
|
+
}
|
|
345
|
+
async set(key, value) {
|
|
346
|
+
await this.save({ [key]: value });
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Check if a tool:command pattern is authorized for THIS SESSION only
|
|
350
|
+
*/
|
|
351
|
+
async isSessionAuthorized(tool, command) {
|
|
352
|
+
const pattern = `${tool}:${command}`;
|
|
353
|
+
return this.sessionAllow.has(pattern);
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Check if a tool:command pattern is allowed (session or persistent)
|
|
357
|
+
*/
|
|
358
|
+
async isAllowed(tool, command) {
|
|
359
|
+
const pattern = `${tool}:${command}`;
|
|
360
|
+
if (this.sessionAllow.has(pattern)) {
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
363
|
+
const s = await this.load();
|
|
364
|
+
for (const deny of s.permissions.deny) {
|
|
365
|
+
if (this.matchPattern(pattern, deny)) {
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
for (const allow of s.permissions.allow) {
|
|
370
|
+
if (this.matchPattern(pattern, allow)) {
|
|
371
|
+
return true;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Check if a tool:command pattern is allowed to bypass sandbox
|
|
378
|
+
*/
|
|
379
|
+
async isUnsandboxed(tool, command) {
|
|
380
|
+
const pattern = `${tool}:${command}`;
|
|
381
|
+
if (this.sessionUnsandboxed.has(pattern)) {
|
|
382
|
+
return true;
|
|
383
|
+
}
|
|
384
|
+
const s = await this.load();
|
|
385
|
+
for (const allow of s.permissions.allowUnsandboxed) {
|
|
386
|
+
if (this.matchPattern(pattern, allow)) {
|
|
387
|
+
return true;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Check if a tool:command pattern is explicitly denied
|
|
394
|
+
*/
|
|
395
|
+
async isDenied(tool, command) {
|
|
396
|
+
const pattern = `${tool}:${command}`;
|
|
397
|
+
if (this.sessionDeny.has(pattern)) {
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
const s = await this.load();
|
|
401
|
+
for (const deny of s.permissions.deny) {
|
|
402
|
+
if (this.matchPattern(pattern, deny)) {
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Simple glob-like pattern matching
|
|
410
|
+
* Supports * as wildcard
|
|
411
|
+
*/
|
|
412
|
+
matchPattern(value, pattern) {
|
|
413
|
+
const regex = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
414
|
+
return new RegExp(`^${regex}$`).test(value);
|
|
415
|
+
}
|
|
416
|
+
clearCache() {
|
|
417
|
+
this.cache = null;
|
|
418
|
+
}
|
|
419
|
+
getPath() {
|
|
420
|
+
return this.settingsPath;
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
var settings = new SettingsManager();
|
|
424
|
+
|
|
425
|
+
export {
|
|
426
|
+
cachedSettings,
|
|
427
|
+
SettingsSchema,
|
|
428
|
+
settings
|
|
429
|
+
};
|