@cortexkit/pi-magic-context 0.40.0 → 0.41.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 +9 -0
- package/dist/historian-calibration-extension.js +58 -0
- package/dist/index-3k71e196.js +378 -0
- package/dist/{index-kamc8t8p.js → index-ts6nabp0.js} +429 -282
- package/dist/index.js +1109 -455
- package/dist/{safe-notification-target-q00qgjm6.js → safe-notification-target-g8fx80va.js} +1 -1
- package/dist/subagent-entry.js +2 -2
- package/package.json +87 -87
- package/dist/index-hk6sj7dn.js +0 -147
- /package/dist/{index-8sseka65.js → index-wnrygn5h.js} +0 -0
package/README.md
CHANGED
|
@@ -131,6 +131,15 @@ Magic Context stores everything in a single shared SQLite database at:
|
|
|
131
131
|
~/.local/share/cortexkit/magic-context/context.db
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
+
When a host isolates `XDG_DATA_HOME` per process, set
|
|
135
|
+
`MAGIC_CONTEXT_STORAGE_DIR` to the absolute, complete shared Magic Context
|
|
136
|
+
storage directory. The explicit path takes precedence over the XDG-derived path
|
|
137
|
+
and does not change Pi's own configuration or session directories. The host must
|
|
138
|
+
propagate one identical value to every process that shares the database; Magic
|
|
139
|
+
Context never originates this variable from its default. This affects the
|
|
140
|
+
harness-side database only, not `subc` daemon state. Mixed-version processes on
|
|
141
|
+
one directory still block migrations until all processes use a compatible build.
|
|
142
|
+
|
|
134
143
|
This is the **same database** the OpenCode plugin and OMP extension use. Tables are scoped by:
|
|
135
144
|
- `harness` column (`'pi'` or `'opencode'`) for session-scoped data; OMP intentionally uses `'pi'`
|
|
136
145
|
- `project_path` (resolved git root) for project-scoped data (memories, embeddings, dreamer runs)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import"./index-1yh8g550.js";
|
|
2
|
+
|
|
3
|
+
// src/historian-calibration-extension.ts
|
|
4
|
+
var HISTORIAN_TEMPERATURE_ENV = "MAGIC_CONTEXT_HISTORIAN_TEMPERATURE";
|
|
5
|
+
var HISTORIAN_MAX_OUTPUT_TOKENS_ENV = "MAGIC_CONTEXT_HISTORIAN_MAX_OUTPUT_TOKENS";
|
|
6
|
+
function finiteNumber(value) {
|
|
7
|
+
if (value === undefined || value.trim().length === 0)
|
|
8
|
+
return;
|
|
9
|
+
const parsed = Number(value);
|
|
10
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : undefined;
|
|
11
|
+
}
|
|
12
|
+
function calibrateHistorianProviderPayload(payload, temperature, maxOutputTokens) {
|
|
13
|
+
if (typeof payload !== "object" || payload === null || Array.isArray(payload))
|
|
14
|
+
return payload;
|
|
15
|
+
const calibrated = { ...payload };
|
|
16
|
+
const generationConfig = calibrated.generationConfig;
|
|
17
|
+
if (typeof generationConfig === "object" && generationConfig !== null && !Array.isArray(generationConfig)) {
|
|
18
|
+
calibrated.generationConfig = {
|
|
19
|
+
...generationConfig,
|
|
20
|
+
temperature,
|
|
21
|
+
maxOutputTokens
|
|
22
|
+
};
|
|
23
|
+
return calibrated;
|
|
24
|
+
}
|
|
25
|
+
const inferenceConfig = calibrated.inferenceConfig;
|
|
26
|
+
if (typeof inferenceConfig === "object" && inferenceConfig !== null && !Array.isArray(inferenceConfig)) {
|
|
27
|
+
calibrated.inferenceConfig = {
|
|
28
|
+
...inferenceConfig,
|
|
29
|
+
temperature,
|
|
30
|
+
maxTokens: maxOutputTokens
|
|
31
|
+
};
|
|
32
|
+
return calibrated;
|
|
33
|
+
}
|
|
34
|
+
calibrated.temperature = temperature;
|
|
35
|
+
if ("max_output_tokens" in calibrated) {
|
|
36
|
+
calibrated.max_output_tokens = maxOutputTokens;
|
|
37
|
+
} else if ("max_completion_tokens" in calibrated) {
|
|
38
|
+
calibrated.max_completion_tokens = maxOutputTokens;
|
|
39
|
+
} else if ("max_tokens" in calibrated) {
|
|
40
|
+
calibrated.max_tokens = maxOutputTokens;
|
|
41
|
+
} else if ("maxTokens" in calibrated) {
|
|
42
|
+
calibrated.maxTokens = maxOutputTokens;
|
|
43
|
+
}
|
|
44
|
+
return calibrated;
|
|
45
|
+
}
|
|
46
|
+
function historianCalibrationExtension(pi) {
|
|
47
|
+
const temperature = finiteNumber(process.env[HISTORIAN_TEMPERATURE_ENV]);
|
|
48
|
+
const maxOutputTokens = finiteNumber(process.env[HISTORIAN_MAX_OUTPUT_TOKENS_ENV]);
|
|
49
|
+
if (temperature === undefined || maxOutputTokens === undefined)
|
|
50
|
+
return;
|
|
51
|
+
pi.on("before_provider_request", (event) => calibrateHistorianProviderPayload(event.payload, temperature, maxOutputTokens));
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
HISTORIAN_MAX_OUTPUT_TOKENS_ENV,
|
|
55
|
+
HISTORIAN_TEMPERATURE_ENV,
|
|
56
|
+
calibrateHistorianProviderPayload,
|
|
57
|
+
historianCalibrationExtension as default
|
|
58
|
+
};
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
// ../plugin/src/shared/harness.ts
|
|
2
|
+
var currentHarness = "opencode";
|
|
3
|
+
var harnessLocked = false;
|
|
4
|
+
function setHarness(value) {
|
|
5
|
+
if (harnessLocked && currentHarness !== value) {
|
|
6
|
+
throw new Error(`Magic Context: harness already locked to "${currentHarness}"; cannot change to "${value}"`);
|
|
7
|
+
}
|
|
8
|
+
currentHarness = value;
|
|
9
|
+
harnessLocked = true;
|
|
10
|
+
}
|
|
11
|
+
function getHarness() {
|
|
12
|
+
return currentHarness;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// ../plugin/src/shared/data-path.ts
|
|
16
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
|
|
17
|
+
import * as os from "node:os";
|
|
18
|
+
import * as path from "node:path";
|
|
19
|
+
function getDataDir() {
|
|
20
|
+
return process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share");
|
|
21
|
+
}
|
|
22
|
+
function getMagicContextTempDir(harness = getHarness()) {
|
|
23
|
+
return path.join(os.tmpdir(), harness, "magic-context");
|
|
24
|
+
}
|
|
25
|
+
function getMagicContextLogPath(harness = getHarness()) {
|
|
26
|
+
const envPath = process.env.MAGIC_CONTEXT_LOG_PATH?.trim();
|
|
27
|
+
if (envPath)
|
|
28
|
+
return envPath;
|
|
29
|
+
return path.join(getMagicContextTempDir(harness), "magic-context.log");
|
|
30
|
+
}
|
|
31
|
+
function getProjectMagicContextDir(directory) {
|
|
32
|
+
return path.join(directory, ".cortexkit", "magic-context");
|
|
33
|
+
}
|
|
34
|
+
var GITIGNORE_GUARD_OPEN = "# >>> cortexkit:magic-context";
|
|
35
|
+
var GITIGNORE_GUARD_CLOSE = "# <<< cortexkit:magic-context";
|
|
36
|
+
function ensureCortexKitArtifactGitignore(directory) {
|
|
37
|
+
try {
|
|
38
|
+
const cortexKitDir = path.join(directory, ".cortexkit");
|
|
39
|
+
const gitignorePath = path.join(cortexKitDir, ".gitignore");
|
|
40
|
+
let existing = "";
|
|
41
|
+
if (existsSync(gitignorePath)) {
|
|
42
|
+
existing = readFileSync(gitignorePath, "utf8");
|
|
43
|
+
if (existing.includes(GITIGNORE_GUARD_OPEN))
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const block = `${GITIGNORE_GUARD_OPEN}
|
|
47
|
+
magic-context/
|
|
48
|
+
${GITIGNORE_GUARD_CLOSE}
|
|
49
|
+
`;
|
|
50
|
+
const needsLeadingNewline = existing.length > 0 && !existing.endsWith(`
|
|
51
|
+
`);
|
|
52
|
+
const next = existing + (needsLeadingNewline ? `
|
|
53
|
+
` : "") + block;
|
|
54
|
+
mkdirSync(cortexKitDir, { recursive: true });
|
|
55
|
+
writeFileSync(gitignorePath, next, "utf8");
|
|
56
|
+
} catch {}
|
|
57
|
+
}
|
|
58
|
+
function getProjectMagicContextHistorianDir(directory) {
|
|
59
|
+
return path.join(getProjectMagicContextDir(directory), "historian");
|
|
60
|
+
}
|
|
61
|
+
function getOpenCodeStorageDir() {
|
|
62
|
+
return path.join(getDataDir(), "opencode", "storage");
|
|
63
|
+
}
|
|
64
|
+
function getMagicContextStorageResolution() {
|
|
65
|
+
const testDataDir = process.env.MAGIC_CONTEXT_TEST_DATA_DIR?.trim();
|
|
66
|
+
if (testDataDir) {
|
|
67
|
+
const perTestDataHome = process.env.XDG_DATA_HOME?.trim();
|
|
68
|
+
if (perTestDataHome && path.resolve(perTestDataHome) !== path.resolve(testDataDir)) {
|
|
69
|
+
return {
|
|
70
|
+
path: path.join(perTestDataHome, "cortexkit", "magic-context"),
|
|
71
|
+
source: "test isolation"
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
path: path.join(testDataDir, "cortexkit", "magic-context"),
|
|
76
|
+
source: "test isolation"
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (false) {}
|
|
80
|
+
const explicitStorageDir = process.env.MAGIC_CONTEXT_STORAGE_DIR?.trim();
|
|
81
|
+
if (explicitStorageDir) {
|
|
82
|
+
if (!path.isAbsolute(explicitStorageDir)) {
|
|
83
|
+
throw new Error("MAGIC_CONTEXT_STORAGE_DIR must be an absolute path");
|
|
84
|
+
}
|
|
85
|
+
return { path: explicitStorageDir, source: "environment override" };
|
|
86
|
+
}
|
|
87
|
+
const xdgDataHome = process.env.XDG_DATA_HOME?.trim();
|
|
88
|
+
if (xdgDataHome) {
|
|
89
|
+
return {
|
|
90
|
+
path: path.join(xdgDataHome, "cortexkit", "magic-context"),
|
|
91
|
+
source: "XDG_DATA_HOME"
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
path: path.join(os.homedir(), ".local", "share", "cortexkit", "magic-context"),
|
|
96
|
+
source: "platform default"
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function getMagicContextStorageDir() {
|
|
100
|
+
return getMagicContextStorageResolution().path;
|
|
101
|
+
}
|
|
102
|
+
function getLegacyOpenCodeMagicContextStorageDir() {
|
|
103
|
+
return path.join(getOpenCodeStorageDir(), "plugin", "magic-context");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ../plugin/src/shared/logger.ts
|
|
107
|
+
import * as fs from "node:fs";
|
|
108
|
+
import * as path2 from "node:path";
|
|
109
|
+
|
|
110
|
+
// ../plugin/src/shared/redaction.ts
|
|
111
|
+
import { homedir as homedir2, userInfo } from "node:os";
|
|
112
|
+
function escapeRegex(value) {
|
|
113
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
114
|
+
}
|
|
115
|
+
var SECRET_WORDS = [
|
|
116
|
+
"key",
|
|
117
|
+
"token",
|
|
118
|
+
"secret",
|
|
119
|
+
"password",
|
|
120
|
+
"auth",
|
|
121
|
+
"authorization",
|
|
122
|
+
"bearer",
|
|
123
|
+
"credential"
|
|
124
|
+
];
|
|
125
|
+
var SECRET_SEGMENT_PATTERN = new RegExp(`^(?:${SECRET_WORDS.map((w) => `${w}s?`).join("|")})$`, "i");
|
|
126
|
+
var TRAILING_DESCRIPTORS = new Set(["id", "ids", "value", "values", "header", "headers"]);
|
|
127
|
+
function redactionTypeForKey(key) {
|
|
128
|
+
const normalized = key.trim().toLowerCase().replace(/[^a-z0-9_.-]+/g, "_");
|
|
129
|
+
const suffix = normalized.split(".").filter(Boolean).at(-1) ?? normalized;
|
|
130
|
+
return suffix || "secret";
|
|
131
|
+
}
|
|
132
|
+
function isNonSecretScalarValue(value) {
|
|
133
|
+
const v = value.trim();
|
|
134
|
+
if (v === "true" || v === "false" || v === "null" || v === "undefined")
|
|
135
|
+
return true;
|
|
136
|
+
return /^[+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(v);
|
|
137
|
+
}
|
|
138
|
+
var SECRET_QUALIFIERS = new Set([
|
|
139
|
+
"api",
|
|
140
|
+
"access",
|
|
141
|
+
"private",
|
|
142
|
+
"client",
|
|
143
|
+
"auth",
|
|
144
|
+
"authorization",
|
|
145
|
+
"secret",
|
|
146
|
+
"bearer",
|
|
147
|
+
"session",
|
|
148
|
+
"refresh",
|
|
149
|
+
"service",
|
|
150
|
+
"x",
|
|
151
|
+
"openai",
|
|
152
|
+
"anthropic",
|
|
153
|
+
"google",
|
|
154
|
+
"github",
|
|
155
|
+
"huggingface",
|
|
156
|
+
"aws",
|
|
157
|
+
"azure"
|
|
158
|
+
]);
|
|
159
|
+
function isSecretKey(key) {
|
|
160
|
+
const segments = key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().split(/[._-]+/).filter(Boolean);
|
|
161
|
+
if (segments.length === 0)
|
|
162
|
+
return false;
|
|
163
|
+
if (segments.length === 1) {
|
|
164
|
+
const first = segments[0];
|
|
165
|
+
return Boolean(first && SECRET_SEGMENT_PATTERN.test(first));
|
|
166
|
+
}
|
|
167
|
+
for (let i = 0;i < segments.length; i++) {
|
|
168
|
+
const seg = segments[i];
|
|
169
|
+
if (!seg || !SECRET_SEGMENT_PATTERN.test(seg))
|
|
170
|
+
continue;
|
|
171
|
+
let trailingOk = true;
|
|
172
|
+
for (let j = i + 1;j < segments.length; j++) {
|
|
173
|
+
const tail = segments[j];
|
|
174
|
+
if (!tail)
|
|
175
|
+
continue;
|
|
176
|
+
if (TRAILING_DESCRIPTORS.has(tail))
|
|
177
|
+
continue;
|
|
178
|
+
if (SECRET_SEGMENT_PATTERN.test(tail))
|
|
179
|
+
continue;
|
|
180
|
+
trailingOk = false;
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
if (!trailingOk)
|
|
184
|
+
continue;
|
|
185
|
+
for (let k = i - 1;k >= 0; k--) {
|
|
186
|
+
const lead = segments[k];
|
|
187
|
+
if (lead && SECRET_QUALIFIERS.has(lead))
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
function sanitizePathString(value) {
|
|
194
|
+
const home = process.env.HOME || process.env.USERPROFILE || homedir2();
|
|
195
|
+
const username = userInfo().username;
|
|
196
|
+
let sanitized = value;
|
|
197
|
+
if (home) {
|
|
198
|
+
sanitized = sanitized.replace(new RegExp(escapeRegex(home), "g"), "~");
|
|
199
|
+
}
|
|
200
|
+
sanitized = sanitized.replace(/\/Users\/[^/]+\//g, "/Users/<USER>/");
|
|
201
|
+
sanitized = sanitized.replace(/\/home\/[^/]+\//g, "/home/<USER>/");
|
|
202
|
+
sanitized = sanitized.replace(/C:\\Users\\[^\\]+\\/g, "C:\\Users\\<USER>\\");
|
|
203
|
+
if (username) {
|
|
204
|
+
sanitized = sanitized.replace(new RegExp(escapeRegex(username), "g"), "<USER>");
|
|
205
|
+
}
|
|
206
|
+
return sanitized;
|
|
207
|
+
}
|
|
208
|
+
var SECRET_TEXT_PATTERNS = [
|
|
209
|
+
{
|
|
210
|
+
pattern: /\bsk-ant-(?:api03-)?[A-Za-z0-9_-]{32,}/g,
|
|
211
|
+
replacement: "<ANTHROPIC_API_KEY_REDACTED>"
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
pattern: /\bsk-(?:proj-)?[A-Za-z0-9_-]{12,}/g,
|
|
215
|
+
replacement: "<OPENAI_API_KEY_REDACTED>"
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
pattern: /\bgithub_pat_[A-Za-z0-9_]{20,}/g,
|
|
219
|
+
replacement: "<GITHUB_PAT_REDACTED>"
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
pattern: /\b(?:gh[opsu]|ghr)_[A-Za-z0-9]{30,}/g,
|
|
223
|
+
replacement: "<GITHUB_TOKEN_REDACTED>"
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
pattern: /\bhf_[A-Za-z0-9]{30,}/g,
|
|
227
|
+
replacement: "<HUGGINGFACE_TOKEN_REDACTED>"
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
pattern: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g,
|
|
231
|
+
replacement: "<AWS_ACCESS_KEY_ID_REDACTED>"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
pattern: /\bxox[abprsuvc]-[A-Za-z0-9-]{10,}/g,
|
|
235
|
+
replacement: "<SLACK_TOKEN_REDACTED>"
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
pattern: /\bAIza[A-Za-z0-9_-]{35}\b/g,
|
|
239
|
+
replacement: "<GOOGLE_API_KEY_REDACTED>"
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
pattern: /\b(Authorization\s*:\s*Bearer\s+)([A-Za-z0-9._~+/=-]{8,})/gi,
|
|
243
|
+
replacement: (_full, prefix) => `${prefix}<REDACTED:bearer>`
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
pattern: /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,
|
|
247
|
+
replacement: "<JWT_REDACTED>"
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
pattern: /(["'])([^"']*(?:key|token|secret|password|auth|bearer|credential)[^"']*)\1(\s*:\s*)(["'])([^"']*)\4/gi,
|
|
251
|
+
replacement: (full, quote, key, separator, valueQuote, value) => isNonSecretScalarValue(value) ? full : `${quote}${key}${quote}${separator}${valueQuote}<REDACTED:${redactionTypeForKey(key)}>${valueQuote}`
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
pattern: /\b([A-Za-z0-9_.-]*(?:key|token|secret|password|auth|bearer|credential)[A-Za-z0-9_.-]*)\s*=\s*([^\s'"`]+)/gi,
|
|
255
|
+
replacement: (full, key, value) => isNonSecretScalarValue(value) ? full : `${key}=<REDACTED:${redactionTypeForKey(key)}>`
|
|
256
|
+
}
|
|
257
|
+
];
|
|
258
|
+
function redactSecretText(value) {
|
|
259
|
+
let redacted = value;
|
|
260
|
+
for (const { pattern, replacement } of SECRET_TEXT_PATTERNS) {
|
|
261
|
+
if (typeof replacement === "string") {
|
|
262
|
+
redacted = redacted.replace(pattern, replacement);
|
|
263
|
+
} else {
|
|
264
|
+
redacted = redacted.replace(pattern, replacement);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return redacted;
|
|
268
|
+
}
|
|
269
|
+
function sanitizeDiagnosticText(value) {
|
|
270
|
+
return redactSecretText(sanitizePathString(value));
|
|
271
|
+
}
|
|
272
|
+
var SHAREABILITY_SENSITIVE_PATTERNS = [
|
|
273
|
+
/\bC:\/Users\/[^/\s]+/i,
|
|
274
|
+
/(?:^|\s)~\/[^\s]+/,
|
|
275
|
+
/\b(?:api[_-]?key|secret|token|password|passwd|pwd|client[_-]?secret|access[_-]?key)\b\s*[:=]\s*\S+/i,
|
|
276
|
+
/\b(?:localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(?::\d+)?\b/i,
|
|
277
|
+
/\b(?:10|127)\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/,
|
|
278
|
+
/\b192\.168\.\d{1,3}\.\d{1,3}\b/,
|
|
279
|
+
/\b172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}\b/
|
|
280
|
+
];
|
|
281
|
+
function hasShareabilitySensitiveText(text) {
|
|
282
|
+
try {
|
|
283
|
+
if (sanitizeDiagnosticText(text) !== text)
|
|
284
|
+
return true;
|
|
285
|
+
return SHAREABILITY_SENSITIVE_PATTERNS.some((pattern) => pattern.test(text));
|
|
286
|
+
} catch {
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
function sanitizeConfigValue(value, keyPath = []) {
|
|
291
|
+
if (value === null || typeof value === "number" || typeof value === "boolean")
|
|
292
|
+
return value;
|
|
293
|
+
const key = keyPath.at(-1) ?? "";
|
|
294
|
+
if (key && isSecretKey(key)) {
|
|
295
|
+
return `<REDACTED:${redactionTypeForKey(key)}>`;
|
|
296
|
+
}
|
|
297
|
+
if (typeof value === "string")
|
|
298
|
+
return sanitizeDiagnosticText(value);
|
|
299
|
+
if (Array.isArray(value)) {
|
|
300
|
+
return value.map((entry, index) => sanitizeConfigValue(entry, [...keyPath, String(index)]));
|
|
301
|
+
}
|
|
302
|
+
if (value && typeof value === "object") {
|
|
303
|
+
return Object.fromEntries(Object.entries(value).map(([entryKey, entry]) => [
|
|
304
|
+
entryKey,
|
|
305
|
+
sanitizeConfigValue(entry, [...keyPath, entryKey])
|
|
306
|
+
]));
|
|
307
|
+
}
|
|
308
|
+
return value;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// ../plugin/src/shared/logger.ts
|
|
312
|
+
var isTestEnv = false;
|
|
313
|
+
var buffer = [];
|
|
314
|
+
var flushTimer = null;
|
|
315
|
+
var FLUSH_INTERVAL_MS = 500;
|
|
316
|
+
var BUFFER_SIZE_LIMIT = 50;
|
|
317
|
+
var swallowedWriteCount = 0;
|
|
318
|
+
var lastErrorMessage = null;
|
|
319
|
+
var lastErrorTime = null;
|
|
320
|
+
function recordSwallowedWrite(error) {
|
|
321
|
+
try {
|
|
322
|
+
swallowedWriteCount++;
|
|
323
|
+
lastErrorMessage = sanitizeDiagnosticText(error instanceof Error ? error.message : String(error));
|
|
324
|
+
lastErrorTime = new Date().toISOString();
|
|
325
|
+
} catch {}
|
|
326
|
+
}
|
|
327
|
+
function ensureDir(filePath) {
|
|
328
|
+
fs.mkdirSync(path2.dirname(filePath), { recursive: true });
|
|
329
|
+
}
|
|
330
|
+
function flush() {
|
|
331
|
+
if (flushTimer) {
|
|
332
|
+
clearTimeout(flushTimer);
|
|
333
|
+
flushTimer = null;
|
|
334
|
+
}
|
|
335
|
+
if (buffer.length === 0)
|
|
336
|
+
return;
|
|
337
|
+
const data = buffer.join("");
|
|
338
|
+
buffer = [];
|
|
339
|
+
try {
|
|
340
|
+
const logFile = getMagicContextLogPath();
|
|
341
|
+
ensureDir(logFile);
|
|
342
|
+
fs.appendFileSync(logFile, data);
|
|
343
|
+
} catch (error) {
|
|
344
|
+
recordSwallowedWrite(error);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
function scheduleFlush() {
|
|
348
|
+
if (flushTimer)
|
|
349
|
+
return;
|
|
350
|
+
flushTimer = setTimeout(() => {
|
|
351
|
+
flushTimer = null;
|
|
352
|
+
flush();
|
|
353
|
+
}, FLUSH_INTERVAL_MS);
|
|
354
|
+
}
|
|
355
|
+
function log(message, data) {
|
|
356
|
+
if (isTestEnv)
|
|
357
|
+
return;
|
|
358
|
+
try {
|
|
359
|
+
const timestamp = new Date().toISOString();
|
|
360
|
+
const serialized = data === undefined ? "" : data instanceof Error ? ` ${sanitizeDiagnosticText(`${data.message}${data.stack ? `
|
|
361
|
+
${data.stack}` : ""}`)}` : ` ${JSON.stringify(sanitizeConfigValue(data))}`;
|
|
362
|
+
buffer.push(`[${timestamp}] ${sanitizeDiagnosticText(message)}${serialized}
|
|
363
|
+
`);
|
|
364
|
+
if (buffer.length >= BUFFER_SIZE_LIMIT) {
|
|
365
|
+
flush();
|
|
366
|
+
} else {
|
|
367
|
+
scheduleFlush();
|
|
368
|
+
}
|
|
369
|
+
} catch {}
|
|
370
|
+
}
|
|
371
|
+
function sessionLog(sessionId, message, data) {
|
|
372
|
+
log(`[magic-context][${sessionId}] ${message}`, data);
|
|
373
|
+
}
|
|
374
|
+
if (!isTestEnv) {
|
|
375
|
+
process.on("exit", flush);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export { sanitizeDiagnosticText, hasShareabilitySensitiveText, setHarness, getHarness, getDataDir, ensureCortexKitArtifactGitignore, getProjectMagicContextHistorianDir, getMagicContextStorageResolution, getMagicContextStorageDir, getLegacyOpenCodeMagicContextStorageDir, log, sessionLog };
|