negotium 0.2.19 → 0.2.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-helpers.js +367 -313
- package/dist/agent-helpers.js.map +17 -17
- package/dist/background-bash.js +3 -2
- package/dist/background-bash.js.map +3 -3
- package/dist/browser-runtime.js +60 -36
- package/dist/browser-runtime.js.map +6 -6
- package/dist/{chunk-fc58cqry.js → chunk-g2kqfdwm.js} +154 -24
- package/dist/{chunk-fc58cqry.js.map → chunk-g2kqfdwm.js.map} +6 -5
- package/dist/hosted-agent.js +183 -53
- package/dist/hosted-agent.js.map +7 -6
- package/dist/main.js +671 -425
- package/dist/main.js.map +23 -23
- package/dist/mcp-factories.js +334 -280
- package/dist/mcp-factories.js.map +17 -17
- package/dist/prompts.js +3 -2
- package/dist/prompts.js.map +3 -3
- package/dist/query-runtime.js +47 -26
- package/dist/query-runtime.js.map +4 -4
- package/dist/registry.js +3 -3
- package/dist/registry.js.map +2 -2
- package/dist/rollout.js +1 -1
- package/dist/runtime/src/agents/archiver.ts +3 -2
- package/dist/runtime/src/application/switch-topic-access-mode.ts +81 -8
- package/dist/runtime/src/bus.ts +19 -2
- package/dist/runtime/src/mcp/session-comm/runtime.ts +16 -0
- package/dist/runtime/src/platform/config.ts +13 -1
- package/dist/runtime/src/runtime/ask-callbacks.ts +19 -11
- package/dist/runtime/src/runtime/background-sessions.ts +9 -7
- package/dist/runtime/src/runtime/visual-store.ts +31 -23
- package/dist/runtime/src/storage/api-topics.ts +26 -0
- package/dist/runtime/src/storage/browser-profiles.ts +16 -8
- package/dist/runtime/src/storage/runtime-events.ts +30 -20
- package/dist/runtime/src/storage/runtime-gateway-submissions.ts +24 -16
- package/dist/runtime/src/storage/runtime-turn-requests.ts +9 -1
- package/dist/runtime/src/storage/self-schedules.ts +32 -24
- package/dist/runtime/src/storage/storage-host.ts +105 -43
- package/dist/runtime/src/storage/vault.ts +12 -3
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-helpers.js +47 -26
- package/dist/runtime-helpers.js.map +4 -4
- package/dist/storage.js +76 -41
- package/dist/storage.js.map +4 -4
- package/dist/types/packages/core/src/storage/api-topics.d.ts +15 -0
- package/dist/types/packages/core/src/storage/storage-host.d.ts +10 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js +140 -10
- package/dist/vault.js.map +6 -5
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { db } from "#storage/forum-db";
|
|
3
3
|
import { TURN_LEASE_STALE_MS } from "#storage/runtime-leases";
|
|
4
4
|
import { TOPIC_MAINTENANCE_STALE_MS } from "#storage/runtime-topic-state";
|
|
5
|
+
import { registerStorageSchemaInitializer } from "#storage/storage-host";
|
|
5
6
|
|
|
6
7
|
export type SelfScheduleStatus = "pending" | "running";
|
|
7
8
|
|
|
@@ -33,30 +34,37 @@ interface SelfScheduleRow {
|
|
|
33
34
|
running_query_id: string | null;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
db.exec
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
37
|
+
// Registered rather than executed at import time. A bare top-level `db.exec`
|
|
38
|
+
// resolves the storage connection the moment this module is imported, which for
|
|
39
|
+
// an embedding host is before `configureStorageHost()` has run — Negotium then
|
|
40
|
+
// opens its own database in the default state directory, caches it, and every
|
|
41
|
+
// later caller silently keeps using it instead of the host's.
|
|
42
|
+
registerStorageSchemaInitializer((database) => {
|
|
43
|
+
database.exec(`
|
|
44
|
+
CREATE TABLE IF NOT EXISTS runtime_self_schedules (
|
|
45
|
+
id TEXT PRIMARY KEY,
|
|
46
|
+
topic_id TEXT NOT NULL,
|
|
47
|
+
user_id TEXT NOT NULL,
|
|
48
|
+
message TEXT NOT NULL,
|
|
49
|
+
deliver_at INTEGER NOT NULL,
|
|
50
|
+
created_at INTEGER NOT NULL,
|
|
51
|
+
updated_at INTEGER NOT NULL,
|
|
52
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'running')),
|
|
53
|
+
claimed_by TEXT,
|
|
54
|
+
claimed_at INTEGER,
|
|
55
|
+
running_query_id TEXT
|
|
56
|
+
)
|
|
57
|
+
`);
|
|
58
|
+
database.exec(`
|
|
59
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_runtime_self_schedules_one_pending
|
|
60
|
+
ON runtime_self_schedules(topic_id)
|
|
61
|
+
WHERE status = 'pending'
|
|
62
|
+
`);
|
|
63
|
+
database.exec(`
|
|
64
|
+
CREATE INDEX IF NOT EXISTS idx_runtime_self_schedules_due
|
|
65
|
+
ON runtime_self_schedules(status, deliver_at)
|
|
66
|
+
`);
|
|
67
|
+
});
|
|
60
68
|
|
|
61
69
|
function rowToSchedule(row: SelfScheduleRow): SelfSchedule {
|
|
62
70
|
return {
|
|
@@ -14,28 +14,73 @@ export type {
|
|
|
14
14
|
StorageTransaction,
|
|
15
15
|
} from "#storage/storage-contract";
|
|
16
16
|
|
|
17
|
-
let configuredHost: Readonly<StorageHostConfig> = {};
|
|
18
17
|
type InternalStorageDatabase = InstanceType<typeof Database>;
|
|
19
18
|
type OwnedStorageDatabase = InternalStorageDatabase & { close(): void };
|
|
20
|
-
let fallbackDatabase: OwnedStorageDatabase | null = null;
|
|
21
|
-
let fallbackDatabasePath: string | null = null;
|
|
22
19
|
|
|
23
20
|
interface StorageHostFrame {
|
|
24
21
|
active: boolean;
|
|
25
22
|
patch: Readonly<StorageHostConfig>;
|
|
26
23
|
}
|
|
27
24
|
|
|
28
|
-
const storageHostFrames: StorageHostFrame[] = [];
|
|
29
|
-
|
|
30
25
|
type StorageSchemaInitializer = (database: InternalStorageDatabase) => void;
|
|
31
26
|
interface RegisteredSchemaInitializer {
|
|
32
27
|
initialize: StorageSchemaInitializer;
|
|
33
28
|
priority: number;
|
|
34
29
|
}
|
|
35
30
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
interface StorageHostState {
|
|
32
|
+
configuredHost: Readonly<StorageHostConfig>;
|
|
33
|
+
fallbackDatabase: OwnedStorageDatabase | null;
|
|
34
|
+
fallbackDatabasePath: string | null;
|
|
35
|
+
frames: StorageHostFrame[];
|
|
36
|
+
schemaInitializers: RegisteredSchemaInitializer[];
|
|
37
|
+
initializedSchemas: WeakMap<InternalStorageDatabase, Set<StorageSchemaInitializer>>;
|
|
38
|
+
initializingDatabases: WeakSet<InternalStorageDatabase>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Which database an embedded Negotium uses is a property of the *process*, so
|
|
43
|
+
* the state deciding it is keyed off a registered symbol rather than held in
|
|
44
|
+
* module scope.
|
|
45
|
+
*
|
|
46
|
+
* Module scope would be equivalent only if every caller resolved to the same
|
|
47
|
+
* module instance, and in the published package they do not:
|
|
48
|
+
* `build-negotium-package.ts` emits most public entrypoints as independent
|
|
49
|
+
* graphs, so each gets a private copy of this file. A host that configured
|
|
50
|
+
* `negotium/storage` therefore left `negotium/agent-helpers` unconfigured, and
|
|
51
|
+
* that copy opened a second database under the default state directory — with
|
|
52
|
+
* no error, since both files are valid and writable.
|
|
53
|
+
*
|
|
54
|
+
* Merging those entrypoints into one graph looks tidier and does cut ~3MB from
|
|
55
|
+
* `dist`, but Bun 1.2.15 (the pinned version) emits a shared chunk's export
|
|
56
|
+
* list twice and the result is invalid ESM — "Cannot export a duplicate name".
|
|
57
|
+
* That is bundler output with no counterpart in this source, so there is
|
|
58
|
+
* nothing to de-duplicate here; it is fixed in Bun 1.3.14. Until the floor
|
|
59
|
+
* moves, correctness cannot depend on how the package is chunked.
|
|
60
|
+
*/
|
|
61
|
+
const STORAGE_HOST_STATE = Symbol.for("negotium.storage-host.state.v1");
|
|
62
|
+
|
|
63
|
+
function storageState(): StorageHostState {
|
|
64
|
+
const holder = globalThis as typeof globalThis & { [STORAGE_HOST_STATE]?: StorageHostState };
|
|
65
|
+
const existing = holder[STORAGE_HOST_STATE];
|
|
66
|
+
if (existing) return existing;
|
|
67
|
+
const created: StorageHostState = {
|
|
68
|
+
configuredHost: {},
|
|
69
|
+
fallbackDatabase: null,
|
|
70
|
+
fallbackDatabasePath: null,
|
|
71
|
+
frames: [],
|
|
72
|
+
schemaInitializers: [],
|
|
73
|
+
initializedSchemas: new WeakMap(),
|
|
74
|
+
initializingDatabases: new WeakSet(),
|
|
75
|
+
};
|
|
76
|
+
Object.defineProperty(holder, STORAGE_HOST_STATE, {
|
|
77
|
+
value: created,
|
|
78
|
+
enumerable: false,
|
|
79
|
+
writable: false,
|
|
80
|
+
configurable: false,
|
|
81
|
+
});
|
|
82
|
+
return created;
|
|
83
|
+
}
|
|
39
84
|
|
|
40
85
|
function envPath(name: string, fallback: string): string {
|
|
41
86
|
const value = process.env[name]?.trim();
|
|
@@ -114,41 +159,55 @@ export function initializeDatabase(database: InternalStorageDatabase): void {
|
|
|
114
159
|
|
|
115
160
|
function defaultDatabase(): InternalStorageDatabase {
|
|
116
161
|
const path = defaultSessionsDatabasePath();
|
|
117
|
-
|
|
118
|
-
if (fallbackDatabase) fallbackDatabase
|
|
162
|
+
const state = storageState();
|
|
163
|
+
if (state.fallbackDatabase && state.fallbackDatabasePath === path) return state.fallbackDatabase;
|
|
164
|
+
if (state.fallbackDatabase) state.fallbackDatabase.close();
|
|
119
165
|
mkdirSync(dirname(path), { recursive: true });
|
|
120
|
-
fallbackDatabase = new Database(path, { create: true }) as unknown as OwnedStorageDatabase;
|
|
121
|
-
fallbackDatabasePath = path;
|
|
122
|
-
initializeDatabase(fallbackDatabase);
|
|
123
|
-
return fallbackDatabase;
|
|
166
|
+
state.fallbackDatabase = new Database(path, { create: true }) as unknown as OwnedStorageDatabase;
|
|
167
|
+
state.fallbackDatabasePath = path;
|
|
168
|
+
initializeDatabase(state.fallbackDatabase);
|
|
169
|
+
return state.fallbackDatabase;
|
|
124
170
|
}
|
|
125
171
|
|
|
126
172
|
export function resolveStorageDatabase(): InternalStorageDatabase {
|
|
127
|
-
return (configuredHost.database ?? defaultDatabase()) as InternalStorageDatabase;
|
|
173
|
+
return (storageState().configuredHost.database ?? defaultDatabase()) as InternalStorageDatabase;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* The host-injected connection, or null when Negotium owns its own store.
|
|
178
|
+
*
|
|
179
|
+
* Unlike {@link resolveStorageDatabase} this never opens anything. Callers that
|
|
180
|
+
* manage their own short-lived connections need to know whether a host store
|
|
181
|
+
* exists *before* deciding to open one by path: opening it anyway is how an
|
|
182
|
+
* embedded Negotium ends up writing half its state into the host's database and
|
|
183
|
+
* the other half into `~/.negotium`, with nothing reporting an error.
|
|
184
|
+
*/
|
|
185
|
+
export function configuredStorageDatabase(): InternalStorageDatabase | null {
|
|
186
|
+
return (storageState().configuredHost.database as InternalStorageDatabase | undefined) ?? null;
|
|
128
187
|
}
|
|
129
188
|
|
|
130
189
|
export function resolveStorageDataDir(): string {
|
|
131
|
-
return configuredHost.dataDir ?? defaultDataDir();
|
|
190
|
+
return storageState().configuredHost.dataDir ?? defaultDataDir();
|
|
132
191
|
}
|
|
133
192
|
|
|
134
193
|
export function resolveStorageLogDir(): string {
|
|
135
|
-
return configuredHost.logDir ?? defaultLogDir();
|
|
194
|
+
return storageState().configuredHost.logDir ?? defaultLogDir();
|
|
136
195
|
}
|
|
137
196
|
|
|
138
197
|
export function resolveStorageSessionAsksDir(): string {
|
|
139
|
-
return configuredHost.sessionAsksDir ?? defaultSessionAsksDir();
|
|
198
|
+
return storageState().configuredHost.sessionAsksDir ?? defaultSessionAsksDir();
|
|
140
199
|
}
|
|
141
200
|
|
|
142
201
|
export function resolveStorageWorkspaceDir(): string {
|
|
143
|
-
return configuredHost.workspaceDir ?? defaultWorkspaceDir();
|
|
202
|
+
return storageState().configuredHost.workspaceDir ?? defaultWorkspaceDir();
|
|
144
203
|
}
|
|
145
204
|
|
|
146
205
|
export function resolveStorageSharedWikiDir(): string {
|
|
147
|
-
return configuredHost.sharedWikiDir ?? join(resolveStorageWorkspaceDir(), "wiki");
|
|
206
|
+
return storageState().configuredHost.sharedWikiDir ?? join(resolveStorageWorkspaceDir(), "wiki");
|
|
148
207
|
}
|
|
149
208
|
|
|
150
209
|
export function resolveStorageUsersLogDir(): string {
|
|
151
|
-
return configuredHost.usersLogDir ?? join(resolveStorageDataDir(), "users");
|
|
210
|
+
return storageState().configuredHost.usersLogDir ?? join(resolveStorageDataDir(), "users");
|
|
152
211
|
}
|
|
153
212
|
|
|
154
213
|
const STORAGE_PATH_KEYS = [
|
|
@@ -176,11 +235,9 @@ function normalizeStorageHostPatch(options: StorageHostConfig): Readonly<Storage
|
|
|
176
235
|
}
|
|
177
236
|
|
|
178
237
|
function refreshConfiguredHost(): void {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
...storageHostFrames.filter((frame) => frame.active).map((frame) => frame.patch),
|
|
183
|
-
),
|
|
238
|
+
const state = storageState();
|
|
239
|
+
state.configuredHost = Object.freeze(
|
|
240
|
+
Object.assign({}, ...state.frames.filter((frame) => frame.active).map((frame) => frame.patch)),
|
|
184
241
|
);
|
|
185
242
|
}
|
|
186
243
|
|
|
@@ -193,52 +250,57 @@ function refreshConfiguredHost(): void {
|
|
|
193
250
|
*/
|
|
194
251
|
export function configureStorageHost(options: StorageHostConfig): () => void {
|
|
195
252
|
const frame: StorageHostFrame = { active: true, patch: normalizeStorageHostPatch(options) };
|
|
196
|
-
|
|
253
|
+
storageState().frames.push(frame);
|
|
197
254
|
refreshConfiguredHost();
|
|
198
255
|
return () => {
|
|
199
256
|
if (!frame.active) return;
|
|
200
257
|
frame.active = false;
|
|
201
|
-
const
|
|
202
|
-
|
|
258
|
+
const frames = storageState().frames;
|
|
259
|
+
const index = frames.indexOf(frame);
|
|
260
|
+
if (index >= 0) frames.splice(index, 1);
|
|
203
261
|
refreshConfiguredHost();
|
|
204
262
|
};
|
|
205
263
|
}
|
|
206
264
|
|
|
207
265
|
/** Remove every configured host layer and restore standalone fallbacks. */
|
|
208
266
|
export function resetStorageHost(): void {
|
|
209
|
-
|
|
210
|
-
|
|
267
|
+
const frames = storageState().frames;
|
|
268
|
+
for (const frame of frames) frame.active = false;
|
|
269
|
+
frames.length = 0;
|
|
211
270
|
refreshConfiguredHost();
|
|
212
271
|
}
|
|
213
272
|
|
|
214
273
|
/** Close only Negotium's fallback connection. Injected connections are borrowed. */
|
|
215
274
|
export function closeStorageDatabase(): void {
|
|
216
|
-
|
|
217
|
-
fallbackDatabase
|
|
218
|
-
fallbackDatabase
|
|
219
|
-
|
|
275
|
+
const state = storageState();
|
|
276
|
+
if (!state.fallbackDatabase) return;
|
|
277
|
+
state.fallbackDatabase.close();
|
|
278
|
+
state.fallbackDatabase = null;
|
|
279
|
+
state.fallbackDatabasePath = null;
|
|
220
280
|
}
|
|
221
281
|
|
|
222
282
|
export function registerStorageSchemaInitializer(
|
|
223
283
|
initialize: StorageSchemaInitializer,
|
|
224
284
|
priority = 100,
|
|
225
285
|
): void {
|
|
226
|
-
|
|
227
|
-
|
|
286
|
+
const initializers = storageState().schemaInitializers;
|
|
287
|
+
initializers.push({ initialize, priority });
|
|
288
|
+
initializers.sort((a, b) => a.priority - b.priority);
|
|
228
289
|
}
|
|
229
290
|
|
|
230
291
|
export function ensureStorageSchemas(
|
|
231
292
|
database: InternalStorageDatabase = resolveStorageDatabase(),
|
|
232
293
|
): void {
|
|
233
|
-
|
|
234
|
-
|
|
294
|
+
const state = storageState();
|
|
295
|
+
if (state.initializingDatabases.has(database)) return;
|
|
296
|
+
let initialized = state.initializedSchemas.get(database);
|
|
235
297
|
if (!initialized) {
|
|
236
298
|
initialized = new Set();
|
|
237
|
-
initializedSchemas.set(database, initialized);
|
|
299
|
+
state.initializedSchemas.set(database, initialized);
|
|
238
300
|
}
|
|
239
|
-
initializingDatabases.add(database);
|
|
301
|
+
state.initializingDatabases.add(database);
|
|
240
302
|
try {
|
|
241
|
-
for (const entry of schemaInitializers) {
|
|
303
|
+
for (const entry of state.schemaInitializers) {
|
|
242
304
|
if (initialized.has(entry.initialize)) continue;
|
|
243
305
|
// Mark first so a migration that calls through the public db proxy does
|
|
244
306
|
// not recursively invoke itself. Remove on failure so the next call can retry.
|
|
@@ -251,7 +313,7 @@ export function ensureStorageSchemas(
|
|
|
251
313
|
}
|
|
252
314
|
}
|
|
253
315
|
} finally {
|
|
254
|
-
initializingDatabases.delete(database);
|
|
316
|
+
state.initializingDatabases.delete(database);
|
|
255
317
|
}
|
|
256
318
|
}
|
|
257
319
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { chmodSync, mkdirSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { VAULT_MASTER_KEY } from "#platform/config";
|
|
4
4
|
import { Database } from "#storage/sqlite";
|
|
5
|
+
import { resolveStorageDataDir } from "#storage/storage-host";
|
|
5
6
|
import { decryptVaultValue, encryptVaultValue } from "#storage/vault-crypto";
|
|
6
7
|
|
|
7
8
|
export type VaultDatabase = Pick<InstanceType<typeof Database>, "exec" | "prepare">;
|
|
@@ -72,7 +73,14 @@ function openVaultDatabase(dataDir: string): VaultDatabase {
|
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
function activeVaultDatabase(): VaultDatabase {
|
|
75
|
-
if (!vaultDb)
|
|
76
|
+
if (!vaultDb) {
|
|
77
|
+
// `resolveStorageDataDir()`, not the import-time `DATA_DIR` constant: an
|
|
78
|
+
// embedding host configures its data directory during bootstrap, and any
|
|
79
|
+
// vault access that happens before `configureVaultStorage()` runs would
|
|
80
|
+
// otherwise pin the vault to Negotium's own state directory for the life of
|
|
81
|
+
// the process — silently, since both paths are valid and writable.
|
|
82
|
+
vaultDb = openVaultDatabase(resolveStorageDataDir());
|
|
83
|
+
}
|
|
76
84
|
return vaultDb;
|
|
77
85
|
}
|
|
78
86
|
|
|
@@ -83,7 +91,8 @@ export function configureVaultStorage(options: VaultStorageOptions): () => void
|
|
|
83
91
|
}
|
|
84
92
|
const previousDb = vaultDb;
|
|
85
93
|
const previousMasterKey = vaultMasterKey;
|
|
86
|
-
const configuredDb =
|
|
94
|
+
const configuredDb =
|
|
95
|
+
options.database ?? openVaultDatabase(options.dataDir ?? resolveStorageDataDir());
|
|
87
96
|
if (options.database) initializeVaultDatabase(configuredDb);
|
|
88
97
|
vaultDb = configuredDb;
|
|
89
98
|
vaultMasterKey = options.masterKey ?? VAULT_MASTER_KEY;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const NEGOTIUM_VERSION = "0.2.
|
|
1
|
+
export const NEGOTIUM_VERSION = "0.2.20";
|
package/dist/runtime-helpers.js
CHANGED
|
@@ -534,11 +534,12 @@ function versionAtLeast(actualVersion, minimumVersion) {
|
|
|
534
534
|
}
|
|
535
535
|
return true;
|
|
536
536
|
}
|
|
537
|
+
var BROWSER_RS_VERSION_PROBE_TIMEOUT_MS = 15000;
|
|
537
538
|
function browserRsMeetsMinimumVersion(candidate) {
|
|
538
539
|
try {
|
|
539
540
|
const output = execFileSync(candidate, ["--version"], {
|
|
540
541
|
encoding: "utf8",
|
|
541
|
-
timeout:
|
|
542
|
+
timeout: BROWSER_RS_VERSION_PROBE_TIMEOUT_MS,
|
|
542
543
|
stdio: ["ignore", "pipe", "ignore"]
|
|
543
544
|
}).trim();
|
|
544
545
|
const match = output.match(/^browser-rs (\d+)\.(\d+)\.(\d+)$/);
|
|
@@ -764,12 +765,29 @@ if (isBun) {
|
|
|
764
765
|
}
|
|
765
766
|
|
|
766
767
|
// ../../packages/core/src/storage/storage-host.ts
|
|
767
|
-
var
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
768
|
+
var STORAGE_HOST_STATE = Symbol.for("negotium.storage-host.state.v1");
|
|
769
|
+
function storageState() {
|
|
770
|
+
const holder = globalThis;
|
|
771
|
+
const existing = holder[STORAGE_HOST_STATE];
|
|
772
|
+
if (existing)
|
|
773
|
+
return existing;
|
|
774
|
+
const created = {
|
|
775
|
+
configuredHost: {},
|
|
776
|
+
fallbackDatabase: null,
|
|
777
|
+
fallbackDatabasePath: null,
|
|
778
|
+
frames: [],
|
|
779
|
+
schemaInitializers: [],
|
|
780
|
+
initializedSchemas: new WeakMap,
|
|
781
|
+
initializingDatabases: new WeakSet
|
|
782
|
+
};
|
|
783
|
+
Object.defineProperty(holder, STORAGE_HOST_STATE, {
|
|
784
|
+
value: created,
|
|
785
|
+
enumerable: false,
|
|
786
|
+
writable: false,
|
|
787
|
+
configurable: false
|
|
788
|
+
});
|
|
789
|
+
return created;
|
|
790
|
+
}
|
|
773
791
|
function envPath(name, fallback) {
|
|
774
792
|
const value = process.env[name]?.trim();
|
|
775
793
|
return resolve2(value || fallback);
|
|
@@ -814,37 +832,40 @@ function initializeDatabase(database) {
|
|
|
814
832
|
}
|
|
815
833
|
function defaultDatabase() {
|
|
816
834
|
const path = defaultSessionsDatabasePath();
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
835
|
+
const state = storageState();
|
|
836
|
+
if (state.fallbackDatabase && state.fallbackDatabasePath === path)
|
|
837
|
+
return state.fallbackDatabase;
|
|
838
|
+
if (state.fallbackDatabase)
|
|
839
|
+
state.fallbackDatabase.close();
|
|
821
840
|
mkdirSync4(dirname3(path), { recursive: true });
|
|
822
|
-
fallbackDatabase = new Database(path, { create: true });
|
|
823
|
-
fallbackDatabasePath = path;
|
|
824
|
-
initializeDatabase(fallbackDatabase);
|
|
825
|
-
return fallbackDatabase;
|
|
841
|
+
state.fallbackDatabase = new Database(path, { create: true });
|
|
842
|
+
state.fallbackDatabasePath = path;
|
|
843
|
+
initializeDatabase(state.fallbackDatabase);
|
|
844
|
+
return state.fallbackDatabase;
|
|
826
845
|
}
|
|
827
846
|
function resolveStorageDatabase() {
|
|
828
|
-
return configuredHost.database ?? defaultDatabase();
|
|
847
|
+
return storageState().configuredHost.database ?? defaultDatabase();
|
|
829
848
|
}
|
|
830
849
|
function resolveStorageDataDir() {
|
|
831
|
-
return configuredHost.dataDir ?? defaultDataDir();
|
|
850
|
+
return storageState().configuredHost.dataDir ?? defaultDataDir();
|
|
832
851
|
}
|
|
833
852
|
function registerStorageSchemaInitializer(initialize, priority = 100) {
|
|
834
|
-
|
|
835
|
-
|
|
853
|
+
const initializers = storageState().schemaInitializers;
|
|
854
|
+
initializers.push({ initialize, priority });
|
|
855
|
+
initializers.sort((a, b) => a.priority - b.priority);
|
|
836
856
|
}
|
|
837
857
|
function ensureStorageSchemas(database = resolveStorageDatabase()) {
|
|
838
|
-
|
|
858
|
+
const state = storageState();
|
|
859
|
+
if (state.initializingDatabases.has(database))
|
|
839
860
|
return;
|
|
840
|
-
let initialized = initializedSchemas.get(database);
|
|
861
|
+
let initialized = state.initializedSchemas.get(database);
|
|
841
862
|
if (!initialized) {
|
|
842
863
|
initialized = new Set;
|
|
843
|
-
initializedSchemas.set(database, initialized);
|
|
864
|
+
state.initializedSchemas.set(database, initialized);
|
|
844
865
|
}
|
|
845
|
-
initializingDatabases.add(database);
|
|
866
|
+
state.initializingDatabases.add(database);
|
|
846
867
|
try {
|
|
847
|
-
for (const entry of schemaInitializers) {
|
|
868
|
+
for (const entry of state.schemaInitializers) {
|
|
848
869
|
if (initialized.has(entry.initialize))
|
|
849
870
|
continue;
|
|
850
871
|
initialized.add(entry.initialize);
|
|
@@ -856,7 +877,7 @@ function ensureStorageSchemas(database = resolveStorageDatabase()) {
|
|
|
856
877
|
}
|
|
857
878
|
}
|
|
858
879
|
} finally {
|
|
859
|
-
initializingDatabases.delete(database);
|
|
880
|
+
state.initializingDatabases.delete(database);
|
|
860
881
|
}
|
|
861
882
|
}
|
|
862
883
|
var internalStorageDatabase = new Proxy({}, {
|
|
@@ -1558,4 +1579,4 @@ export {
|
|
|
1558
1579
|
CLAUDE_EFFORT_VALUES
|
|
1559
1580
|
};
|
|
1560
1581
|
|
|
1561
|
-
//# debugId=
|
|
1582
|
+
//# debugId=E2956B1D02484F8564756E2164756E21
|