@bastani/atomic 0.9.44-alpha.3 → 0.9.44-alpha.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/CHANGELOG.md +17 -0
- package/dist/builtin/intercom/CHANGELOG.md +6 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +12 -0
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +92 -37
- package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +92 -37
- package/dist/builtin/workflows/src/index.js +92 -37
- package/dist/builtin/workflows/src/local-worker-entry.mjs +92 -37
- package/dist/core/storage/errors.d.ts +5 -1
- package/dist/core/storage/errors.d.ts.map +1 -1
- package/dist/core/storage/errors.js +8 -2
- package/dist/core/storage/errors.js.map +1 -1
- package/dist/core/storage/node-sqlite.d.ts +2 -1
- package/dist/core/storage/node-sqlite.d.ts.map +1 -1
- package/dist/core/storage/node-sqlite.js +83 -7
- package/dist/core/storage/node-sqlite.js.map +1 -1
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
|
@@ -37,6 +37,25 @@ function snapshotParams(params) {
|
|
|
37
37
|
function finalizeReleasedStatements() {
|
|
38
38
|
globalThis.Bun?.gc(true);
|
|
39
39
|
}
|
|
40
|
+
/** Default for how long a transaction keeps retrying `BEGIN IMMEDIATE` while another connection holds the write lock. */
|
|
41
|
+
const DEFAULT_NODE_SQLITE_LOCK_WAIT_MS = 30_000;
|
|
42
|
+
const LOCK_RETRY_BASE_DELAY_MS = 5;
|
|
43
|
+
const LOCK_RETRY_MAX_DELAY_MS = 100;
|
|
44
|
+
/** SQLITE_BUSY, including its extended codes: another connection holds the lock this statement needs. */
|
|
45
|
+
function isSqliteBusy(cause) {
|
|
46
|
+
const code = cause?.errcode;
|
|
47
|
+
return typeof code === "number" && (code & 0xff) === 5;
|
|
48
|
+
}
|
|
49
|
+
/** The driver's own reason, kept in the error message so it survives relays that forward only `message`. */
|
|
50
|
+
function sqliteFailureDetail(cause) {
|
|
51
|
+
if (!(cause instanceof Error) || cause.message === "")
|
|
52
|
+
return undefined;
|
|
53
|
+
const code = cause.errcode;
|
|
54
|
+
return typeof code === "number" ? `${cause.message} (SQLite code ${code})` : cause.message;
|
|
55
|
+
}
|
|
56
|
+
function unavailable(descriptor, cause, detail = sqliteFailureDetail(cause)) {
|
|
57
|
+
return new StorageUnavailableError(descriptor, cause, detail);
|
|
58
|
+
}
|
|
40
59
|
function normalizeRow(row) {
|
|
41
60
|
return Object.fromEntries(Object.entries(row).map(([key, value]) => [
|
|
42
61
|
key,
|
|
@@ -58,7 +77,9 @@ class NodeSqliteDatabase {
|
|
|
58
77
|
executor;
|
|
59
78
|
ownsConnection;
|
|
60
79
|
transactionIdentity;
|
|
61
|
-
|
|
80
|
+
lockWaitMs;
|
|
81
|
+
constructor(connection, descriptor, ownsConnection = true, transactionIdentity = connection, lockWaitMs = DEFAULT_NODE_SQLITE_LOCK_WAIT_MS) {
|
|
82
|
+
this.lockWaitMs = lockWaitMs;
|
|
62
83
|
this.transactionIdentity = transactionIdentity;
|
|
63
84
|
this.ownsConnection = ownsConnection;
|
|
64
85
|
this.connection = connection;
|
|
@@ -70,7 +91,62 @@ class NodeSqliteDatabase {
|
|
|
70
91
|
return operation();
|
|
71
92
|
}
|
|
72
93
|
catch (cause) {
|
|
73
|
-
throw
|
|
94
|
+
throw unavailable(this.descriptor, cause);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* One non-blocking `BEGIN IMMEDIATE`. node:sqlite runs `busy_timeout` synchronously, so a lock held by another
|
|
99
|
+
* process would freeze this process's event loop for the whole timeout. The attempt runs with `busy_timeout=0`
|
|
100
|
+
* and the connection's own value is restored before returning or throwing, so single statements outside a
|
|
101
|
+
* transaction keep it. Callers reach this only through `enqueue` and the transaction gate, so nothing else runs
|
|
102
|
+
* on the connection in between.
|
|
103
|
+
*/
|
|
104
|
+
tryBegin() {
|
|
105
|
+
this.driver(() => {
|
|
106
|
+
const configured = Number(this.connection.prepare("PRAGMA busy_timeout").get()?.timeout ?? 0);
|
|
107
|
+
this.connection.exec("PRAGMA busy_timeout=0");
|
|
108
|
+
let began = false;
|
|
109
|
+
try {
|
|
110
|
+
this.connection.exec("BEGIN IMMEDIATE");
|
|
111
|
+
began = true;
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
try {
|
|
115
|
+
this.connection.exec(`PRAGMA busy_timeout=${configured}`);
|
|
116
|
+
}
|
|
117
|
+
catch (restoreFailure) {
|
|
118
|
+
// Never hand back a transaction on a connection whose lock wait is no longer the configured one.
|
|
119
|
+
if (began)
|
|
120
|
+
this.connection.exec("ROLLBACK");
|
|
121
|
+
// biome-ignore lint/correctness/noUnsafeFinally: a failed restore must replace the attempt's outcome.
|
|
122
|
+
throw restoreFailure;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Takes the write lock without blocking the event loop. Nothing has run yet when `BEGIN IMMEDIATE` reports
|
|
129
|
+
* SQLITE_BUSY, so the attempt is retried after a jittered timer until `lockWaitMs` has passed; every other
|
|
130
|
+
* failure, and a lock still held at the deadline, rejects at once with its cause.
|
|
131
|
+
*/
|
|
132
|
+
async begin() {
|
|
133
|
+
const started = Date.now();
|
|
134
|
+
for (let attempt = 0;; attempt += 1) {
|
|
135
|
+
try {
|
|
136
|
+
this.tryBegin();
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
const cause = error instanceof StorageUnavailableError ? error.cause : undefined;
|
|
141
|
+
if (!isSqliteBusy(cause))
|
|
142
|
+
throw error;
|
|
143
|
+
const remaining = started + this.lockWaitMs - Date.now();
|
|
144
|
+
if (remaining <= 0) {
|
|
145
|
+
throw unavailable(this.descriptor, cause, `${sqliteFailureDetail(cause)}; gave up after waiting ${Date.now() - started} ms for the write lock`);
|
|
146
|
+
}
|
|
147
|
+
const backoff = Math.min(LOCK_RETRY_MAX_DELAY_MS, LOCK_RETRY_BASE_DELAY_MS * 2 ** attempt);
|
|
148
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(remaining, backoff * (0.5 + Math.random() / 2))));
|
|
149
|
+
}
|
|
74
150
|
}
|
|
75
151
|
}
|
|
76
152
|
createExecutor(active) {
|
|
@@ -123,7 +199,7 @@ class NodeSqliteDatabase {
|
|
|
123
199
|
}
|
|
124
200
|
transaction(callback) {
|
|
125
201
|
return this.enqueue(() => gateTransaction(this.transactionIdentity, async () => {
|
|
126
|
-
await this.
|
|
202
|
+
await this.begin();
|
|
127
203
|
let active = true;
|
|
128
204
|
const transaction = this.createExecutor(() => active);
|
|
129
205
|
try {
|
|
@@ -156,7 +232,7 @@ class NodeSqliteDatabase {
|
|
|
156
232
|
return this.closePromise;
|
|
157
233
|
}
|
|
158
234
|
}
|
|
159
|
-
export async function openNodeSqliteDatabase(path, { busyTimeoutMs = 5000, readOnly = false } = {}) {
|
|
235
|
+
export async function openNodeSqliteDatabase(path, { busyTimeoutMs = 5000, lockWaitMs = DEFAULT_NODE_SQLITE_LOCK_WAIT_MS, readOnly = false, } = {}) {
|
|
160
236
|
const descriptor = { adapter: "node-sqlite", location: path };
|
|
161
237
|
// Load node:sqlite on first open: importing it prints Node's experimental warning, which every importer of the
|
|
162
238
|
// package entry point would otherwise see.
|
|
@@ -177,7 +253,7 @@ export async function openNodeSqliteDatabase(path, { busyTimeoutMs = 5000, readO
|
|
|
177
253
|
connection.exec("PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL; PRAGMA foreign_keys=ON");
|
|
178
254
|
const location = connection.location();
|
|
179
255
|
const identity = location === null ? connection : await realpath(location);
|
|
180
|
-
return new NodeSqliteDatabase(connection, descriptor, true, identity);
|
|
256
|
+
return new NodeSqliteDatabase(connection, descriptor, true, identity, lockWaitMs);
|
|
181
257
|
}
|
|
182
258
|
catch (cause) {
|
|
183
259
|
try {
|
|
@@ -186,7 +262,7 @@ export async function openNodeSqliteDatabase(path, { busyTimeoutMs = 5000, readO
|
|
|
186
262
|
catch {
|
|
187
263
|
// Preserve the opening failure if cleanup also fails.
|
|
188
264
|
}
|
|
189
|
-
throw
|
|
265
|
+
throw unavailable(descriptor, cause);
|
|
190
266
|
}
|
|
191
267
|
}
|
|
192
268
|
export function wrapNodeSqliteDatabase(connection) {
|
|
@@ -197,7 +273,7 @@ export function wrapNodeSqliteDatabase(connection) {
|
|
|
197
273
|
return new NodeSqliteDatabase(connection, descriptor, false);
|
|
198
274
|
}
|
|
199
275
|
catch (cause) {
|
|
200
|
-
throw
|
|
276
|
+
throw unavailable(descriptor, cause);
|
|
201
277
|
}
|
|
202
278
|
}
|
|
203
279
|
//# sourceMappingURL=node-sqlite.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-sqlite.js","sourceRoot":"","sources":["../../../src/core/storage/node-sqlite.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, realpath } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { DatabaseSync } from \"node:sqlite\";\nimport type { SqliteDatabase, SqliteExecutor, SqliteRow, SqliteValue, StorageDescriptor } from \"./database.js\";\nimport {\n\tStorageAdapterLoadError,\n\ttype StorageFailureCause,\n\tStorageInvalidTextError,\n\tStorageRollbackError,\n\tStorageTransactionClosedError,\n\tStorageUnavailableError,\n\tStoreClosedError,\n} from \"./errors.js\";\n\ninterface TransactionGates {\n\treadonly files: Map<string, Promise<void>>;\n\treadonly connections: WeakMap<DatabaseSync, Promise<void>>;\n}\n\n// Share gates across module reloads as well as adapter instances. Only live queues retain file identities.\nconst TRANSACTION_GATES = Symbol.for(\"atomic-storage/node-sqlite-transaction-gates@1\");\nconst gateBag = globalThis as typeof globalThis & Record<symbol, TransactionGates | undefined>;\nconst gates: TransactionGates = gateBag[TRANSACTION_GATES] ?? { files: new Map(), connections: new WeakMap() };\ngateBag[TRANSACTION_GATES] = gates;\n\nfunction gateTransaction<T>(identity: string | DatabaseSync, operation: () => Promise<T>): Promise<T> {\n\tconst prior = typeof identity === \"string\" ? gates.files.get(identity) : gates.connections.get(identity);\n\tconst result = (prior ?? Promise.resolve()).then(operation);\n\tconst settled = result.then(\n\t\t() => {},\n\t\t() => {},\n\t);\n\tif (typeof identity === \"string\") gates.files.set(identity, settled);\n\telse gates.connections.set(identity, settled);\n\tvoid settled.then(() => {\n\t\tif (typeof identity === \"string\") {\n\t\t\tif (gates.files.get(identity) === settled) gates.files.delete(identity);\n\t\t} else if (gates.connections.get(identity) === settled) gates.connections.delete(identity);\n\t});\n\treturn result;\n}\n\n/** Copies binary parameters so queued work binds the bytes the caller passed, not later buffer contents. */\nfunction snapshotParams(params: readonly SqliteValue[]): SqliteValue[] {\n\treturn params.map((value) => (value instanceof Uint8Array ? new Uint8Array(value) : value));\n}\n\n/**\n * Bun's `DatabaseSync.close()` defers closing the file until garbage collection finalizes every statement the\n * connection prepared, so the database, WAL and shared-memory files stay open (and locked on Windows). The adapter\n * keeps no statement references, so a synchronous collection finalizes them and releases the files. Node finalizes\n * statements inside `close()` and has no `Bun` global.\n */\nfunction finalizeReleasedStatements(): void {\n\t(globalThis as { Bun?: { gc(force: boolean): void } }).Bun?.gc(true);\n}\n\nfunction normalizeRow(row: Record<string, SqliteValue>): SqliteRow {\n\treturn Object.fromEntries(\n\t\tObject.entries(row).map(([key, value]) => [\n\t\t\tkey,\n\t\t\ttypeof value === \"bigint\" &&\n\t\t\tvalue >= -BigInt(Number.MAX_SAFE_INTEGER) &&\n\t\t\tvalue <= BigInt(Number.MAX_SAFE_INTEGER)\n\t\t\t\t? Number(value)\n\t\t\t\t: value instanceof Uint8Array\n\t\t\t\t\t? new Uint8Array(value)\n\t\t\t\t\t: value,\n\t\t]),\n\t);\n}\n\nclass NodeSqliteDatabase implements SqliteDatabase {\n\treadonly descriptor: StorageDescriptor;\n\tprivate readonly connection: DatabaseSync;\n\tprivate tail: Promise<void> = Promise.resolve();\n\tprivate closing = false;\n\tprivate closePromise?: Promise<void>;\n\tprivate readonly executor: SqliteExecutor;\n\n\tprivate readonly ownsConnection: boolean;\n\tprivate readonly transactionIdentity: string | DatabaseSync;\n\n\tconstructor(\n\t\tconnection: DatabaseSync,\n\t\tdescriptor: StorageDescriptor,\n\t\townsConnection = true,\n\t\ttransactionIdentity: string | DatabaseSync = connection,\n\t) {\n\t\tthis.transactionIdentity = transactionIdentity;\n\t\tthis.ownsConnection = ownsConnection;\n\t\tthis.connection = connection;\n\t\tthis.descriptor = descriptor;\n\t\tthis.executor = this.createExecutor(() => true);\n\t}\n\n\tprivate driver<T>(operation: () => T): T {\n\t\ttry {\n\t\t\treturn operation();\n\t\t} catch (cause) {\n\t\t\tthrow new StorageUnavailableError(this.descriptor, cause as StorageFailureCause);\n\t\t}\n\t}\n\n\tprivate createExecutor(active: () => boolean): SqliteExecutor {\n\t\tconst execute = async <T>(operation: () => T, params: readonly SqliteValue[] = []): Promise<T> => {\n\t\t\tif (!active()) throw new StorageTransactionClosedError();\n\t\t\tconst invalidIndex = params.findIndex((value) => typeof value === \"string\" && value.includes(\"\\0\"));\n\t\t\tif (invalidIndex !== -1) throw new StorageInvalidTextError(invalidIndex);\n\t\t\treturn this.driver(operation);\n\t\t};\n\t\tconst statement = (sql: string) => {\n\t\t\tconst prepared = this.connection.prepare(sql);\n\t\t\tprepared.setReadBigInts(true);\n\t\t\treturn prepared;\n\t\t};\n\t\treturn {\n\t\t\texec: (sql) => execute(() => this.connection.exec(sql)),\n\t\t\trun: (sql, ...params) => execute(() => ({ changes: Number(statement(sql).run(...params).changes) }), params),\n\t\t\tget: <T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]) =>\n\t\t\t\texecute(() => {\n\t\t\t\t\tconst row = statement(sql).get(...params);\n\t\t\t\t\treturn row === undefined ? undefined : (normalizeRow(row) as T);\n\t\t\t\t}, params),\n\t\t\tall: <T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]) =>\n\t\t\t\texecute(\n\t\t\t\t\t() =>\n\t\t\t\t\t\tstatement(sql)\n\t\t\t\t\t\t\t.all(...params)\n\t\t\t\t\t\t\t.map((row) => normalizeRow(row) as T),\n\t\t\t\t\tparams,\n\t\t\t\t),\n\t\t};\n\t}\n\n\tprivate enqueue<T>(operation: () => Promise<T>): Promise<T> {\n\t\tif (this.closing) return Promise.reject(new StoreClosedError(this.descriptor));\n\t\tconst result = this.tail.then(operation);\n\t\tthis.tail = result.then(\n\t\t\t() => {},\n\t\t\t() => {},\n\t\t);\n\t\treturn result;\n\t}\n\n\texec(sql: string): Promise<void> {\n\t\treturn this.enqueue(() => this.executor.exec(sql));\n\t}\n\n\trun(sql: string, ...params: readonly SqliteValue[]) {\n\t\tconst bound = snapshotParams(params);\n\t\treturn this.enqueue(() => this.executor.run(sql, ...bound));\n\t}\n\n\tget<T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]): Promise<T | undefined> {\n\t\tconst bound = snapshotParams(params);\n\t\treturn this.enqueue(() => this.executor.get<T>(sql, ...bound));\n\t}\n\n\tall<T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]): Promise<T[]> {\n\t\tconst bound = snapshotParams(params);\n\t\treturn this.enqueue(() => this.executor.all<T>(sql, ...bound));\n\t}\n\n\ttransaction<T>(callback: (transaction: SqliteExecutor) => Promise<T>): Promise<T> {\n\t\treturn this.enqueue(() =>\n\t\t\tgateTransaction(this.transactionIdentity, async () => {\n\t\t\t\tawait this.executor.exec(\"BEGIN IMMEDIATE\");\n\t\t\t\tlet active = true;\n\t\t\t\tconst transaction = this.createExecutor(() => active);\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await callback(transaction);\n\t\t\t\t\tactive = false;\n\t\t\t\t\tawait this.executor.exec(\"COMMIT\");\n\t\t\t\t\treturn result;\n\t\t\t\t} catch (cause) {\n\t\t\t\t\tactive = false;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.executor.exec(\"ROLLBACK\");\n\t\t\t\t\t} catch (rollbackCause) {\n\t\t\t\t\t\tthrow new StorageRollbackError(cause as StorageFailureCause, rollbackCause as StorageFailureCause);\n\t\t\t\t\t}\n\t\t\t\t\tthrow cause;\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t}\n\n\tclose(): Promise<void> {\n\t\tif (!this.closePromise) {\n\t\t\tthis.closing = true;\n\t\t\tthis.closePromise = this.tail.then(() =>\n\t\t\t\tthis.driver(() => {\n\t\t\t\t\tif (this.ownsConnection) this.connection.close();\n\t\t\t\t\tfinalizeReleasedStatements();\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn this.closePromise;\n\t}\n}\n\nexport async function openNodeSqliteDatabase(\n\tpath: string,\n\t{ busyTimeoutMs = 5000, readOnly = false }: { busyTimeoutMs?: number; readOnly?: boolean } = {},\n): Promise<SqliteDatabase> {\n\tconst descriptor = { adapter: \"node-sqlite\", location: path };\n\t// Load node:sqlite on first open: importing it prints Node's experimental warning, which every importer of the\n\t// package entry point would otherwise see.\n\tlet Database: typeof DatabaseSync;\n\ttry {\n\t\t({ DatabaseSync: Database } = await import(\"node:sqlite\"));\n\t} catch (cause) {\n\t\tthrow new StorageAdapterLoadError(\"node:sqlite\", cause as StorageFailureCause);\n\t}\n\tlet connection: DatabaseSync | undefined;\n\ttry {\n\t\tif (!readOnly && path !== \":memory:\") await mkdir(dirname(path), { recursive: true });\n\t\tconnection = new Database(path, { readOnly });\n\t\tconnection.exec(`PRAGMA busy_timeout=${busyTimeoutMs}`);\n\t\tif (!readOnly) connection.exec(\"PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL; PRAGMA foreign_keys=ON\");\n\t\tconst location = connection.location();\n\t\tconst identity = location === null ? connection : await realpath(location);\n\t\treturn new NodeSqliteDatabase(connection, descriptor, true, identity);\n\t} catch (cause) {\n\t\ttry {\n\t\t\tconnection?.close();\n\t\t} catch {\n\t\t\t// Preserve the opening failure if cleanup also fails.\n\t\t}\n\t\tthrow new StorageUnavailableError(descriptor, cause as StorageFailureCause);\n\t}\n}\n\nexport function wrapNodeSqliteDatabase(connection: DatabaseSync): SqliteDatabase {\n\tconst descriptor = { adapter: \"node-sqlite\", location: \":memory:\" };\n\ttry {\n\t\tdescriptor.location = connection.location() || \":memory:\";\n\t\tconnection.exec(\n\t\t\t\"PRAGMA busy_timeout=5000; PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL; PRAGMA foreign_keys=ON\",\n\t\t);\n\t\treturn new NodeSqliteDatabase(connection, descriptor, false);\n\t} catch (cause) {\n\t\tthrow new StorageUnavailableError(descriptor, cause as StorageFailureCause);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"node-sqlite.js","sourceRoot":"","sources":["../../../src/core/storage/node-sqlite.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, realpath } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { DatabaseSync } from \"node:sqlite\";\nimport type { SqliteDatabase, SqliteExecutor, SqliteRow, SqliteValue, StorageDescriptor } from \"./database.js\";\nimport {\n\tStorageAdapterLoadError,\n\ttype StorageFailureCause,\n\tStorageInvalidTextError,\n\tStorageRollbackError,\n\tStorageTransactionClosedError,\n\tStorageUnavailableError,\n\tStoreClosedError,\n} from \"./errors.js\";\n\ninterface TransactionGates {\n\treadonly files: Map<string, Promise<void>>;\n\treadonly connections: WeakMap<DatabaseSync, Promise<void>>;\n}\n\n// Share gates across module reloads as well as adapter instances. Only live queues retain file identities.\nconst TRANSACTION_GATES = Symbol.for(\"atomic-storage/node-sqlite-transaction-gates@1\");\nconst gateBag = globalThis as typeof globalThis & Record<symbol, TransactionGates | undefined>;\nconst gates: TransactionGates = gateBag[TRANSACTION_GATES] ?? { files: new Map(), connections: new WeakMap() };\ngateBag[TRANSACTION_GATES] = gates;\n\nfunction gateTransaction<T>(identity: string | DatabaseSync, operation: () => Promise<T>): Promise<T> {\n\tconst prior = typeof identity === \"string\" ? gates.files.get(identity) : gates.connections.get(identity);\n\tconst result = (prior ?? Promise.resolve()).then(operation);\n\tconst settled = result.then(\n\t\t() => {},\n\t\t() => {},\n\t);\n\tif (typeof identity === \"string\") gates.files.set(identity, settled);\n\telse gates.connections.set(identity, settled);\n\tvoid settled.then(() => {\n\t\tif (typeof identity === \"string\") {\n\t\t\tif (gates.files.get(identity) === settled) gates.files.delete(identity);\n\t\t} else if (gates.connections.get(identity) === settled) gates.connections.delete(identity);\n\t});\n\treturn result;\n}\n\n/** Copies binary parameters so queued work binds the bytes the caller passed, not later buffer contents. */\nfunction snapshotParams(params: readonly SqliteValue[]): SqliteValue[] {\n\treturn params.map((value) => (value instanceof Uint8Array ? new Uint8Array(value) : value));\n}\n\n/**\n * Bun's `DatabaseSync.close()` defers closing the file until garbage collection finalizes every statement the\n * connection prepared, so the database, WAL and shared-memory files stay open (and locked on Windows). The adapter\n * keeps no statement references, so a synchronous collection finalizes them and releases the files. Node finalizes\n * statements inside `close()` and has no `Bun` global.\n */\nfunction finalizeReleasedStatements(): void {\n\t(globalThis as { Bun?: { gc(force: boolean): void } }).Bun?.gc(true);\n}\n\n/** Default for how long a transaction keeps retrying `BEGIN IMMEDIATE` while another connection holds the write lock. */\nconst DEFAULT_NODE_SQLITE_LOCK_WAIT_MS = 30_000;\nconst LOCK_RETRY_BASE_DELAY_MS = 5;\nconst LOCK_RETRY_MAX_DELAY_MS = 100;\n\n/** SQLITE_BUSY, including its extended codes: another connection holds the lock this statement needs. */\nfunction isSqliteBusy(cause: unknown): boolean {\n\tconst code = (cause as { errcode?: unknown } | null | undefined)?.errcode;\n\treturn typeof code === \"number\" && (code & 0xff) === 5;\n}\n\n/** The driver's own reason, kept in the error message so it survives relays that forward only `message`. */\nfunction sqliteFailureDetail(cause: unknown): string | undefined {\n\tif (!(cause instanceof Error) || cause.message === \"\") return undefined;\n\tconst code = (cause as { errcode?: unknown }).errcode;\n\treturn typeof code === \"number\" ? `${cause.message} (SQLite code ${code})` : cause.message;\n}\n\nfunction unavailable(descriptor: StorageDescriptor, cause: unknown, detail = sqliteFailureDetail(cause)) {\n\treturn new StorageUnavailableError(descriptor, cause as StorageFailureCause, detail);\n}\n\nfunction normalizeRow(row: Record<string, SqliteValue>): SqliteRow {\n\treturn Object.fromEntries(\n\t\tObject.entries(row).map(([key, value]) => [\n\t\t\tkey,\n\t\t\ttypeof value === \"bigint\" &&\n\t\t\tvalue >= -BigInt(Number.MAX_SAFE_INTEGER) &&\n\t\t\tvalue <= BigInt(Number.MAX_SAFE_INTEGER)\n\t\t\t\t? Number(value)\n\t\t\t\t: value instanceof Uint8Array\n\t\t\t\t\t? new Uint8Array(value)\n\t\t\t\t\t: value,\n\t\t]),\n\t);\n}\n\nclass NodeSqliteDatabase implements SqliteDatabase {\n\treadonly descriptor: StorageDescriptor;\n\tprivate readonly connection: DatabaseSync;\n\tprivate tail: Promise<void> = Promise.resolve();\n\tprivate closing = false;\n\tprivate closePromise?: Promise<void>;\n\tprivate readonly executor: SqliteExecutor;\n\n\tprivate readonly ownsConnection: boolean;\n\tprivate readonly transactionIdentity: string | DatabaseSync;\n\tprivate readonly lockWaitMs: number;\n\n\tconstructor(\n\t\tconnection: DatabaseSync,\n\t\tdescriptor: StorageDescriptor,\n\t\townsConnection = true,\n\t\ttransactionIdentity: string | DatabaseSync = connection,\n\t\tlockWaitMs = DEFAULT_NODE_SQLITE_LOCK_WAIT_MS,\n\t) {\n\t\tthis.lockWaitMs = lockWaitMs;\n\t\tthis.transactionIdentity = transactionIdentity;\n\t\tthis.ownsConnection = ownsConnection;\n\t\tthis.connection = connection;\n\t\tthis.descriptor = descriptor;\n\t\tthis.executor = this.createExecutor(() => true);\n\t}\n\n\tprivate driver<T>(operation: () => T): T {\n\t\ttry {\n\t\t\treturn operation();\n\t\t} catch (cause) {\n\t\t\tthrow unavailable(this.descriptor, cause);\n\t\t}\n\t}\n\n\t/**\n\t * One non-blocking `BEGIN IMMEDIATE`. node:sqlite runs `busy_timeout` synchronously, so a lock held by another\n\t * process would freeze this process's event loop for the whole timeout. The attempt runs with `busy_timeout=0`\n\t * and the connection's own value is restored before returning or throwing, so single statements outside a\n\t * transaction keep it. Callers reach this only through `enqueue` and the transaction gate, so nothing else runs\n\t * on the connection in between.\n\t */\n\tprivate tryBegin(): void {\n\t\tthis.driver(() => {\n\t\t\tconst configured = Number(this.connection.prepare(\"PRAGMA busy_timeout\").get()?.timeout ?? 0);\n\t\t\tthis.connection.exec(\"PRAGMA busy_timeout=0\");\n\t\t\tlet began = false;\n\t\t\ttry {\n\t\t\t\tthis.connection.exec(\"BEGIN IMMEDIATE\");\n\t\t\t\tbegan = true;\n\t\t\t} finally {\n\t\t\t\ttry {\n\t\t\t\t\tthis.connection.exec(`PRAGMA busy_timeout=${configured}`);\n\t\t\t\t} catch (restoreFailure) {\n\t\t\t\t\t// Never hand back a transaction on a connection whose lock wait is no longer the configured one.\n\t\t\t\t\tif (began) this.connection.exec(\"ROLLBACK\");\n\t\t\t\t\t// biome-ignore lint/correctness/noUnsafeFinally: a failed restore must replace the attempt's outcome.\n\t\t\t\t\tthrow restoreFailure;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Takes the write lock without blocking the event loop. Nothing has run yet when `BEGIN IMMEDIATE` reports\n\t * SQLITE_BUSY, so the attempt is retried after a jittered timer until `lockWaitMs` has passed; every other\n\t * failure, and a lock still held at the deadline, rejects at once with its cause.\n\t */\n\tprivate async begin(): Promise<void> {\n\t\tconst started = Date.now();\n\t\tfor (let attempt = 0; ; attempt += 1) {\n\t\t\ttry {\n\t\t\t\tthis.tryBegin();\n\t\t\t\treturn;\n\t\t\t} catch (error) {\n\t\t\t\tconst cause = error instanceof StorageUnavailableError ? error.cause : undefined;\n\t\t\t\tif (!isSqliteBusy(cause)) throw error;\n\t\t\t\tconst remaining = started + this.lockWaitMs - Date.now();\n\t\t\t\tif (remaining <= 0) {\n\t\t\t\t\tthrow unavailable(\n\t\t\t\t\t\tthis.descriptor,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t\t`${sqliteFailureDetail(cause)}; gave up after waiting ${Date.now() - started} ms for the write lock`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst backoff = Math.min(LOCK_RETRY_MAX_DELAY_MS, LOCK_RETRY_BASE_DELAY_MS * 2 ** attempt);\n\t\t\t\tawait new Promise((resolve) =>\n\t\t\t\t\tsetTimeout(resolve, Math.min(remaining, backoff * (0.5 + Math.random() / 2))),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate createExecutor(active: () => boolean): SqliteExecutor {\n\t\tconst execute = async <T>(operation: () => T, params: readonly SqliteValue[] = []): Promise<T> => {\n\t\t\tif (!active()) throw new StorageTransactionClosedError();\n\t\t\tconst invalidIndex = params.findIndex((value) => typeof value === \"string\" && value.includes(\"\\0\"));\n\t\t\tif (invalidIndex !== -1) throw new StorageInvalidTextError(invalidIndex);\n\t\t\treturn this.driver(operation);\n\t\t};\n\t\tconst statement = (sql: string) => {\n\t\t\tconst prepared = this.connection.prepare(sql);\n\t\t\tprepared.setReadBigInts(true);\n\t\t\treturn prepared;\n\t\t};\n\t\treturn {\n\t\t\texec: (sql) => execute(() => this.connection.exec(sql)),\n\t\t\trun: (sql, ...params) => execute(() => ({ changes: Number(statement(sql).run(...params).changes) }), params),\n\t\t\tget: <T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]) =>\n\t\t\t\texecute(() => {\n\t\t\t\t\tconst row = statement(sql).get(...params);\n\t\t\t\t\treturn row === undefined ? undefined : (normalizeRow(row) as T);\n\t\t\t\t}, params),\n\t\t\tall: <T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]) =>\n\t\t\t\texecute(\n\t\t\t\t\t() =>\n\t\t\t\t\t\tstatement(sql)\n\t\t\t\t\t\t\t.all(...params)\n\t\t\t\t\t\t\t.map((row) => normalizeRow(row) as T),\n\t\t\t\t\tparams,\n\t\t\t\t),\n\t\t};\n\t}\n\n\tprivate enqueue<T>(operation: () => Promise<T>): Promise<T> {\n\t\tif (this.closing) return Promise.reject(new StoreClosedError(this.descriptor));\n\t\tconst result = this.tail.then(operation);\n\t\tthis.tail = result.then(\n\t\t\t() => {},\n\t\t\t() => {},\n\t\t);\n\t\treturn result;\n\t}\n\n\texec(sql: string): Promise<void> {\n\t\treturn this.enqueue(() => this.executor.exec(sql));\n\t}\n\n\trun(sql: string, ...params: readonly SqliteValue[]) {\n\t\tconst bound = snapshotParams(params);\n\t\treturn this.enqueue(() => this.executor.run(sql, ...bound));\n\t}\n\n\tget<T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]): Promise<T | undefined> {\n\t\tconst bound = snapshotParams(params);\n\t\treturn this.enqueue(() => this.executor.get<T>(sql, ...bound));\n\t}\n\n\tall<T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]): Promise<T[]> {\n\t\tconst bound = snapshotParams(params);\n\t\treturn this.enqueue(() => this.executor.all<T>(sql, ...bound));\n\t}\n\n\ttransaction<T>(callback: (transaction: SqliteExecutor) => Promise<T>): Promise<T> {\n\t\treturn this.enqueue(() =>\n\t\t\tgateTransaction(this.transactionIdentity, async () => {\n\t\t\t\tawait this.begin();\n\t\t\t\tlet active = true;\n\t\t\t\tconst transaction = this.createExecutor(() => active);\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await callback(transaction);\n\t\t\t\t\tactive = false;\n\t\t\t\t\tawait this.executor.exec(\"COMMIT\");\n\t\t\t\t\treturn result;\n\t\t\t\t} catch (cause) {\n\t\t\t\t\tactive = false;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.executor.exec(\"ROLLBACK\");\n\t\t\t\t\t} catch (rollbackCause) {\n\t\t\t\t\t\tthrow new StorageRollbackError(cause as StorageFailureCause, rollbackCause as StorageFailureCause);\n\t\t\t\t\t}\n\t\t\t\t\tthrow cause;\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t}\n\n\tclose(): Promise<void> {\n\t\tif (!this.closePromise) {\n\t\t\tthis.closing = true;\n\t\t\tthis.closePromise = this.tail.then(() =>\n\t\t\t\tthis.driver(() => {\n\t\t\t\t\tif (this.ownsConnection) this.connection.close();\n\t\t\t\t\tfinalizeReleasedStatements();\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn this.closePromise;\n\t}\n}\n\nexport async function openNodeSqliteDatabase(\n\tpath: string,\n\t{\n\t\tbusyTimeoutMs = 5000,\n\t\tlockWaitMs = DEFAULT_NODE_SQLITE_LOCK_WAIT_MS,\n\t\treadOnly = false,\n\t}: { busyTimeoutMs?: number; lockWaitMs?: number; readOnly?: boolean } = {},\n): Promise<SqliteDatabase> {\n\tconst descriptor = { adapter: \"node-sqlite\", location: path };\n\t// Load node:sqlite on first open: importing it prints Node's experimental warning, which every importer of the\n\t// package entry point would otherwise see.\n\tlet Database: typeof DatabaseSync;\n\ttry {\n\t\t({ DatabaseSync: Database } = await import(\"node:sqlite\"));\n\t} catch (cause) {\n\t\tthrow new StorageAdapterLoadError(\"node:sqlite\", cause as StorageFailureCause);\n\t}\n\tlet connection: DatabaseSync | undefined;\n\ttry {\n\t\tif (!readOnly && path !== \":memory:\") await mkdir(dirname(path), { recursive: true });\n\t\tconnection = new Database(path, { readOnly });\n\t\tconnection.exec(`PRAGMA busy_timeout=${busyTimeoutMs}`);\n\t\tif (!readOnly) connection.exec(\"PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL; PRAGMA foreign_keys=ON\");\n\t\tconst location = connection.location();\n\t\tconst identity = location === null ? connection : await realpath(location);\n\t\treturn new NodeSqliteDatabase(connection, descriptor, true, identity, lockWaitMs);\n\t} catch (cause) {\n\t\ttry {\n\t\t\tconnection?.close();\n\t\t} catch {\n\t\t\t// Preserve the opening failure if cleanup also fails.\n\t\t}\n\t\tthrow unavailable(descriptor, cause);\n\t}\n}\n\nexport function wrapNodeSqliteDatabase(connection: DatabaseSync): SqliteDatabase {\n\tconst descriptor = { adapter: \"node-sqlite\", location: \":memory:\" };\n\ttry {\n\t\tdescriptor.location = connection.location() || \":memory:\";\n\t\tconnection.exec(\n\t\t\t\"PRAGMA busy_timeout=5000; PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL; PRAGMA foreign_keys=ON\",\n\t\t);\n\t\treturn new NodeSqliteDatabase(connection, descriptor, false);\n\t} catch (cause) {\n\t\tthrow unavailable(descriptor, cause);\n\t}\n}\n"]}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/atomic",
|
|
3
|
-
"version": "0.9.44-alpha.
|
|
3
|
+
"version": "0.9.44-alpha.5",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bastani/atomic",
|
|
9
|
-
"version": "0.9.44-alpha.
|
|
9
|
+
"version": "0.9.44-alpha.5",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@bastani/atomic-natives": "0.9.44-alpha.
|
|
13
|
-
"@bastani/pi-ai": "0.9.44-alpha.
|
|
12
|
+
"@bastani/atomic-natives": "0.9.44-alpha.5",
|
|
13
|
+
"@bastani/pi-ai": "0.9.44-alpha.5",
|
|
14
14
|
"@earendil-works/pi-agent-core": "1.4.0",
|
|
15
15
|
"@earendil-works/pi-codemode": "1.4.0",
|
|
16
16
|
"@earendil-works/pi-tui": "1.4.0",
|
|
@@ -427,18 +427,18 @@
|
|
|
427
427
|
}
|
|
428
428
|
},
|
|
429
429
|
"node_modules/@bastani/atomic-natives": {
|
|
430
|
-
"version": "0.9.44-alpha.
|
|
431
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.44-alpha.
|
|
430
|
+
"version": "0.9.44-alpha.5",
|
|
431
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.44-alpha.5.tgz",
|
|
432
432
|
"license": "MIT",
|
|
433
433
|
"optionalDependencies": {
|
|
434
|
-
"@bastani/atomic-natives-darwin-arm64": "0.9.44-alpha.
|
|
435
|
-
"@bastani/atomic-natives-darwin-x64": "0.9.44-alpha.
|
|
436
|
-
"@bastani/atomic-natives-linux-arm64-gnu": "0.9.44-alpha.
|
|
437
|
-
"@bastani/atomic-natives-linux-arm64-musl": "0.9.44-alpha.
|
|
438
|
-
"@bastani/atomic-natives-linux-x64-gnu": "0.9.44-alpha.
|
|
439
|
-
"@bastani/atomic-natives-linux-x64-musl": "0.9.44-alpha.
|
|
440
|
-
"@bastani/atomic-natives-win32-arm64-msvc": "0.9.44-alpha.
|
|
441
|
-
"@bastani/atomic-natives-win32-x64-msvc": "0.9.44-alpha.
|
|
434
|
+
"@bastani/atomic-natives-darwin-arm64": "0.9.44-alpha.5",
|
|
435
|
+
"@bastani/atomic-natives-darwin-x64": "0.9.44-alpha.5",
|
|
436
|
+
"@bastani/atomic-natives-linux-arm64-gnu": "0.9.44-alpha.5",
|
|
437
|
+
"@bastani/atomic-natives-linux-arm64-musl": "0.9.44-alpha.5",
|
|
438
|
+
"@bastani/atomic-natives-linux-x64-gnu": "0.9.44-alpha.5",
|
|
439
|
+
"@bastani/atomic-natives-linux-x64-musl": "0.9.44-alpha.5",
|
|
440
|
+
"@bastani/atomic-natives-win32-arm64-msvc": "0.9.44-alpha.5",
|
|
441
|
+
"@bastani/atomic-natives-win32-x64-msvc": "0.9.44-alpha.5"
|
|
442
442
|
},
|
|
443
443
|
"engines": {
|
|
444
444
|
"bun": ">=1.4.2",
|
|
@@ -446,8 +446,8 @@
|
|
|
446
446
|
}
|
|
447
447
|
},
|
|
448
448
|
"node_modules/@bastani/atomic-natives-darwin-arm64": {
|
|
449
|
-
"version": "0.9.44-alpha.
|
|
450
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.44-alpha.
|
|
449
|
+
"version": "0.9.44-alpha.5",
|
|
450
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.44-alpha.5.tgz",
|
|
451
451
|
"license": "MIT",
|
|
452
452
|
"os": [
|
|
453
453
|
"darwin"
|
|
@@ -458,8 +458,8 @@
|
|
|
458
458
|
"optional": true
|
|
459
459
|
},
|
|
460
460
|
"node_modules/@bastani/atomic-natives-darwin-x64": {
|
|
461
|
-
"version": "0.9.44-alpha.
|
|
462
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.44-alpha.
|
|
461
|
+
"version": "0.9.44-alpha.5",
|
|
462
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.44-alpha.5.tgz",
|
|
463
463
|
"license": "MIT",
|
|
464
464
|
"os": [
|
|
465
465
|
"darwin"
|
|
@@ -470,8 +470,8 @@
|
|
|
470
470
|
"optional": true
|
|
471
471
|
},
|
|
472
472
|
"node_modules/@bastani/atomic-natives-linux-arm64-gnu": {
|
|
473
|
-
"version": "0.9.44-alpha.
|
|
474
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.44-alpha.
|
|
473
|
+
"version": "0.9.44-alpha.5",
|
|
474
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.44-alpha.5.tgz",
|
|
475
475
|
"license": "MIT",
|
|
476
476
|
"os": [
|
|
477
477
|
"linux"
|
|
@@ -485,8 +485,8 @@
|
|
|
485
485
|
"optional": true
|
|
486
486
|
},
|
|
487
487
|
"node_modules/@bastani/atomic-natives-linux-arm64-musl": {
|
|
488
|
-
"version": "0.9.44-alpha.
|
|
489
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-musl/-/atomic-natives-linux-arm64-musl-0.9.44-alpha.
|
|
488
|
+
"version": "0.9.44-alpha.5",
|
|
489
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-musl/-/atomic-natives-linux-arm64-musl-0.9.44-alpha.5.tgz",
|
|
490
490
|
"license": "MIT",
|
|
491
491
|
"os": [
|
|
492
492
|
"linux"
|
|
@@ -500,8 +500,8 @@
|
|
|
500
500
|
"optional": true
|
|
501
501
|
},
|
|
502
502
|
"node_modules/@bastani/atomic-natives-linux-x64-gnu": {
|
|
503
|
-
"version": "0.9.44-alpha.
|
|
504
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.44-alpha.
|
|
503
|
+
"version": "0.9.44-alpha.5",
|
|
504
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.44-alpha.5.tgz",
|
|
505
505
|
"license": "MIT",
|
|
506
506
|
"os": [
|
|
507
507
|
"linux"
|
|
@@ -515,8 +515,8 @@
|
|
|
515
515
|
"optional": true
|
|
516
516
|
},
|
|
517
517
|
"node_modules/@bastani/atomic-natives-linux-x64-musl": {
|
|
518
|
-
"version": "0.9.44-alpha.
|
|
519
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-musl/-/atomic-natives-linux-x64-musl-0.9.44-alpha.
|
|
518
|
+
"version": "0.9.44-alpha.5",
|
|
519
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-musl/-/atomic-natives-linux-x64-musl-0.9.44-alpha.5.tgz",
|
|
520
520
|
"license": "MIT",
|
|
521
521
|
"os": [
|
|
522
522
|
"linux"
|
|
@@ -530,8 +530,8 @@
|
|
|
530
530
|
"optional": true
|
|
531
531
|
},
|
|
532
532
|
"node_modules/@bastani/atomic-natives-win32-arm64-msvc": {
|
|
533
|
-
"version": "0.9.44-alpha.
|
|
534
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.44-alpha.
|
|
533
|
+
"version": "0.9.44-alpha.5",
|
|
534
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.44-alpha.5.tgz",
|
|
535
535
|
"license": "MIT",
|
|
536
536
|
"os": [
|
|
537
537
|
"win32"
|
|
@@ -542,8 +542,8 @@
|
|
|
542
542
|
"optional": true
|
|
543
543
|
},
|
|
544
544
|
"node_modules/@bastani/atomic-natives-win32-x64-msvc": {
|
|
545
|
-
"version": "0.9.44-alpha.
|
|
546
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.44-alpha.
|
|
545
|
+
"version": "0.9.44-alpha.5",
|
|
546
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.44-alpha.5.tgz",
|
|
547
547
|
"license": "MIT",
|
|
548
548
|
"os": [
|
|
549
549
|
"win32"
|
|
@@ -554,8 +554,8 @@
|
|
|
554
554
|
"optional": true
|
|
555
555
|
},
|
|
556
556
|
"node_modules/@bastani/pi-ai": {
|
|
557
|
-
"version": "0.9.44-alpha.
|
|
558
|
-
"resolved": "https://registry.npmjs.org/@bastani/pi-ai/-/pi-ai-0.9.44-alpha.
|
|
557
|
+
"version": "0.9.44-alpha.5",
|
|
558
|
+
"resolved": "https://registry.npmjs.org/@bastani/pi-ai/-/pi-ai-0.9.44-alpha.5.tgz",
|
|
559
559
|
"license": "MIT",
|
|
560
560
|
"dependencies": {
|
|
561
561
|
"@anthropic-ai/sdk": "0.129.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/atomic",
|
|
3
|
-
"version": "0.9.44-alpha.
|
|
3
|
+
"version": "0.9.44-alpha.5",
|
|
4
4
|
"description": "Atomic coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"atomicConfig": {
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
"prepublishOnly": "bun run clean && bun run build && bun run shrinkwrap"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"@bastani/atomic-natives": "0.9.44-alpha.
|
|
93
|
-
"@bastani/pi-ai": "0.9.44-alpha.
|
|
92
|
+
"@bastani/atomic-natives": "0.9.44-alpha.5",
|
|
93
|
+
"@bastani/pi-ai": "0.9.44-alpha.5",
|
|
94
94
|
"@earendil-works/pi-agent-core": "1.4.0",
|
|
95
95
|
"@earendil-works/pi-codemode": "1.4.0",
|
|
96
96
|
"@earendil-works/pi-tui": "1.4.0",
|