@cortexkit/pi-magic-context 0.49.12 → 0.49.14

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.
Files changed (32) hide show
  1. package/dist/auto-search-worker.js +3 -3
  2. package/dist/chunk-embedding-write-worker.js +87 -0
  3. package/dist/{embedding-backfill-14tqcfrn.js → embedding-backfill-7kj16fh9.js} +5 -4
  4. package/dist/embedding-worker.js +1 -1
  5. package/dist/historian-calibration-extension.js +1 -1
  6. package/dist/{index-gykw2zhn.js → index-0awvkeb5.js} +5 -5
  7. package/dist/index-1mrvw9en.js +225 -0
  8. package/dist/index-1vw4f2pe.js +907 -0
  9. package/dist/{index-zapgkmp7.js → index-65kty5te.js} +37 -48
  10. package/dist/{index-53xdqb3d.js → index-75ah9413.js} +1 -1
  11. package/dist/{index-af9nb5db.js → index-7qc73yk5.js} +60 -3
  12. package/dist/{index-xpsht877.js → index-7wagp5jp.js} +2 -2
  13. package/dist/{index-6hex51s9.js → index-a4pk5yv9.js} +2 -2
  14. package/dist/{index-z5ftst3e.js → index-ccsscaap.js} +3 -3
  15. package/dist/{index-ed9d2ded.js → index-j0n09wtp.js} +4 -1
  16. package/dist/{index-f6e8jsrh.js → index-nwbhe6qv.js} +188 -241
  17. package/dist/{index-xmdkde4v.js → index-y29y2j2w.js} +12 -1
  18. package/dist/index.js +2398 -2068
  19. package/dist/{message-index-bounded-ws37m1nt.js → message-index-bounded-z4d3x9ty.js} +4 -4
  20. package/dist/{message-index-dfs6k35a.js → message-index-dw4z9efj.js} +4 -4
  21. package/dist/migration-worker.js +2 -2
  22. package/dist/{project-embedding-registry-ymvne11v.js → project-embedding-registry-52zwmtbn.js} +4 -3
  23. package/dist/raw-ordinal-warmup-worker.js +3 -3
  24. package/dist/{read-session-chunk-83864b37.js → read-session-chunk-0fsgg2k1.js} +2 -2
  25. package/dist/{search-85e21wb8.js → search-ddbz6v60.js} +12 -11
  26. package/dist/{storage-tags-zmf30zqp.js → storage-tags-3kb5tvgg.js} +3 -1
  27. package/dist/subagent-entry.js +12 -11
  28. package/dist/tag-snapshot-worker-pi.js +235 -0
  29. package/package.json +3 -3
  30. /package/dist/{index-j24916mq.js → index-9jvktm7k.js} +0 -0
  31. /package/dist/{index-69vas84q.js → index-b7p25tm0.js} +0 -0
  32. /package/dist/{index-3cnarwf8.js → index-bet4sd3e.js} +0 -0
