@oh-my-pi/pi-coding-agent 11.8.2 → 11.8.3
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/docs/tui.md +9 -9
- package/package.json +7 -7
- package/src/cli/file-processor.ts +8 -13
- package/src/cli/oclif-help.ts +1 -1
- package/src/cli.ts +14 -0
- package/src/commit/git/index.ts +16 -16
- package/src/config/keybindings.ts +11 -11
- package/src/config/model-registry.ts +31 -66
- package/src/config/settings.ts +88 -95
- package/src/config.ts +2 -2
- package/src/cursor.ts +4 -4
- package/src/debug/index.ts +28 -28
- package/src/discovery/codex.ts +5 -13
- package/src/discovery/cursor.ts +2 -7
- package/src/exa/mcp-client.ts +2 -2
- package/src/exa/websets.ts +2 -2
- package/src/export/html/index.ts +3 -3
- package/src/export/ttsr.ts +27 -27
- package/src/extensibility/custom-tools/loader.ts +9 -9
- package/src/extensibility/extensions/runner.ts +64 -64
- package/src/extensibility/hooks/runner.ts +46 -46
- package/src/extensibility/plugins/manager.ts +49 -49
- package/src/index.ts +0 -1
- package/src/internal-urls/router.ts +5 -5
- package/src/ipy/kernel.ts +61 -57
- package/src/lsp/client.ts +1 -1
- package/src/lsp/clients/biome-client.ts +2 -2
- package/src/lsp/clients/lsp-linter-client.ts +7 -7
- package/src/lsp/index.ts +9 -9
- package/src/mcp/manager.ts +47 -47
- package/src/mcp/tool-bridge.ts +12 -12
- package/src/mcp/transports/http.ts +34 -34
- package/src/mcp/transports/stdio.ts +47 -47
- package/src/modes/components/assistant-message.ts +25 -25
- package/src/modes/components/bash-execution.ts +51 -51
- package/src/modes/components/bordered-loader.ts +7 -7
- package/src/modes/components/branch-summary-message.ts +7 -7
- package/src/modes/components/compaction-summary-message.ts +7 -7
- package/src/modes/components/countdown-timer.ts +15 -15
- package/src/modes/components/custom-editor.ts +22 -22
- package/src/modes/components/custom-message.ts +21 -21
- package/src/modes/components/dynamic-border.ts +3 -3
- package/src/modes/components/extensions/extension-dashboard.ts +72 -72
- package/src/modes/components/extensions/extension-list.ts +99 -97
- package/src/modes/components/extensions/inspector-panel.ts +26 -26
- package/src/modes/components/footer.ts +36 -36
- package/src/modes/components/history-search.ts +52 -52
- package/src/modes/components/hook-editor.ts +20 -20
- package/src/modes/components/hook-input.ts +20 -20
- package/src/modes/components/hook-message.ts +22 -22
- package/src/modes/components/hook-selector.ts +52 -52
- package/src/modes/components/index.ts +0 -1
- package/src/modes/components/login-dialog.ts +57 -57
- package/src/modes/components/model-selector.ts +173 -173
- package/src/modes/components/oauth-selector.ts +45 -45
- package/src/modes/components/plugin-settings.ts +52 -52
- package/src/modes/components/python-execution.ts +53 -53
- package/src/modes/components/queue-mode-selector.ts +7 -7
- package/src/modes/components/read-tool-group.ts +23 -23
- package/src/modes/components/session-selector.ts +40 -37
- package/src/modes/components/settings-selector.ts +80 -80
- package/src/modes/components/show-images-selector.ts +7 -7
- package/src/modes/components/skill-message.ts +27 -27
- package/src/modes/components/status-line-segment-editor.ts +81 -81
- package/src/modes/components/status-line.ts +73 -73
- package/src/modes/components/theme-selector.ts +11 -11
- package/src/modes/components/thinking-selector.ts +7 -7
- package/src/modes/components/todo-display.ts +19 -19
- package/src/modes/components/todo-reminder.ts +9 -9
- package/src/modes/components/tool-execution.ts +204 -196
- package/src/modes/components/tree-selector.ts +144 -144
- package/src/modes/components/ttsr-notification.ts +17 -17
- package/src/modes/components/user-message-selector.ts +18 -18
- package/src/modes/components/welcome.ts +10 -10
- package/src/modes/controllers/command-controller.ts +0 -7
- package/src/modes/controllers/event-controller.ts +23 -23
- package/src/modes/controllers/extension-ui-controller.ts +13 -13
- package/src/modes/controllers/input-controller.ts +4 -9
- package/src/modes/interactive-mode.ts +234 -241
- package/src/modes/rpc/rpc-client.ts +77 -77
- package/src/modes/rpc/rpc-mode.ts +5 -5
- package/src/modes/theme/theme.ts +113 -113
- package/src/modes/types.ts +0 -1
- package/src/patch/index.ts +45 -45
- package/src/prompts/tools/task.md +22 -2
- package/src/session/agent-session.ts +463 -476
- package/src/session/agent-storage.ts +72 -75
- package/src/session/auth-storage.ts +186 -252
- package/src/session/history-storage.ts +36 -38
- package/src/session/session-manager.ts +300 -299
- package/src/session/session-storage.ts +65 -90
- package/src/ssh/connection-manager.ts +9 -9
- package/src/task/agents.ts +1 -1
- package/src/task/executor.ts +2 -2
- package/src/task/index.ts +13 -12
- package/src/task/subprocess-tool-registry.ts +5 -5
- package/src/tools/ask.ts +7 -7
- package/src/tools/bash.ts +8 -7
- package/src/tools/browser.ts +123 -123
- package/src/tools/calculator.ts +46 -46
- package/src/tools/context.ts +9 -9
- package/src/tools/exit-plan-mode.ts +5 -5
- package/src/tools/fetch.ts +5 -5
- package/src/tools/find.ts +16 -16
- package/src/tools/grep.ts +10 -10
- package/src/tools/notebook.ts +6 -6
- package/src/tools/output-meta.ts +10 -2
- package/src/tools/python.ts +12 -11
- package/src/tools/read.ts +17 -17
- package/src/tools/ssh.ts +9 -9
- package/src/tools/submit-result.ts +13 -13
- package/src/tools/todo-write.ts +6 -6
- package/src/tools/write.ts +10 -10
- package/src/tui/output-block.ts +6 -6
- package/src/tui/utils.ts +9 -9
- package/src/utils/event-bus.ts +10 -10
- package/src/utils/frontmatter.ts +1 -1
- package/src/utils/ignore-files.ts +1 -1
- package/src/web/search/index.ts +5 -5
- package/src/web/search/providers/anthropic.ts +7 -2
- package/examples/hooks/snake.ts +0 -342
- package/src/modes/components/armin.ts +0 -379
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Database } from "bun:sqlite";
|
|
1
|
+
import { Database, type Statement } from "bun:sqlite";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { logger } from "@oh-my-pi/pi-utils";
|
|
@@ -6,9 +6,6 @@ import { getAgentDbPath } from "../config";
|
|
|
6
6
|
import type { RawSettings as Settings } from "../config/settings";
|
|
7
7
|
import type { AuthCredential } from "./auth-storage";
|
|
8
8
|
|
|
9
|
-
/** Prepared SQLite statement type from bun:sqlite */
|
|
10
|
-
type Statement = ReturnType<Database["prepare"]>;
|
|
11
|
-
|
|
12
9
|
/** Row shape for settings table queries */
|
|
13
10
|
type SettingsRow = {
|
|
14
11
|
key: string;
|
|
@@ -118,28 +115,28 @@ function deserializeCredential(row: AuthRow): AuthCredential | null {
|
|
|
118
115
|
* Uses singleton pattern per database path; access via AgentStorage.open().
|
|
119
116
|
*/
|
|
120
117
|
export class AgentStorage {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
118
|
+
#db: Database;
|
|
119
|
+
static #instances = new Map<string, AgentStorage>();
|
|
120
|
+
|
|
121
|
+
#listSettingsStmt: Statement;
|
|
122
|
+
#getCacheStmt: Statement;
|
|
123
|
+
#upsertCacheStmt: Statement;
|
|
124
|
+
#deleteExpiredCacheStmt: Statement;
|
|
125
|
+
#listAuthStmt: Statement;
|
|
126
|
+
#listAuthByProviderStmt: Statement;
|
|
127
|
+
#insertAuthStmt: Statement;
|
|
128
|
+
#updateAuthStmt: Statement;
|
|
129
|
+
#deleteAuthStmt: Statement;
|
|
130
|
+
#deleteAuthByProviderStmt: Statement;
|
|
131
|
+
#countAuthStmt: Statement;
|
|
132
|
+
#upsertModelUsageStmt: Statement;
|
|
133
|
+
#listModelUsageStmt: Statement;
|
|
134
|
+
#modelUsageCache: string[] | null = null;
|
|
138
135
|
|
|
139
136
|
private constructor(dbPath: string) {
|
|
140
|
-
this
|
|
137
|
+
this.#ensureDir(dbPath);
|
|
141
138
|
try {
|
|
142
|
-
this
|
|
139
|
+
this.#db = new Database(dbPath);
|
|
143
140
|
} catch (err) {
|
|
144
141
|
const dir = path.dirname(dbPath);
|
|
145
142
|
const dirExists = fs.existsSync(dir);
|
|
@@ -151,37 +148,37 @@ export class AgentStorage {
|
|
|
151
148
|
);
|
|
152
149
|
}
|
|
153
150
|
|
|
154
|
-
this
|
|
155
|
-
this
|
|
151
|
+
this.#initializeSchema();
|
|
152
|
+
this.#hardenPermissions(dbPath);
|
|
156
153
|
|
|
157
|
-
this
|
|
154
|
+
this.#listSettingsStmt = this.#db.prepare("SELECT key, value FROM settings");
|
|
158
155
|
|
|
159
|
-
this
|
|
160
|
-
this
|
|
156
|
+
this.#getCacheStmt = this.#db.prepare("SELECT value FROM cache WHERE key = ? AND expires_at > unixepoch()");
|
|
157
|
+
this.#upsertCacheStmt = this.#db.prepare(
|
|
161
158
|
"INSERT INTO cache (key, value, expires_at) VALUES (?, ?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value, expires_at = excluded.expires_at",
|
|
162
159
|
);
|
|
163
|
-
this
|
|
160
|
+
this.#deleteExpiredCacheStmt = this.#db.prepare("DELETE FROM cache WHERE expires_at <= unixepoch()");
|
|
164
161
|
|
|
165
|
-
this
|
|
162
|
+
this.#listAuthStmt = this.#db.prepare(
|
|
166
163
|
"SELECT id, provider, credential_type, data FROM auth_credentials ORDER BY id ASC",
|
|
167
164
|
);
|
|
168
|
-
this
|
|
165
|
+
this.#listAuthByProviderStmt = this.#db.prepare(
|
|
169
166
|
"SELECT id, provider, credential_type, data FROM auth_credentials WHERE provider = ? ORDER BY id ASC",
|
|
170
167
|
);
|
|
171
|
-
this
|
|
168
|
+
this.#insertAuthStmt = this.#db.prepare(
|
|
172
169
|
"INSERT INTO auth_credentials (provider, credential_type, data) VALUES (?, ?, ?) RETURNING id",
|
|
173
170
|
);
|
|
174
|
-
this
|
|
171
|
+
this.#updateAuthStmt = this.#db.prepare(
|
|
175
172
|
"UPDATE auth_credentials SET credential_type = ?, data = ?, updated_at = unixepoch() WHERE id = ?",
|
|
176
173
|
);
|
|
177
|
-
this
|
|
178
|
-
this
|
|
179
|
-
this
|
|
174
|
+
this.#deleteAuthStmt = this.#db.prepare("DELETE FROM auth_credentials WHERE id = ?");
|
|
175
|
+
this.#deleteAuthByProviderStmt = this.#db.prepare("DELETE FROM auth_credentials WHERE provider = ?");
|
|
176
|
+
this.#countAuthStmt = this.#db.prepare("SELECT COUNT(*) as count FROM auth_credentials");
|
|
180
177
|
|
|
181
|
-
this
|
|
178
|
+
this.#upsertModelUsageStmt = this.#db.prepare(
|
|
182
179
|
"INSERT INTO model_usage (model_key, last_used_at) VALUES (?, unixepoch()) ON CONFLICT(model_key) DO UPDATE SET last_used_at = unixepoch()",
|
|
183
180
|
);
|
|
184
|
-
this
|
|
181
|
+
this.#listModelUsageStmt = this.#db.prepare(
|
|
185
182
|
"SELECT model_key, last_used_at FROM model_usage ORDER BY last_used_at DESC",
|
|
186
183
|
);
|
|
187
184
|
}
|
|
@@ -190,8 +187,8 @@ export class AgentStorage {
|
|
|
190
187
|
* Creates tables if missing and migrates legacy single-blob settings to key-value format.
|
|
191
188
|
* Handles v1 to v2 schema migration for settings table.
|
|
192
189
|
*/
|
|
193
|
-
|
|
194
|
-
this
|
|
190
|
+
#initializeSchema(): void {
|
|
191
|
+
this.#db.exec(`
|
|
195
192
|
PRAGMA journal_mode=WAL;
|
|
196
193
|
PRAGMA synchronous=NORMAL;
|
|
197
194
|
PRAGMA busy_timeout=5000;
|
|
@@ -221,13 +218,13 @@ CREATE TABLE IF NOT EXISTS model_usage (
|
|
|
221
218
|
CREATE TABLE IF NOT EXISTS schema_version (version INTEGER PRIMARY KEY);
|
|
222
219
|
`);
|
|
223
220
|
|
|
224
|
-
const settingsInfo = this
|
|
221
|
+
const settingsInfo = this.#db.prepare("PRAGMA table_info(settings)").all() as Array<{ name?: string }>;
|
|
225
222
|
const hasSettingsTable = settingsInfo.length > 0;
|
|
226
223
|
const hasKey = settingsInfo.some(column => column.name === "key");
|
|
227
224
|
const hasValue = settingsInfo.some(column => column.name === "value");
|
|
228
225
|
|
|
229
226
|
if (!hasSettingsTable) {
|
|
230
|
-
this
|
|
227
|
+
this.#db.exec(`
|
|
231
228
|
CREATE TABLE settings (
|
|
232
229
|
key TEXT PRIMARY KEY,
|
|
233
230
|
value TEXT NOT NULL,
|
|
@@ -237,7 +234,7 @@ CREATE TABLE settings (
|
|
|
237
234
|
} else if (!hasKey || !hasValue) {
|
|
238
235
|
// Migrate v1 schema: single JSON blob in `data` column → per-key rows
|
|
239
236
|
let legacySettings: Record<string, unknown> | null = null;
|
|
240
|
-
const row = this
|
|
237
|
+
const row = this.#db.prepare("SELECT data FROM settings WHERE id = 1").get() as { data?: string } | undefined;
|
|
241
238
|
if (row?.data) {
|
|
242
239
|
try {
|
|
243
240
|
const parsed = JSON.parse(row.data);
|
|
@@ -251,9 +248,9 @@ CREATE TABLE settings (
|
|
|
251
248
|
}
|
|
252
249
|
}
|
|
253
250
|
|
|
254
|
-
const migrate = this
|
|
255
|
-
this
|
|
256
|
-
this
|
|
251
|
+
const migrate = this.#db.transaction((settings: Record<string, unknown> | null) => {
|
|
252
|
+
this.#db.exec("DROP TABLE settings");
|
|
253
|
+
this.#db.exec(`
|
|
257
254
|
CREATE TABLE settings (
|
|
258
255
|
key TEXT PRIMARY KEY,
|
|
259
256
|
value TEXT NOT NULL,
|
|
@@ -261,7 +258,7 @@ CREATE TABLE settings (
|
|
|
261
258
|
);
|
|
262
259
|
`);
|
|
263
260
|
if (settings) {
|
|
264
|
-
const insert = this
|
|
261
|
+
const insert = this.#db.prepare(
|
|
265
262
|
"INSERT INTO settings (key, value, updated_at) VALUES (?, ?, unixepoch())",
|
|
266
263
|
);
|
|
267
264
|
for (const [key, value] of Object.entries(settings)) {
|
|
@@ -276,7 +273,7 @@ CREATE TABLE settings (
|
|
|
276
273
|
migrate(legacySettings);
|
|
277
274
|
}
|
|
278
275
|
|
|
279
|
-
const versionRow = this
|
|
276
|
+
const versionRow = this.#db.prepare("SELECT version FROM schema_version ORDER BY version DESC LIMIT 1").get() as
|
|
280
277
|
| { version?: number }
|
|
281
278
|
| undefined;
|
|
282
279
|
if (versionRow?.version !== undefined && versionRow.version !== SCHEMA_VERSION) {
|
|
@@ -285,7 +282,7 @@ CREATE TABLE settings (
|
|
|
285
282
|
expected: SCHEMA_VERSION,
|
|
286
283
|
});
|
|
287
284
|
}
|
|
288
|
-
this
|
|
285
|
+
this.#db.prepare("INSERT OR REPLACE INTO schema_version(version) VALUES (?)").run(SCHEMA_VERSION);
|
|
289
286
|
}
|
|
290
287
|
|
|
291
288
|
/**
|
|
@@ -295,7 +292,7 @@ CREATE TABLE settings (
|
|
|
295
292
|
* @returns AgentStorage instance for the given path
|
|
296
293
|
*/
|
|
297
294
|
static async open(dbPath: string = getAgentDbPath()): Promise<AgentStorage> {
|
|
298
|
-
const existing = AgentStorage
|
|
295
|
+
const existing = AgentStorage.#instances.get(dbPath);
|
|
299
296
|
if (existing) return existing;
|
|
300
297
|
|
|
301
298
|
const maxRetries = 3;
|
|
@@ -305,7 +302,7 @@ CREATE TABLE settings (
|
|
|
305
302
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
306
303
|
try {
|
|
307
304
|
const storage = new AgentStorage(dbPath);
|
|
308
|
-
AgentStorage
|
|
305
|
+
AgentStorage.#instances.set(dbPath, storage);
|
|
309
306
|
return storage;
|
|
310
307
|
} catch (err) {
|
|
311
308
|
const isSqliteBusy = err && typeof err === "object" && (err as { code?: string }).code === "SQLITE_BUSY";
|
|
@@ -329,7 +326,7 @@ CREATE TABLE settings (
|
|
|
329
326
|
* @deprecated Use config.yml instead. This is only for migration.
|
|
330
327
|
*/
|
|
331
328
|
getSettings(): Settings | null {
|
|
332
|
-
const rows = (this
|
|
329
|
+
const rows = (this.#listSettingsStmt.all() as SettingsRow[]) ?? [];
|
|
333
330
|
if (rows.length === 0) return null;
|
|
334
331
|
const settings: Record<string, unknown> = {};
|
|
335
332
|
for (const row of rows) {
|
|
@@ -360,7 +357,7 @@ CREATE TABLE settings (
|
|
|
360
357
|
*/
|
|
361
358
|
getCache(key: string): string | null {
|
|
362
359
|
try {
|
|
363
|
-
const row = this
|
|
360
|
+
const row = this.#getCacheStmt.get(key) as { value?: string } | undefined;
|
|
364
361
|
return row?.value ?? null;
|
|
365
362
|
} catch {
|
|
366
363
|
return null;
|
|
@@ -372,7 +369,7 @@ CREATE TABLE settings (
|
|
|
372
369
|
*/
|
|
373
370
|
setCache(key: string, value: string, expiresAtSec: number): void {
|
|
374
371
|
try {
|
|
375
|
-
this
|
|
372
|
+
this.#upsertCacheStmt.run(key, value, expiresAtSec);
|
|
376
373
|
} catch (error) {
|
|
377
374
|
logger.warn("AgentStorage failed to set cache", { key, error: String(error) });
|
|
378
375
|
}
|
|
@@ -383,7 +380,7 @@ CREATE TABLE settings (
|
|
|
383
380
|
*/
|
|
384
381
|
cleanExpiredCache(): void {
|
|
385
382
|
try {
|
|
386
|
-
this
|
|
383
|
+
this.#deleteExpiredCacheStmt.run();
|
|
387
384
|
} catch {
|
|
388
385
|
// Ignore cleanup errors
|
|
389
386
|
}
|
|
@@ -395,8 +392,8 @@ CREATE TABLE settings (
|
|
|
395
392
|
*/
|
|
396
393
|
recordModelUsage(modelKey: string): void {
|
|
397
394
|
try {
|
|
398
|
-
this
|
|
399
|
-
this
|
|
395
|
+
this.#upsertModelUsageStmt.run(modelKey);
|
|
396
|
+
this.#modelUsageCache = null;
|
|
400
397
|
} catch (error) {
|
|
401
398
|
logger.warn("AgentStorage failed to record model usage", { modelKey, error: String(error) });
|
|
402
399
|
}
|
|
@@ -408,13 +405,13 @@ CREATE TABLE settings (
|
|
|
408
405
|
* @returns Array of model keys ("provider/modelId") in MRU order
|
|
409
406
|
*/
|
|
410
407
|
getModelUsageOrder(): string[] {
|
|
411
|
-
if (this
|
|
412
|
-
return this
|
|
408
|
+
if (this.#modelUsageCache) {
|
|
409
|
+
return this.#modelUsageCache;
|
|
413
410
|
}
|
|
414
411
|
try {
|
|
415
|
-
const rows = this
|
|
416
|
-
this
|
|
417
|
-
return this
|
|
412
|
+
const rows = this.#listModelUsageStmt.all() as ModelUsageRow[];
|
|
413
|
+
this.#modelUsageCache = rows.map(row => row.model_key);
|
|
414
|
+
return this.#modelUsageCache;
|
|
418
415
|
} catch (error) {
|
|
419
416
|
logger.warn("AgentStorage failed to get model usage order", { error: String(error) });
|
|
420
417
|
return [];
|
|
@@ -426,7 +423,7 @@ CREATE TABLE settings (
|
|
|
426
423
|
* @returns True if at least one credential is stored
|
|
427
424
|
*/
|
|
428
425
|
hasAuthCredentials(): boolean {
|
|
429
|
-
const row = this
|
|
426
|
+
const row = this.#countAuthStmt.get() as { count?: number } | undefined;
|
|
430
427
|
return (row?.count ?? 0) > 0;
|
|
431
428
|
}
|
|
432
429
|
|
|
@@ -438,8 +435,8 @@ CREATE TABLE settings (
|
|
|
438
435
|
listAuthCredentials(provider?: string): StoredAuthCredential[] {
|
|
439
436
|
const rows =
|
|
440
437
|
(provider
|
|
441
|
-
? (this
|
|
442
|
-
: (this
|
|
438
|
+
? (this.#listAuthByProviderStmt.all(provider) as AuthRow[])
|
|
439
|
+
: (this.#listAuthStmt.all() as AuthRow[])) ?? [];
|
|
443
440
|
|
|
444
441
|
const results: StoredAuthCredential[] = [];
|
|
445
442
|
for (const row of rows) {
|
|
@@ -458,11 +455,11 @@ CREATE TABLE settings (
|
|
|
458
455
|
* @returns Array of newly stored credentials with their database IDs
|
|
459
456
|
*/
|
|
460
457
|
replaceAuthCredentialsForProvider(provider: string, credentials: AuthCredential[]): StoredAuthCredential[] {
|
|
461
|
-
const replace = this
|
|
462
|
-
this
|
|
458
|
+
const replace = this.#db.transaction((providerName: string, items: AuthCredential[]) => {
|
|
459
|
+
this.#deleteAuthByProviderStmt.run(providerName);
|
|
463
460
|
const inserted: StoredAuthCredential[] = [];
|
|
464
461
|
for (const credential of items) {
|
|
465
|
-
const record = this
|
|
462
|
+
const record = this.#insertAuthCredential(providerName, credential);
|
|
466
463
|
if (record) inserted.push(record);
|
|
467
464
|
}
|
|
468
465
|
return inserted;
|
|
@@ -483,7 +480,7 @@ CREATE TABLE settings (
|
|
|
483
480
|
return;
|
|
484
481
|
}
|
|
485
482
|
try {
|
|
486
|
-
this
|
|
483
|
+
this.#updateAuthStmt.run(serialized.credentialType, serialized.data, id);
|
|
487
484
|
} catch (error) {
|
|
488
485
|
logger.warn("AgentStorage updateAuthCredential failed", { id, error: String(error) });
|
|
489
486
|
}
|
|
@@ -495,7 +492,7 @@ CREATE TABLE settings (
|
|
|
495
492
|
*/
|
|
496
493
|
deleteAuthCredential(id: number): void {
|
|
497
494
|
try {
|
|
498
|
-
this
|
|
495
|
+
this.#deleteAuthStmt.run(id);
|
|
499
496
|
} catch (error) {
|
|
500
497
|
logger.warn("AgentStorage deleteAuthCredential failed", { id, error: String(error) });
|
|
501
498
|
}
|
|
@@ -507,7 +504,7 @@ CREATE TABLE settings (
|
|
|
507
504
|
*/
|
|
508
505
|
deleteAuthCredentialsForProvider(provider: string): void {
|
|
509
506
|
try {
|
|
510
|
-
this
|
|
507
|
+
this.#deleteAuthByProviderStmt.run(provider);
|
|
511
508
|
} catch (error) {
|
|
512
509
|
logger.warn("AgentStorage deleteAuthCredentialsForProvider failed", {
|
|
513
510
|
provider,
|
|
@@ -522,14 +519,14 @@ CREATE TABLE settings (
|
|
|
522
519
|
* @param credential - Credential to insert
|
|
523
520
|
* @returns Stored credential with database ID, or null on failure
|
|
524
521
|
*/
|
|
525
|
-
|
|
522
|
+
#insertAuthCredential(provider: string, credential: AuthCredential): StoredAuthCredential | null {
|
|
526
523
|
const serialized = serializeCredential(credential);
|
|
527
524
|
if (!serialized) {
|
|
528
525
|
logger.warn("AgentStorage insertAuthCredential invalid type", { provider, type: credential.type });
|
|
529
526
|
return null;
|
|
530
527
|
}
|
|
531
528
|
try {
|
|
532
|
-
const row = this
|
|
529
|
+
const row = this.#insertAuthStmt.get(provider, serialized.credentialType, serialized.data) as
|
|
533
530
|
| { id?: number }
|
|
534
531
|
| undefined;
|
|
535
532
|
if (!row?.id) {
|
|
@@ -547,7 +544,7 @@ CREATE TABLE settings (
|
|
|
547
544
|
* Ensures the parent directory for the database file exists.
|
|
548
545
|
* @param dbPath - Path to the database file
|
|
549
546
|
*/
|
|
550
|
-
|
|
547
|
+
#ensureDir(dbPath: string): void {
|
|
551
548
|
const dir = path.dirname(dbPath);
|
|
552
549
|
try {
|
|
553
550
|
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
@@ -564,7 +561,7 @@ CREATE TABLE settings (
|
|
|
564
561
|
}
|
|
565
562
|
}
|
|
566
563
|
|
|
567
|
-
|
|
564
|
+
#hardenPermissions(dbPath: string): void {
|
|
568
565
|
const dir = path.dirname(dbPath);
|
|
569
566
|
try {
|
|
570
567
|
fs.chmodSync(dir, 0o700);
|