@cortexkit/opencode-magic-context 0.44.0 → 0.44.2
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/README.md +6 -0
- package/dist/agents/dreamer.d.ts +4 -6
- package/dist/agents/dreamer.d.ts.map +1 -1
- package/dist/agents/magic-context-prompt.d.ts +2 -0
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/{announcement-1a8bvswd.js → announcement-n8hs7kjw.js} +2 -2
- package/dist/config/live-child-output-cap.d.ts +18 -0
- package/dist/config/live-child-output-cap.d.ts.map +1 -0
- package/dist/config/schema/magic-context.d.ts +64 -11
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-48f7np9d.js → conflict-warning-hook-1msyvb51.js} +6 -6
- package/dist/{derive-budgets-8kgevxmx.js → derive-budgets-gd2270s0.js} +3 -3
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts +11 -0
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-storage.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/docs-proposals.d.ts +2 -0
- package/dist/features/magic-context/dreamer/docs-proposals.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/manual-summary.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts +1 -1
- package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories.d.ts +5 -0
- package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/open-opencode-db.d.ts +2 -0
- package/dist/features/magic-context/dreamer/open-opencode-db.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/primer-seed.d.ts +11 -5
- package/dist/features/magic-context/dreamer/primer-seed.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts +7 -2
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/retrospective-raw-provider.d.ts +2 -2
- package/dist/features/magic-context/dreamer/retrospective-raw-provider.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts +8 -1
- package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts +5 -0
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-gates.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-prompts.d.ts +18 -2
- package/dist/features/magic-context/dreamer/task-prompts.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-registry.d.ts +12 -0
- package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-scheduler.d.ts +3 -1
- package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/token-budget.d.ts +33 -0
- package/dist/features/magic-context/dreamer/token-budget.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/verify-diff.d.ts +15 -0
- package/dist/features/magic-context/dreamer/verify-diff.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/verify-gate.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify-prompt.d.ts +5 -2
- package/dist/features/magic-context/dreamer/verify-prompt.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify-read-cap.d.ts +4 -0
- package/dist/features/magic-context/dreamer/verify-read-cap.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/verify.d.ts +5 -0
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/git-log-reader.d.ts.map +1 -1
- package/dist/features/magic-context/memory/project-identity-cache.d.ts +6 -0
- package/dist/features/magic-context/memory/project-identity-cache.d.ts.map +1 -0
- package/dist/features/magic-context/memory/project-identity.d.ts +15 -22
- package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory-fts.d.ts +1 -0
- package/dist/features/magic-context/memory/storage-memory-fts.d.ts.map +1 -1
- package/dist/features/magic-context/memory/verification-paths.d.ts +1 -0
- package/dist/features/magic-context/memory/verification-paths.d.ts.map +1 -1
- package/dist/features/magic-context/mural/mural-font.generated.d.ts.map +1 -1
- package/dist/features/magic-context/project-embedding-registry.d.ts +5 -0
- package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/session-activity.d.ts +10 -0
- package/dist/features/magic-context/session-activity.d.ts.map +1 -0
- package/dist/features/magic-context/session-cache-ttl.d.ts +10 -0
- package/dist/features/magic-context/session-cache-ttl.d.ts.map +1 -0
- package/dist/features/magic-context/session-project-backfill.d.ts +4 -1
- package/dist/features/magic-context/session-project-backfill.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/compiler.d.ts +5 -0
- package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts +1 -0
- package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/storage.d.ts +1 -1
- package/dist/features/magic-context/smart-notes/storage.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/types.d.ts +2 -0
- package/dist/features/magic-context/smart-notes/types.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts +2 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-identity-merge.d.ts +4 -1
- package/dist/features/magic-context/storage-identity-merge.d.ts.map +1 -1
- package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
- package/dist/features/magic-context/v22-deferred-backfill.d.ts.map +1 -1
- package/dist/hooks/auto-update-checker/checker.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner.d.ts +1 -0
- package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/dropped-input-guard.d.ts.map +1 -1
- package/dist/hooks/magic-context/embed-session-state.d.ts +3 -0
- package/dist/hooks/magic-context/embed-session-state.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts +1 -0
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-payloads.d.ts +1 -0
- package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-replay.d.ts +6 -4
- package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
- package/dist/hooks/magic-context/opencode-v1-store-fixture.d.ts +12 -0
- package/dist/hooks/magic-context/opencode-v1-store-fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts +16 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts +5 -1
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts +10 -0
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/storage-busy-refusal.d.ts +7 -0
- package/dist/hooks/magic-context/storage-busy-refusal.d.ts.map +1 -0
- package/dist/hooks/magic-context/strip-content.d.ts +1 -0
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +1 -0
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/{index-5f4qsnaq.js → index-18tjha8g.js} +2 -2
- package/dist/{index-4b30nf6z.js → index-32b096cc.js} +1 -1
- package/dist/{index-tjq5jztd.js → index-3bygzk2d.js} +1 -1
- package/dist/{index-cj5qe2nw.js → index-3x9caerx.js} +8 -6
- package/dist/index-40s1xz22.js +125 -0
- package/dist/{index-pye48m79.js → index-egkfvhms.js} +130 -42
- package/dist/{index-2zf5fv89.js → index-esxfcz5z.js} +171 -12
- package/dist/index-gtzcmv90.js +7260 -0
- package/dist/{index-6w9p73jz.js → index-jqcbs2k1.js} +10 -0
- package/dist/{index-v6wsttqt.js → index-kr5qehbd.js} +1 -1
- package/dist/{index-dx0xnd4q.js → index-kwe03yde.js} +1 -1
- package/dist/{index-c906f3ff.js → index-r9vkp4n9.js} +4 -4
- package/dist/{index-6z9g64js.js → index-s70wtd8k.js} +4 -1
- package/dist/{index-01ft0h3p.js → index-stb5fg12.js} +2 -2
- package/dist/{index-rdey8znw.js → index-ttdn47aq.js} +35260 -32540
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15123 -23504
- package/dist/{message-time-backfill-rm9wmcem.js → message-time-backfill-q374fxc5.js} +3 -3
- package/dist/plugin/dream-timer.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/messages-transform.d.ts +10 -9
- package/dist/plugin/messages-transform.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts +1 -0
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/{read-session-chunk-ktz5zt70.js → read-session-chunk-wmvgnd24.js} +6 -4
- package/dist/{recomp-orchestrator-ahekzt0s.js → recomp-orchestrator-rk40ff15.js} +10 -9
- package/dist/{safe-notification-target-6w0esgd6.js → safe-notification-target-50gm9c58.js} +3 -3
- package/dist/{send-session-notification-w7xbnrsm.js → send-session-notification-6xsrcxnp.js} +5 -5
- package/dist/shared/cache-ttl-display.d.ts +3 -1
- package/dist/shared/cache-ttl-display.d.ts.map +1 -1
- package/dist/shared/harness.d.ts +11 -0
- package/dist/shared/harness.d.ts.map +1 -1
- package/dist/shared/model-cache-ttl.d.ts +9 -0
- package/dist/shared/model-cache-ttl.d.ts.map +1 -0
- package/dist/shared/model-suggestion-retry.d.ts +1 -1
- package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
- package/dist/shared/prompt-async-transport.d.ts +7 -7
- package/dist/shared/prompt-async-transport.d.ts.map +1 -1
- package/dist/shared/rpc-server.d.ts.map +1 -1
- package/dist/shared/rpc-types.d.ts +1 -1
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/rpc-utils.d.ts +21 -0
- package/dist/shared/rpc-utils.d.ts.map +1 -1
- package/dist/shared/sqlite-write-locker-test-support.d.ts.map +1 -1
- package/dist/shared/sqlite.d.ts +12 -0
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/status-view.d.ts +1 -1
- package/dist/shared/status-view.d.ts.map +1 -1
- package/dist/shared/subagent-runner.d.ts +3 -1
- package/dist/shared/subagent-runner.d.ts.map +1 -1
- package/dist/shared/user-facing-codes.d.ts +5 -0
- package/dist/shared/user-facing-codes.d.ts.map +1 -1
- package/dist/{task-config-mgf5nsh3.js → task-config-2bm68628.js} +1 -1
- package/dist/tools/ctx-expand/render.d.ts.map +1 -1
- package/dist/transform-postprocess-phase-t7xgdhdf.js +36 -0
- package/dist/v2/hidden-completion.d.ts +2 -0
- package/dist/v2/hidden-completion.d.ts.map +1 -1
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/hooks/hidden-child.d.ts +1 -0
- package/dist/v2/hooks/hidden-child.d.ts.map +1 -1
- package/dist/v2/hooks/lkg-system.d.ts +11 -0
- package/dist/v2/hooks/lkg-system.d.ts.map +1 -0
- package/dist/v2/hooks/session-project-backfill.d.ts +1 -1
- package/dist/v2/hooks/session-project-backfill.d.ts.map +1 -1
- package/dist/v2/hooks/storage-gate.d.ts +11 -5
- package/dist/v2/hooks/storage-gate.d.ts.map +1 -1
- package/dist/v2/host-service.d.ts +2 -1
- package/dist/v2/host-service.d.ts.map +1 -1
- package/dist/v2/server.js +95347 -93236
- package/dist/v2/store-reader.d.ts +2 -0
- package/dist/v2/store-reader.d.ts.map +1 -1
- package/dist/wrapup-orchestrator-h8tr10c6.js +19 -0
- package/package.json +1 -1
- package/src/agents/dreamer.ts +4 -6
- package/src/agents/hidden-agent-registrations.ts +3 -3
- package/src/agents/magic-context-prompt.test.ts +125 -0
- package/src/agents/magic-context-prompt.ts +12 -7
- package/src/agents/permissions.test.ts +3 -4
- package/src/config/latch-permanence-guard.test.ts +9 -0
- package/src/config/live-child-output-cap.test.ts +101 -0
- package/src/config/live-child-output-cap.ts +74 -0
- package/src/config/live-run-config.test.ts +24 -11
- package/src/config/schema/magic-context.test.ts +16 -1
- package/src/config/schema/magic-context.ts +27 -10
- package/src/features/magic-context/dreamer/task-registry.ts +13 -0
- package/src/shared/cache-ttl-display.ts +14 -20
- package/src/shared/harness.ts +14 -0
- package/src/shared/logger.test.ts +1 -0
- package/src/shared/model-cache-ttl.test.ts +40 -0
- package/src/shared/model-cache-ttl.ts +58 -0
- package/src/shared/model-suggestion-retry.ts +9 -2
- package/src/shared/prompt-async-transport.test.ts +254 -1
- package/src/shared/prompt-async-transport.ts +153 -44
- package/src/shared/prompt-surface-a1-golden.md +13 -13
- package/src/shared/rpc-async-probes.test.ts +230 -0
- package/src/shared/rpc-server.ts +6 -4
- package/src/shared/rpc-types.ts +1 -1
- package/src/shared/rpc-utils.test.ts +27 -1
- package/src/shared/rpc-utils.ts +161 -9
- package/src/shared/sqlite-acquisition-fence.test.ts +132 -0
- package/src/shared/sqlite-acquisition-routing.test.ts +94 -0
- package/src/shared/sqlite-pass-scope.test.ts +182 -0
- package/src/shared/sqlite-transaction-mode-guard.test.ts +42 -10
- package/src/shared/sqlite-write-locker-test-support.ts +1 -0
- package/src/shared/sqlite.ts +142 -56
- package/src/shared/status-view.ts +1 -1
- package/src/shared/storage-busy.test.ts +95 -0
- package/src/shared/subagent-runner.ts +4 -0
- package/src/shared/user-facing-codes.ts +6 -0
- package/src/shared/windows-hidden-spawns.test.ts +132 -0
- package/src/shared/write-transaction-attribution.test.ts +1 -0
- package/dist/wrapup-orchestrator-9srk0kjf.js +0 -18
package/src/shared/sqlite.ts
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
* `run()` → {changes,lastInsertRowid}) is identical and was verified directly.
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
42
43
|
import { statSync } from "node:fs";
|
|
43
44
|
// Type import only — runtime is loaded dynamically below. @types/better-sqlite3
|
|
44
45
|
// has the richest definitions and is a structural superset of the API surface
|
|
@@ -211,6 +212,70 @@ export interface SqliteMemoryStats {
|
|
|
211
212
|
const trackedSqliteConnections = new Map<number, TrackedSqliteConnection>();
|
|
212
213
|
let nextSqliteConnectionSequence = 1;
|
|
213
214
|
|
|
215
|
+
/** Route native Bun and Node transaction entry through the same acquisition retry.
|
|
216
|
+
* Native Bun transaction wrappers execute BEGIN internally, bypassing an exec override,
|
|
217
|
+
* so both runtimes use this small synchronous wrapper instead. Writable handles
|
|
218
|
+
* default to IMMEDIATE; explicit deferred calls and readonly handles keep read
|
|
219
|
+
* snapshots without acquiring the writer lock. */
|
|
220
|
+
function installTransactionRouting(db: BetterSqlite3.Database, readonly: boolean): void {
|
|
221
|
+
const nativeExec = db.exec.bind(db);
|
|
222
|
+
Object.defineProperty(db, "exec", {
|
|
223
|
+
configurable: true,
|
|
224
|
+
writable: true,
|
|
225
|
+
value: (sql: string) => {
|
|
226
|
+
if (/^\s*BEGIN\s+(?:IMMEDIATE|EXCLUSIVE)(?:\s+TRANSACTION)?\s*;?\s*$/i.test(sql)) {
|
|
227
|
+
retryAcquisition(() => nativeExec(sql), sql.trim());
|
|
228
|
+
return db;
|
|
229
|
+
}
|
|
230
|
+
return nativeExec(sql);
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
Object.defineProperty(db, "transaction", {
|
|
234
|
+
configurable: true,
|
|
235
|
+
writable: true,
|
|
236
|
+
// biome-ignore lint/suspicious/noExplicitAny: preserve the native callback's receiver and argument types.
|
|
237
|
+
value: (fn: (...args: any[]) => any) => {
|
|
238
|
+
const make = (mode: "IMMEDIATE" | "EXCLUSIVE" | "DEFERRED") =>
|
|
239
|
+
function (this: unknown, ...args: unknown[]): unknown {
|
|
240
|
+
const nested = isInTransaction(db);
|
|
241
|
+
// Equal savepoint names stack LIFO, matching both native backends.
|
|
242
|
+
const savepoint = "mc_tx_sp";
|
|
243
|
+
db.exec(nested ? `SAVEPOINT ${savepoint}` : `BEGIN ${mode}`);
|
|
244
|
+
try {
|
|
245
|
+
const result = fn.apply(this, args);
|
|
246
|
+
db.exec(nested ? `RELEASE ${savepoint}` : "COMMIT");
|
|
247
|
+
return result;
|
|
248
|
+
} catch (error) {
|
|
249
|
+
if (isInTransaction(db)) {
|
|
250
|
+
if (nested) {
|
|
251
|
+
db.exec(`ROLLBACK TO ${savepoint}`);
|
|
252
|
+
db.exec(`RELEASE ${savepoint}`);
|
|
253
|
+
} else db.exec("ROLLBACK");
|
|
254
|
+
}
|
|
255
|
+
throw error;
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
const defaultTransaction = make(readonly ? "DEFERRED" : "IMMEDIATE");
|
|
259
|
+
const variants = {
|
|
260
|
+
default: defaultTransaction,
|
|
261
|
+
deferred: make("DEFERRED"),
|
|
262
|
+
immediate: make("IMMEDIATE"),
|
|
263
|
+
exclusive: make("EXCLUSIVE"),
|
|
264
|
+
database: db,
|
|
265
|
+
};
|
|
266
|
+
for (const transaction of [
|
|
267
|
+
variants.default,
|
|
268
|
+
variants.deferred,
|
|
269
|
+
variants.immediate,
|
|
270
|
+
variants.exclusive,
|
|
271
|
+
]) {
|
|
272
|
+
Object.assign(transaction, variants);
|
|
273
|
+
}
|
|
274
|
+
return defaultTransaction;
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
214
279
|
function trackSqliteConnection(
|
|
215
280
|
db: BetterSqlite3.Database,
|
|
216
281
|
filename: unknown,
|
|
@@ -232,6 +297,7 @@ function trackSqliteConnection(
|
|
|
232
297
|
((options as { readonly?: unknown }).readonly === true ||
|
|
233
298
|
(options as { readOnly?: unknown }).readOnly === true),
|
|
234
299
|
};
|
|
300
|
+
installTransactionRouting(db, metadata.readonly);
|
|
235
301
|
Object.defineProperty(db, "close", {
|
|
236
302
|
configurable: true,
|
|
237
303
|
value: (...args: unknown[]) => {
|
|
@@ -260,18 +326,10 @@ const TrackedDatabase = new Proxy(DatabaseImpl, {
|
|
|
260
326
|
* Wrap node:sqlite's `DatabaseSync` so it presents the better-sqlite3/bun
|
|
261
327
|
* surface the rest of the codebase calls:
|
|
262
328
|
* - translate the `{ readonly }` constructor option → node:sqlite's `readOnly`
|
|
263
|
-
*
|
|
264
|
-
* using `db.isTransaction` to pick BEGIN (top-level) vs SAVEPOINT (nested),
|
|
265
|
-
* so it composes correctly with manual `BEGIN IMMEDIATE` blocks too.
|
|
329
|
+
* Transaction routing is installed for both runtimes by trackSqliteConnection.
|
|
266
330
|
*/
|
|
267
331
|
// biome-ignore lint/suspicious/noExplicitAny: node:sqlite has no shipped types here; the public export is cast to the better-sqlite3 shape.
|
|
268
332
|
function buildNodeSqliteDatabaseClass(DatabaseSync: any): typeof BetterSqlite3 {
|
|
269
|
-
// Single constant savepoint name is correct for arbitrary nesting depth:
|
|
270
|
-
// SQLite savepoints with the same name stack LIFO — RELEASE / ROLLBACK TO
|
|
271
|
-
// always target the most recent. node:sqlite is synchronous + single-process
|
|
272
|
-
// per connection, so there is no concurrent-savepoint hazard.
|
|
273
|
-
const SAVEPOINT = "mc_tx_sp";
|
|
274
|
-
|
|
275
333
|
class NodeSqliteDatabase extends DatabaseSync {
|
|
276
334
|
constructor(filename?: string | Buffer, options?: BetterSqlite3.Options) {
|
|
277
335
|
const translated: Record<string, unknown> = { ...options };
|
|
@@ -306,52 +364,6 @@ function buildNodeSqliteDatabaseClass(DatabaseSync: any): typeof BetterSqlite3 {
|
|
|
306
364
|
}
|
|
307
365
|
return stmt;
|
|
308
366
|
}
|
|
309
|
-
|
|
310
|
-
// biome-ignore lint/suspicious/noExplicitAny: mirrors better-sqlite3's generic transaction(fn) signature.
|
|
311
|
-
transaction<F extends (...args: any[]) => any>(fn: F): F {
|
|
312
|
-
// biome-ignore lint/suspicious/noExplicitAny: faithful pass-through of this/args to fn.
|
|
313
|
-
const self = this as any;
|
|
314
|
-
const execute = (
|
|
315
|
-
mode: "" | "DEFERRED" | "IMMEDIATE" | "EXCLUSIVE",
|
|
316
|
-
receiver: unknown,
|
|
317
|
-
args: unknown[],
|
|
318
|
-
) => {
|
|
319
|
-
const nested = self.isTransaction === true;
|
|
320
|
-
self.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : `BEGIN${mode ? ` ${mode}` : ""}`);
|
|
321
|
-
try {
|
|
322
|
-
const result = fn.apply(receiver, args);
|
|
323
|
-
self.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
|
|
324
|
-
return result;
|
|
325
|
-
} catch (error) {
|
|
326
|
-
if (nested) {
|
|
327
|
-
// ROLLBACK TO unwinds the savepoint's changes but leaves
|
|
328
|
-
// it on the stack; RELEASE then pops it (better-sqlite3
|
|
329
|
-
// does both).
|
|
330
|
-
self.exec(`ROLLBACK TO ${SAVEPOINT}`);
|
|
331
|
-
self.exec(`RELEASE ${SAVEPOINT}`);
|
|
332
|
-
} else {
|
|
333
|
-
self.exec("ROLLBACK");
|
|
334
|
-
}
|
|
335
|
-
throw error;
|
|
336
|
-
}
|
|
337
|
-
};
|
|
338
|
-
const wrapped = function (this: unknown, ...args: unknown[]): unknown {
|
|
339
|
-
return execute("", this, args);
|
|
340
|
-
};
|
|
341
|
-
wrapped.default = function (this: unknown, ...args: unknown[]): unknown {
|
|
342
|
-
return execute("", this, args);
|
|
343
|
-
};
|
|
344
|
-
wrapped.deferred = function (this: unknown, ...args: unknown[]): unknown {
|
|
345
|
-
return execute("DEFERRED", this, args);
|
|
346
|
-
};
|
|
347
|
-
wrapped.immediate = function (this: unknown, ...args: unknown[]): unknown {
|
|
348
|
-
return execute("IMMEDIATE", this, args);
|
|
349
|
-
};
|
|
350
|
-
wrapped.exclusive = function (this: unknown, ...args: unknown[]): unknown {
|
|
351
|
-
return execute("EXCLUSIVE", this, args);
|
|
352
|
-
};
|
|
353
|
-
return wrapped as unknown as F;
|
|
354
|
-
}
|
|
355
367
|
}
|
|
356
368
|
|
|
357
369
|
return NodeSqliteDatabase as unknown as typeof BetterSqlite3;
|
|
@@ -476,6 +488,80 @@ export type Database = BetterSqlite3.Database;
|
|
|
476
488
|
export type Statement = BetterSqlite3.Statement<unknown[], unknown>;
|
|
477
489
|
|
|
478
490
|
const privilegeDepth = new WeakMap<Database, number>();
|
|
491
|
+
const transformPassScope = new AsyncLocalStorage<{ active: boolean } | undefined>();
|
|
492
|
+
|
|
493
|
+
/** Only an awaited foreground transform may spend the extra acquisition budget.
|
|
494
|
+
* The mutable lease also expires for detached descendants when that pass ends. */
|
|
495
|
+
export function withSqliteTransformPass<T>(operation: () => T): T {
|
|
496
|
+
const lease = { active: true };
|
|
497
|
+
return transformPassScope.run(lease, () => {
|
|
498
|
+
try {
|
|
499
|
+
const result = operation();
|
|
500
|
+
if (result && typeof (result as { then?: unknown }).then === "function") {
|
|
501
|
+
return Promise.resolve(result).finally(() => {
|
|
502
|
+
lease.active = false;
|
|
503
|
+
}) as T;
|
|
504
|
+
}
|
|
505
|
+
lease.active = false;
|
|
506
|
+
return result;
|
|
507
|
+
} catch (error) {
|
|
508
|
+
lease.active = false;
|
|
509
|
+
throw error;
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/** Start detached maintenance work without borrowing a foreground pass's budget. */
|
|
515
|
+
export function withoutSqliteTransformPass<T>(operation: () => T): T {
|
|
516
|
+
return transformPassScope.run(undefined, operation);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/** Bun names SQLite codes; node:sqlite exposes the numeric (possibly extended) errcode. */
|
|
520
|
+
export function isTransientSqliteError(error: unknown): boolean {
|
|
521
|
+
if (!error || typeof error !== "object") return false;
|
|
522
|
+
const value = error as { code?: unknown; errcode?: unknown };
|
|
523
|
+
return (
|
|
524
|
+
(typeof value.code === "string" && /^(SQLITE_BUSY|SQLITE_LOCKED)(_|$)/.test(value.code)) ||
|
|
525
|
+
(typeof value.errcode === "number" && [5, 6].includes(value.errcode & 0xff))
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
export class SqliteAcquisitionBusyError extends Error {
|
|
530
|
+
readonly code = "SQLITE_BUSY";
|
|
531
|
+
readonly stage: string;
|
|
532
|
+
constructor(cause: unknown, stage = "BEGIN IMMEDIATE") {
|
|
533
|
+
super("SQLite writer acquisition remained busy after 3 attempts", { cause });
|
|
534
|
+
this.name = "SqliteAcquisitionBusyError";
|
|
535
|
+
this.stage = stage;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/** Retry only acquisition: no privilege flag, callback or in-memory mutation has run yet. */
|
|
540
|
+
function retryAcquisition(acquire: () => unknown, stage: string): void {
|
|
541
|
+
// Maintenance writers retry on their next tick. Multiplying their native
|
|
542
|
+
// busy timeout here would stall every session sharing the host event loop.
|
|
543
|
+
if (!transformPassScope.getStore()?.active) {
|
|
544
|
+
acquire();
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
const delays = [500, 1000];
|
|
548
|
+
for (let attempt = 0; ; attempt++) {
|
|
549
|
+
try {
|
|
550
|
+
acquire();
|
|
551
|
+
return;
|
|
552
|
+
} catch (error) {
|
|
553
|
+
// Handles created by this module already retry inside exec. Do not
|
|
554
|
+
// apply the attempt budget twice; externally supplied handles still
|
|
555
|
+
// need the acquisition retry performed by withPrivilegedWriter.
|
|
556
|
+
if (error instanceof SqliteAcquisitionBusyError || !isTransientSqliteError(error))
|
|
557
|
+
throw error;
|
|
558
|
+
if (attempt === delays.length) throw new SqliteAcquisitionBusyError(error, stage);
|
|
559
|
+
// The database API is synchronous on both hosts. With busy_timeout=5000,
|
|
560
|
+
// three attempts plus these waits bound one acquisition to 16.5 seconds.
|
|
561
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, delays[attempt]);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
479
565
|
|
|
480
566
|
function isInTransaction(db: Database): boolean {
|
|
481
567
|
const candidate = db as unknown as { inTransaction?: unknown; isTransaction?: unknown };
|
|
@@ -501,7 +587,7 @@ export function withPrivilegedWriter<T>(db: Database, operation: () => T): T {
|
|
|
501
587
|
if (nested) {
|
|
502
588
|
db.exec(`SAVEPOINT ${savepoint}`);
|
|
503
589
|
} else {
|
|
504
|
-
db.exec("BEGIN IMMEDIATE");
|
|
590
|
+
retryAcquisition(() => db.exec("BEGIN IMMEDIATE"), "BEGIN IMMEDIATE");
|
|
505
591
|
}
|
|
506
592
|
privilegeDepth.set(db, previousDepth + 1);
|
|
507
593
|
try {
|
|
@@ -124,7 +124,7 @@ export interface StatusViewSource {
|
|
|
124
124
|
readonly protectedTagCount: number;
|
|
125
125
|
readonly isSubagent: boolean;
|
|
126
126
|
readonly cacheTtl: string;
|
|
127
|
-
readonly cacheTtlSource?: "
|
|
127
|
+
readonly cacheTtlSource?: import("./cache-ttl-display").CacheTtlDisplaySource;
|
|
128
128
|
readonly cacheTtlModelKey?: string;
|
|
129
129
|
readonly lastResponseTime: number;
|
|
130
130
|
readonly cacheRemainingMs: number;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { afterAll, afterEach, describe, expect, spyOn, test } from "bun:test";
|
|
2
|
+
import {
|
|
3
|
+
Database,
|
|
4
|
+
isTransientSqliteError,
|
|
5
|
+
withSqliteTransformPass,
|
|
6
|
+
withPrivilegedWriter as writePrivileged,
|
|
7
|
+
} from "./sqlite";
|
|
8
|
+
|
|
9
|
+
const withPrivilegedWriter = <T>(db: Database, operation: () => T): T =>
|
|
10
|
+
withSqliteTransformPass(() => writePrivileged(db, operation));
|
|
11
|
+
|
|
12
|
+
const wait = spyOn(Atomics, "wait");
|
|
13
|
+
afterEach(() => wait.mockClear());
|
|
14
|
+
afterAll(() => wait.mockRestore());
|
|
15
|
+
|
|
16
|
+
describe("writer acquisition backoff", () => {
|
|
17
|
+
for (const clearsOn of [2, 3]) {
|
|
18
|
+
test(`acquisition clears on attempt ${clearsOn} and invokes callback exactly once`, () => {
|
|
19
|
+
const db = new Database(":memory:");
|
|
20
|
+
db.exec(
|
|
21
|
+
"CREATE TABLE context_privilege_state(id INTEGER PRIMARY KEY, enabled INTEGER); CREATE TABLE result(value TEXT)",
|
|
22
|
+
);
|
|
23
|
+
const exec = db.exec.bind(db);
|
|
24
|
+
let attempts = 0;
|
|
25
|
+
let callbacks = 0;
|
|
26
|
+
const delays: number[] = [];
|
|
27
|
+
wait.mockImplementation((_array, _index, _value, timeout) => {
|
|
28
|
+
delays.push(timeout!);
|
|
29
|
+
return "timed-out";
|
|
30
|
+
});
|
|
31
|
+
const intercepted = spyOn(db, "exec").mockImplementation((sql) => {
|
|
32
|
+
if (sql === "BEGIN IMMEDIATE" && ++attempts < clearsOn)
|
|
33
|
+
throw Object.assign(new Error("locked"), { code: "SQLITE_BUSY" });
|
|
34
|
+
return exec(sql);
|
|
35
|
+
});
|
|
36
|
+
try {
|
|
37
|
+
const result = withPrivilegedWriter(db, () => {
|
|
38
|
+
callbacks++;
|
|
39
|
+
db.prepare("INSERT INTO result VALUES (?)").run("managed");
|
|
40
|
+
return JSON.stringify(db.prepare("SELECT * FROM result").all());
|
|
41
|
+
});
|
|
42
|
+
expect(result).toBe('[{"value":"managed"}]');
|
|
43
|
+
expect(attempts).toBe(clearsOn);
|
|
44
|
+
expect(callbacks).toBe(1);
|
|
45
|
+
expect(delays).toEqual([500, 1000].slice(0, clearsOn - 1));
|
|
46
|
+
} finally {
|
|
47
|
+
intercepted.mockRestore();
|
|
48
|
+
db.close();
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
test("exhausted acquisition never invokes callback", () => {
|
|
53
|
+
const db = new Database(":memory:");
|
|
54
|
+
let calls = 0;
|
|
55
|
+
wait.mockImplementation(() => "timed-out");
|
|
56
|
+
const exec = spyOn(db, "exec").mockImplementation(() => {
|
|
57
|
+
throw Object.assign(new Error("original lock"), { code: "SQLITE_LOCKED" });
|
|
58
|
+
});
|
|
59
|
+
try {
|
|
60
|
+
expect(() => withPrivilegedWriter(db, () => calls++)).toThrow("after 3 attempts");
|
|
61
|
+
expect(exec).toHaveBeenCalledTimes(3);
|
|
62
|
+
expect(calls).toBe(0);
|
|
63
|
+
} finally {
|
|
64
|
+
exec.mockRestore();
|
|
65
|
+
db.close();
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
test("busy callback rolls back without retrying mutations", () => {
|
|
69
|
+
const db = new Database(":memory:");
|
|
70
|
+
db.exec(
|
|
71
|
+
"CREATE TABLE context_privilege_state(id INTEGER PRIMARY KEY, enabled INTEGER); CREATE TABLE result(value TEXT)",
|
|
72
|
+
);
|
|
73
|
+
let calls = 0;
|
|
74
|
+
try {
|
|
75
|
+
expect(() =>
|
|
76
|
+
withPrivilegedWriter(db, () => {
|
|
77
|
+
calls++;
|
|
78
|
+
db.exec("INSERT INTO result VALUES ('partial')");
|
|
79
|
+
throw Object.assign(new Error("after acquisition"), { code: "SQLITE_BUSY" });
|
|
80
|
+
}),
|
|
81
|
+
).toThrow("after acquisition");
|
|
82
|
+
expect(calls).toBe(1);
|
|
83
|
+
expect(db.prepare("SELECT * FROM result").all()).toEqual([]);
|
|
84
|
+
expect(wait).not.toHaveBeenCalled();
|
|
85
|
+
} finally {
|
|
86
|
+
db.close();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
test("recognizes Bun extended and Node numeric contention codes only", () => {
|
|
90
|
+
expect(isTransientSqliteError({ code: "SQLITE_BUSY_SNAPSHOT" })).toBe(true);
|
|
91
|
+
expect(isTransientSqliteError({ code: "ERR_SQLITE_ERROR", errcode: 5 })).toBe(true);
|
|
92
|
+
expect(isTransientSqliteError({ code: "ERR_SQLITE_ERROR", errcode: 262 })).toBe(true);
|
|
93
|
+
expect(isTransientSqliteError({ code: "SQLITE_CORRUPT" })).toBe(false);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
@@ -71,6 +71,8 @@ export interface SubagentRunOptions {
|
|
|
71
71
|
temperature?: number | undefined;
|
|
72
72
|
/** Requested output-token budget for the provider request. */
|
|
73
73
|
maxOutputTokens?: number | undefined;
|
|
74
|
+
/** Per-child cumulative prompt tokens for tool-loop dreamer tasks. */
|
|
75
|
+
tokenBudget?: number | undefined;
|
|
74
76
|
cwd?: string | undefined;
|
|
75
77
|
signal?: AbortSignal | undefined;
|
|
76
78
|
/**
|
|
@@ -208,6 +210,8 @@ export type SubagentRunResult =
|
|
|
208
210
|
| {
|
|
209
211
|
ok: false;
|
|
210
212
|
reason:
|
|
213
|
+
| "step_limit"
|
|
214
|
+
| "token_budget"
|
|
211
215
|
| "invalid_prompt"
|
|
212
216
|
| "timeout"
|
|
213
217
|
| "abort"
|
|
@@ -38,6 +38,11 @@ export const USER_FACING_FAILURES = {
|
|
|
38
38
|
sentence: "Memory maintenance stopped at its hidden agent step limit.",
|
|
39
39
|
action: "This task needs less work per run; changing the model connection will not help.",
|
|
40
40
|
},
|
|
41
|
+
dream_token_budget: {
|
|
42
|
+
code: "MC-D11",
|
|
43
|
+
sentence: "Memory maintenance reached its prompt-token budget.",
|
|
44
|
+
action: "The unfinished items will be retried on the next run.",
|
|
45
|
+
},
|
|
41
46
|
dream_empty_completion: {
|
|
42
47
|
code: "MC-D03",
|
|
43
48
|
sentence: "Memory maintenance received no usable response.",
|
|
@@ -285,6 +290,7 @@ const DREAM_FAILURE_KEYS = {
|
|
|
285
290
|
provider_timeout: "dream_provider_timeout",
|
|
286
291
|
provider_error: "dream_provider_error",
|
|
287
292
|
step_limit: "dream_step_limit",
|
|
293
|
+
token_budget: "dream_token_budget",
|
|
288
294
|
empty_completion: "dream_empty_completion",
|
|
289
295
|
no_models: "dream_no_models",
|
|
290
296
|
child_aborted: "dream_child_aborted",
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
3
|
+
import { join, relative, resolve } from "node:path";
|
|
4
|
+
import ts from "typescript";
|
|
5
|
+
|
|
6
|
+
const root = resolve(import.meta.dir, "../../../..");
|
|
7
|
+
const subprocessNames = new Set([
|
|
8
|
+
"exec",
|
|
9
|
+
"execSync",
|
|
10
|
+
"execFile",
|
|
11
|
+
"execFileSync",
|
|
12
|
+
"spawn",
|
|
13
|
+
"spawnSync",
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
function sourceFiles(dir: string): string[] {
|
|
17
|
+
return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
|
|
18
|
+
const path = join(dir, entry.name);
|
|
19
|
+
return entry.isDirectory() ? sourceFiles(path) : path.endsWith(".ts") ? [path] : [];
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function missingHiddenOptions(path: string): string[] {
|
|
24
|
+
const text = readFileSync(path, "utf8");
|
|
25
|
+
if (!/node:child_process|Bun\.spawn/.test(text)) return [];
|
|
26
|
+
const source = ts.createSourceFile(path, text, ts.ScriptTarget.Latest, true);
|
|
27
|
+
const imports = new Set<string>();
|
|
28
|
+
const variables = new Map<string, ts.Expression>();
|
|
29
|
+
for (const statement of source.statements) {
|
|
30
|
+
if (
|
|
31
|
+
ts.isImportDeclaration(statement) &&
|
|
32
|
+
statement.moduleSpecifier.getText(source).includes("node:child_process")
|
|
33
|
+
) {
|
|
34
|
+
const bindings = statement.importClause?.namedBindings;
|
|
35
|
+
if (bindings && ts.isNamedImports(bindings)) {
|
|
36
|
+
for (const element of bindings.elements) {
|
|
37
|
+
if (subprocessNames.has(element.propertyName?.text ?? element.name.text))
|
|
38
|
+
imports.add(element.name.text);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function collect(node: ts.Node): void {
|
|
44
|
+
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer)
|
|
45
|
+
variables.set(node.name.text, node.initializer);
|
|
46
|
+
ts.forEachChild(node, collect);
|
|
47
|
+
}
|
|
48
|
+
collect(source);
|
|
49
|
+
function hidden(node: ts.Expression | undefined, seen = new Set<string>()): boolean {
|
|
50
|
+
if (!node) return false;
|
|
51
|
+
if (ts.isIdentifier(node)) {
|
|
52
|
+
if (seen.has(node.text)) return false;
|
|
53
|
+
seen.add(node.text);
|
|
54
|
+
return hidden(variables.get(node.text), seen);
|
|
55
|
+
}
|
|
56
|
+
if (!ts.isObjectLiteralExpression(node)) return false;
|
|
57
|
+
// Later spreads can override an earlier flag, so inspect the effective last assignment.
|
|
58
|
+
for (const property of [...node.properties].reverse()) {
|
|
59
|
+
if (
|
|
60
|
+
ts.isPropertyAssignment(property) &&
|
|
61
|
+
property.name.getText(source) === "windowsHide"
|
|
62
|
+
) {
|
|
63
|
+
return property.initializer.kind === ts.SyntaxKind.TrueKeyword;
|
|
64
|
+
}
|
|
65
|
+
if (ts.isSpreadAssignment(property) && hidden(property.expression, new Set(seen)))
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
const failures: string[] = [];
|
|
71
|
+
function visit(node: ts.Node): void {
|
|
72
|
+
if (ts.isCallExpression(node)) {
|
|
73
|
+
const expression = node.expression;
|
|
74
|
+
let name: string | undefined;
|
|
75
|
+
if (
|
|
76
|
+
ts.isIdentifier(expression) &&
|
|
77
|
+
(imports.has(expression.text) ||
|
|
78
|
+
[
|
|
79
|
+
"execFileAsync",
|
|
80
|
+
"execFileSyncForIdentity",
|
|
81
|
+
"rpcIdentityExecFileSync",
|
|
82
|
+
"execFileForVerificationPaths",
|
|
83
|
+
].includes(expression.text) ||
|
|
84
|
+
(expression.text === "exec" && path.endsWith("rpc-utils.ts")))
|
|
85
|
+
)
|
|
86
|
+
name = expression.text;
|
|
87
|
+
if (ts.isPropertyAccessExpression(expression)) {
|
|
88
|
+
const owner = expression.expression.getText(source);
|
|
89
|
+
if (
|
|
90
|
+
owner === "Bun" &&
|
|
91
|
+
(expression.name.text === "spawn" || expression.name.text === "spawnSync")
|
|
92
|
+
)
|
|
93
|
+
name = "Bun.spawn";
|
|
94
|
+
if (
|
|
95
|
+
(owner === "deps" || owner === "this") &&
|
|
96
|
+
(subprocessNames.has(expression.name.text) ||
|
|
97
|
+
expression.name.text === "spawnImpl")
|
|
98
|
+
)
|
|
99
|
+
name = expression.name.text;
|
|
100
|
+
}
|
|
101
|
+
if (name) {
|
|
102
|
+
const index =
|
|
103
|
+
name === "Bun.spawn"
|
|
104
|
+
? node.arguments.length === 1
|
|
105
|
+
? 0
|
|
106
|
+
: 1
|
|
107
|
+
: name === "execSync" || (name === "exec" && !path.endsWith("rpc-utils.ts"))
|
|
108
|
+
? 1
|
|
109
|
+
: 2;
|
|
110
|
+
// A single-argument Bun.spawnSync({cmd, ...}) passes options as its first argument.
|
|
111
|
+
const option = node.arguments[index];
|
|
112
|
+
if (!hidden(option)) {
|
|
113
|
+
const line =
|
|
114
|
+
source.getLineAndCharacterOfPosition(node.getStart(source)).line + 1;
|
|
115
|
+
failures.push(`${relative(root, path)}:${line} ${name}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
ts.forEachChild(node, visit);
|
|
120
|
+
}
|
|
121
|
+
visit(source);
|
|
122
|
+
return failures;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
describe("Windows child processes", () => {
|
|
126
|
+
test("every plugin, Pi and CLI subprocess hides its Windows console", () => {
|
|
127
|
+
const failures = ["plugin", "pi-plugin", "cli"].flatMap((pkg) =>
|
|
128
|
+
sourceFiles(join(root, "packages", pkg, "src")).flatMap(missingHiddenOptions),
|
|
129
|
+
);
|
|
130
|
+
expect(failures).toEqual([]);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
runManagedWrapup2
|
|
3
|
-
} from "./index-cj5qe2nw.js";
|
|
4
|
-
import"./index-rdey8znw.js";
|
|
5
|
-
import"./index-sd3egckz.js";
|
|
6
|
-
import"./index-01ft0h3p.js";
|
|
7
|
-
import"./index-c906f3ff.js";
|
|
8
|
-
import"./index-2zf5fv89.js";
|
|
9
|
-
import"./index-y5145x8k.js";
|
|
10
|
-
import"./index-pye48m79.js";
|
|
11
|
-
import"./index-v6wsttqt.js";
|
|
12
|
-
import"./index-jdxxq8cz.js";
|
|
13
|
-
import"./index-dx0xnd4q.js";
|
|
14
|
-
import"./index-tjq5jztd.js";
|
|
15
|
-
import"./index-6z9g64js.js";
|
|
16
|
-
export {
|
|
17
|
-
runManagedWrapup2 as runManagedWrapup
|
|
18
|
-
};
|