@cortexkit/pi-magic-context 0.46.1 → 0.48.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/dist/auto-search-worker.js +112 -0
- package/dist/embedding-activity-ew6dshfd.js +10 -0
- package/dist/embedding-backfill-bnnytehy.js +20 -0
- package/dist/embedding-cache-7rp4gqzr.js +16 -0
- package/dist/embedding-worker.js +11 -8
- package/dist/harness-9872e0ym.js +10 -0
- package/dist/historian-calibration-extension.js +3 -2
- package/dist/index-0am8a7k1.js +152 -0
- package/dist/index-0h2mkab2.js +17 -0
- package/dist/index-135e8hvg.js +43 -0
- package/dist/{index-wv28nczk.js → index-3cgbv47m.js} +354 -38
- package/dist/index-419bndtm.js +2309 -0
- package/dist/index-544c0e0x.js +3026 -0
- package/dist/index-5hd7h4rr.js +3098 -0
- package/dist/index-5jp1h0bz.js +750 -0
- package/dist/index-603mt6nm.js +171 -0
- package/dist/index-674f6qs2.js +16 -0
- package/dist/{index-r01b1b78.js → index-6pgq5ns2.js} +157 -2454
- package/dist/index-72bdc1bd.js +3591 -0
- package/dist/index-8976mezv.js +209 -0
- package/dist/{index-td885aah.js → index-8y5knskr.js} +98 -231
- package/dist/{index-ykb8kkm3.js → index-98z1c1r0.js} +14599 -22287
- package/dist/index-9p40dgkm.js +22 -0
- package/dist/index-9x1f96r8.js +11 -0
- package/dist/{index-266qrgss.js → index-9xb0axhc.js} +301 -27
- package/dist/{index-phh7e055.js → index-bgmv2kaf.js} +28 -28
- package/dist/index-dkx0b1kt.js +514 -0
- package/dist/{index-7n8gb6j3.js → index-f956htf3.js} +28 -31
- package/dist/index-fapenpch.js +13 -0
- package/dist/index-fm3ksh5e.js +1060 -0
- package/dist/{index-2p1e8706.js → index-fp37he9a.js} +3 -3
- package/dist/index-hrf13mn3.js +2388 -0
- package/dist/index-pvm4pd5d.js +3069 -0
- package/dist/index-r7xg4hvw.js +3480 -0
- package/dist/index-rt5jgzp1.js +1127 -0
- package/dist/{index-n3g5mwa8.js → index-wrm4nbj7.js} +3 -3
- package/dist/index-xjqheg7a.js +931 -0
- package/dist/index-yhzhdp3m.js +143 -0
- package/dist/{index-w76x3af7.js → index-zrr5t5a7.js} +1 -3
- package/dist/index.js +6345 -2585
- package/dist/logger-v3dsxdnm.js +19 -0
- package/dist/message-index-bounded-t7vvty76.js +120 -0
- package/dist/{message-time-backfill-4688z1k2.js → message-time-backfill-4ndf7hrq.js} +7 -6
- package/dist/migration-worker.js +24 -16
- package/dist/project-embedding-registry-jy2hmq28.js +85 -0
- package/dist/raw-ordinal-warmup-worker.js +60 -0
- package/dist/{read-session-chunk-tc6yn2pe.js → read-session-chunk-47pjn7fz.js} +12 -6
- package/dist/read-session-raw-yn8nawav.js +55 -0
- package/dist/{safe-notification-target-6cn3z99t.js → safe-notification-target-3c1ns931.js} +3 -2
- package/dist/search-42szfhwp.js +40 -0
- package/dist/sqlite-3yye76ht.js +44 -0
- package/dist/sqlite-context-pragmas-gcgch6qz.js +6 -0
- package/dist/storage-memory-1z20y55x.js +71 -0
- package/dist/storage-tags-jym5z6yk.js +127 -0
- package/dist/subagent-entry.js +36 -16
- package/dist/transformers-node-wasm.js +18415 -18415
- package/package.json +3 -3
- package/dist/index-4vfrjwf6.js +0 -7737
- package/dist/index-xvw8zptx.js +0 -5123
- /package/dist/{index-901ekbga.js → index-5prbx026.js} +0 -0
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getMagicContextStorageDir,
|
|
3
|
+
log2
|
|
4
|
+
} from "./index-f956htf3.js";
|
|
5
|
+
import {
|
|
6
|
+
writeStorageFileAtomicSync
|
|
7
|
+
} from "./index-vf38qhee.js";
|
|
8
|
+
|
|
9
|
+
// ../plugin/src/features/magic-context/memory/project-identity.ts
|
|
10
|
+
import { execFileSync } from "node:child_process";
|
|
11
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
12
|
+
import { existsSync, realpathSync, statSync } from "node:fs";
|
|
13
|
+
import { homedir } from "node:os";
|
|
14
|
+
import path3 from "node:path";
|
|
15
|
+
|
|
16
|
+
// ../plugin/src/features/magic-context/memory/project-identity-cache.ts
|
|
17
|
+
import { createHash } from "node:crypto";
|
|
18
|
+
import { readFileSync } from "node:fs";
|
|
19
|
+
import path2 from "node:path";
|
|
20
|
+
|
|
21
|
+
// ../plugin/src/shared/project-directory-key.ts
|
|
22
|
+
import path from "node:path";
|
|
23
|
+
function projectDirectoryKey(directory) {
|
|
24
|
+
const slashed = directory.replaceAll("\\", "/").replace(/^\/\/\?\/UNC\//i, "//").replace(/^\/\/\?\//, "");
|
|
25
|
+
if (/^[a-z]:\//i.test(slashed) || slashed.startsWith("//")) {
|
|
26
|
+
return path.win32.normalize(slashed).replaceAll("\\", "/").replace(/\/$/, "").toLowerCase();
|
|
27
|
+
}
|
|
28
|
+
return path.resolve(directory);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ../plugin/src/features/magic-context/memory/project-identity-cache.ts
|
|
32
|
+
function cachePath(directory, storageDir = getMagicContextStorageDir()) {
|
|
33
|
+
const hash = createHash("sha256").update(projectDirectoryKey(directory)).digest("hex");
|
|
34
|
+
return path2.join(storageDir, "project-identities", `${hash}.json`);
|
|
35
|
+
}
|
|
36
|
+
function rememberGitIdentity(directory, identity) {
|
|
37
|
+
try {
|
|
38
|
+
const destination = cachePath(directory);
|
|
39
|
+
writeStorageFileAtomicSync(destination, JSON.stringify({ directory: projectDirectoryKey(directory), identity }));
|
|
40
|
+
} catch {}
|
|
41
|
+
}
|
|
42
|
+
function readRememberedGitIdentity(directory, storageDir) {
|
|
43
|
+
try {
|
|
44
|
+
const record = JSON.parse(readFileSync(cachePath(directory, storageDir), "utf8"));
|
|
45
|
+
if (record.directory === projectDirectoryKey(directory) && /^git:[0-9a-f]{7,64}$/.test(record.identity))
|
|
46
|
+
return record.identity;
|
|
47
|
+
} catch {}
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ../plugin/src/features/magic-context/memory/project-identity.ts
|
|
52
|
+
var GIT_TIMEOUT_MS = 5000;
|
|
53
|
+
var TRANSIENT_FAILURE_COOLDOWN_MS = 5 * 60 * 1000;
|
|
54
|
+
var identityCache = new Map;
|
|
55
|
+
var linkedGitWorktreeCache = new Map;
|
|
56
|
+
var lastKnownGitIdentityCache = new Map;
|
|
57
|
+
var directoryFallbackCache = new Map;
|
|
58
|
+
var transientFailureCooldown = new Map;
|
|
59
|
+
var dubiousOwnershipFallbackDirectories = new Set;
|
|
60
|
+
var dubiousOwnershipLoggedDirectories = new Set;
|
|
61
|
+
var dubiousOwnershipWarnedDirectories = new Set;
|
|
62
|
+
var transientGitIdentityReuseLoggedDirectories = new Set;
|
|
63
|
+
var sessionIdentityCache = new Map;
|
|
64
|
+
var homeProjectPermission = false;
|
|
65
|
+
var pausedIdentityReasons = new Map;
|
|
66
|
+
var pausedIdentityLogged = new Set;
|
|
67
|
+
function setHomeProjectPermission(allowed) {
|
|
68
|
+
homeProjectPermission = allowed;
|
|
69
|
+
}
|
|
70
|
+
var execFileSyncForIdentity = execFileSync;
|
|
71
|
+
var userHomeDirectoryForIdentity = () => homedir();
|
|
72
|
+
var nowMs = () => Date.now();
|
|
73
|
+
var filesystemProbeObserverForTests;
|
|
74
|
+
|
|
75
|
+
class ProjectIdentityError extends Error {
|
|
76
|
+
errorClass;
|
|
77
|
+
rawDirectory;
|
|
78
|
+
constructor(errorClass, rawDirectory, message, cause) {
|
|
79
|
+
super(message);
|
|
80
|
+
this.name = "ProjectIdentityError";
|
|
81
|
+
this.errorClass = errorClass;
|
|
82
|
+
this.rawDirectory = rawDirectory;
|
|
83
|
+
if (cause) {
|
|
84
|
+
this.cause = cause;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function asError(error) {
|
|
89
|
+
return error instanceof Error ? error : undefined;
|
|
90
|
+
}
|
|
91
|
+
function getErrorCode(error) {
|
|
92
|
+
if (error === null || typeof error !== "object" || !("code" in error)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const code = error.code;
|
|
96
|
+
return typeof code === "string" ? code : undefined;
|
|
97
|
+
}
|
|
98
|
+
function getErrorSignal(error) {
|
|
99
|
+
if (error === null || typeof error !== "object" || !("signal" in error)) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const signal = error.signal;
|
|
103
|
+
return typeof signal === "string" ? signal : undefined;
|
|
104
|
+
}
|
|
105
|
+
function getErrorKilled(error) {
|
|
106
|
+
if (error === null || typeof error !== "object" || !("killed" in error)) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
return error.killed === true;
|
|
110
|
+
}
|
|
111
|
+
function getErrorStderr(error) {
|
|
112
|
+
if (error === null || typeof error !== "object" || !("stderr" in error)) {
|
|
113
|
+
return "";
|
|
114
|
+
}
|
|
115
|
+
const stderr = error.stderr;
|
|
116
|
+
if (typeof stderr === "string") {
|
|
117
|
+
return stderr;
|
|
118
|
+
}
|
|
119
|
+
if (Buffer.isBuffer(stderr)) {
|
|
120
|
+
return stderr.toString("utf8");
|
|
121
|
+
}
|
|
122
|
+
return "";
|
|
123
|
+
}
|
|
124
|
+
function directoryFallback(directory) {
|
|
125
|
+
const canonical = path3.resolve(directory);
|
|
126
|
+
const hash = createHash2("md5").update(canonical, "utf8").digest("hex").slice(0, 12);
|
|
127
|
+
return `dir:${hash}`;
|
|
128
|
+
}
|
|
129
|
+
function rememberedIdentityOrDirectoryFallback(canonical) {
|
|
130
|
+
return readRememberedGitIdentity(canonical) ?? directoryFallback(canonical);
|
|
131
|
+
}
|
|
132
|
+
function assertDirectoryUsable(canonicalDirectory, rawDirectory) {
|
|
133
|
+
try {
|
|
134
|
+
const stat = statSync(canonicalDirectory);
|
|
135
|
+
if (!stat.isDirectory()) {
|
|
136
|
+
throw new ProjectIdentityError("unknown", rawDirectory, `Project path is not a directory: ${canonicalDirectory}`);
|
|
137
|
+
}
|
|
138
|
+
} catch (error) {
|
|
139
|
+
if (error instanceof ProjectIdentityError) {
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
const code = getErrorCode(error);
|
|
143
|
+
if (code === "EACCES" || code === "EPERM") {
|
|
144
|
+
throw new ProjectIdentityError("permission_denied", rawDirectory, `Permission denied while accessing project directory: ${canonicalDirectory}`, asError(error));
|
|
145
|
+
}
|
|
146
|
+
throw new ProjectIdentityError("unknown", rawDirectory, `Unable to access project directory: ${canonicalDirectory}`, asError(error));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function isGitTimeoutError(error) {
|
|
150
|
+
const code = getErrorCode(error);
|
|
151
|
+
const signal = getErrorSignal(error);
|
|
152
|
+
return code === "ETIMEDOUT" || signal === "SIGTERM" || signal === "SIGKILL" || getErrorKilled(error);
|
|
153
|
+
}
|
|
154
|
+
function hasUnbornHead(directory) {
|
|
155
|
+
const options = {
|
|
156
|
+
cwd: directory,
|
|
157
|
+
encoding: "utf8",
|
|
158
|
+
env: { ...process.env, LC_ALL: "C", LANG: "C" },
|
|
159
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
160
|
+
timeout: GIT_TIMEOUT_MS,
|
|
161
|
+
windowsHide: true
|
|
162
|
+
};
|
|
163
|
+
try {
|
|
164
|
+
execFileSyncForIdentity("git", ["rev-parse", "--git-dir"], options);
|
|
165
|
+
try {
|
|
166
|
+
execFileSyncForIdentity("git", ["rev-parse", "--verify", "--quiet", "HEAD"], options);
|
|
167
|
+
return false;
|
|
168
|
+
} catch (error) {
|
|
169
|
+
return !isGitTimeoutError(error) && typeof error === "object" && error !== null && "status" in error && error.status === 1 && getErrorStderr(error) === "";
|
|
170
|
+
}
|
|
171
|
+
} catch {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function classifyGitError(error, rawDirectory) {
|
|
176
|
+
if (isGitTimeoutError(error)) {
|
|
177
|
+
return new ProjectIdentityError("git_timeout", rawDirectory, `git rev-list timed out after ${GIT_TIMEOUT_MS}ms`, asError(error));
|
|
178
|
+
}
|
|
179
|
+
const code = getErrorCode(error);
|
|
180
|
+
if (code === "ENOENT") {
|
|
181
|
+
return new ProjectIdentityError("git_missing", rawDirectory, "git binary is not available in PATH", asError(error));
|
|
182
|
+
}
|
|
183
|
+
if (code === "EACCES" || code === "EPERM") {
|
|
184
|
+
return new ProjectIdentityError("permission_denied", rawDirectory, "Permission denied while spawning git", asError(error));
|
|
185
|
+
}
|
|
186
|
+
const stderr = getErrorStderr(error).toLowerCase();
|
|
187
|
+
if (stderr.includes("detected dubious ownership")) {
|
|
188
|
+
return new ProjectIdentityError("dubious_ownership", rawDirectory, "git refused to read the repository because it detected dubious ownership", asError(error));
|
|
189
|
+
}
|
|
190
|
+
if (stderr.includes("not a git repository") || stderr.includes("does not have any commits yet") || stderr.includes("ambiguous argument 'head'") || stderr.includes("unknown revision or path")) {
|
|
191
|
+
return new ProjectIdentityError("not_git_repo", rawDirectory, "Directory has no git root commit; caller may use directory fallback", asError(error));
|
|
192
|
+
}
|
|
193
|
+
return new ProjectIdentityError("unknown", rawDirectory, "git rev-list failed while resolving project identity", asError(error));
|
|
194
|
+
}
|
|
195
|
+
function resolveProjectIdentityStrict(directory, allowHomeProject = homeProjectPermission) {
|
|
196
|
+
assertProjectAllowed(directory, allowHomeProject);
|
|
197
|
+
const canonical = path3.resolve(directory);
|
|
198
|
+
const cached = identityCache.get(canonical);
|
|
199
|
+
if (cached !== undefined) {
|
|
200
|
+
return cached;
|
|
201
|
+
}
|
|
202
|
+
assertDirectoryUsable(canonical, directory);
|
|
203
|
+
if (!hasGitDir(canonical)) {
|
|
204
|
+
throw new ProjectIdentityError("not_git_repo", directory, "Directory has no git metadata; caller may use directory fallback");
|
|
205
|
+
}
|
|
206
|
+
let output;
|
|
207
|
+
try {
|
|
208
|
+
output = execFileSyncForIdentity("git", ["rev-list", "--max-parents=0", "HEAD"], {
|
|
209
|
+
cwd: canonical,
|
|
210
|
+
encoding: "utf8",
|
|
211
|
+
env: { ...process.env, LC_ALL: "C", LANG: "C" },
|
|
212
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
213
|
+
timeout: GIT_TIMEOUT_MS,
|
|
214
|
+
windowsHide: true
|
|
215
|
+
});
|
|
216
|
+
} catch (error) {
|
|
217
|
+
const classified = classifyGitError(error, directory);
|
|
218
|
+
if (classified.errorClass === "not_git_repo" && hasUnbornHead(canonical)) {
|
|
219
|
+
throw new ProjectIdentityError("no_commits", directory, "Git repository has no commits yet");
|
|
220
|
+
}
|
|
221
|
+
throw classified;
|
|
222
|
+
}
|
|
223
|
+
const rootCommit = output.split(`
|
|
224
|
+
`).map((line) => line.trim().slice(0, 64)).filter((line) => /^[0-9a-f]{7,64}$/.test(line)).sort()[0];
|
|
225
|
+
if (!rootCommit) {
|
|
226
|
+
throw new ProjectIdentityError("unknown", directory, "git rev-list returned no valid root commit hash");
|
|
227
|
+
}
|
|
228
|
+
const identity = `git:${rootCommit}`;
|
|
229
|
+
identityCache.set(canonical, identity);
|
|
230
|
+
lastKnownGitIdentityCache.set(canonical, identity);
|
|
231
|
+
rememberGitIdentity(canonical, identity);
|
|
232
|
+
const root = gitRootDirectory(canonical);
|
|
233
|
+
if (root && root !== canonical)
|
|
234
|
+
rememberGitIdentity(root, identity);
|
|
235
|
+
transientFailureCooldown.delete(canonical);
|
|
236
|
+
dubiousOwnershipFallbackDirectories.delete(canonical);
|
|
237
|
+
transientGitIdentityReuseLoggedDirectories.delete(canonical);
|
|
238
|
+
return identity;
|
|
239
|
+
}
|
|
240
|
+
function shouldUseDirectoryFallback(error) {
|
|
241
|
+
return error.errorClass !== "home_project_disabled";
|
|
242
|
+
}
|
|
243
|
+
function getActiveCooldown(canonical) {
|
|
244
|
+
const until = transientFailureCooldown.get(canonical);
|
|
245
|
+
if (until === undefined)
|
|
246
|
+
return;
|
|
247
|
+
if (nowMs() < until)
|
|
248
|
+
return until;
|
|
249
|
+
transientFailureCooldown.delete(canonical);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
function lastKnownGitIdentity(canonical) {
|
|
253
|
+
return lastKnownGitIdentityCache.get(canonical) ?? identityCache.get(canonical) ?? readRememberedGitIdentity(canonical);
|
|
254
|
+
}
|
|
255
|
+
function nearestLastKnownGitIdentity(canonical) {
|
|
256
|
+
const visited = new Set;
|
|
257
|
+
const walk = (start) => {
|
|
258
|
+
let current = start;
|
|
259
|
+
while (!visited.has(current)) {
|
|
260
|
+
visited.add(current);
|
|
261
|
+
const cached = lastKnownGitIdentity(current);
|
|
262
|
+
if (cached !== undefined)
|
|
263
|
+
return { identity: cached, source: current };
|
|
264
|
+
if (existsSync(path3.join(current, ".git")))
|
|
265
|
+
break;
|
|
266
|
+
const parent = path3.dirname(current);
|
|
267
|
+
if (parent === current)
|
|
268
|
+
break;
|
|
269
|
+
current = parent;
|
|
270
|
+
}
|
|
271
|
+
return;
|
|
272
|
+
};
|
|
273
|
+
const exactOrAncestor = walk(canonical);
|
|
274
|
+
if (exactOrAncestor)
|
|
275
|
+
return exactOrAncestor;
|
|
276
|
+
try {
|
|
277
|
+
const realCanonical = realpathSync.native(canonical);
|
|
278
|
+
if (realCanonical !== canonical)
|
|
279
|
+
return walk(realCanonical);
|
|
280
|
+
} catch {}
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
function reuseLastKnownGitIdentity(canonical) {
|
|
284
|
+
const cached = nearestLastKnownGitIdentity(canonical);
|
|
285
|
+
if (cached === undefined)
|
|
286
|
+
return;
|
|
287
|
+
if (!transientGitIdentityReuseLoggedDirectories.has(canonical)) {
|
|
288
|
+
transientGitIdentityReuseLoggedDirectories.add(canonical);
|
|
289
|
+
const sourceNote = cached.source === canonical ? "" : ` from ancestor ${cached.source}`;
|
|
290
|
+
log2(`[magic-context] git identity resolution is temporarily unavailable for ${canonical}; reusing the last successful project identity${sourceNote} to avoid splitting project-scoped memory`);
|
|
291
|
+
}
|
|
292
|
+
return cached.identity;
|
|
293
|
+
}
|
|
294
|
+
function formatDubiousOwnershipWarning(canonical) {
|
|
295
|
+
return `Magic Context: git refused to read ${canonical} (dubious ownership — the repo is owned by a different user). Memory features are paused unless a previous git identity is available. Fix: git config --global --add safe.directory ${canonical}`;
|
|
296
|
+
}
|
|
297
|
+
function recordDubiousOwnershipFallback(canonical) {
|
|
298
|
+
dubiousOwnershipFallbackDirectories.add(canonical);
|
|
299
|
+
if (dubiousOwnershipLoggedDirectories.has(canonical))
|
|
300
|
+
return;
|
|
301
|
+
dubiousOwnershipLoggedDirectories.add(canonical);
|
|
302
|
+
log2(`[magic-context] ${formatDubiousOwnershipWarning(canonical)}`);
|
|
303
|
+
}
|
|
304
|
+
function canonicalUserHomeDirectory() {
|
|
305
|
+
const homeDirectory = userHomeDirectoryForIdentity();
|
|
306
|
+
try {
|
|
307
|
+
return realpathSync.native(homeDirectory);
|
|
308
|
+
} catch {
|
|
309
|
+
return homeDirectory;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
function isUserHomeDirectory(directory) {
|
|
313
|
+
if (projectDirectoryKey(directory) === projectDirectoryKey(userHomeDirectoryForIdentity()))
|
|
314
|
+
return true;
|
|
315
|
+
try {
|
|
316
|
+
return projectDirectoryKey(realpathSync.native(path3.resolve(directory))) === projectDirectoryKey(canonicalUserHomeDirectory());
|
|
317
|
+
} catch {
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function assertProjectAllowed(directory, allowHomeProject) {
|
|
322
|
+
const canonical = path3.resolve(directory);
|
|
323
|
+
if (!allowHomeProject && (isUserHomeDirectory(directory) || isUserHomeDirectory(gitRootDirectory(canonical) ?? canonical))) {
|
|
324
|
+
throw new ProjectIdentityError("home_project_disabled", directory, "Home project memory is disabled; set allow_home_project to opt in");
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
function resolveProjectIdentity(directory, allowHomeProject = homeProjectPermission) {
|
|
328
|
+
assertProjectAllowed(directory, allowHomeProject);
|
|
329
|
+
const canonical = path3.resolve(directory);
|
|
330
|
+
const cachedFallback = directoryFallbackCache.get(canonical);
|
|
331
|
+
if (cachedFallback !== undefined) {
|
|
332
|
+
if (!hasGitDir(canonical)) {
|
|
333
|
+
return cachedFallback;
|
|
334
|
+
}
|
|
335
|
+
directoryFallbackCache.delete(canonical);
|
|
336
|
+
}
|
|
337
|
+
if (getActiveCooldown(canonical) !== undefined) {
|
|
338
|
+
if (hasGitDir(canonical)) {
|
|
339
|
+
const cachedGitIdentity = reuseLastKnownGitIdentity(canonical);
|
|
340
|
+
if (cachedGitIdentity !== undefined) {
|
|
341
|
+
return cachedGitIdentity;
|
|
342
|
+
}
|
|
343
|
+
throw new ProjectIdentityError("git_identity_unavailable", directory, "Git identity unavailable; memory features paused until the retry cooldown expires");
|
|
344
|
+
}
|
|
345
|
+
return rememberedIdentityOrDirectoryFallback(canonical);
|
|
346
|
+
}
|
|
347
|
+
try {
|
|
348
|
+
return resolveProjectIdentityStrict(directory, allowHomeProject);
|
|
349
|
+
} catch (error) {
|
|
350
|
+
if (error instanceof ProjectIdentityError && shouldUseDirectoryFallback(error)) {
|
|
351
|
+
if (error.errorClass === "no_commits")
|
|
352
|
+
return directoryFallback(canonical);
|
|
353
|
+
if (!hasGitDir(canonical)) {
|
|
354
|
+
if (error.errorClass === "permission_denied")
|
|
355
|
+
throw error;
|
|
356
|
+
const resolved = rememberedIdentityOrDirectoryFallback(canonical);
|
|
357
|
+
directoryFallbackCache.set(canonical, resolved);
|
|
358
|
+
transientFailureCooldown.delete(canonical);
|
|
359
|
+
return resolved;
|
|
360
|
+
}
|
|
361
|
+
transientFailureCooldown.set(canonical, nowMs() + TRANSIENT_FAILURE_COOLDOWN_MS);
|
|
362
|
+
const cachedGitIdentity = reuseLastKnownGitIdentity(canonical);
|
|
363
|
+
if (error.errorClass === "dubious_ownership")
|
|
364
|
+
recordDubiousOwnershipFallback(canonical);
|
|
365
|
+
if (cachedGitIdentity !== undefined) {
|
|
366
|
+
return cachedGitIdentity;
|
|
367
|
+
}
|
|
368
|
+
throw error;
|
|
369
|
+
}
|
|
370
|
+
throw error;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
function resolveProjectIdentityOrFallback(directory, allowHomeProject = homeProjectPermission) {
|
|
374
|
+
try {
|
|
375
|
+
return resolveProjectIdentity(directory, allowHomeProject);
|
|
376
|
+
} catch (error) {
|
|
377
|
+
const canonical = path3.resolve(directory);
|
|
378
|
+
if (hasGitDir(canonical) || error instanceof ProjectIdentityError && error.errorClass === "home_project_disabled")
|
|
379
|
+
throw error;
|
|
380
|
+
const fallback = rememberedIdentityOrDirectoryFallback(canonical);
|
|
381
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
382
|
+
log2(`[magic-context] project identity resolution failed for ${canonical}; using directory fallback ${fallback}: ${message}`);
|
|
383
|
+
return fallback;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
function hasGitDir(canonical) {
|
|
387
|
+
if (hasGitDirInAncestorChain(canonical)) {
|
|
388
|
+
return true;
|
|
389
|
+
}
|
|
390
|
+
try {
|
|
391
|
+
const realCanonical = realpathSync.native(canonical);
|
|
392
|
+
return realCanonical !== canonical && hasGitDirInAncestorChain(realCanonical);
|
|
393
|
+
} catch {
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
function gitRootInAncestorChain(startDirectory) {
|
|
398
|
+
let current = startDirectory;
|
|
399
|
+
while (true) {
|
|
400
|
+
if (existsSync(path3.join(current, ".git"))) {
|
|
401
|
+
try {
|
|
402
|
+
return realpathSync.native(current);
|
|
403
|
+
} catch {
|
|
404
|
+
return path3.resolve(current);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
const parent = path3.dirname(current);
|
|
408
|
+
if (parent === current) {
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
current = parent;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
function hasGitDirInAncestorChain(startDirectory) {
|
|
415
|
+
return gitRootInAncestorChain(startDirectory) !== null;
|
|
416
|
+
}
|
|
417
|
+
function gitRootDirectory(canonical) {
|
|
418
|
+
const direct = gitRootInAncestorChain(canonical);
|
|
419
|
+
if (direct)
|
|
420
|
+
return direct;
|
|
421
|
+
try {
|
|
422
|
+
const realCanonical = realpathSync.native(canonical);
|
|
423
|
+
return realCanonical === canonical ? null : gitRootInAncestorChain(realCanonical);
|
|
424
|
+
} catch {
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
function directoryHasGitMetadata(directory) {
|
|
429
|
+
return gitRootDirectory(path3.resolve(directory)) !== null;
|
|
430
|
+
}
|
|
431
|
+
function isUsableProjectIdentity(identity) {
|
|
432
|
+
return typeof identity === "string" && identity.trim().length > 0;
|
|
433
|
+
}
|
|
434
|
+
function resolveProjectIdentityForSession(directory, allowHomeProject = homeProjectPermission) {
|
|
435
|
+
const resolvedDirectory = path3.resolve(directory);
|
|
436
|
+
const cacheKey = `${allowHomeProject ? "1" : "0"}\x00${resolvedDirectory}`;
|
|
437
|
+
const cached = sessionIdentityCache.get(cacheKey);
|
|
438
|
+
if (cached && (cached.revalidateAt === null || nowMs() < cached.revalidateAt) && !(cached.identity?.startsWith("dir:") && hasGitDir(resolvedDirectory))) {
|
|
439
|
+
return cached.identity;
|
|
440
|
+
}
|
|
441
|
+
sessionIdentityCache.delete(cacheKey);
|
|
442
|
+
filesystemProbeObserverForTests?.();
|
|
443
|
+
const canonicalDirectory = (() => {
|
|
444
|
+
try {
|
|
445
|
+
filesystemProbeObserverForTests?.();
|
|
446
|
+
return realpathSync.native(resolvedDirectory);
|
|
447
|
+
} catch {
|
|
448
|
+
return resolvedDirectory;
|
|
449
|
+
}
|
|
450
|
+
})();
|
|
451
|
+
filesystemProbeObserverForTests?.();
|
|
452
|
+
const homeRoot = gitRootDirectory(canonicalDirectory);
|
|
453
|
+
const inheritsHomeRepository = homeRoot !== null && isUserHomeDirectory(homeRoot);
|
|
454
|
+
let identity;
|
|
455
|
+
if (!allowHomeProject && (isUserHomeDirectory(directory) || inheritsHomeRepository)) {
|
|
456
|
+
identity = undefined;
|
|
457
|
+
} else {
|
|
458
|
+
try {
|
|
459
|
+
identity = resolveProjectIdentityOrFallback(isUserHomeDirectory(directory) ? canonicalUserHomeDirectory() : directory, allowHomeProject);
|
|
460
|
+
} catch (error) {
|
|
461
|
+
if (!(error instanceof ProjectIdentityError))
|
|
462
|
+
throw error;
|
|
463
|
+
const reason = error.errorClass === "git_identity_unavailable" ? pausedIdentityReasons.get(resolvedDirectory) ?? error.errorClass : error.errorClass;
|
|
464
|
+
pausedIdentityReasons.set(resolvedDirectory, reason);
|
|
465
|
+
const logKey = `${resolvedDirectory}\x00${reason}`;
|
|
466
|
+
if (!pausedIdentityLogged.has(logKey)) {
|
|
467
|
+
pausedIdentityLogged.add(logKey);
|
|
468
|
+
log2(`[magic-context] memory features paused for ${resolvedDirectory}: ${reason}`);
|
|
469
|
+
}
|
|
470
|
+
identity = undefined;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
if (identity !== undefined)
|
|
474
|
+
pausedIdentityReasons.delete(resolvedDirectory);
|
|
475
|
+
sessionIdentityCache.set(cacheKey, {
|
|
476
|
+
identity,
|
|
477
|
+
revalidateAt: identity?.startsWith("git:") === true ? null : nowMs() + TRANSIENT_FAILURE_COOLDOWN_MS
|
|
478
|
+
});
|
|
479
|
+
return identity;
|
|
480
|
+
}
|
|
481
|
+
function normalizeStoredProjectPath(rawOrStored) {
|
|
482
|
+
if (rawOrStored.startsWith("git:") || rawOrStored.startsWith("dir:")) {
|
|
483
|
+
return rawOrStored;
|
|
484
|
+
}
|
|
485
|
+
try {
|
|
486
|
+
return resolveProjectIdentity(rawOrStored);
|
|
487
|
+
} catch {
|
|
488
|
+
return rawOrStored;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
function storedPathBelongsToIdentity(storedProjectPath, projectIdentity) {
|
|
492
|
+
return storedProjectPath === projectIdentity || normalizeStoredProjectPath(storedProjectPath) === projectIdentity;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// ../plugin/src/plugin/boot-quiet.ts
|
|
496
|
+
var BOOT_QUIET_MS = 120000;
|
|
497
|
+
var bootQuietUntilMs = 0;
|
|
498
|
+
function beginBootQuietPeriod(now = Date.now()) {
|
|
499
|
+
if (bootQuietUntilMs === 0)
|
|
500
|
+
bootQuietUntilMs = now + BOOT_QUIET_MS;
|
|
501
|
+
}
|
|
502
|
+
function bootQuietRemainingMs(now = Date.now()) {
|
|
503
|
+
return Math.max(0, bootQuietUntilMs - now);
|
|
504
|
+
}
|
|
505
|
+
function scheduleAfterBootQuiet(task, additionalDelayMs = 0) {
|
|
506
|
+
const timer = setTimeout(task, bootQuietRemainingMs() + Math.max(0, additionalDelayMs));
|
|
507
|
+
timer.unref?.();
|
|
508
|
+
return timer;
|
|
509
|
+
}
|
|
510
|
+
function setBootQuietPeriodForTests(startAtMs) {
|
|
511
|
+
bootQuietUntilMs = startAtMs === null ? 0 : startAtMs + BOOT_QUIET_MS;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
export { setHomeProjectPermission, ProjectIdentityError, resolveProjectIdentityStrict, isUserHomeDirectory, resolveProjectIdentity, directoryHasGitMetadata, isUsableProjectIdentity, resolveProjectIdentityForSession, normalizeStoredProjectPath, storedPathBelongsToIdentity, beginBootQuietPeriod, bootQuietRemainingMs, scheduleAfterBootQuiet, setBootQuietPeriodForTests };
|
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
currentHarness = value;
|
|
9
|
-
harnessLocked = true;
|
|
10
|
-
}
|
|
11
|
-
function getHarness() {
|
|
12
|
-
return currentHarness;
|
|
13
|
-
}
|
|
14
|
-
function harnessOwnsOpenCodeStore(harness = currentHarness) {
|
|
15
|
-
return harness === "opencode" || harness === "opencode2";
|
|
16
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
getHarness2
|
|
3
|
+
} from "./index-0h2mkab2.js";
|
|
4
|
+
|
|
5
|
+
// ../plugin/src/shared/logger.ts
|
|
6
|
+
import * as fs from "node:fs";
|
|
7
|
+
import * as path2 from "node:path";
|
|
17
8
|
|
|
18
9
|
// ../plugin/src/shared/data-path.ts
|
|
19
10
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
@@ -28,10 +19,10 @@ var registeredTempDirs = new Set;
|
|
|
28
19
|
function getDataDir() {
|
|
29
20
|
return process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share");
|
|
30
21
|
}
|
|
31
|
-
function getMagicContextTempDir(harness =
|
|
22
|
+
function getMagicContextTempDir(harness = getHarness2()) {
|
|
32
23
|
return path.join(os.tmpdir(), harness, "magic-context");
|
|
33
24
|
}
|
|
34
|
-
function getMagicContextLogPath(harness =
|
|
25
|
+
function getMagicContextLogPath(harness = getHarness2()) {
|
|
35
26
|
const envPath = process.env.MAGIC_CONTEXT_LOG_PATH?.trim();
|
|
36
27
|
if (envPath)
|
|
37
28
|
return envPath;
|
|
@@ -112,10 +103,6 @@ function getLegacyOpenCodeMagicContextStorageDir() {
|
|
|
112
103
|
return path.join(getOpenCodeStorageDir(), "plugin", "magic-context");
|
|
113
104
|
}
|
|
114
105
|
|
|
115
|
-
// ../plugin/src/shared/logger.ts
|
|
116
|
-
import * as fs from "node:fs";
|
|
117
|
-
import * as path2 from "node:path";
|
|
118
|
-
|
|
119
106
|
// ../plugin/src/shared/redaction.ts
|
|
120
107
|
import { homedir as homedir2, userInfo } from "node:os";
|
|
121
108
|
function escapeRegex(value) {
|
|
@@ -409,7 +396,7 @@ function classifyStalePluginBuild(error) {
|
|
|
409
396
|
}
|
|
410
397
|
}
|
|
411
398
|
const ownDist = distForModule(import.meta.url);
|
|
412
|
-
return ownDist && chunk.startsWith(`${ownDist}/`) ? { chunk, guidance: stalePluginBuildGuidance(
|
|
399
|
+
return ownDist && chunk.startsWith(`${ownDist}/`) ? { chunk, guidance: stalePluginBuildGuidance(getHarness2()) } : null;
|
|
413
400
|
}
|
|
414
401
|
|
|
415
402
|
class StalePluginBuildError extends Error {
|
|
@@ -444,7 +431,7 @@ async function importPluginModule(load) {
|
|
|
444
431
|
const build = classifyStalePluginBuild(error);
|
|
445
432
|
if (!build)
|
|
446
433
|
throw error;
|
|
447
|
-
|
|
434
|
+
log2("[magic-context] lazy import failed", error);
|
|
448
435
|
throw new StalePluginBuildError(build);
|
|
449
436
|
}
|
|
450
437
|
}
|
|
@@ -592,10 +579,10 @@ function scheduleFlush() {
|
|
|
592
579
|
}, FLUSH_INTERVAL_MS);
|
|
593
580
|
}
|
|
594
581
|
var lineForwarder = null;
|
|
595
|
-
function
|
|
582
|
+
function setLogLineForwarder2(forward) {
|
|
596
583
|
lineForwarder = forward;
|
|
597
584
|
}
|
|
598
|
-
function
|
|
585
|
+
function writeForwardedLogLine2(line) {
|
|
599
586
|
if (isTestEnv)
|
|
600
587
|
return;
|
|
601
588
|
try {
|
|
@@ -608,7 +595,7 @@ function writeForwardedLogLine(line) {
|
|
|
608
595
|
scheduleFlush();
|
|
609
596
|
} catch {}
|
|
610
597
|
}
|
|
611
|
-
function
|
|
598
|
+
function log2(message, data) {
|
|
612
599
|
try {
|
|
613
600
|
let diagnostic = stalePluginBuildDiagnostic(data);
|
|
614
601
|
if (diagnostic === undefined)
|
|
@@ -640,14 +627,24 @@ ${data.stack}` : ""}`)}` : ` ${JSON.stringify(sanitizeConfigValue(data))}`;
|
|
|
640
627
|
}
|
|
641
628
|
} catch {}
|
|
642
629
|
}
|
|
643
|
-
function
|
|
644
|
-
|
|
630
|
+
function sessionLog2(sessionId, message, data) {
|
|
631
|
+
log2(`[magic-context][${sessionId}] ${message}`, data);
|
|
645
632
|
}
|
|
646
|
-
function
|
|
633
|
+
function getLoggerDiagnostics2() {
|
|
634
|
+
return {
|
|
635
|
+
swallowedWriteCount,
|
|
636
|
+
lastErrorMessage,
|
|
637
|
+
lastErrorTime
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
function flushLogger2() {
|
|
647
641
|
flush();
|
|
648
642
|
}
|
|
643
|
+
function getLogFilePath2() {
|
|
644
|
+
return getMagicContextLogPath();
|
|
645
|
+
}
|
|
649
646
|
if (!isTestEnv) {
|
|
650
647
|
process.on("exit", flush);
|
|
651
648
|
}
|
|
652
649
|
|
|
653
|
-
export {
|
|
650
|
+
export { getDataDir, ensureCortexKitArtifactGitignore, getProjectMagicContextHistorianDir, getMagicContextStorageDir, getLegacyOpenCodeMagicContextStorageDir, sanitizeDiagnosticText, hasShareabilitySensitiveText, registerStalePluginBuildHost, classifyStalePluginBuild, importPluginModule, setLogLineForwarder2, writeForwardedLogLine2, log2, sessionLog2, getLoggerDiagnostics2, flushLogger2, getLogFilePath2 };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// ../plugin/src/shared/sqlite-context-pragmas.ts
|
|
2
|
+
function configureContextDatabasePragmas2(db, readonly = false) {
|
|
3
|
+
const [row] = db.prepare(readonly ? "PRAGMA journal_mode" : "PRAGMA journal_mode=WAL").all();
|
|
4
|
+
const mode = row?.journal_mode?.toLowerCase();
|
|
5
|
+
if (mode === "memory" || readonly && mode !== "wal")
|
|
6
|
+
return;
|
|
7
|
+
if (mode !== "wal") {
|
|
8
|
+
throw new Error(`context.db requires WAL before synchronous=NORMAL (got ${mode ?? "unknown"})`);
|
|
9
|
+
}
|
|
10
|
+
db.exec("PRAGMA synchronous=NORMAL");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { configureContextDatabasePragmas2 };
|