@@ -1,16 +1,6 @@
1
- import {
2
- getHarness2
3
- } from "./index-0h2mkab2.js";
4
- import {
5
- sanitizeDiagnosticText,
6
- log2
7
- } from "./index-7bqrfyny.js";
8
- import {
9
- isUserHomeDirectory,
10
- setBootQuietPeriodForTests
11
- } from "./index-6ex901g3.js";
12
1
  import {
13
2
  inRootAsyncContext2,
3
+ getSqliteDatabasePath2,
14
4
  withSqliteBackgroundWriter2,
15
5
  withoutSqliteTransformPass2,
16
6
  isTransientSqliteError2
@@ -18,6 +8,13 @@ import {
18
8
  import {
19
9
  estimateTokens
20
10
  } from "./index-g4jf772p.js";
11
+ import {
12
+ getHarness2
13
+ } from "./index-0h2mkab2.js";
14
+ import {
15
+ sanitizeDiagnosticText,
16
+ log2
17
+ } from "./index-7bqrfyny.js";
21
18
  import {
22
19
  SYNAPSE_DEFAULT_MODEL,
23
20
  isSynapseEmbeddingTruncated,
@@ -41,7 +38,7 @@ import {
41
38
  countSessionCompartmentEmbedCoverage,
42
39
  countSessionCompartmentEmbedCoveragePolite,
43
40
  countUnembeddedSessionCompartmentsPolite
44
- } from "./index-af9nb5db.js";
41
+ } from "./index-7qc73yk5.js";
45
42
  import {
46
43
  DEFAULT_LOCAL_EMBEDDING_MODEL
47
44
  } from "./index-1k729e4f.js";
@@ -51,10 +48,21 @@ import {
51
48
  getEmbeddingProviderIdentity,
52
49
  dominantEmbeddingFailure,
53
50
  LocalEmbeddingProvider
54
- } from "./index-j24916mq.js";
51
+ } from "./index-9jvktm7k.js";
52
+ import {
53
+ setBootQuietPeriodForTests
54
+ } from "./index-6ex901g3.js";
55
55
  import {
56
56
  isEmbeddingHostBusy2
57
57
  } from "./index-9p40dgkm.js";
58
+ import {
59
+ findMisScopedCompartmentChunkEmbeddingIdsForProject,
60
+ recordSessionProjectIdentity,
61
+ repairMisScopedCompartmentChunkEmbeddingsForProject,
62
+ acquireGitSweepLease,
63
+ renewGitSweepLease,
64
+ releaseGitSweepLease
65
+ } from "./index-1mrvw9en.js";
58
66
  import {
59
67
  saveEmbeddingIfHashMatches,
60
68
  getMemoryEmbedCoverage,
@@ -64,82 +72,32 @@ import {
64
72
  logSlowWriteTransaction
65
73
  } from "./index-d4dt19md.js";
66
74
 
67
- // ../plugin/src/features/magic-context/session-project-storage.ts
68
- var SESSION_CHUNK_REPAIR_BATCH_SIZE = 100;
69
- var upsertSessionProjectStatements = new WeakMap;
70
- var repairSessionChunkProjectStatements = new WeakMap;
71
- var misScopedProjectChunkStatements = new WeakMap;
72
- var MIS_SCOPED_PROJECT_CHUNK_IDS_SQL = `
73
- SELECT e.id FROM compartment_chunk_embeddings e
74
- JOIN session_projects sp ON sp.session_id = e.session_id AND sp.harness = e.harness
75
- WHERE e.project_path = ? AND sp.project_path <> e.project_path
76
- UNION ALL
77
- SELECT e.id FROM session_projects sp
78
- JOIN compartment_chunk_embeddings e ON e.session_id = sp.session_id
79
- WHERE sp.project_path = ? AND e.harness = sp.harness AND e.project_path <> sp.project_path`;
80
- function getUpsertSessionProjectStatement(db) {
81
- let stmt = upsertSessionProjectStatements.get(db);
82
- if (!stmt) {
83
- stmt = db.prepare(`INSERT INTO session_projects (session_id, harness, project_path, updated_at)
84
- VALUES (?, ?, ?, ?)
85
- ON CONFLICT(session_id, harness) DO UPDATE SET
86
- project_path = excluded.project_path,
87
- updated_at = excluded.updated_at
88
- WHERE session_projects.project_path <> excluded.project_path`);
89
- upsertSessionProjectStatements.set(db, stmt);
90
- }
91
- return stmt;
92
- }
93
- function getRepairSessionChunkProjectStatement(db) {
94
- let stmt = repairSessionChunkProjectStatements.get(db);
95
- if (!stmt) {
96
- stmt = db.prepare(`UPDATE compartment_chunk_embeddings
97
- SET project_path = ?
98
- WHERE id IN (
99
- SELECT id
100
- FROM compartment_chunk_embeddings
101
- WHERE session_id = ?
102
- AND harness = ?
103
- AND project_path <> ?
104
- LIMIT ?
105
- )`);
106
- repairSessionChunkProjectStatements.set(db, stmt);
75
+ // ../plugin/src/hooks/magic-context/embed-session-state.ts
76
+ var embedPauseBySession = new Set;
77
+ var embedRunStateBySession = new Map;
78
+ var activeEmbeddingSessions = new Map;
79
+ var autoEmbedAttemptedBySession = new Set;
80
+ var autoEmbedIdentityBySession = new Map;
81
+ var autoEmbedRetryAfterBySession = new Map;
82
+ function invalidateAutoEmbedSession(sessionId) {
83
+ autoEmbedAttemptedBySession.delete(sessionId);
84
+ autoEmbedIdentityBySession.delete(sessionId);
85
+ autoEmbedRetryAfterBySession.delete(sessionId);
86
+ }
87
+ function getEmbedDrainUiStatus(sessionId, progress) {
88
+ if (embedPauseBySession.has(sessionId)) {
89
+ return { status: "paused" };
90
+ }
91
+ const activeRun = embedRunStateBySession.get(sessionId);
92
+ if (activeRun && !activeRun.signal.aborted || progress?.kind === "embed" && progress.phase === "recomp") {
93
+ return { status: "running" };
94
+ }
95
+ if (progress?.kind === "embed" && (progress.phase === "failed" || progress.phase === "skipped") && progress.message) {
96
+ if (/provider/i.test(progress.message)) {
97
+ return { status: "stopped", detail: progress.message };
98
+ }
107
99
  }
108
- return stmt;
109
- }
110
- function findMisScopedCompartmentChunkEmbeddingIdsForProject(db, projectPath) {
111
- return db.prepare(`SELECT id FROM (${MIS_SCOPED_PROJECT_CHUNK_IDS_SQL}) LIMIT 25`).all(projectPath, projectPath).map(({ id }) => id);
112
- }
113
- function recordSessionProjectIdentity(db, sessionId, projectPath) {
114
- if (!sessionId || !projectPath)
115
- return;
116
- if (!projectPath.startsWith("git:") && !projectPath.startsWith("dir:") && isUserHomeDirectory(projectPath))
117
- return;
118
- const harness = getHarness2();
119
- const now = Date.now();
120
- let previousProjectPath;
121
- db.transaction(() => {
122
- const existing = db.prepare("SELECT project_path FROM session_projects WHERE session_id = ? AND harness = ?").get(sessionId, harness);
123
- previousProjectPath = existing?.project_path;
124
- getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
125
- getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath, SESSION_CHUNK_REPAIR_BATCH_SIZE);
126
- }).immediate();
127
- return previousProjectPath === projectPath ? undefined : { previousProjectPath, projectPath };
128
- }
129
- function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath, ids = findMisScopedCompartmentChunkEmbeddingIdsForProject(db, projectPath)) {
130
- if (!projectPath || ids.length === 0)
131
- return 0;
132
- return db.prepare(`UPDATE compartment_chunk_embeddings
133
- SET project_path = (SELECT sp.project_path FROM session_projects sp
134
- WHERE sp.session_id = compartment_chunk_embeddings.session_id
135
- AND sp.harness = compartment_chunk_embeddings.harness)
136
- WHERE id IN (${ids.map(() => "?").join(",")}) AND EXISTS (
137
- SELECT 1 FROM session_projects sp
138
- WHERE sp.session_id = compartment_chunk_embeddings.session_id
139
- AND sp.harness = compartment_chunk_embeddings.harness
140
- AND sp.project_path <> compartment_chunk_embeddings.project_path
141
- AND (sp.project_path = ? OR compartment_chunk_embeddings.project_path = ?)
142
- )`).run(...ids, projectPath, projectPath).changes;
100
+ return { status: "idle" };
143
101
  }
144
102
 
145
103
  // ../plugin/src/shared/background-batch-drain.ts
@@ -739,6 +697,84 @@ class OpenAICompatibleEmbeddingProvider {
739
697
  // ../plugin/src/features/magic-context/project-embedding-registry.ts
740
698
  import { createHash as createHash3, randomUUID } from "node:crypto";
741
699
 
700
+ // ../plugin/src/features/magic-context/chunk-embedding-writer.ts
701
+ import { Worker } from "node:worker_threads";
702
+ function createChunkEmbeddingWriter(db) {
703
+ const path = getSqliteDatabasePath2(db);
704
+ if (!path)
705
+ return null;
706
+ if (path.startsWith("file:"))
707
+ throw new Error("chunk embedding writer requires a filesystem path");
708
+ const entry = new URL(import.meta.url.endsWith(".ts") ? "./chunk-embedding-write-worker.ts" : "./chunk-embedding-write-worker.js", import.meta.url);
709
+ const timeout = db.prepare("PRAGMA busy_timeout").get().timeout;
710
+ const worker = inRootAsyncContext2(() => new Worker(entry, { workerData: { path, harness: getHarness2(), timeout } }));
711
+ let pending;
712
+ let failure;
713
+ let deadline;
714
+ worker.on("message", (reply) => {
715
+ clearTimeout(deadline);
716
+ const request = pending;
717
+ pending = undefined;
718
+ if (reply.error)
719
+ request?.reject(new Error(reply.error));
720
+ else
721
+ request?.resolve(reply.value);
722
+ });
723
+ const fail = (error) => {
724
+ clearTimeout(deadline);
725
+ failure = error;
726
+ pending?.reject(error);
727
+ pending = undefined;
728
+ };
729
+ worker.on("error", fail);
730
+ worker.on("exit", (code) => fail(new Error(`chunk embedding writer exited (${code})`)));
731
+ worker.unref();
732
+ let queue = Promise.resolve();
733
+ const request = (message) => {
734
+ const result = queue.then(() => {
735
+ if (failure)
736
+ throw failure;
737
+ return new Promise((resolve, reject) => {
738
+ pending = { resolve, reject };
739
+ deadline = inRootAsyncContext2(() => setTimeout(() => {
740
+ fail(new Error("chunk embedding database operation timed out; coverage will be rechecked"));
741
+ worker.terminate();
742
+ }, 30000));
743
+ deadline.unref();
744
+ worker.postMessage(message);
745
+ });
746
+ });
747
+ queue = result.catch(() => {});
748
+ return result;
749
+ };
750
+ return {
751
+ async replace(rows, sourceKey) {
752
+ if (rows.some((row) => isSynapseEmbeddingTruncated(row.vector)))
753
+ return;
754
+ await request({ kind: "replace", rows, sourceKey });
755
+ },
756
+ project: (project, session) => request({ kind: "project", project, session }),
757
+ count: (project, session, model, tokens) => request({ kind: "count", project, session, model, tokens }),
758
+ candidates: (project, session, model, limit, excluded, tokens) => request({
759
+ kind: "candidates",
760
+ project,
761
+ session,
762
+ model,
763
+ limit,
764
+ excluded,
765
+ tokens
766
+ }),
767
+ backoff: (candidate, project, model) => request({ kind: "backoff", candidate, project, model }),
768
+ acquire: (project, holder) => request({ kind: "acquire", project, holder }),
769
+ renew: (project, holder) => request({ kind: "renew", project, holder }),
770
+ release: (project, holder) => request({ kind: "release", project, holder }),
771
+ async close() {
772
+ clearTimeout(deadline);
773
+ await worker.terminate();
774
+ }
775
+ };
776
+ }
777
+
742
778
  // ../plugin/src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
743
779
  var saveStatements = new WeakMap;
744
780
  var loadProjectStatements = new WeakMap;
@@ -921,142 +957,6 @@ function enforceProjectCap(db, projectPath, maxCommits) {
921
957
  return evicted;
922
958
  }
923
959
 
924
- // ../plugin/src/features/magic-context/git-commits/sweep-coordinator.ts
925
- var GIT_SWEEP_COOLDOWN_MS = 10 * 60 * 1000;
926
- var GIT_SWEEP_LEASE_TTL_MS = 5 * 60 * 1000;
927
- var GIT_SWEEP_NON_INDEXABLE_REPROBE_MS = 24 * 60 * 60 * 1000;
928
- var GIT_SWEEP_LEASE_RENEWAL_MS = 60 * 1000;
929
- function runImmediate(db, body) {
930
- db.exec("BEGIN IMMEDIATE");
931
- const transactionStartedAt = performance.now();
932
- let committed = false;
933
- try {
934
- const result = body();
935
- db.exec("COMMIT");
936
- committed = true;
937
- logSlowWriteTransaction("git_sweep_lease", transactionStartedAt);
938
- return result;
939
- } finally {
940
- if (!committed) {
941
- try {
942
- db.exec("ROLLBACK");
943
- } catch {}
944
- }
945
- }
946
- }
947
- function rowToState(row) {
948
- return {
949
- projectPath: row.project_path,
950
- leaseHolder: row.lease_holder,
951
- leaseExpiresAt: row.lease_expires_at,
952
- lastSweptAt: row.last_swept_at
953
- };
954
- }
955
- function getGitSweepCoordinatorState(db, projectPath) {
956
- const row = db.prepare(`SELECT project_path, lease_holder, lease_expires_at, last_swept_at
957
- FROM git_sweep_coordinator
958
- WHERE project_path = ?`).get(projectPath);
959
- return row ? rowToState(row) : null;
960
- }
961
- function acquireGitSweepLease(db, projectPath, holderId, options = {}) {
962
- const cooldownMs = options.cooldownMs ?? GIT_SWEEP_COOLDOWN_MS;
963
- const leaseTtlMs = options.leaseTtlMs ?? GIT_SWEEP_LEASE_TTL_MS;
964
- return runImmediate(db, () => {
965
- const now = Date.now();
966
- const row = getGitSweepCoordinatorState(db, projectPath);
967
- if (row?.leaseHolder && row.leaseExpiresAt !== null && row.leaseExpiresAt > now) {
968
- return {
969
- acquired: false,
970
- projectPath,
971
- reason: "lease_active",
972
- leaseHolder: row.leaseHolder,
973
- leaseExpiresAt: row.leaseExpiresAt,
974
- lastSweptAt: row.lastSweptAt,
975
- nextAllowedAt: null
976
- };
977
- }
978
- if (!options.ignoreCooldown && row?.lastSweptAt !== null && row?.lastSweptAt !== undefined) {
979
- const nextAllowedAt = row.lastSweptAt + cooldownMs;
980
- if (nextAllowedAt > now) {
981
- return {
982
- acquired: false,
983
- projectPath,
984
- reason: "cooldown_active",
985
- leaseHolder: row.leaseHolder,
986
- leaseExpiresAt: row.leaseExpiresAt,
987
- lastSweptAt: row.lastSweptAt,
988
- nextAllowedAt
989
- };
990
- }
991
- }
992
- const leaseExpiresAt = now + leaseTtlMs;
993
- db.prepare(`INSERT INTO git_sweep_coordinator (
994
- project_path,
995
- lease_holder,
996
- lease_expires_at,
997
- last_swept_at
998
- ) VALUES (?, ?, ?, NULL)
999
- ON CONFLICT(project_path) DO UPDATE SET
1000
- lease_holder = excluded.lease_holder,
1001
- lease_expires_at = excluded.lease_expires_at`).run(projectPath, holderId, leaseExpiresAt);
1002
- return {
1003
- acquired: true,
1004
- projectPath,
1005
- holderId,
1006
- acquiredAt: now,
1007
- leaseExpiresAt
1008
- };
1009
- });
1010
- }
1011
- function renewGitSweepLease(db, projectPath, holderId, leaseTtlMs = GIT_SWEEP_LEASE_TTL_MS) {
1012
- return runImmediate(db, () => {
1013
- const now = Date.now();
1014
- const leaseExpiresAt = now + leaseTtlMs;
1015
- const result = db.prepare(`UPDATE git_sweep_coordinator
1016
- SET lease_expires_at = ?
1017
- WHERE project_path = ?
1018
- AND lease_holder = ?
1019
- AND lease_expires_at > ?`).run(leaseExpiresAt, projectPath, holderId, now);
1020
- return result.changes === 1;
1021
- });
1022
- }
1023
- function markGitSweepSuccessAndRelease(db, projectPath, holderId) {
1024
- return runImmediate(db, () => {
1025
- const now = Date.now();
1026
- const result = db.prepare(`UPDATE git_sweep_coordinator
1027
- SET lease_holder = NULL,
1028
- lease_expires_at = NULL,
1029
- last_swept_at = ?
1030
- WHERE project_path = ?
1031
- AND lease_holder = ?
1032
- AND lease_expires_at > ?`).run(now, projectPath, holderId, now);
1033
- return result.changes === 1;
1034
- });
1035
- }
1036
- function parkGitSweepNonIndexable(db, projectPath, holderId, reprobeMs = GIT_SWEEP_NON_INDEXABLE_REPROBE_MS) {
1037
- return runImmediate(db, () => {
1038
- const now = Date.now();
1039
- const sweptAt = now + reprobeMs - GIT_SWEEP_COOLDOWN_MS;
1040
- const result = db.prepare(`UPDATE git_sweep_coordinator
1041
- SET lease_holder = NULL,
1042
- lease_expires_at = NULL,
1043
- last_swept_at = ?
1044
- WHERE project_path = ?
1045
- AND lease_holder = ?
1046
- AND lease_expires_at > ?`).run(sweptAt, projectPath, holderId, now);
1047
- return result.changes === 1;
1048
- });
1049
- }
1050
- function releaseGitSweepLease(db, projectPath, holderId) {
1051
- runImmediate(db, () => {
1052
- db.prepare(`UPDATE git_sweep_coordinator
1053
- SET lease_holder = NULL,
1054
- lease_expires_at = NULL
1055
- WHERE project_path = ?
1056
- AND lease_holder = ?`).run(projectPath, holderId);
1057
- });
1058
- }
1059
-
1060
960
  // ../plugin/src/features/magic-context/shadow-backfill-state.ts
1061
961
  var SHADOW_BACKFILL_PROVENANCE_KEY = "_magicContextShadowBackfill";
1062
962
  function parseJsonRecord(value) {
@@ -2752,7 +2652,16 @@ async function embedCompartmentChunkBatch(db, projectIdentity, batchSize, signal
2752
2652
  if (!snapshot?.historyEnabled || snapshot.chunkModelId === "off")
2753
2653
  return 0;
2754
2654
  repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectIdentity);
2755
- const candidates = await loadUnembeddedCompartmentChunkCandidatesPolite(db, projectIdentity, snapshot.chunkModelId, batchSize, getProjectEmbeddingMaxInputTokens2(projectIdentity), true);
2655
+ const priorModels = db.prepare(`SELECT COUNT(*) AS total,
2656
+ COALESCE(MAX(model_id = ?), 0) AS current
2657
+ FROM compartment_chunk_embeddings WHERE compartment_id = ?`);
2658
+ const candidates = await loadUnembeddedCompartmentChunkCandidatesPolite(db, projectIdentity, snapshot.chunkModelId, batchSize, getProjectEmbeddingMaxInputTokens2(projectIdentity), true, (candidate) => {
2659
+ const activity = activeEmbeddingSessions.get(candidate.sessionId);
2660
+ if (activity?.project === projectIdentity && activity.model === snapshot.chunkModelId && !embedPauseBySession.has(candidate.sessionId))
2661
+ return true;
2662
+ const prior = priorModels.get(snapshot.chunkModelId, candidate.id);
2663
+ return prior.total === 0 || prior.current !== 0;
2664
+ });
2756
2665
  if (candidates.length === 0)
2757
2666
  return 0;
2758
2667
  const { embedded } = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates, signal);
@@ -2762,7 +2671,7 @@ function getLastEmbeddingFailureForProject(projectIdentity) {
2762
2671
  const registration = projectRegistrations.get(projectIdentity);
2763
2672
  return registration?.provider?.getLastFailureReason?.() ?? null;
2764
2673
  }
2765
- async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates, signal) {
2674
+ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates, signal, writer) {
2766
2675
  const noWork = [];
2767
2676
  const failed = [];
2768
2677
  const failureReasons = [];
@@ -2777,7 +2686,10 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
2777
2686
  continue;
2778
2687
  const canonicalText = mappedText || buildCompartmentSummaryFallbackText(db, candidate.id);
2779
2688
  if (canonicalText.length === 0) {
2780
- recordChunkEmbedBackoff(db, candidate, projectIdentity, modelId);
2689
+ if (writer)
2690
+ await writer.backoff(candidate, projectIdentity, modelId);
2691
+ else
2692
+ recordChunkEmbedBackoff(db, candidate, projectIdentity, modelId);
2781
2693
  noWork.push(candidate.id);
2782
2694
  continue;
2783
2695
  }
@@ -2834,6 +2746,8 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
2834
2746
  if (result) {
2835
2747
  let writeSliceStarted = performance.now();
2836
2748
  for (const item of slice) {
2749
+ if (signal?.aborted || getProjectChunkEmbeddingModelId2(projectIdentity) !== modelId)
2750
+ break;
2837
2751
  if (persistedIds.has(item.candidate.id))
2838
2752
  continue;
2839
2753
  const vectors = item.windows.map((window) => result.vectors.get(`chunk:${item.candidate.id}:${window.windowIndex}`));
@@ -2848,7 +2762,10 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
2848
2762
  modelId,
2849
2763
  vector: vectors[index]
2850
2764
  }));
2851
- replaceCompartmentChunkEmbeddings(db, rows, item.windowSourceKey);
2765
+ if (writer)
2766
+ await writer.replace(rows, item.windowSourceKey);
2767
+ else
2768
+ replaceCompartmentChunkEmbeddings(db, rows, item.windowSourceKey);
2852
2769
  persistedIds.add(item.candidate.id);
2853
2770
  enqueueShadowEmbeddingItems2(projectIdentity, "chunk", [
2854
2771
  String(item.candidate.id)
@@ -2873,7 +2790,10 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
2873
2790
  if (!signal?.aborted) {
2874
2791
  for (const item of slice) {
2875
2792
  if (!persistedIds.has(item.candidate.id)) {
2876
- recordChunkEmbedBackoff(db, item.candidate, projectIdentity, modelId);
2793
+ if (writer)
2794
+ await writer.backoff(item.candidate, projectIdentity, modelId);
2795
+ else
2796
+ recordChunkEmbedBackoff(db, item.candidate, projectIdentity, modelId);
2877
2797
  failed.push(item.candidate.id);
2878
2798
  }
2879
2799
  }
@@ -2928,11 +2848,28 @@ async function embedSessionCompartmentChunks2(db, projectIdentity, sessionId, op
2928
2848
  if (!snapshot?.historyEnabled || snapshot.chunkModelId === "off") {
2929
2849
  return { status: "disabled", embedded: 0, total: 0 };
2930
2850
  }
2931
- recordSessionProjectIdentity(db, sessionId, projectIdentity);
2851
+ if (options?.automatic && !options.databaseWorker) {
2852
+ const worker = createChunkEmbeddingWriter(db);
2853
+ if (worker) {
2854
+ try {
2855
+ return await embedSessionCompartmentChunks2(db, projectIdentity, sessionId, {
2856
+ ...options,
2857
+ databaseWorker: worker
2858
+ });
2859
+ } finally {
2860
+ await worker.close();
2861
+ }
2862
+ }
2863
+ }
2864
+ const writer = options?.databaseWorker ?? null;
2865
+ if (writer)
2866
+ await writer.project(projectIdentity, sessionId);
2867
+ else
2868
+ recordSessionProjectIdentity(db, sessionId, projectIdentity);
2932
2869
  const maxInputTokens = getProjectEmbeddingMaxInputTokens2(projectIdentity);
2933
- const total = await countUnembeddedSessionCompartmentsPolite(db, projectIdentity, sessionId, snapshot.chunkModelId, maxInputTokens);
2870
+ const total = writer ? await writer.count(projectIdentity, sessionId, snapshot.chunkModelId, maxInputTokens) : await countUnembeddedSessionCompartmentsPolite(db, projectIdentity, sessionId, snapshot.chunkModelId, maxInputTokens);
2934
2871
  const holderId = `session-embed-${randomUUID()}`;
2935
- const lease = acquireGitSweepLease(db, projectIdentity, holderId, { ignoreCooldown: true });
2872
+ const lease = writer ? await writer.acquire(projectIdentity, holderId) : acquireGitSweepLease(db, projectIdentity, holderId, { ignoreCooldown: true });
2936
2873
  if (!lease.acquired)
2937
2874
  return { status: "busy", embedded: 0, total };
2938
2875
  let leaseLost = false;
@@ -2942,9 +2879,9 @@ async function embedSessionCompartmentChunks2(db, projectIdentity, sessionId, op
2942
2879
  drainAbort.abort();
2943
2880
  else
2944
2881
  options?.signal?.addEventListener("abort", forwardCallerAbort, { once: true });
2945
- const renewal = inRootAsyncContext2(() => setInterval(() => {
2882
+ const renewal = inRootAsyncContext2(() => setInterval(async () => {
2946
2883
  try {
2947
- if (!renewGitSweepLease(db, projectIdentity, holderId)) {
2884
+ if (!(writer ? await writer.renew(projectIdentity, holderId) : renewGitSweepLease(db, projectIdentity, holderId))) {
2948
2885
  leaseLost = true;
2949
2886
  drainAbort.abort();
2950
2887
  }
@@ -2962,11 +2899,18 @@ async function embedSessionCompartmentChunks2(db, projectIdentity, sessionId, op
2962
2899
  try {
2963
2900
  options?.onProgress?.({ embedded, total });
2964
2901
  for (;; ) {
2965
- if (leaseLost || drainAbort.signal.aborted || isEmbeddingHostBusy2()) {
2902
+ if (leaseLost || drainAbort.signal.aborted || !options?.automatic && isEmbeddingHostBusy2() || getProjectEmbeddingSnapshot2(projectIdentity)?.generation !== snapshot.generation) {
2966
2903
  aborted = true;
2967
2904
  break;
2968
2905
  }
2969
- const candidates = await loadUnembeddedSessionChunkCandidatesPolite(db, projectIdentity, sessionId, snapshot.chunkModelId, batchSize, [...skipIds, ...failedIds], maxInputTokens, true);
2906
+ if (options?.automatic && isEmbeddingHostBusy2()) {
2907
+ await new Promise((resolve) => setTimeout(resolve, 100));
2908
+ if (drainAbort.signal.aborted) {
2909
+ aborted = true;
2910
+ break;
2911
+ }
2912
+ }
2913
+ const candidates = writer ? await writer.candidates(projectIdentity, sessionId, snapshot.chunkModelId, batchSize, [...skipIds, ...failedIds], maxInputTokens) : await loadUnembeddedSessionChunkCandidatesPolite(db, projectIdentity, sessionId, snapshot.chunkModelId, batchSize, [...skipIds, ...failedIds], maxInputTokens, true);
2970
2914
  if (candidates.length === 0)
2971
2915
  break;
2972
2916
  const {
@@ -2974,8 +2918,8 @@ async function embedSessionCompartmentChunks2(db, projectIdentity, sessionId, op
2974
2918
  noWork,
2975
2919
  failed,
2976
2920
  failureReasons: batchFailureReasons
2977
- } = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates, drainAbort.signal);
2978
- if (leaseLost || !renewGitSweepLease(db, projectIdentity, holderId)) {
2921
+ } = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates, drainAbort.signal, writer);
2922
+ if (leaseLost || !(writer ? await writer.renew(projectIdentity, holderId) : renewGitSweepLease(db, projectIdentity, holderId))) {
2979
2923
  leaseLost = true;
2980
2924
  drainAbort.abort();
2981
2925
  aborted = true;
@@ -3003,7 +2947,10 @@ async function embedSessionCompartmentChunks2(db, projectIdentity, sessionId, op
3003
2947
  clearInterval(renewal);
3004
2948
  options?.signal?.removeEventListener("abort", forwardCallerAbort);
3005
2949
  try {
3006
- releaseGitSweepLease(db, projectIdentity, holderId);
2950
+ if (writer)
2951
+ await writer.release(projectIdentity, holderId);
2952
+ else
2953
+ releaseGitSweepLease(db, projectIdentity, holderId);
3007
2954
  } catch (error) {
3008
2955
  log2("[magic-context] embed drain: lease release failed (will TTL-expire):", error);
3009
2956
  }
@@ -3013,7 +2960,7 @@ async function embedSessionCompartmentChunks2(db, projectIdentity, sessionId, op
3013
2960
  if (aborted)
3014
2961
  return { status: "aborted", embedded, total, failed: failedIds.length };
3015
2962
  if (providerDown || failedIds.length > 0) {
3016
- const remaining = Math.max(failedIds.length, await countUnembeddedSessionCompartmentsPolite(db, projectIdentity, sessionId, snapshot.chunkModelId, maxInputTokens) - skipIds.length);
2963
+ const remaining = Math.max(failedIds.length, (writer ? await writer.count(projectIdentity, sessionId, snapshot.chunkModelId, maxInputTokens) : await countUnembeddedSessionCompartmentsPolite(db, projectIdentity, sessionId, snapshot.chunkModelId, maxInputTokens)) - skipIds.length);
3017
2964
  if (remaining > 0) {
3018
2965
  return {
3019
2966
  status: "stalled",
@@ -3148,4 +3095,4 @@ function _resetProjectEmbeddingRegistryForTests2() {
3148
3095
  setBootQuietPeriodForTests(null);
3149
3096
  }
3150
3097
 
3151
- export { recordSessionProjectIdentity, drainBackgroundBatches, recordEmbeddingMeasurement, OpenAICompatibleEmbeddingProvider, saveCommitEmbedding, loadProjectCommitEmbeddings, loadUnembeddedCommits, countEmbeddedCommits, upsertCommits, getLatestIndexedCommitSha, enforceProjectCap, GIT_SWEEP_LEASE_RENEWAL_MS, acquireGitSweepLease, renewGitSweepLease, markGitSweepSuccessAndRelease, parkGitSweepNonIndexable, releaseGitSweepLease, describeShadowBackfillWriteRefusal2, listShadowBackfillStalls2, getShadowBackfillStopReason2, markProjectLoadUntrusted2, contentSha2562, drainProjectEmbeddingIdentityMaintenance2, drainStaleEmbeddingIdentitiesForProject2, registerProjectEmbedding2, registerProjectShadowEmbedding2, getShadowEmbeddingMeasurementCohort2, getPrimaryEmbeddingMeasurementCohort2, embedShadowTextForProject2, enqueueShadowEmbeddingItems2, getShadowBackfillRemaining2, flushShadowEmbeddingBacklog2, registerProjectInObservationMode2, unregisterProjectShadowEmbedding2, unregisterProjectEmbedding2, getProjectEmbeddingSnapshot2, installProjectEmbeddingSearchBridge2, getProjectChunkEmbeddingModelId2, getProjectEmbeddingMaxInputTokens2, embedTextForProject2, embedBatchForProject2, embedItemsForProject2, embedUnembeddedMemoriesForProject2, drainCommitBacklogForProject2, embedUnembeddedCompartmentChunksForProject2, embedSessionCompartmentChunks2, getEmbeddingCoverageStatus2, getAutoEmbeddingSessionCoverage2, sweepAllRegisteredProjects2, _setTestProviderFactoryForProject2, _resetProjectEmbeddingRegistryForTests2 };
3098
+ export { embedPauseBySession, embedRunStateBySession, activeEmbeddingSessions, autoEmbedAttemptedBySession, autoEmbedIdentityBySession, autoEmbedRetryAfterBySession, invalidateAutoEmbedSession, getEmbedDrainUiStatus, drainBackgroundBatches, recordEmbeddingMeasurement, OpenAICompatibleEmbeddingProvider, saveCommitEmbedding, loadProjectCommitEmbeddings, loadUnembeddedCommits, countEmbeddedCommits, upsertCommits, getLatestIndexedCommitSha, enforceProjectCap, describeShadowBackfillWriteRefusal2, listShadowBackfillStalls2, getShadowBackfillStopReason2, markProjectLoadUntrusted2, contentSha2562, drainProjectEmbeddingIdentityMaintenance2, drainStaleEmbeddingIdentitiesForProject2, registerProjectEmbedding2, registerProjectShadowEmbedding2, getShadowEmbeddingMeasurementCohort2, getPrimaryEmbeddingMeasurementCohort2, embedShadowTextForProject2, enqueueShadowEmbeddingItems2, getShadowBackfillRemaining2, flushShadowEmbeddingBacklog2, registerProjectInObservationMode2, unregisterProjectShadowEmbedding2, unregisterProjectEmbedding2, getProjectEmbeddingSnapshot2, installProjectEmbeddingSearchBridge2, getProjectChunkEmbeddingModelId2, getProjectEmbeddingMaxInputTokens2, embedTextForProject2, embedBatchForProject2, embedItemsForProject2, embedUnembeddedMemoriesForProject2, drainCommitBacklogForProject2, embedUnembeddedCompartmentChunksForProject2, embedSessionCompartmentChunks2, getEmbeddingCoverageStatus2, getAutoEmbeddingSessionCoverage2, sweepAllRegisteredProjects2, _setTestProviderFactoryForProject2, _resetProjectEmbeddingRegistryForTests2 };
@@ -1,3 +1,14 @@
1
+ // ../plugin/src/agents/permissions.ts
2
+ var DREAMER_PRIMER_INVESTIGATOR_ALLOWED_TOOLS = [
3
+ "read",
4
+ "grep",
5
+ "glob",
6
+ "aft_outline",
7
+ "aft_zoom",
8
+ "aft_search",
9
+ "ctx_search"
10
+ ];
11
+
1
12
  // ../plugin/src/agents/hidden-agent-registrations.ts
2
13
  var HIDDEN_AGENT_DESCRIPTION = "Internal Magic Context maintenance agent. Not for general tasks — do not select for user work.";
3
14
  function buildHiddenAgentRegistrations(args) {
@@ -355,4 +366,4 @@ function readHostSystemPrompt(ctx) {
355
366
  return;
356
367
  }
357
368
 
358
- export { buildHiddenAgentRegistrations, logTemperatureDecision, subagentTemperature, subagentStepCap, promptFingerprint, SubagentTelemetry, readHostSystemPrompt };
369
+ export { DREAMER_PRIMER_INVESTIGATOR_ALLOWED_TOOLS, buildHiddenAgentRegistrations, logTemperatureDecision, subagentTemperature, subagentStepCap, promptFingerprint, SubagentTelemetry, readHostSystemPrompt };