@mingxy/cerebro 2.3.4 → 2.3.5
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/package.json +2 -2
- package/src/client.ts +412 -403
- package/src/config.ts +277 -275
- package/src/hooks.ts +1040 -1019
- package/src/index.ts +229 -229
- package/src/tools.ts +455 -455
- package/web/assets/{index-CTdp-yyn.js → index-zOJZZn-i.js} +3 -3
- package/web/icons.svg +24 -24
- package/web/index.html +14 -14
- package/src/client.test.ts +0 -373
- package/src/config.test.ts +0 -405
- package/src/hooks-tier1.test.ts +0 -220
- package/src/hooks-tier2.test.ts +0 -275
- package/src/hooks-tier3.test.ts +0 -461
- package/src/index.test.ts +0 -190
- package/src/keywords.test.ts +0 -283
- package/src/logger.test.ts +0 -640
- package/src/privacy.test.ts +0 -128
- package/src/tags.test.ts +0 -86
- package/src/tools.test.ts +0 -508
- package/src/updater.test.ts +0 -380
- package/src/web-server.test.ts +0 -740
package/src/config.ts
CHANGED
|
@@ -1,275 +1,277 @@
|
|
|
1
|
-
import { readFileSync, appendFileSync, mkdirSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
|
|
5
|
-
// ── Nested config interface ──────────────────────────────────────────
|
|
6
|
-
|
|
7
|
-
export interface CerebroPluginConfig {
|
|
8
|
-
connection: {
|
|
9
|
-
apiUrl: string;
|
|
10
|
-
apiKey: string;
|
|
11
|
-
requestTimeoutMs: number;
|
|
12
|
-
};
|
|
13
|
-
content: {
|
|
14
|
-
maxQueryLength: number;
|
|
15
|
-
maxContentChars: number;
|
|
16
|
-
maxContentLength: number;
|
|
17
|
-
};
|
|
18
|
-
injection: {
|
|
19
|
-
recentCount: number;
|
|
20
|
-
searchCount: number;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (overrides.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
const
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
return LEVEL_MAP.INFO;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (process.env.
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
export
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
return
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
|
|
1
|
+
import { readFileSync, appendFileSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
|
|
5
|
+
// ── Nested config interface ──────────────────────────────────────────
|
|
6
|
+
|
|
7
|
+
export interface CerebroPluginConfig {
|
|
8
|
+
connection: {
|
|
9
|
+
apiUrl: string;
|
|
10
|
+
apiKey: string;
|
|
11
|
+
requestTimeoutMs: number;
|
|
12
|
+
};
|
|
13
|
+
content: {
|
|
14
|
+
maxQueryLength: number;
|
|
15
|
+
maxContentChars: number;
|
|
16
|
+
maxContentLength: number;
|
|
17
|
+
};
|
|
18
|
+
injection: {
|
|
19
|
+
recentCount: number;
|
|
20
|
+
searchCount: number;
|
|
21
|
+
globalCount: number;
|
|
22
|
+
recentTruncateChars: number;
|
|
23
|
+
searchTruncateChars: number;
|
|
24
|
+
recentTimeoutMs: number;
|
|
25
|
+
searchTimeoutMs: number;
|
|
26
|
+
profileTimeoutMs: number;
|
|
27
|
+
};
|
|
28
|
+
ingest: {
|
|
29
|
+
autoCaptureThreshold: number;
|
|
30
|
+
ingestMode: "smart" | "raw";
|
|
31
|
+
};
|
|
32
|
+
logging: {
|
|
33
|
+
logEnabled: boolean;
|
|
34
|
+
logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR";
|
|
35
|
+
logDir: string;
|
|
36
|
+
};
|
|
37
|
+
ui: {
|
|
38
|
+
toastDelayMs: number;
|
|
39
|
+
};
|
|
40
|
+
web?: {
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
port?: number;
|
|
43
|
+
};
|
|
44
|
+
agentMemoryPolicy?: Record<string, "none" | "readonly" | "readwrite">;
|
|
45
|
+
defaultPolicy?: "none" | "readonly" | "readwrite";
|
|
46
|
+
autoUpdate?: boolean; // default false
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ── Defaults ─────────────────────────────────────────────────────────
|
|
50
|
+
|
|
51
|
+
const DEFAULTS: CerebroPluginConfig = {
|
|
52
|
+
connection: {
|
|
53
|
+
apiUrl: "https://www.mengxy.cc",
|
|
54
|
+
apiKey: "",
|
|
55
|
+
requestTimeoutMs: 15000,
|
|
56
|
+
},
|
|
57
|
+
content: {
|
|
58
|
+
maxQueryLength: 200,
|
|
59
|
+
maxContentChars: 30000,
|
|
60
|
+
maxContentLength: 3000,
|
|
61
|
+
},
|
|
62
|
+
injection: {
|
|
63
|
+
recentCount: 5,
|
|
64
|
+
searchCount: 10,
|
|
65
|
+
globalCount: 3,
|
|
66
|
+
recentTruncateChars: 0, // 0 = 不截断
|
|
67
|
+
searchTruncateChars: 0, // 0 = 不截断
|
|
68
|
+
recentTimeoutMs: 3000,
|
|
69
|
+
searchTimeoutMs: 5000,
|
|
70
|
+
profileTimeoutMs: 2000,
|
|
71
|
+
},
|
|
72
|
+
ingest: {
|
|
73
|
+
autoCaptureThreshold: 5,
|
|
74
|
+
ingestMode: "smart",
|
|
75
|
+
},
|
|
76
|
+
logging: {
|
|
77
|
+
logEnabled: true,
|
|
78
|
+
logLevel: "INFO",
|
|
79
|
+
logDir: join(homedir(), ".config", "cerebro"),
|
|
80
|
+
},
|
|
81
|
+
ui: {
|
|
82
|
+
toastDelayMs: 7000,
|
|
83
|
+
},
|
|
84
|
+
web: {
|
|
85
|
+
enabled: true,
|
|
86
|
+
},
|
|
87
|
+
autoUpdate: false,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// ── Flat-to-nested migration ─────────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
/** Shape of legacy flat config (pre-nesting). */
|
|
93
|
+
interface FlatConfig {
|
|
94
|
+
apiUrl?: string;
|
|
95
|
+
apiKey?: string;
|
|
96
|
+
requestTimeoutMs?: number;
|
|
97
|
+
maxQueryLength?: number;
|
|
98
|
+
maxContentChars?: number;
|
|
99
|
+
maxContentLength?: number;
|
|
100
|
+
autoCaptureThreshold?: number;
|
|
101
|
+
ingestMode?: "smart" | "raw";
|
|
102
|
+
toastDelayMs?: number;
|
|
103
|
+
logEnabled?: boolean;
|
|
104
|
+
logLevel?: "DEBUG" | "INFO" | "WARN" | "ERROR";
|
|
105
|
+
logDir?: string;
|
|
106
|
+
// Nested fields that would indicate new format
|
|
107
|
+
connection?: unknown;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function isFlatConfig(cfg: Record<string, unknown>): boolean {
|
|
111
|
+
return "apiUrl" in cfg && !("connection" in cfg);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function migrateFlatToNested(flat: FlatConfig): CerebroPluginConfig {
|
|
115
|
+
return {
|
|
116
|
+
connection: {
|
|
117
|
+
apiUrl: flat.apiUrl ?? DEFAULTS.connection.apiUrl,
|
|
118
|
+
apiKey: flat.apiKey ?? DEFAULTS.connection.apiKey,
|
|
119
|
+
requestTimeoutMs: flat.requestTimeoutMs ?? DEFAULTS.connection.requestTimeoutMs,
|
|
120
|
+
},
|
|
121
|
+
content: {
|
|
122
|
+
maxQueryLength: flat.maxQueryLength ?? DEFAULTS.content.maxQueryLength,
|
|
123
|
+
maxContentChars: flat.maxContentChars ?? DEFAULTS.content.maxContentChars,
|
|
124
|
+
maxContentLength: flat.maxContentLength ?? DEFAULTS.content.maxContentLength,
|
|
125
|
+
},
|
|
126
|
+
injection: { ...DEFAULTS.injection },
|
|
127
|
+
ingest: {
|
|
128
|
+
autoCaptureThreshold: flat.autoCaptureThreshold ?? DEFAULTS.ingest.autoCaptureThreshold,
|
|
129
|
+
ingestMode: flat.ingestMode ?? DEFAULTS.ingest.ingestMode,
|
|
130
|
+
},
|
|
131
|
+
logging: {
|
|
132
|
+
logEnabled: flat.logEnabled ?? DEFAULTS.logging.logEnabled,
|
|
133
|
+
logLevel: flat.logLevel ?? DEFAULTS.logging.logLevel,
|
|
134
|
+
logDir: flat.logDir ?? DEFAULTS.logging.logDir,
|
|
135
|
+
},
|
|
136
|
+
ui: {
|
|
137
|
+
toastDelayMs: flat.toastDelayMs ?? DEFAULTS.ui.toastDelayMs,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
143
|
+
|
|
144
|
+
type IngestMode = "smart" | "raw";
|
|
145
|
+
const INGEST_MODES: ReadonlySet<string> = new Set<IngestMode>(["smart", "raw"]);
|
|
146
|
+
|
|
147
|
+
function deepMerge(base: CerebroPluginConfig, overrides: Partial<CerebroPluginConfig>): CerebroPluginConfig {
|
|
148
|
+
const result: CerebroPluginConfig = {
|
|
149
|
+
connection: { ...base.connection, ...overrides.connection },
|
|
150
|
+
content: { ...base.content, ...overrides.content },
|
|
151
|
+
injection: { ...base.injection, ...overrides.injection },
|
|
152
|
+
ingest: { ...base.ingest, ...overrides.ingest },
|
|
153
|
+
logging: { ...base.logging, ...overrides.logging },
|
|
154
|
+
ui: { ...base.ui, ...overrides.ui },
|
|
155
|
+
};
|
|
156
|
+
result.web = { ...base.web!, ...overrides.web };
|
|
157
|
+
if (overrides.agentMemoryPolicy) result.agentMemoryPolicy = overrides.agentMemoryPolicy;
|
|
158
|
+
if (overrides.defaultPolicy) result.defaultPolicy = overrides.defaultPolicy;
|
|
159
|
+
if (overrides.autoUpdate !== undefined) result.autoUpdate = overrides.autoUpdate;
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ── Load config ──────────────────────────────────────────────────────
|
|
164
|
+
|
|
165
|
+
const LEVEL_MAP: Record<string, number> = { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3 };
|
|
166
|
+
|
|
167
|
+
function readConfiguredLogLevel(): number {
|
|
168
|
+
try {
|
|
169
|
+
const cfgPath = join(homedir(), ".config", "cerebro", "config.json");
|
|
170
|
+
const raw = JSON.parse(readFileSync(cfgPath, "utf-8")) as Record<string, unknown>;
|
|
171
|
+
const nested = (raw?.logging as Record<string, unknown>)?.logLevel as string | undefined;
|
|
172
|
+
const flat = raw?.logLevel as string | undefined;
|
|
173
|
+
const level = nested ?? flat ?? "INFO";
|
|
174
|
+
return LEVEL_MAP[level] ?? LEVEL_MAP.INFO;
|
|
175
|
+
} catch {
|
|
176
|
+
return LEVEL_MAP.INFO;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const CONFIGURED_MIN_LEVEL = readConfiguredLogLevel();
|
|
181
|
+
|
|
182
|
+
/** File-only logger for config.ts (cannot import logger.ts due to circular dependency). */
|
|
183
|
+
function configLog(message: string, fields?: Record<string, unknown>, level: string = "WARN"): void {
|
|
184
|
+
const lvl = LEVEL_MAP[level] ?? 0;
|
|
185
|
+
if (lvl < CONFIGURED_MIN_LEVEL) return;
|
|
186
|
+
try {
|
|
187
|
+
const logDir = join(homedir(), ".config", "cerebro", "logs");
|
|
188
|
+
const logPath = join(logDir, "cerebro.log");
|
|
189
|
+
const ts = new Date().toISOString().replace("T", " ").replace(/\.\d+Z$/, "");
|
|
190
|
+
const parts = [`${level.padEnd(5)} ${ts} service=cerebro ${message}`];
|
|
191
|
+
if (fields) {
|
|
192
|
+
for (const [k, v] of Object.entries(fields)) {
|
|
193
|
+
parts.push(`${k}=${typeof v === "string" ? v : JSON.stringify(v)}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
mkdirSync(logDir, { recursive: true });
|
|
197
|
+
appendFileSync(logPath, parts.join(" ") + "\n");
|
|
198
|
+
} catch (writeErr) {
|
|
199
|
+
process.stderr.write(`[cerebro] configLog write failed: ${writeErr instanceof Error ? writeErr.message : String(writeErr)}\n`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function loadPluginConfig(overrides?: Partial<CerebroPluginConfig>): CerebroPluginConfig {
|
|
204
|
+
let config: CerebroPluginConfig = structuredClone(DEFAULTS);
|
|
205
|
+
|
|
206
|
+
// Try loading from config file
|
|
207
|
+
try {
|
|
208
|
+
const cfgPath = join(homedir(), ".config", "cerebro", "config.json");
|
|
209
|
+
const raw = JSON.parse(readFileSync(cfgPath, "utf-8")) as Record<string, unknown>;
|
|
210
|
+
|
|
211
|
+
// Auto-migrate flat format
|
|
212
|
+
const parsed: CerebroPluginConfig = isFlatConfig(raw) ? migrateFlatToNested(raw as FlatConfig) : raw as unknown as CerebroPluginConfig;
|
|
213
|
+
|
|
214
|
+
// Merge nested groups with defaults for safety
|
|
215
|
+
config = deepMerge(config, parsed);
|
|
216
|
+
} catch (e) {
|
|
217
|
+
configLog("config.json load failed, using defaults", { error: String(e) });
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Apply explicit overrides (from opencode.json)
|
|
221
|
+
if (overrides) {
|
|
222
|
+
config = deepMerge(config, overrides);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Apply environment variable overrides last — env vars have highest priority
|
|
226
|
+
if (process.env.OMEM_API_URL) config.connection.apiUrl = process.env.OMEM_API_URL;
|
|
227
|
+
if (process.env.OMEM_API_KEY) config.connection.apiKey = process.env.OMEM_API_KEY;
|
|
228
|
+
if (process.env.OMEM_REQUEST_TIMEOUT_MS) {
|
|
229
|
+
config.connection.requestTimeoutMs = parseInt(process.env.OMEM_REQUEST_TIMEOUT_MS, 10) || DEFAULTS.connection.requestTimeoutMs;
|
|
230
|
+
}
|
|
231
|
+
if (process.env.OMEM_AUTO_CAPTURE_THRESHOLD) {
|
|
232
|
+
config.ingest.autoCaptureThreshold = parseInt(process.env.OMEM_AUTO_CAPTURE_THRESHOLD, 10) || DEFAULTS.ingest.autoCaptureThreshold;
|
|
233
|
+
}
|
|
234
|
+
if (INGEST_MODES.has(process.env.OMEM_INGEST_MODE ?? "")) {
|
|
235
|
+
config.ingest.ingestMode = process.env.OMEM_INGEST_MODE as IngestMode;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (process.env.OMEM_WEB_ENABLED === "false" || process.env.OMEM_WEB_ENABLED === "0") {
|
|
239
|
+
config.web = { ...config.web!, enabled: false };
|
|
240
|
+
}
|
|
241
|
+
if (process.env.OMEM_LOCAL_PORT) {
|
|
242
|
+
config.web = { ...config.web!, port: parseInt(process.env.OMEM_LOCAL_PORT, 10) || DEFAULTS.web!.port };
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Expand ~ to home directory in logDir
|
|
246
|
+
if (config.logging.logDir?.startsWith("~")) {
|
|
247
|
+
config.logging.logDir = config.logging.logDir.replace(/^~/, homedir());
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return config;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// ── Agent policy resolver ────────────────────────────────────────────
|
|
254
|
+
|
|
255
|
+
export type AgentPolicy = "none" | "readonly" | "readwrite";
|
|
256
|
+
|
|
257
|
+
export function resolveAgentPolicy(
|
|
258
|
+
agentName: string,
|
|
259
|
+
config: Partial<CerebroPluginConfig>,
|
|
260
|
+
): AgentPolicy {
|
|
261
|
+
const policies = config.agentMemoryPolicy;
|
|
262
|
+
if (policies) {
|
|
263
|
+
const exact = policies[agentName];
|
|
264
|
+
if (exact) return exact;
|
|
265
|
+
const lower = agentName.toLowerCase();
|
|
266
|
+
for (const [key, policy] of Object.entries(policies)) {
|
|
267
|
+
if (lower.startsWith(key.toLowerCase()) || key.toLowerCase().startsWith(lower)) {
|
|
268
|
+
return policy;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (config.defaultPolicy) return config.defaultPolicy;
|
|
273
|
+
configLog("resolveAgentPolicy: defaulting to readwrite", { agentName }, "DEBUG");
|
|
274
|
+
return "readwrite";
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export { DEFAULTS };
|