codex-overleaf-link 1.1.1
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/LICENSE +21 -0
- package/README.md +457 -0
- package/bin/codex-overleaf-link.mjs +223 -0
- package/extension/src/shared/agentTranscript.js +1175 -0
- package/extension/src/shared/auditRecords.js +568 -0
- package/extension/src/shared/compatibility.js +372 -0
- package/extension/src/shared/compileAdapter.js +176 -0
- package/extension/src/shared/governanceRules.js +252 -0
- package/extension/src/shared/i18n.js +565 -0
- package/extension/src/shared/models.js +106 -0
- package/extension/src/shared/otText.js +505 -0
- package/extension/src/shared/projectFiles.js +180 -0
- package/extension/src/shared/reviewing.js +99 -0
- package/extension/src/shared/sensitiveScan.js +116 -0
- package/extension/src/shared/sessionState.js +1084 -0
- package/extension/src/shared/staleGuard.js +150 -0
- package/extension/src/shared/storageDb.js +986 -0
- package/extension/src/shared/storageKeys.js +29 -0
- package/extension/src/shared/storageMigration.js +168 -0
- package/extension/src/shared/summary.js +248 -0
- package/extension/src/shared/undoOperations.js +369 -0
- package/native-host/src/codexArgs.js +43 -0
- package/native-host/src/codexHome.js +538 -0
- package/native-host/src/codexModels.js +247 -0
- package/native-host/src/codexPrompt.js +192 -0
- package/native-host/src/codexPromptAssembly.js +411 -0
- package/native-host/src/codexSessionRunner.js +1247 -0
- package/native-host/src/commandApproval.js +914 -0
- package/native-host/src/debugLog.js +78 -0
- package/native-host/src/diffEngine.js +247 -0
- package/native-host/src/index.js +132 -0
- package/native-host/src/launcher.js +81 -0
- package/native-host/src/localSkills.js +476 -0
- package/native-host/src/manifest.js +226 -0
- package/native-host/src/mirrorSensitiveScan.js +119 -0
- package/native-host/src/mirrorWorkspace.js +1019 -0
- package/native-host/src/nativeDoctor.js +826 -0
- package/native-host/src/nativeEnvironment.js +315 -0
- package/native-host/src/nativeHostPlatform.js +112 -0
- package/native-host/src/nativeMessaging.js +60 -0
- package/native-host/src/nativeQuotas.js +294 -0
- package/native-host/src/nativeResponseBudget.js +194 -0
- package/native-host/src/runtimeInstaller.js +357 -0
- package/native-host/src/taskRunner.js +3 -0
- package/native-host/src/taskRunnerRuntime.js +1083 -0
- package/native-host/src/textPatch.js +287 -0
- package/package.json +40 -0
- package/scripts/codex-json-agent.mjs +269 -0
- package/scripts/install-native-host.mjs +255 -0
- package/scripts/npm-package-files-v1.1.1.txt +52 -0
- package/scripts/uninstall-native-host.mjs +298 -0
- package/scripts/verify-npm-package.mjs +296 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const os = require('node:os');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
const { getDefaultRuntimeRoot } = require('./nativeHostPlatform');
|
|
7
|
+
|
|
8
|
+
const MANAGED_BY = 'codex-overleaf-link';
|
|
9
|
+
const MARKER_FILE = '.codex-overleaf-runtime.json';
|
|
10
|
+
const DEFAULT_RUNTIME_ROOT = getDefaultRuntimeRoot();
|
|
11
|
+
|
|
12
|
+
function buildRuntimeFileManifest(options = {}) {
|
|
13
|
+
const packageRoot = path.resolve(options.packageRoot || getDefaultPackageRoot());
|
|
14
|
+
const files = [
|
|
15
|
+
fileEntry(packageRoot, 'package.json'),
|
|
16
|
+
...directoryEntries(packageRoot, 'native-host/src'),
|
|
17
|
+
...directoryEntries(packageRoot, 'extension/src/shared'),
|
|
18
|
+
fileEntry(packageRoot, 'scripts/codex-json-agent.mjs'),
|
|
19
|
+
fileEntry(packageRoot, 'scripts/install-native-host.mjs'),
|
|
20
|
+
fileEntry(packageRoot, 'scripts/uninstall-native-host.mjs')
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
return files.sort((left, right) => left.relativePath.localeCompare(right.relativePath));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function assertSafeManagedRuntimeRoot(runtimeRoot, options = {}) {
|
|
27
|
+
if (!runtimeRoot || typeof runtimeRoot !== 'string') {
|
|
28
|
+
throw new Error('Runtime root is required');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const platformPath = options.platformPath || path;
|
|
32
|
+
const resolvedRoot = platformPath.resolve(runtimeRoot);
|
|
33
|
+
const homeDir = platformPath.resolve(options.homeDir || os.homedir());
|
|
34
|
+
const repoRoot = platformPath.resolve(options.packageRoot || getDefaultPackageRoot());
|
|
35
|
+
const defaultRoot = platformPath.resolve(options.defaultRuntimeRoot || DEFAULT_RUNTIME_ROOT);
|
|
36
|
+
const broadSystemDirs = getBroadSystemDirs(platformPath, options);
|
|
37
|
+
|
|
38
|
+
if (samePath(resolvedRoot, platformPath.parse(resolvedRoot).root, platformPath)) {
|
|
39
|
+
throwUnsafe(runtimeRoot);
|
|
40
|
+
}
|
|
41
|
+
if (samePath(resolvedRoot, homeDir, platformPath)) {
|
|
42
|
+
throwUnsafe(runtimeRoot);
|
|
43
|
+
}
|
|
44
|
+
if (samePath(resolvedRoot, repoRoot, platformPath)) {
|
|
45
|
+
throwUnsafe(runtimeRoot);
|
|
46
|
+
}
|
|
47
|
+
for (const systemDir of broadSystemDirs) {
|
|
48
|
+
if (samePath(resolvedRoot, systemDir, platformPath)) {
|
|
49
|
+
throwUnsafe(runtimeRoot);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (samePath(resolvedRoot, defaultRoot, platformPath)) {
|
|
54
|
+
return resolvedRoot;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const baseName = platformPath.basename(resolvedRoot);
|
|
58
|
+
const allowedTempRuntimeNames = new Set(['runtime', 'native-host-runtime', 'codex-overleaf-runtime']);
|
|
59
|
+
if (allowedTempRuntimeNames.has(baseName) && isUnderHostTempDir(resolvedRoot, platformPath)) {
|
|
60
|
+
return resolvedRoot;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
throwUnsafe(runtimeRoot);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function installRuntimeFromPackage(options = {}) {
|
|
67
|
+
const packageRoot = path.resolve(options.packageRoot || getDefaultPackageRoot());
|
|
68
|
+
const runtimeRootInput = options.runtimeRoot || DEFAULT_RUNTIME_ROOT;
|
|
69
|
+
assertSafeManagedRuntimeRoot(runtimeRootInput, { ...options, packageRoot });
|
|
70
|
+
const runtimeRoot = path.resolve(runtimeRootInput);
|
|
71
|
+
|
|
72
|
+
const existingMarker = readRuntimeMarker(runtimeRoot);
|
|
73
|
+
if (fs.existsSync(runtimeRoot) && !isManagedMarker(existingMarker)) {
|
|
74
|
+
throw new Error(`Refusing to replace unmarked runtime root: ${runtimeRoot}`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const parentDir = path.dirname(runtimeRoot);
|
|
78
|
+
fs.mkdirSync(parentDir, { recursive: true });
|
|
79
|
+
const unique = `${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
80
|
+
const stagingRoot = path.join(parentDir, `.${path.basename(runtimeRoot)}.staging-${unique}`);
|
|
81
|
+
const rollbackRoot = path.join(parentDir, `.${path.basename(runtimeRoot)}.rollback-${unique}`);
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
copyRuntimeFiles(packageRoot, stagingRoot);
|
|
85
|
+
writeRuntimeMarker(stagingRoot, packageRoot);
|
|
86
|
+
verifyInstalledRuntime(stagingRoot, options.verifyRuntime);
|
|
87
|
+
|
|
88
|
+
let rollbackCreated = false;
|
|
89
|
+
if (fs.existsSync(runtimeRoot)) {
|
|
90
|
+
fs.renameSync(runtimeRoot, rollbackRoot);
|
|
91
|
+
rollbackCreated = true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
fs.renameSync(stagingRoot, runtimeRoot);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
if (rollbackCreated && !fs.existsSync(runtimeRoot) && fs.existsSync(rollbackRoot)) {
|
|
98
|
+
fs.renameSync(rollbackRoot, runtimeRoot);
|
|
99
|
+
}
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
let warning;
|
|
104
|
+
if (rollbackCreated) {
|
|
105
|
+
try {
|
|
106
|
+
cleanupRollback(rollbackRoot, options.cleanupRollback);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
warning = `Installed runtime, but failed to remove rollback directory ${rollbackRoot}: ${error.message}`;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
ok: true,
|
|
114
|
+
action: existingMarker ? 'replaced' : 'installed',
|
|
115
|
+
runtimeRoot,
|
|
116
|
+
marker: readRuntimeMarker(runtimeRoot),
|
|
117
|
+
warning
|
|
118
|
+
};
|
|
119
|
+
} catch (error) {
|
|
120
|
+
safeRemove(stagingRoot);
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function uninstallManagedRuntime(options = {}) {
|
|
126
|
+
const runtimeRootInput = options.runtimeRoot || DEFAULT_RUNTIME_ROOT;
|
|
127
|
+
assertSafeManagedRuntimeRoot(runtimeRootInput, options);
|
|
128
|
+
const runtimeRoot = path.resolve(runtimeRootInput);
|
|
129
|
+
|
|
130
|
+
if (!fs.existsSync(runtimeRoot)) {
|
|
131
|
+
return { ok: true, action: 'not-found', runtimeRoot, removed: false, kept: false };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const marker = readRuntimeMarker(runtimeRoot);
|
|
135
|
+
if (!isManagedMarker(marker)) {
|
|
136
|
+
throw new Error(`Refusing to remove unmarked runtime root: ${runtimeRoot}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (options.keepRuntime) {
|
|
140
|
+
return { ok: true, action: 'kept', runtimeRoot, removed: false, kept: true, marker };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
fs.rmSync(runtimeRoot, { recursive: true, force: true });
|
|
144
|
+
return { ok: true, action: 'removed', runtimeRoot, removed: true, kept: false, marker };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function readRuntimeMarker(runtimeRoot) {
|
|
148
|
+
const markerPath = path.join(runtimeRoot, MARKER_FILE);
|
|
149
|
+
try {
|
|
150
|
+
const marker = JSON.parse(fs.readFileSync(markerPath, 'utf8'));
|
|
151
|
+
return marker && typeof marker === 'object' ? marker : null;
|
|
152
|
+
} catch (error) {
|
|
153
|
+
if (error && (error.code === 'ENOENT' || error.name === 'SyntaxError')) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function copyRuntimeFiles(packageRoot, runtimeRoot) {
|
|
161
|
+
for (const entry of buildRuntimeFileManifest({ packageRoot })) {
|
|
162
|
+
copyFile(entry.sourcePath, path.join(runtimeRoot, entry.relativePath));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function writeRuntimeMarker(runtimeRoot, packageRoot) {
|
|
167
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
|
|
168
|
+
const marker = {
|
|
169
|
+
managedBy: MANAGED_BY,
|
|
170
|
+
version: typeof pkg.version === 'string' ? pkg.version : 'unknown',
|
|
171
|
+
installedFrom: 'npm',
|
|
172
|
+
installedAt: new Date().toISOString()
|
|
173
|
+
};
|
|
174
|
+
fs.writeFileSync(path.join(runtimeRoot, MARKER_FILE), `${JSON.stringify(marker, null, 2)}\n`, 'utf8');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function verifyInstalledRuntime(stagingRoot, verifyRuntime) {
|
|
178
|
+
if (typeof verifyRuntime === 'function') {
|
|
179
|
+
verifyRuntime(stagingRoot);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const requiredFiles = [
|
|
184
|
+
'package.json',
|
|
185
|
+
'native-host/src/index.js',
|
|
186
|
+
'scripts/codex-json-agent.mjs'
|
|
187
|
+
];
|
|
188
|
+
for (const relativePath of requiredFiles) {
|
|
189
|
+
if (!fs.existsSync(path.join(stagingRoot, relativePath))) {
|
|
190
|
+
throw new Error(`Runtime verification failed; missing ${relativePath}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function fileEntry(packageRoot, relativePath) {
|
|
196
|
+
return {
|
|
197
|
+
relativePath,
|
|
198
|
+
sourcePath: path.join(packageRoot, relativePath)
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function directoryEntries(packageRoot, relativeDir) {
|
|
203
|
+
const sourceDir = path.join(packageRoot, relativeDir);
|
|
204
|
+
const entries = [];
|
|
205
|
+
for (const dirent of fs.readdirSync(sourceDir, { withFileTypes: true })) {
|
|
206
|
+
const childRelativePath = path.posix.join(relativeDir.replace(/\\/g, '/'), dirent.name);
|
|
207
|
+
const childSourcePath = path.join(packageRoot, childRelativePath);
|
|
208
|
+
if (dirent.isDirectory()) {
|
|
209
|
+
entries.push(...directoryEntries(packageRoot, childRelativePath));
|
|
210
|
+
} else if (dirent.isFile()) {
|
|
211
|
+
entries.push({ relativePath: childRelativePath, sourcePath: childSourcePath });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return entries;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function copyFile(source, target) {
|
|
218
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
219
|
+
fs.copyFileSync(source, target);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function isManagedMarker(marker) {
|
|
223
|
+
return marker && marker.managedBy === MANAGED_BY;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function getDefaultPackageRoot() {
|
|
227
|
+
return path.resolve(__dirname, '../..');
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function getBroadSystemDirs(platformPath, options = {}) {
|
|
231
|
+
if (platformPath === path.win32) {
|
|
232
|
+
const roots = ['C:\\', 'C:\\Windows', 'C:\\Program Files', 'C:\\Program Files (x86)'];
|
|
233
|
+
return roots.map((value) => platformPath.resolve(value));
|
|
234
|
+
}
|
|
235
|
+
const dirs = ['/', '/bin', '/etc', '/opt', '/private', '/sbin', '/tmp', '/usr', '/usr/local', '/var'];
|
|
236
|
+
if (options.extraUnsafeRoots) {
|
|
237
|
+
dirs.push(...options.extraUnsafeRoots);
|
|
238
|
+
}
|
|
239
|
+
return dirs.map((value) => platformPath.resolve(value));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function isUnderHostTempDir(targetRoot, platformPath) {
|
|
243
|
+
const tempDir = platformPath.resolve(os.tmpdir());
|
|
244
|
+
const parentPath = platformPath.dirname(platformPath.resolve(targetRoot));
|
|
245
|
+
const existingParent = findExistingAncestor(parentPath, platformPath);
|
|
246
|
+
if (!existingParent) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const realTempDir = realpathSyncForPlatform(os.tmpdir(), platformPath);
|
|
251
|
+
const realParent = realpathSyncForPlatform(existingParent, platformPath);
|
|
252
|
+
const lexicalUnderTemp = isSameOrDescendantPath(parentPath, tempDir, platformPath);
|
|
253
|
+
const realUnderTemp = isSameOrDescendantPath(realParent, realTempDir, platformPath);
|
|
254
|
+
|
|
255
|
+
if (!lexicalUnderTemp && !realUnderTemp) {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (lexicalUnderTemp) {
|
|
260
|
+
if (!hasNoSymlinkAncestorsBelowTemp(parentPath, tempDir, platformPath)) {
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
return realUnderTemp;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (platformPath === path.win32 && realUnderTemp) {
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function isSameOrDescendantPath(targetPath, parentPath, platformPath) {
|
|
274
|
+
const resolvedTarget = platformPath.resolve(targetPath);
|
|
275
|
+
const resolvedParent = platformPath.resolve(parentPath);
|
|
276
|
+
if (samePath(resolvedTarget, resolvedParent, platformPath)) {
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const relative = platformPath.relative(resolvedParent, resolvedTarget);
|
|
281
|
+
return Boolean(relative) && !relative.startsWith('..') && !platformPath.isAbsolute(relative);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function realpathSyncForPlatform(targetPath, platformPath) {
|
|
285
|
+
const realpathSync = fs.realpathSync.native || fs.realpathSync;
|
|
286
|
+
return platformPath.resolve(realpathSync(targetPath));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function findExistingAncestor(targetPath, platformPath = path) {
|
|
290
|
+
let current = platformPath.resolve(targetPath);
|
|
291
|
+
while (true) {
|
|
292
|
+
if (fs.existsSync(current)) {
|
|
293
|
+
return current;
|
|
294
|
+
}
|
|
295
|
+
const parent = platformPath.dirname(current);
|
|
296
|
+
if (parent === current) {
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
current = parent;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function hasNoSymlinkAncestorsBelowTemp(parentPath, tempDir, platformPath) {
|
|
304
|
+
let current = platformPath.resolve(parentPath);
|
|
305
|
+
const resolvedTempDir = platformPath.resolve(tempDir);
|
|
306
|
+
while (!samePath(current, resolvedTempDir, platformPath)) {
|
|
307
|
+
if (fs.existsSync(current)) {
|
|
308
|
+
try {
|
|
309
|
+
if (fs.lstatSync(current).isSymbolicLink()) {
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
} catch {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const parent = platformPath.dirname(current);
|
|
317
|
+
if (parent === current) {
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
current = parent;
|
|
321
|
+
}
|
|
322
|
+
return true;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function samePath(left, right, platformPath) {
|
|
326
|
+
const resolvedLeft = platformPath.resolve(left);
|
|
327
|
+
const resolvedRight = platformPath.resolve(right);
|
|
328
|
+
if (platformPath === path.win32) {
|
|
329
|
+
return resolvedLeft.toLowerCase() === resolvedRight.toLowerCase();
|
|
330
|
+
}
|
|
331
|
+
return resolvedLeft === resolvedRight;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function throwUnsafe(runtimeRoot) {
|
|
335
|
+
throw new Error(`Refusing to recursively remove unsafe runtime root: ${runtimeRoot}`);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function safeRemove(target) {
|
|
339
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function cleanupRollback(rollbackRoot, injectedCleanupRollback) {
|
|
343
|
+
if (typeof injectedCleanupRollback === 'function') {
|
|
344
|
+
injectedCleanupRollback(rollbackRoot);
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
safeRemove(rollbackRoot);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
module.exports = {
|
|
351
|
+
DEFAULT_RUNTIME_ROOT,
|
|
352
|
+
buildRuntimeFileManifest,
|
|
353
|
+
assertSafeManagedRuntimeRoot,
|
|
354
|
+
installRuntimeFromPackage,
|
|
355
|
+
uninstallManagedRuntime,
|
|
356
|
+
readRuntimeMarker
|
|
357
|
+
};
|