@cortexkit/opencode-magic-context 0.21.7 → 0.22.0
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 +116 -325
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/agents/permissions.d.ts +29 -14
- package/dist/agents/permissions.d.ts.map +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/migrate-experimental.d.ts +29 -0
- package/dist/config/migrate-experimental.d.ts.map +1 -0
- package/dist/config/schema/magic-context.d.ts +80 -104
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/features/builtin-commands/commands.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-embedding.d.ts +34 -0
- package/dist/features/magic-context/compartment-embedding.d.ts.map +1 -0
- package/dist/features/magic-context/compartment-events.d.ts +50 -0
- package/dist/features/magic-context/compartment-events.d.ts.map +1 -0
- package/dist/features/magic-context/compartment-storage.d.ts +22 -0
- package/dist/features/magic-context/compartment-storage.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/lease.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/queue.d.ts +13 -2
- package/dist/features/magic-context/dreamer/queue.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/runner.d.ts +11 -0
- package/dist/features/magic-context/dreamer/runner.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-prompts.d.ts +1 -1
- package/dist/features/magic-context/dreamer/task-prompts.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/key-files/identify-key-files.d.ts +1 -1
- package/dist/features/magic-context/key-files/identify-key-files.d.ts.map +1 -1
- package/dist/features/magic-context/key-files/project-key-files.d.ts.map +1 -1
- package/dist/features/magic-context/key-files/read-stats.d.ts +1 -1
- package/dist/features/magic-context/key-files/read-stats.d.ts.map +1 -1
- package/dist/features/magic-context/memory/constants.d.ts +4 -0
- package/dist/features/magic-context/memory/constants.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
- package/dist/features/magic-context/memory/index.d.ts +1 -1
- package/dist/features/magic-context/memory/index.d.ts.map +1 -1
- package/dist/features/magic-context/memory/memory-migration.d.ts +133 -0
- package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -0
- package/dist/features/magic-context/memory/project-identity.d.ts +38 -7
- package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory-fts.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory.d.ts +15 -1
- package/dist/features/magic-context/memory/storage-memory.d.ts.map +1 -1
- package/dist/features/magic-context/memory/types.d.ts +3 -1
- package/dist/features/magic-context/memory/types.d.ts.map +1 -1
- package/dist/features/magic-context/message-index.d.ts.map +1 -1
- package/dist/features/magic-context/migrations.d.ts +7 -0
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/project-docs-hash.d.ts +6 -0
- package/dist/features/magic-context/project-docs-hash.d.ts.map +1 -0
- package/dist/features/magic-context/project-identity.d.ts +2 -0
- package/dist/features/magic-context/project-identity.d.ts.map +1 -0
- package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts +51 -7
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-historian-runs.d.ts +73 -0
- package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -0
- package/dist/features/magic-context/storage-identity-rekey-map.d.ts +11 -0
- package/dist/features/magic-context/storage-identity-rekey-map.d.ts.map +1 -0
- package/dist/features/magic-context/storage-m0-mutation-log.d.ts +22 -0
- package/dist/features/magic-context/storage-m0-mutation-log.d.ts.map +1 -0
- package/dist/features/magic-context/storage-memory-mutation-log.d.ts +25 -0
- package/dist/features/magic-context/storage-memory-mutation-log.d.ts.map +1 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts +5 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-shared.d.ts +44 -0
- package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta.d.ts +2 -1
- package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
- package/dist/features/magic-context/storage-project-state.d.ts +19 -0
- package/dist/features/magic-context/storage-project-state.d.ts.map +1 -0
- package/dist/features/magic-context/storage-subagent-invocations.d.ts +61 -0
- package/dist/features/magic-context/storage-subagent-invocations.d.ts.map +1 -0
- package/dist/features/magic-context/storage-tags.d.ts +21 -1
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/storage-v22-backfill-failures.d.ts +24 -0
- package/dist/features/magic-context/storage-v22-backfill-failures.d.ts.map +1 -0
- package/dist/features/magic-context/storage.d.ts +13 -3
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/subagent-token-capture.d.ts +33 -0
- package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -0
- package/dist/features/magic-context/tagger.d.ts +15 -1
- package/dist/features/magic-context/tagger.d.ts.map +1 -1
- package/dist/features/magic-context/types.d.ts +21 -0
- package/dist/features/magic-context/types.d.ts.map +1 -1
- package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
- package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
- package/dist/features/magic-context/v22-deferred-backfill.d.ts +46 -0
- package/dist/features/magic-context/v22-deferred-backfill.d.ts.map +1 -0
- package/dist/features/magic-context/work-metrics.d.ts +79 -0
- package/dist/features/magic-context/work-metrics.d.ts.map +1 -0
- package/dist/hooks/auto-update-checker/cache.d.ts.map +1 -1
- package/dist/hooks/auto-update-checker/checker.d.ts.map +1 -1
- package/dist/hooks/magic-context/cache-busting-signals.d.ts +9 -0
- package/dist/hooks/magic-context/cache-busting-signals.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +13 -1
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-parser.d.ts +25 -0
- package/dist/hooks/magic-context/compartment-parser.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-prompt.d.ts +27 -16
- package/dist/hooks/magic-context/compartment-prompt.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts +2 -0
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-mapping.d.ts +6 -2
- package/dist/hooks/magic-context/compartment-runner-mapping.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts +9 -1
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-types.d.ts +68 -4
- package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/decay-curve.d.ts +78 -0
- package/dist/hooks/magic-context/decay-curve.d.ts.map +1 -0
- package/dist/hooks/magic-context/decay-render.d.ts +67 -0
- package/dist/hooks/magic-context/decay-render.d.ts.map +1 -0
- package/dist/hooks/magic-context/event-handler.d.ts +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts +17 -0
- 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/historian-prompt.generated.d.ts +2 -0
- package/dist/hooks/magic-context/historian-prompt.generated.d.ts.map +1 -0
- package/dist/hooks/magic-context/hook-handlers.d.ts +3 -0
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +9 -21
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts +126 -0
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/key-files-block.d.ts.map +1 -1
- package/dist/hooks/magic-context/live-session-state.d.ts +9 -0
- package/dist/hooks/magic-context/live-session-state.d.ts.map +1 -1
- package/dist/hooks/magic-context/m0-token-breakdown.d.ts +35 -0
- package/dist/hooks/magic-context/m0-token-breakdown.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts +9 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts +7 -0
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/recomp-orchestrator.d.ts +104 -0
- package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -0
- package/dist/hooks/magic-context/reference-retrieval.d.ts +61 -0
- package/dist/hooks/magic-context/reference-retrieval.d.ts.map +1 -0
- package/dist/hooks/magic-context/reference-seeds.generated.d.ts +8 -0
- package/dist/hooks/magic-context/reference-seeds.generated.d.ts.map +1 -0
- package/dist/hooks/magic-context/send-session-notification.d.ts +1 -1
- package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +5 -6
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/tokenizer-calibration.d.ts +6 -0
- package/dist/hooks/magic-context/tokenizer-calibration.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts +0 -7
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +18 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +9 -7
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/upgrade-reminder.d.ts +73 -0
- package/dist/hooks/magic-context/upgrade-reminder.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22111 -16352
- package/dist/plugin/conflict-warning-hook.d.ts +13 -0
- package/dist/plugin/conflict-warning-hook.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/tool-registry.d.ts.map +1 -1
- package/dist/shared/announcement.d.ts +1 -1
- package/dist/shared/announcement.d.ts.map +1 -1
- package/dist/shared/rpc-client.d.ts +1 -0
- package/dist/shared/rpc-client.d.ts.map +1 -1
- package/dist/shared/rpc-notifications.d.ts +27 -5
- package/dist/shared/rpc-notifications.d.ts.map +1 -1
- package/dist/shared/rpc-server.d.ts +1 -0
- package/dist/shared/rpc-server.d.ts.map +1 -1
- package/dist/shared/rpc-types.d.ts +32 -2
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/rpc-utils.d.ts +9 -0
- package/dist/shared/rpc-utils.d.ts.map +1 -1
- package/dist/shared/sqlite-helpers.d.ts +7 -7
- package/dist/shared/sqlite.d.ts +23 -14
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/subagent-runner.d.ts +5 -0
- package/dist/shared/subagent-runner.d.ts.map +1 -1
- package/dist/shared/tag-transcript.d.ts +10 -1
- package/dist/shared/tag-transcript.d.ts.map +1 -1
- package/dist/tools/ctx-expand/tools.d.ts +5 -1
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
- package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
- package/dist/tui/data/context-db.d.ts +16 -1
- package/dist/tui/data/context-db.d.ts.map +1 -1
- package/package.json +2 -4
- package/src/shared/announcement.ts +6 -7
- package/src/shared/rpc-client.test.ts +49 -2
- package/src/shared/rpc-client.ts +19 -9
- package/src/shared/rpc-notifications.test.ts +54 -1
- package/src/shared/rpc-notifications.ts +82 -13
- package/src/shared/rpc-server.ts +33 -4
- package/src/shared/rpc-types.ts +32 -2
- package/src/shared/rpc-utils.ts +10 -0
- package/src/shared/sqlite-helpers.ts +9 -9
- package/src/shared/sqlite.ts +99 -80
- package/src/shared/subagent-runner.ts +14 -0
- package/src/shared/tag-transcript.test.ts +280 -0
- package/src/shared/tag-transcript.ts +162 -33
- package/src/tui/data/context-db.ts +77 -11
- package/src/tui/index.tsx +240 -57
- package/src/tui/slots/sidebar-content.tsx +415 -101
- package/dist/hooks/magic-context/compartment-runner-compressor.d.ts +0 -87
- package/dist/hooks/magic-context/compartment-runner-compressor.d.ts.map +0 -1
- package/dist/shared/native-binding.d.ts +0 -87
- package/dist/shared/native-binding.d.ts.map +0 -1
- package/src/shared/native-binding.ts +0 -311
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import type { Compartment } from "../../features/magic-context/compartment-storage";
|
|
2
|
-
import type { PluginContext } from "../../plugin/types";
|
|
3
|
-
import type { Database } from "../../shared/sqlite";
|
|
4
|
-
export interface CompressorDeps {
|
|
5
|
-
client: PluginContext["client"];
|
|
6
|
-
db: Database;
|
|
7
|
-
sessionId: string;
|
|
8
|
-
directory: string;
|
|
9
|
-
historyBudgetTokens: number;
|
|
10
|
-
historianTimeoutMs?: number;
|
|
11
|
-
fallbackModels?: readonly string[];
|
|
12
|
-
/** Floor = ceil(lastEndMessage / minCompartmentRatio). Default 1000. */
|
|
13
|
-
minCompartmentRatio?: number;
|
|
14
|
-
/** Maximum depth any compartment range can be compressed to. Default 5. */
|
|
15
|
-
maxMergeDepth?: number;
|
|
16
|
-
/** Cap on compartments sent to the LLM in one pass. Default 15. */
|
|
17
|
-
maxCompartmentsPerPass?: number;
|
|
18
|
-
/** Newest compartments always excluded from compression. Default 10. */
|
|
19
|
-
graceCompartments?: number;
|
|
20
|
-
/** False when historian.disable=true; compressor prompts use the historian agent. */
|
|
21
|
-
historianRunnable?: boolean;
|
|
22
|
-
/** Holder id for the DB-backed compartment-state lease guarding publish paths. */
|
|
23
|
-
compartmentLeaseHolderId?: string;
|
|
24
|
-
}
|
|
25
|
-
interface ScoredCompartment {
|
|
26
|
-
compartment: Compartment;
|
|
27
|
-
index: number;
|
|
28
|
-
tokenEstimate: number;
|
|
29
|
-
averageDepth: number;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Check if the compartment block exceeds the history budget and run a compression pass if needed.
|
|
33
|
-
* Returns true if compression ran successfully, false otherwise.
|
|
34
|
-
*/
|
|
35
|
-
export declare function runCompressionPassIfNeeded(deps: CompressorDeps): Promise<boolean>;
|
|
36
|
-
interface SelectionConstraints {
|
|
37
|
-
/** Max compartments to pick per pass (LLM batch cap). */
|
|
38
|
-
maxPickable: number;
|
|
39
|
-
/** Max compression depth a compartment range can reach. */
|
|
40
|
-
maxMergeDepth: number;
|
|
41
|
-
/** Number of newest compartments always excluded (grace period). */
|
|
42
|
-
graceCompartments: number;
|
|
43
|
-
/** compartments.length - floor; we can't reduce below this without violating floor. */
|
|
44
|
-
floorHeadroom: number;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Pick a contiguous same-depth band of compartments to compress next.
|
|
48
|
-
*
|
|
49
|
-
* Strategy (depth-first, oldest-within-tier):
|
|
50
|
-
* 1. Eligible scope = [0, scored.length - graceCompartments).
|
|
51
|
-
* Newest `graceCompartments` are never compressed (protects just-published
|
|
52
|
-
* historian output).
|
|
53
|
-
* 2. Within eligible scope, ignore compartments whose rounded depth is
|
|
54
|
-
* already at `maxMergeDepth` — they're done.
|
|
55
|
-
* 3. Find the **minimum** depth tier that still exists in scope.
|
|
56
|
-
* 4. Anchor on the **oldest** compartment at that minimum depth (lowest
|
|
57
|
-
* index). Extend forward while the next compartment has the same rounded
|
|
58
|
-
* depth, stopping at maxPickable / floorHeadroom / scope end.
|
|
59
|
-
* 5. Require runLen ≥ 2. If the oldest minimum-depth compartment can't form
|
|
60
|
-
* a run (neighbor has a different depth), the algorithm would stall —
|
|
61
|
-
* so fall back to finding the *next* oldest compartment at minDepth and
|
|
62
|
-
* retry. This preserves the old "skip singleton and move on" safety
|
|
63
|
-
* without abandoning the min-depth invariant.
|
|
64
|
-
*
|
|
65
|
-
* Why this shape:
|
|
66
|
-
* The previous algorithm was oldest-first regardless of depth. After the
|
|
67
|
-
* first pass compressed seq 0-14 to depth 1, the next pass picked seq 0-X
|
|
68
|
-
* AGAIN because they were still the oldest. The cascade ran depth 0→1→2→
|
|
69
|
-
* 3→4→5 on the same range within hours, crushing early compartments to
|
|
70
|
-
* empty title-only shells while the rest of history stayed at depth 0.
|
|
71
|
-
*
|
|
72
|
-
* Depth-first selection means: once seq 0-14 reach depth 1, the next pass
|
|
73
|
-
* prefers any depth-0 band elsewhere (seq 15+) before touching seq 0-14
|
|
74
|
-
* again. Old→new gets pushed down one tier at a time, producing a smooth
|
|
75
|
-
* depth gradient (old = deeper, recent = shallower) like memory decay.
|
|
76
|
-
*
|
|
77
|
-
* Grace window still protects the newest N from compression entirely so
|
|
78
|
-
* freshly-published historian output has time to settle.
|
|
79
|
-
*/
|
|
80
|
-
export declare function selectCompressionBand(scored: ScoredCompartment[], constraints: SelectionConstraints): ScoredCompartment[];
|
|
81
|
-
/**
|
|
82
|
-
* @deprecated Use {@link selectCompressionBand}. Kept as an export for the
|
|
83
|
-
* existing test suite that targets the older naming; semantics are identical.
|
|
84
|
-
*/
|
|
85
|
-
export declare const findOldestContiguousSameDepthBand: typeof selectCompressionBand;
|
|
86
|
-
export {};
|
|
87
|
-
//# sourceMappingURL=compartment-runner-compressor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compartment-runner-compressor.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/compartment-runner-compressor.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAC;AASpF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAcpD,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChC,EAAE,EAAE,QAAQ,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,wEAAwE;IACxE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,2EAA2E;IAC3E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qFAAqF;IACrF,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kFAAkF;IAClF,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACrC;AAaD,UAAU,iBAAiB;IACvB,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CA+LvF;AAiCD,UAAU,oBAAoB;IAC1B,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,aAAa,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,aAAa,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,qBAAqB,CACjC,MAAM,EAAE,iBAAiB,EAAE,EAC3B,WAAW,EAAE,oBAAoB,GAClC,iBAAiB,EAAE,CA4DrB;AAED;;;GAGG;AACH,eAAO,MAAM,iCAAiC,8BAAwB,CAAC"}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Native-binding resolver for Electron-runtime mismatches.
|
|
3
|
-
*
|
|
4
|
-
* Why this module exists
|
|
5
|
-
* ----------------------
|
|
6
|
-
* `better-sqlite3` uses raw v8/nan bindings, so its compiled `.node` file is
|
|
7
|
-
* locked to a specific NODE_MODULE_VERSION (Node-API ABI revision). When
|
|
8
|
-
* OpenCode Desktop (Electron 41 → ABI 145) loads a plugin whose `node_modules`
|
|
9
|
-
* was populated by `bun install` / `npm install` under a different runtime,
|
|
10
|
-
* the fetched prebuild is for `node-vNNN` (e.g. ABI 137 for Node 22) and
|
|
11
|
-
* Electron refuses to load it with:
|
|
12
|
-
*
|
|
13
|
-
* The module '...better_sqlite3.node' was compiled against a different
|
|
14
|
-
* Node.js version using NODE_MODULE_VERSION 137. This version of Node.js
|
|
15
|
-
* requires NODE_MODULE_VERSION 145.
|
|
16
|
-
*
|
|
17
|
-
* `onnxruntime-node` (used by `@huggingface/transformers` for local
|
|
18
|
-
* embeddings) is N-API v3 and is ABI-stable across runtimes, so it does NOT
|
|
19
|
-
* have this problem. Only `better-sqlite3` is affected.
|
|
20
|
-
*
|
|
21
|
-
* What this does
|
|
22
|
-
* --------------
|
|
23
|
-
* On plugin load, before constructing any `Database`:
|
|
24
|
-
*
|
|
25
|
-
* 1. If we are NOT running under Electron (`process.versions.electron` is
|
|
26
|
-
* unset), return null. Bun uses `bun:sqlite` and never reaches this code;
|
|
27
|
-
* Pi/Node-CLI install matching Node-vNNN prebuilds via npm, which work
|
|
28
|
-
* natively against the on-disk binary.
|
|
29
|
-
*
|
|
30
|
-
* 2. If we ARE on Electron, locate the `.node` file path that
|
|
31
|
-
* `better-sqlite3`'s default `bindings()` lookup would try first. Probe
|
|
32
|
-
* its ABI by attempting a sandboxed `process.dlopen`. If it succeeds
|
|
33
|
-
* (Electron-compatible), return null — the default lookup will work.
|
|
34
|
-
*
|
|
35
|
-
* 3. Otherwise, look for a cached Electron prebuild at
|
|
36
|
-
* `<XDG_CACHE_HOME>/cortexkit/native-bindings/better-sqlite3/v<version>/electron-v<abi>-<platform>-<arch>/better_sqlite3.node`.
|
|
37
|
-
* Download it from the `WiseLibs/better-sqlite3` GitHub release if
|
|
38
|
-
* missing, extract with `nanotar` (pure-JS, ~45 KB, zero deps), validate
|
|
39
|
-
* the ABI, and return the absolute path.
|
|
40
|
-
*
|
|
41
|
-
* The caller (`sqlite.ts`) then passes this path through `better-sqlite3`'s
|
|
42
|
-
* documented `nativeBinding` constructor option:
|
|
43
|
-
*
|
|
44
|
-
* new Database(filename, { nativeBinding: <our cached path> })
|
|
45
|
-
*
|
|
46
|
-
* `better-sqlite3` calls `require()` directly on that path, bypassing the
|
|
47
|
-
* normal `bindings()` lookup chain. This is a first-class API the maintainer
|
|
48
|
-
* added for exactly this kind of cross-runtime extension scenario — see
|
|
49
|
-
* `node_modules/better-sqlite3/lib/database.js` `nativeBinding` handling.
|
|
50
|
-
*
|
|
51
|
-
* Why we don't replace the on-disk binary
|
|
52
|
-
* ---------------------------------------
|
|
53
|
-
* An earlier iteration copied the cached Electron binary over the in-tree
|
|
54
|
-
* `node_modules/.../better_sqlite3.node`. That worked but mutates a shared
|
|
55
|
-
* resource: in monorepo dev setups (or any case where multiple runtimes
|
|
56
|
-
* share one `node_modules`), a Pi process opening the plugin from the same
|
|
57
|
-
* workspace would then load the Electron-ABI binary and fail. Returning a
|
|
58
|
-
* separate cached path keeps the on-disk file untouched so each runtime
|
|
59
|
-
* sees the binary it needs.
|
|
60
|
-
*
|
|
61
|
-
* Failure modes
|
|
62
|
-
* -------------
|
|
63
|
-
* If GitHub is unreachable (corporate firewall, offline laptop, rate limit)
|
|
64
|
-
* AND no cached binary exists, this throws. The caller (sqlite.ts →
|
|
65
|
-
* openDatabase) surfaces a `storage unavailable` error and Magic Context
|
|
66
|
-
* disables itself for the run. The user can connect to the network and
|
|
67
|
-
* restart, or wait for a cached binary from a previous successful launch.
|
|
68
|
-
*/
|
|
69
|
-
/**
|
|
70
|
-
* Resolve the absolute path to a `better-sqlite3` `.node` binary that the
|
|
71
|
-
* current runtime can load.
|
|
72
|
-
*
|
|
73
|
-
* - Returns `null` outside Electron (Bun uses `bun:sqlite`; Pi/Node CLI
|
|
74
|
-
* loads matching prebuilds from `node_modules` natively).
|
|
75
|
-
* - Returns `null` on Electron when the on-disk binary already matches
|
|
76
|
-
* the runtime's ABI (rare but possible — a future OpenCode build that
|
|
77
|
-
* post-install-rebuilds for Electron would hit this fast path).
|
|
78
|
-
* - Returns the cached/downloaded prebuild path on Electron when the
|
|
79
|
-
* on-disk binary's ABI doesn't match.
|
|
80
|
-
*
|
|
81
|
-
* The returned path is suitable as the `nativeBinding` option to
|
|
82
|
-
* `new Database(filename, { nativeBinding })`. better-sqlite3 calls `require()`
|
|
83
|
-
* directly on it, bypassing the default `bindings()` lookup chain — this is
|
|
84
|
-
* a documented public API in better-sqlite3, not an internal hack.
|
|
85
|
-
*/
|
|
86
|
-
export declare function resolveBetterSqliteNativeBinding(): Promise<string | null>;
|
|
87
|
-
//# sourceMappingURL=native-binding.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"native-binding.d.ts","sourceRoot":"","sources":["../../src/shared/native-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AA2IH;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuF/E"}
|
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Native-binding resolver for Electron-runtime mismatches.
|
|
3
|
-
*
|
|
4
|
-
* Why this module exists
|
|
5
|
-
* ----------------------
|
|
6
|
-
* `better-sqlite3` uses raw v8/nan bindings, so its compiled `.node` file is
|
|
7
|
-
* locked to a specific NODE_MODULE_VERSION (Node-API ABI revision). When
|
|
8
|
-
* OpenCode Desktop (Electron 41 → ABI 145) loads a plugin whose `node_modules`
|
|
9
|
-
* was populated by `bun install` / `npm install` under a different runtime,
|
|
10
|
-
* the fetched prebuild is for `node-vNNN` (e.g. ABI 137 for Node 22) and
|
|
11
|
-
* Electron refuses to load it with:
|
|
12
|
-
*
|
|
13
|
-
* The module '...better_sqlite3.node' was compiled against a different
|
|
14
|
-
* Node.js version using NODE_MODULE_VERSION 137. This version of Node.js
|
|
15
|
-
* requires NODE_MODULE_VERSION 145.
|
|
16
|
-
*
|
|
17
|
-
* `onnxruntime-node` (used by `@huggingface/transformers` for local
|
|
18
|
-
* embeddings) is N-API v3 and is ABI-stable across runtimes, so it does NOT
|
|
19
|
-
* have this problem. Only `better-sqlite3` is affected.
|
|
20
|
-
*
|
|
21
|
-
* What this does
|
|
22
|
-
* --------------
|
|
23
|
-
* On plugin load, before constructing any `Database`:
|
|
24
|
-
*
|
|
25
|
-
* 1. If we are NOT running under Electron (`process.versions.electron` is
|
|
26
|
-
* unset), return null. Bun uses `bun:sqlite` and never reaches this code;
|
|
27
|
-
* Pi/Node-CLI install matching Node-vNNN prebuilds via npm, which work
|
|
28
|
-
* natively against the on-disk binary.
|
|
29
|
-
*
|
|
30
|
-
* 2. If we ARE on Electron, locate the `.node` file path that
|
|
31
|
-
* `better-sqlite3`'s default `bindings()` lookup would try first. Probe
|
|
32
|
-
* its ABI by attempting a sandboxed `process.dlopen`. If it succeeds
|
|
33
|
-
* (Electron-compatible), return null — the default lookup will work.
|
|
34
|
-
*
|
|
35
|
-
* 3. Otherwise, look for a cached Electron prebuild at
|
|
36
|
-
* `<XDG_CACHE_HOME>/cortexkit/native-bindings/better-sqlite3/v<version>/electron-v<abi>-<platform>-<arch>/better_sqlite3.node`.
|
|
37
|
-
* Download it from the `WiseLibs/better-sqlite3` GitHub release if
|
|
38
|
-
* missing, extract with `nanotar` (pure-JS, ~45 KB, zero deps), validate
|
|
39
|
-
* the ABI, and return the absolute path.
|
|
40
|
-
*
|
|
41
|
-
* The caller (`sqlite.ts`) then passes this path through `better-sqlite3`'s
|
|
42
|
-
* documented `nativeBinding` constructor option:
|
|
43
|
-
*
|
|
44
|
-
* new Database(filename, { nativeBinding: <our cached path> })
|
|
45
|
-
*
|
|
46
|
-
* `better-sqlite3` calls `require()` directly on that path, bypassing the
|
|
47
|
-
* normal `bindings()` lookup chain. This is a first-class API the maintainer
|
|
48
|
-
* added for exactly this kind of cross-runtime extension scenario — see
|
|
49
|
-
* `node_modules/better-sqlite3/lib/database.js` `nativeBinding` handling.
|
|
50
|
-
*
|
|
51
|
-
* Why we don't replace the on-disk binary
|
|
52
|
-
* ---------------------------------------
|
|
53
|
-
* An earlier iteration copied the cached Electron binary over the in-tree
|
|
54
|
-
* `node_modules/.../better_sqlite3.node`. That worked but mutates a shared
|
|
55
|
-
* resource: in monorepo dev setups (or any case where multiple runtimes
|
|
56
|
-
* share one `node_modules`), a Pi process opening the plugin from the same
|
|
57
|
-
* workspace would then load the Electron-ABI binary and fail. Returning a
|
|
58
|
-
* separate cached path keeps the on-disk file untouched so each runtime
|
|
59
|
-
* sees the binary it needs.
|
|
60
|
-
*
|
|
61
|
-
* Failure modes
|
|
62
|
-
* -------------
|
|
63
|
-
* If GitHub is unreachable (corporate firewall, offline laptop, rate limit)
|
|
64
|
-
* AND no cached binary exists, this throws. The caller (sqlite.ts →
|
|
65
|
-
* openDatabase) surfaces a `storage unavailable` error and Magic Context
|
|
66
|
-
* disables itself for the run. The user can connect to the network and
|
|
67
|
-
* restart, or wait for a cached binary from a previous successful launch.
|
|
68
|
-
*/
|
|
69
|
-
|
|
70
|
-
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
71
|
-
import { createRequire } from "node:module";
|
|
72
|
-
import * as path from "node:path";
|
|
73
|
-
import { parseTarGzip } from "nanotar";
|
|
74
|
-
import { getCacheDir } from "./data-path";
|
|
75
|
-
import { log } from "./logger";
|
|
76
|
-
|
|
77
|
-
const PREFIX = "[native-binding]";
|
|
78
|
-
|
|
79
|
-
function logInfo(message: string): void {
|
|
80
|
-
log(`${PREFIX} ${message}`);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function logWarn(message: string): void {
|
|
84
|
-
log(`${PREFIX} WARN ${message}`);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Result of probing a `.node` file's ABI by attempting a sandboxed `dlopen`.
|
|
89
|
-
*
|
|
90
|
-
* - `ok: true` means the runtime accepted the binary; the on-disk file is
|
|
91
|
-
* already Electron-compatible and we don't need to do anything.
|
|
92
|
-
* - `ok: false` carries the parsed `actual` ABI for diagnostics (or `null`
|
|
93
|
-
* if the error message didn't match any known shape).
|
|
94
|
-
*/
|
|
95
|
-
type ProbeResult = { ok: true } | { ok: false; expected: string; actual: string | null };
|
|
96
|
-
|
|
97
|
-
function probeAbi(binaryPath: string): ProbeResult {
|
|
98
|
-
const expected = process.versions.modules;
|
|
99
|
-
try {
|
|
100
|
-
// Throwaway sandbox: process.dlopen runs the module's init function
|
|
101
|
-
// against `sandbox.exports`. On ABI mismatch it throws BEFORE init
|
|
102
|
-
// runs, so the binary is NOT loaded into process memory in the
|
|
103
|
-
// failure case. On success the binary IS loaded (Node refcounts
|
|
104
|
-
// these, so a second dlopen by the real `require()` is cheap).
|
|
105
|
-
const sandbox = { exports: {} as Record<string, unknown> };
|
|
106
|
-
process.dlopen(sandbox, binaryPath);
|
|
107
|
-
return { ok: true };
|
|
108
|
-
} catch (err) {
|
|
109
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
110
|
-
const pair = message.match(/NODE_MODULE_VERSION (\d+).*NODE_MODULE_VERSION (\d+)/s);
|
|
111
|
-
if (pair?.[1] && pair[2]) {
|
|
112
|
-
return { ok: false, expected: pair[2], actual: pair[1] };
|
|
113
|
-
}
|
|
114
|
-
const single = message.match(/NODE_MODULE_VERSION[ =:]+(\d+)/);
|
|
115
|
-
if (single?.[1]) {
|
|
116
|
-
return { ok: false, expected, actual: single[1] };
|
|
117
|
-
}
|
|
118
|
-
// Couldn't parse — log raw message so we can refine the regex if a
|
|
119
|
-
// future runtime emits a different shape.
|
|
120
|
-
logWarn(`could not parse ABI from dlopen error: ${message}`);
|
|
121
|
-
return { ok: false, expected, actual: null };
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Locate the on-disk path `better-sqlite3` ships its `.node` file at, plus
|
|
127
|
-
* the package version. Returns null if better-sqlite3 isn't resolvable —
|
|
128
|
-
* that's a broken install we let propagate naturally through the dynamic
|
|
129
|
-
* import in sqlite.ts.
|
|
130
|
-
*/
|
|
131
|
-
function resolveBetterSqlite3OnDisk(
|
|
132
|
-
requireFn: NodeRequire,
|
|
133
|
-
): { binaryPath: string; pkgVersion: string } | null {
|
|
134
|
-
try {
|
|
135
|
-
const pkgJsonPath = requireFn.resolve("better-sqlite3/package.json");
|
|
136
|
-
const pkgDir = path.dirname(pkgJsonPath);
|
|
137
|
-
const pkgJson = requireFn(pkgJsonPath) as { version: string };
|
|
138
|
-
const binaryPath = path.join(pkgDir, "build", "Release", "better_sqlite3.node");
|
|
139
|
-
return { binaryPath, pkgVersion: pkgJson.version };
|
|
140
|
-
} catch (err) {
|
|
141
|
-
logWarn(
|
|
142
|
-
`could not resolve better-sqlite3 in node_modules: ${err instanceof Error ? err.message : String(err)}`,
|
|
143
|
-
);
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Cache directory for downloaded native bindings. Keyed by
|
|
150
|
-
* `<pkgVersion>/electron-v<abi>-<platform>-<arch>` so a Magic Context update
|
|
151
|
-
* that bumps better-sqlite3 or an OpenCode update that bumps Electron both
|
|
152
|
-
* trigger a fresh download cleanly.
|
|
153
|
-
*/
|
|
154
|
-
function getCachedBinaryPath(pkgVersion: string, abi: string): string {
|
|
155
|
-
return path.join(
|
|
156
|
-
getCacheDir(),
|
|
157
|
-
"cortexkit",
|
|
158
|
-
"native-bindings",
|
|
159
|
-
"better-sqlite3",
|
|
160
|
-
`v${pkgVersion}`,
|
|
161
|
-
`electron-v${abi}-${process.platform}-${process.arch}`,
|
|
162
|
-
"better_sqlite3.node",
|
|
163
|
-
);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Download the Electron-targeted prebuild tarball from WiseLibs/better-sqlite3
|
|
168
|
-
* GitHub releases and extract the `.node` bytes. Throws on HTTP failure or
|
|
169
|
-
* if the tarball doesn't contain the expected file.
|
|
170
|
-
*/
|
|
171
|
-
async function downloadElectronPrebuild(pkgVersion: string, abi: string): Promise<Uint8Array> {
|
|
172
|
-
const filename = `better-sqlite3-v${pkgVersion}-electron-v${abi}-${process.platform}-${process.arch}.tar.gz`;
|
|
173
|
-
const url = `https://github.com/WiseLibs/better-sqlite3/releases/download/v${pkgVersion}/${filename}`;
|
|
174
|
-
logInfo(`downloading ${url}`);
|
|
175
|
-
|
|
176
|
-
const response = await fetch(url, {
|
|
177
|
-
redirect: "follow",
|
|
178
|
-
headers: { "User-Agent": "magic-context-plugin/native-binding" },
|
|
179
|
-
});
|
|
180
|
-
if (!response.ok) {
|
|
181
|
-
throw new Error(
|
|
182
|
-
`failed to download Electron prebuild (HTTP ${response.status} ${response.statusText}) from ${url}`,
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const tarballBytes = new Uint8Array(await response.arrayBuffer());
|
|
187
|
-
logInfo(`downloaded ${(tarballBytes.length / 1024).toFixed(1)} KB; extracting`);
|
|
188
|
-
|
|
189
|
-
const files = await parseTarGzip(tarballBytes);
|
|
190
|
-
const nodeFile = files.find((f) => f.name.endsWith("better_sqlite3.node"));
|
|
191
|
-
if (!nodeFile?.data) {
|
|
192
|
-
const names = files.map((f) => f.name).join(", ");
|
|
193
|
-
throw new Error(
|
|
194
|
-
`Electron prebuild tarball did not contain better_sqlite3.node; got: [${names}]`,
|
|
195
|
-
);
|
|
196
|
-
}
|
|
197
|
-
return nodeFile.data instanceof Uint8Array ? nodeFile.data : new Uint8Array(nodeFile.data);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Singleton promise so concurrent callers (multiple plugin init paths in the
|
|
202
|
-
* same process) only do the check + download once. Reset to null after
|
|
203
|
-
* completion so a future call can retry on transient failures.
|
|
204
|
-
*/
|
|
205
|
-
let inFlight: Promise<string | null> | null = null;
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Resolve the absolute path to a `better-sqlite3` `.node` binary that the
|
|
209
|
-
* current runtime can load.
|
|
210
|
-
*
|
|
211
|
-
* - Returns `null` outside Electron (Bun uses `bun:sqlite`; Pi/Node CLI
|
|
212
|
-
* loads matching prebuilds from `node_modules` natively).
|
|
213
|
-
* - Returns `null` on Electron when the on-disk binary already matches
|
|
214
|
-
* the runtime's ABI (rare but possible — a future OpenCode build that
|
|
215
|
-
* post-install-rebuilds for Electron would hit this fast path).
|
|
216
|
-
* - Returns the cached/downloaded prebuild path on Electron when the
|
|
217
|
-
* on-disk binary's ABI doesn't match.
|
|
218
|
-
*
|
|
219
|
-
* The returned path is suitable as the `nativeBinding` option to
|
|
220
|
-
* `new Database(filename, { nativeBinding })`. better-sqlite3 calls `require()`
|
|
221
|
-
* directly on it, bypassing the default `bindings()` lookup chain — this is
|
|
222
|
-
* a documented public API in better-sqlite3, not an internal hack.
|
|
223
|
-
*/
|
|
224
|
-
export async function resolveBetterSqliteNativeBinding(): Promise<string | null> {
|
|
225
|
-
if (!process.versions.electron) {
|
|
226
|
-
return null;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (inFlight) {
|
|
230
|
-
return inFlight;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const promise = (async () => {
|
|
234
|
-
const expected = process.versions.modules;
|
|
235
|
-
logInfo(
|
|
236
|
-
`Electron detected (v${process.versions.electron}, NODE_MODULE_VERSION ${expected}); verifying better-sqlite3 binding`,
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
const requireFn = createRequire(import.meta.url);
|
|
240
|
-
const resolved = resolveBetterSqlite3OnDisk(requireFn);
|
|
241
|
-
if (!resolved) {
|
|
242
|
-
return null;
|
|
243
|
-
}
|
|
244
|
-
const { binaryPath: diskPath, pkgVersion } = resolved;
|
|
245
|
-
|
|
246
|
-
// Fast path: if the on-disk binary already matches the runtime's
|
|
247
|
-
// ABI, we don't need to override the lookup at all. This handles
|
|
248
|
-
// any future OpenCode build that rebuilds native modules for
|
|
249
|
-
// Electron at install time, plus the case where the user manually
|
|
250
|
-
// ran `prebuild-install --runtime=electron`.
|
|
251
|
-
if (existsSync(diskPath)) {
|
|
252
|
-
const diskProbe = probeAbi(diskPath);
|
|
253
|
-
if (diskProbe.ok) {
|
|
254
|
-
logInfo(
|
|
255
|
-
`on-disk binary already matches Electron ABI v${expected}; using default bindings() lookup`,
|
|
256
|
-
);
|
|
257
|
-
return null;
|
|
258
|
-
}
|
|
259
|
-
logInfo(
|
|
260
|
-
`on-disk binary ABI ${diskProbe.actual ?? "unknown"} != required ${expected}; will use Electron prebuild`,
|
|
261
|
-
);
|
|
262
|
-
} else {
|
|
263
|
-
logWarn(
|
|
264
|
-
`expected better-sqlite3 binary not found at ${diskPath}; will fetch Electron prebuild anyway`,
|
|
265
|
-
);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// Look for a cached Electron prebuild from a previous launch.
|
|
269
|
-
const cachedPath = getCachedBinaryPath(pkgVersion, expected);
|
|
270
|
-
if (existsSync(cachedPath)) {
|
|
271
|
-
const cachedProbe = probeAbi(cachedPath);
|
|
272
|
-
if (cachedProbe.ok) {
|
|
273
|
-
logInfo(`using cached Electron prebuild at ${cachedPath}`);
|
|
274
|
-
return cachedPath;
|
|
275
|
-
}
|
|
276
|
-
logWarn(
|
|
277
|
-
`cached binary at ${cachedPath} has wrong ABI (${cachedProbe.actual ?? "unknown"} != ${expected}); refetching`,
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// Download fresh.
|
|
282
|
-
mkdirSync(path.dirname(cachedPath), { recursive: true });
|
|
283
|
-
const nodeFileBytes = await downloadElectronPrebuild(pkgVersion, expected);
|
|
284
|
-
writeFileSync(cachedPath, nodeFileBytes);
|
|
285
|
-
logInfo(
|
|
286
|
-
`cached Electron prebuild at ${cachedPath} (${(nodeFileBytes.length / 1024).toFixed(1)} KB)`,
|
|
287
|
-
);
|
|
288
|
-
|
|
289
|
-
// Validate the freshly downloaded binary before returning it — if
|
|
290
|
-
// the upstream tarball was malformed or for the wrong ABI, fail
|
|
291
|
-
// loudly here rather than letting the better-sqlite3 constructor
|
|
292
|
-
// throw a less actionable error later.
|
|
293
|
-
const finalProbe = probeAbi(cachedPath);
|
|
294
|
-
if (!finalProbe.ok) {
|
|
295
|
-
throw new Error(
|
|
296
|
-
`downloaded Electron prebuild has wrong ABI (${finalProbe.actual ?? "unknown"} != ${expected}); refusing to use`,
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return cachedPath;
|
|
301
|
-
})();
|
|
302
|
-
|
|
303
|
-
inFlight = promise;
|
|
304
|
-
try {
|
|
305
|
-
return await promise;
|
|
306
|
-
} finally {
|
|
307
|
-
if (inFlight === promise) {
|
|
308
|
-
inFlight = null;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|