@cursor/july 0.1.32 → 0.1.33
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/bin/agent-serve.js +0 -0
- package/dist/docs/404.html +1 -1
- package/dist/docs/ab.html +2 -2
- package/dist/docs/assets/{app.C2aVczmo.js → app.CgZqLyWL.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.B1uHGxBZ.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.DLEzetbD.js → VPLocalSearchBox.C4KigoQn.js} +1 -1
- package/dist/docs/assets/chunks/{theme.BkOH1oMp.js → theme.C_Ty4yT7.js} +2 -2
- package/dist/docs/building-with-agents.html +2 -2
- package/dist/docs/concepts.html +2 -2
- package/dist/docs/deployment.html +2 -2
- package/dist/docs/evals.html +2 -2
- package/dist/docs/example-agents/approval-buddy.html +2 -2
- package/dist/docs/example-agents/benny.html +2 -2
- package/dist/docs/example-agents/bugbot.html +2 -2
- package/dist/docs/example-agents/codebase-wiki.html +2 -2
- package/dist/docs/example-agents/codeowners-review.html +2 -2
- package/dist/docs/example-agents/concierge.html +2 -2
- package/dist/docs/example-agents/fsd.html +2 -2
- package/dist/docs/example-agents/index.html +2 -2
- package/dist/docs/example-agents/knowledge-base.html +2 -2
- package/dist/docs/example-agents/oncall.html +2 -2
- package/dist/docs/example-agents/security-reviewer.html +2 -2
- package/dist/docs/example-agents/slack-agent.html +2 -2
- package/dist/docs/example-agents/weather-agent.html +2 -2
- package/dist/docs/guides/agent-to-agent.html +2 -2
- package/dist/docs/guides/cloud-runtime.html +2 -2
- package/dist/docs/guides/github.html +2 -2
- package/dist/docs/guides/human-in-the-loop.html +2 -2
- package/dist/docs/guides/mcp-oauth.html +2 -2
- package/dist/docs/guides/slack.html +2 -2
- package/dist/docs/guides/webhooks.html +2 -2
- package/dist/docs/hillclimbing.html +2 -2
- package/dist/docs/index.html +2 -2
- package/dist/docs/quickstart.html +2 -2
- package/dist/docs/reference/agent-config.html +2 -2
- package/dist/docs/reference/channels.html +2 -2
- package/dist/docs/reference/cli.html +2 -2
- package/dist/docs/reference/connections.html +2 -2
- package/dist/docs/reference/hooks.html +2 -2
- package/dist/docs/reference/http-api.html +2 -2
- package/dist/docs/reference/instructions.html +2 -2
- package/dist/docs/reference/playground.html +2 -2
- package/dist/docs/reference/project-layout.html +2 -2
- package/dist/docs/reference/prompt.html +2 -2
- package/dist/docs/reference/schedules.html +2 -2
- package/dist/docs/reference/sessions.html +2 -2
- package/dist/docs/reference/skills.html +2 -2
- package/dist/docs/reference/subagents.html +2 -2
- package/dist/docs/reference/tools.html +2 -2
- package/dist/docs/scaffolding-agents.html +2 -2
- package/dist/docs/storage.html +2 -2
- package/dist/docs/troubleshooting.html +2 -2
- package/dist/files-backends/agent-store-presigned-url.d.ts +11 -3
- package/dist/files-backends/agent-store-presigned-url.d.ts.map +1 -1
- package/dist/files-backends/agent-store-presigned-url.js +19 -810
- package/dist/internal/cursor-relay-core.d.ts +12 -0
- package/dist/internal/cursor-relay-core.d.ts.map +1 -1
- package/dist/internal/cursor-relay-core.js +42 -8
- package/dist/internal/review-comments.d.ts +9 -1
- package/dist/internal/review-comments.d.ts.map +1 -1
- package/dist/internal/review-comments.js +76 -0
- package/dist/internal/server.js +8 -1
- package/dist/playground/assets/index-BRhBbnd4.css +1 -0
- package/dist/playground/assets/index-CVlCAcUx.js +85 -0
- package/dist/playground/index.html +2 -2
- package/package.json +1 -22
- package/src/files-backends/agent-store-presigned-url.ts +7 -5
- package/src/internal/cursor-relay-core.ts +62 -3
- package/src/internal/review-comments.ts +102 -2
- package/src/internal/server.ts +9 -1
- package/dist/channels/slack/post-update-delivery.d.ts +0 -85
- package/dist/channels/slack/post-update-delivery.d.ts.map +0 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.xgMnlUSO.js +0 -1
- package/dist/internal/json-dir-store.d.ts +0 -32
- package/dist/internal/json-dir-store.d.ts.map +0 -1
- package/dist/internal/persistence-coordinator.d.ts +0 -127
- package/dist/internal/persistence-coordinator.d.ts.map +0 -1
- package/dist/multi-tenant.d.ts +0 -80
- package/dist/multi-tenant.d.ts.map +0 -1
- package/dist/multi-tenant.js +0 -69
- package/dist/persistence.d.ts +0 -184
- package/dist/persistence.d.ts.map +0 -1
- package/dist/playground/assets/index-50PKeJlG.css +0 -1
- package/dist/playground/assets/index-C0f2Wl1q.js +0 -85
|
@@ -1,786 +1,3 @@
|
|
|
1
|
-
// ../../node_modules/.pnpm/@connectrpc+connect@1.6.1_patch_hash=c9c7616ccfc0246b19c6537f56676d8501713cb6c94b440d13_ef7275568c8b1f1f499006dc986c70d2/node_modules/@connectrpc/connect/dist/esm/code.js
|
|
2
|
-
var Code;
|
|
3
|
-
(function(Code2) {
|
|
4
|
-
Code2[Code2["Canceled"] = 1] = "Canceled";
|
|
5
|
-
Code2[Code2["Unknown"] = 2] = "Unknown";
|
|
6
|
-
Code2[Code2["InvalidArgument"] = 3] = "InvalidArgument";
|
|
7
|
-
Code2[Code2["DeadlineExceeded"] = 4] = "DeadlineExceeded";
|
|
8
|
-
Code2[Code2["NotFound"] = 5] = "NotFound";
|
|
9
|
-
Code2[Code2["AlreadyExists"] = 6] = "AlreadyExists";
|
|
10
|
-
Code2[Code2["PermissionDenied"] = 7] = "PermissionDenied";
|
|
11
|
-
Code2[Code2["ResourceExhausted"] = 8] = "ResourceExhausted";
|
|
12
|
-
Code2[Code2["FailedPrecondition"] = 9] = "FailedPrecondition";
|
|
13
|
-
Code2[Code2["Aborted"] = 10] = "Aborted";
|
|
14
|
-
Code2[Code2["OutOfRange"] = 11] = "OutOfRange";
|
|
15
|
-
Code2[Code2["Unimplemented"] = 12] = "Unimplemented";
|
|
16
|
-
Code2[Code2["Internal"] = 13] = "Internal";
|
|
17
|
-
Code2[Code2["Unavailable"] = 14] = "Unavailable";
|
|
18
|
-
Code2[Code2["DataLoss"] = 15] = "DataLoss";
|
|
19
|
-
Code2[Code2["Unauthenticated"] = 16] = "Unauthenticated";
|
|
20
|
-
})(Code || (Code = {}));
|
|
21
|
-
|
|
22
|
-
// ../agent-store-sync/dist/bcs-transport.js
|
|
23
|
-
var DIRECTORY_LIST_PAGE_SIZE = 1e3;
|
|
24
|
-
var DIRECTORY_LIST_MAX_PAGES = 10;
|
|
25
|
-
var DIRECTORY_LIST_MAX_ENTRIES = DIRECTORY_LIST_PAGE_SIZE * DIRECTORY_LIST_MAX_PAGES;
|
|
26
|
-
|
|
27
|
-
// ../agent-store-sync/dist/conflict-events.js
|
|
28
|
-
import * as fs2 from "node:fs";
|
|
29
|
-
|
|
30
|
-
// ../agent-store-sync/dist/paths.js
|
|
31
|
-
import * as fs from "node:fs";
|
|
32
|
-
import * as os from "node:os";
|
|
33
|
-
import * as path from "node:path";
|
|
34
|
-
var PRIVATE_DIR_MODE = 448;
|
|
35
|
-
var AgentStorePathError = class extends Error {
|
|
36
|
-
constructor({ code, message, failedPath }) {
|
|
37
|
-
super(message);
|
|
38
|
-
this.name = "AgentStorePathError";
|
|
39
|
-
this.code = code;
|
|
40
|
-
this.failedPath = failedPath;
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
function assertNoSymlinkInPath(targetPath, options = {}) {
|
|
44
|
-
const deps = getDeps(options);
|
|
45
|
-
const resolved = deps.path.resolve(targetPath);
|
|
46
|
-
const segments = getPathSegments(resolved, deps.path);
|
|
47
|
-
for (const segment of segments) {
|
|
48
|
-
const stat = tryLstat(segment, deps.fs);
|
|
49
|
-
if (!stat) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (stat.isSymbolicLink()) {
|
|
53
|
-
throw new AgentStorePathError({
|
|
54
|
-
code: "symlink_refused",
|
|
55
|
-
message: `Refusing to use symlinked agent store path: ${segment}`,
|
|
56
|
-
failedPath: segment
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
function ensureSecureDirectoryChain(targetDir, options = {}) {
|
|
62
|
-
const deps = getDeps(options);
|
|
63
|
-
const resolvedTarget = deps.path.resolve(targetDir);
|
|
64
|
-
const trustedBase = options.trustedBase !== void 0 ? deps.path.resolve(options.trustedBase) : findTrustedDirectoryAncestor(resolvedTarget, deps);
|
|
65
|
-
if (resolvedTarget === trustedBase) {
|
|
66
|
-
assertRealDirectorySegment(trustedBase, deps);
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const relative = deps.path.relative(trustedBase, resolvedTarget);
|
|
70
|
-
if (relative.length === 0 || relative.startsWith("..") || deps.path.isAbsolute(relative)) {
|
|
71
|
-
throw new AgentStorePathError({
|
|
72
|
-
code: "invalid_store_base",
|
|
73
|
-
message: `Refusing to create ${resolvedTarget} outside trusted base ${trustedBase}`,
|
|
74
|
-
failedPath: resolvedTarget
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
const segments = relative.split(deps.path.sep).filter((segment) => segment.length > 0);
|
|
78
|
-
let current = trustedBase;
|
|
79
|
-
for (const segment of segments) {
|
|
80
|
-
assertRealDirectorySegment(current, deps);
|
|
81
|
-
current = deps.path.join(current, segment);
|
|
82
|
-
ensureRealDirectorySegment(current, deps);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
function getDeps(options) {
|
|
86
|
-
var _a;
|
|
87
|
-
var _b, _c, _d, _e, _f, _g, _h;
|
|
88
|
-
return {
|
|
89
|
-
env: (_b = options.env) !== null && _b !== void 0 ? _b : process.env,
|
|
90
|
-
fs: (_c = options.fs) !== null && _c !== void 0 ? _c : fs,
|
|
91
|
-
geteuid: (_d = options.geteuid) !== null && _d !== void 0 ? _d : (_a = process.geteuid) === null || _a === void 0 ? void 0 : _a.bind(process),
|
|
92
|
-
osTmpdir: (_e = options.osTmpdir) !== null && _e !== void 0 ? _e : os.tmpdir,
|
|
93
|
-
path: (_f = options.path) !== null && _f !== void 0 ? _f : path,
|
|
94
|
-
platform: (_g = options.platform) !== null && _g !== void 0 ? _g : process.platform,
|
|
95
|
-
windowsAcl: (_h = options.windowsAcl) !== null && _h !== void 0 ? _h : {}
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
function assertDirectoryStat(targetPath, stat) {
|
|
99
|
-
if (stat.isSymbolicLink()) {
|
|
100
|
-
throw new AgentStorePathError({
|
|
101
|
-
code: "symlink_refused",
|
|
102
|
-
message: `Refusing to use symlinked agent store path: ${targetPath}`,
|
|
103
|
-
failedPath: targetPath
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
if (!stat.isDirectory()) {
|
|
107
|
-
throw new AgentStorePathError({
|
|
108
|
-
code: "not_directory",
|
|
109
|
-
message: `Agent store path is not a directory: ${targetPath}`,
|
|
110
|
-
failedPath: targetPath
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
function findTrustedDirectoryAncestor(targetPath, deps) {
|
|
115
|
-
var _a;
|
|
116
|
-
const segments = getPathSegments(deps.path.resolve(targetPath), deps.path);
|
|
117
|
-
let trusted = (_a = segments[0]) !== null && _a !== void 0 ? _a : deps.path.resolve(targetPath);
|
|
118
|
-
for (let i = 1; i < segments.length; i++) {
|
|
119
|
-
const segment = segments[i];
|
|
120
|
-
const stat = tryLstat(segment, deps.fs);
|
|
121
|
-
if (!stat) {
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
if (stat.isSymbolicLink()) {
|
|
125
|
-
throw new AgentStorePathError({
|
|
126
|
-
code: "symlink_refused",
|
|
127
|
-
message: `Refusing to use symlinked agent store path: ${segment}`,
|
|
128
|
-
failedPath: segment
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
if (!stat.isDirectory()) {
|
|
132
|
-
throw new AgentStorePathError({
|
|
133
|
-
code: "not_directory",
|
|
134
|
-
message: `Agent store path is not a directory: ${segment}`,
|
|
135
|
-
failedPath: segment
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
trusted = segment;
|
|
139
|
-
}
|
|
140
|
-
return trusted;
|
|
141
|
-
}
|
|
142
|
-
function assertRealDirectorySegment(targetPath, deps) {
|
|
143
|
-
const stat = tryLstat(targetPath, deps.fs);
|
|
144
|
-
if (!stat) {
|
|
145
|
-
throw new AgentStorePathError({
|
|
146
|
-
code: "not_directory",
|
|
147
|
-
message: `Trusted directory does not exist: ${targetPath}`,
|
|
148
|
-
failedPath: targetPath
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
assertDirectoryStat(targetPath, stat);
|
|
152
|
-
}
|
|
153
|
-
function ensureRealDirectorySegment(targetPath, deps) {
|
|
154
|
-
let stat = tryLstat(targetPath, deps.fs);
|
|
155
|
-
if (!stat) {
|
|
156
|
-
try {
|
|
157
|
-
deps.fs.mkdirSync(targetPath, { mode: PRIVATE_DIR_MODE });
|
|
158
|
-
} catch (error) {
|
|
159
|
-
if (!isNodeError(error) || error.code !== "EEXIST") {
|
|
160
|
-
throw error;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
stat = tryLstat(targetPath, deps.fs);
|
|
164
|
-
if (!stat) {
|
|
165
|
-
throw new AgentStorePathError({
|
|
166
|
-
code: "not_directory",
|
|
167
|
-
message: `Failed to create directory: ${targetPath}`,
|
|
168
|
-
failedPath: targetPath
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
assertDirectoryStat(targetPath, stat);
|
|
173
|
-
}
|
|
174
|
-
function getPathSegments(targetPath, pathModule) {
|
|
175
|
-
const root = pathModule.parse(targetPath).root;
|
|
176
|
-
const rest = targetPath.slice(root.length);
|
|
177
|
-
const parts = rest.split(/[\\/]+/).filter(Boolean);
|
|
178
|
-
const segments = [];
|
|
179
|
-
let current = root;
|
|
180
|
-
if (root) {
|
|
181
|
-
segments.push(root);
|
|
182
|
-
}
|
|
183
|
-
for (const part of parts) {
|
|
184
|
-
current = current === root ? pathModule.join(root, part) : pathModule.join(current, part);
|
|
185
|
-
segments.push(current);
|
|
186
|
-
}
|
|
187
|
-
return segments;
|
|
188
|
-
}
|
|
189
|
-
function tryLstat(targetPath, fsModule) {
|
|
190
|
-
try {
|
|
191
|
-
return fsModule.lstatSync(targetPath);
|
|
192
|
-
} catch (err) {
|
|
193
|
-
if (isNodeError(err) && err.code === "ENOENT") {
|
|
194
|
-
return void 0;
|
|
195
|
-
}
|
|
196
|
-
throw err;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
function isNodeError(err) {
|
|
200
|
-
return err instanceof Error && typeof err.code === "string";
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// ../agent-store-sync/dist/conflict-events.js
|
|
204
|
-
var CONFLICT_JOURNAL_ROTATE_BYTES = 4 * 1024 * 1024;
|
|
205
|
-
var O_NOFOLLOW_FLAG = fs2.constants.O_NOFOLLOW;
|
|
206
|
-
|
|
207
|
-
// ../agent-store-sync/dist/local-index.js
|
|
208
|
-
import * as fs4 from "node:fs";
|
|
209
|
-
import * as path3 from "node:path";
|
|
210
|
-
|
|
211
|
-
// ../agent-store-sync/dist/secure-open.js
|
|
212
|
-
import * as fs3 from "node:fs";
|
|
213
|
-
import * as path2 from "node:path";
|
|
214
|
-
function openSecureSqlitePath(resolvedPath, mode) {
|
|
215
|
-
const parentDir = path2.dirname(resolvedPath);
|
|
216
|
-
const parentDirFd = openParentDirectoryNoFollow(parentDir);
|
|
217
|
-
let cleanupParentFd = true;
|
|
218
|
-
try {
|
|
219
|
-
const parentStat = fs3.fstatSync(parentDirFd);
|
|
220
|
-
if (!parentStat.isDirectory()) {
|
|
221
|
-
throw new AgentStorePathError({
|
|
222
|
-
code: "symlink_refused",
|
|
223
|
-
message: `Refusing to open sqlite under non-directory parent: ${parentDir}`,
|
|
224
|
-
failedPath: parentDir
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
const parentIdentity = {
|
|
228
|
-
dev: parentStat.dev,
|
|
229
|
-
ino: parentStat.ino
|
|
230
|
-
};
|
|
231
|
-
assertParentDirInodeMatchesPath(parentIdentity, parentDir);
|
|
232
|
-
const leafFd = openRegularFileNoFollowCreate(resolvedPath, mode);
|
|
233
|
-
let leafIdentity;
|
|
234
|
-
try {
|
|
235
|
-
const leafStat = fs3.fstatSync(leafFd);
|
|
236
|
-
if (!leafStat.isFile()) {
|
|
237
|
-
throw new AgentStorePathError({
|
|
238
|
-
code: "symlink_refused",
|
|
239
|
-
message: `Refusing to open non-regular sqlite path: ${resolvedPath}`,
|
|
240
|
-
failedPath: resolvedPath
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
assertResolvedPathStillCanonical(resolvedPath);
|
|
244
|
-
leafIdentity = { dev: leafStat.dev, ino: leafStat.ino };
|
|
245
|
-
} finally {
|
|
246
|
-
fs3.closeSync(leafFd);
|
|
247
|
-
}
|
|
248
|
-
let verified = false;
|
|
249
|
-
let closed = false;
|
|
250
|
-
const closeParent = () => {
|
|
251
|
-
if (closed) {
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
closed = true;
|
|
255
|
-
fs3.closeSync(parentDirFd);
|
|
256
|
-
};
|
|
257
|
-
const verifyOpenedInode = () => {
|
|
258
|
-
if (verified) {
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
assertParentDirInodeMatchesPath(parentIdentity, parentDir);
|
|
262
|
-
assertLeafInodeUnchanged(resolvedPath, leafIdentity);
|
|
263
|
-
verified = true;
|
|
264
|
-
};
|
|
265
|
-
cleanupParentFd = false;
|
|
266
|
-
return {
|
|
267
|
-
sqlitePath: resolvedPath,
|
|
268
|
-
verifyOpenedInode,
|
|
269
|
-
close: closeParent
|
|
270
|
-
};
|
|
271
|
-
} finally {
|
|
272
|
-
if (cleanupParentFd) {
|
|
273
|
-
fs3.closeSync(parentDirFd);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
function openRegularFileNoFollowCreate(filePath, mode) {
|
|
278
|
-
const flags = symlinkSafeOpenCreateFlags();
|
|
279
|
-
try {
|
|
280
|
-
return fs3.openSync(filePath, flags, mode);
|
|
281
|
-
} catch (error) {
|
|
282
|
-
if (isNofollowSymlinkRefusal(error)) {
|
|
283
|
-
throw new AgentStorePathError({
|
|
284
|
-
code: "symlink_refused",
|
|
285
|
-
message: `Refusing to open symlinked path: ${filePath}`,
|
|
286
|
-
failedPath: filePath
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
throw error;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
function openParentDirectoryNoFollow(parentDir) {
|
|
293
|
-
const flags = symlinkSafeDirectoryOpenFlags();
|
|
294
|
-
try {
|
|
295
|
-
return fs3.openSync(parentDir, flags);
|
|
296
|
-
} catch (error) {
|
|
297
|
-
if (isNofollowSymlinkRefusal(error) || isNodeError2(error) && error.code === "ENOTDIR" && isSymlink(parentDir)) {
|
|
298
|
-
throw new AgentStorePathError({
|
|
299
|
-
code: "symlink_refused",
|
|
300
|
-
message: `Refusing to open sqlite under symlinked parent: ${parentDir}`,
|
|
301
|
-
failedPath: parentDir
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
throw error;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
function isSymlink(targetPath) {
|
|
308
|
-
try {
|
|
309
|
-
return fs3.lstatSync(targetPath).isSymbolicLink();
|
|
310
|
-
} catch (_a) {
|
|
311
|
-
return false;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
function assertResolvedPathStillCanonical(resolvedPath) {
|
|
315
|
-
let realpath;
|
|
316
|
-
try {
|
|
317
|
-
realpath = fs3.realpathSync.native(resolvedPath);
|
|
318
|
-
} catch (error) {
|
|
319
|
-
throw new AgentStorePathError({
|
|
320
|
-
code: "symlink_refused",
|
|
321
|
-
message: `Unable to resolve realpath for ${resolvedPath}: ${error instanceof Error ? error.message : String(error)}`,
|
|
322
|
-
failedPath: resolvedPath
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
|
-
if (realpath !== resolvedPath) {
|
|
326
|
-
throw new AgentStorePathError({
|
|
327
|
-
code: "symlink_refused",
|
|
328
|
-
message: `Refusing path with symlinked parent: ${resolvedPath} -> ${realpath}`,
|
|
329
|
-
failedPath: resolvedPath
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
function assertLeafInodeUnchanged(resolvedPath, expected) {
|
|
334
|
-
const flags = symlinkSafeReopenFlags();
|
|
335
|
-
let fd;
|
|
336
|
-
try {
|
|
337
|
-
fd = fs3.openSync(resolvedPath, flags);
|
|
338
|
-
} catch (error) {
|
|
339
|
-
if (isNofollowSymlinkRefusal(error)) {
|
|
340
|
-
throw new AgentStorePathError({
|
|
341
|
-
code: "symlink_refused",
|
|
342
|
-
message: `Sqlite path became symlinked between open and verification: ${resolvedPath}`,
|
|
343
|
-
failedPath: resolvedPath
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
throw error;
|
|
347
|
-
}
|
|
348
|
-
try {
|
|
349
|
-
const stat = fs3.fstatSync(fd);
|
|
350
|
-
assertResolvedPathStillCanonical(resolvedPath);
|
|
351
|
-
if (stat.dev !== expected.dev || stat.ino !== expected.ino) {
|
|
352
|
-
throw new AgentStorePathError({
|
|
353
|
-
code: "symlink_refused",
|
|
354
|
-
message: `Sqlite path inode drifted between open and verification (expected dev=${expected.dev} ino=${expected.ino}, got dev=${stat.dev} ino=${stat.ino}): ${resolvedPath}`,
|
|
355
|
-
failedPath: resolvedPath
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
} finally {
|
|
359
|
-
fs3.closeSync(fd);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
function assertParentDirInodeMatchesPath(expected, parentDir) {
|
|
363
|
-
let pathStat;
|
|
364
|
-
try {
|
|
365
|
-
pathStat = fs3.lstatSync(parentDir);
|
|
366
|
-
} catch (error) {
|
|
367
|
-
throw new AgentStorePathError({
|
|
368
|
-
code: "symlink_refused",
|
|
369
|
-
message: `Unable to lstat parent directory ${parentDir}: ${error instanceof Error ? error.message : String(error)}`,
|
|
370
|
-
failedPath: parentDir
|
|
371
|
-
});
|
|
372
|
-
}
|
|
373
|
-
if (pathStat.isSymbolicLink()) {
|
|
374
|
-
throw new AgentStorePathError({
|
|
375
|
-
code: "symlink_refused",
|
|
376
|
-
message: `Parent directory became symlinked between open and verification: ${parentDir}`,
|
|
377
|
-
failedPath: parentDir
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
if (pathStat.dev !== expected.dev || pathStat.ino !== expected.ino) {
|
|
381
|
-
throw new AgentStorePathError({
|
|
382
|
-
code: "symlink_refused",
|
|
383
|
-
message: `Parent directory inode drifted between open and verification (expected dev=${expected.dev} ino=${expected.ino}, got dev=${pathStat.dev} ino=${pathStat.ino}): ${parentDir}`,
|
|
384
|
-
failedPath: parentDir
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
function symlinkSafeOpenCreateFlags() {
|
|
389
|
-
var _a;
|
|
390
|
-
const constants3 = fs3.constants;
|
|
391
|
-
let flags = (_a = constants3.O_RDWR) !== null && _a !== void 0 ? _a : 0;
|
|
392
|
-
if (typeof constants3.O_CREAT === "number") {
|
|
393
|
-
flags |= constants3.O_CREAT;
|
|
394
|
-
}
|
|
395
|
-
if (typeof constants3.O_NOFOLLOW === "number") {
|
|
396
|
-
flags |= constants3.O_NOFOLLOW;
|
|
397
|
-
}
|
|
398
|
-
if (typeof constants3.O_CLOEXEC === "number") {
|
|
399
|
-
flags |= constants3.O_CLOEXEC;
|
|
400
|
-
}
|
|
401
|
-
return flags;
|
|
402
|
-
}
|
|
403
|
-
function symlinkSafeReopenFlags() {
|
|
404
|
-
var _a;
|
|
405
|
-
const constants3 = fs3.constants;
|
|
406
|
-
let flags = (_a = constants3.O_RDONLY) !== null && _a !== void 0 ? _a : 0;
|
|
407
|
-
if (typeof constants3.O_NOFOLLOW === "number") {
|
|
408
|
-
flags |= constants3.O_NOFOLLOW;
|
|
409
|
-
}
|
|
410
|
-
if (typeof constants3.O_CLOEXEC === "number") {
|
|
411
|
-
flags |= constants3.O_CLOEXEC;
|
|
412
|
-
}
|
|
413
|
-
return flags;
|
|
414
|
-
}
|
|
415
|
-
function symlinkSafeDirectoryOpenFlags() {
|
|
416
|
-
var _a;
|
|
417
|
-
const constants3 = fs3.constants;
|
|
418
|
-
let flags = (_a = constants3.O_RDONLY) !== null && _a !== void 0 ? _a : 0;
|
|
419
|
-
if (typeof constants3.O_DIRECTORY === "number") {
|
|
420
|
-
flags |= constants3.O_DIRECTORY;
|
|
421
|
-
}
|
|
422
|
-
if (typeof constants3.O_NOFOLLOW === "number") {
|
|
423
|
-
flags |= constants3.O_NOFOLLOW;
|
|
424
|
-
}
|
|
425
|
-
if (typeof constants3.O_CLOEXEC === "number") {
|
|
426
|
-
flags |= constants3.O_CLOEXEC;
|
|
427
|
-
}
|
|
428
|
-
return flags;
|
|
429
|
-
}
|
|
430
|
-
function isNofollowSymlinkRefusal(error) {
|
|
431
|
-
if (!isNodeError2(error)) {
|
|
432
|
-
return false;
|
|
433
|
-
}
|
|
434
|
-
if (error.code === "ELOOP" || error.code === "EMLINK") {
|
|
435
|
-
return true;
|
|
436
|
-
}
|
|
437
|
-
if (error.code === "EPERM" && hasNofollowConstant()) {
|
|
438
|
-
return true;
|
|
439
|
-
}
|
|
440
|
-
return false;
|
|
441
|
-
}
|
|
442
|
-
function hasNofollowConstant() {
|
|
443
|
-
return typeof fs3.constants.O_NOFOLLOW === "number";
|
|
444
|
-
}
|
|
445
|
-
function isNodeError2(error) {
|
|
446
|
-
return error instanceof Error && typeof error.code === "string";
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
// ../agent-store-sync/dist/local-index.js
|
|
450
|
-
var CURRENT_SCHEMA_VERSION = 3;
|
|
451
|
-
var PRIVATE_FILE_MODE = 384;
|
|
452
|
-
var META_DELETION_ARMED = "deletion_armed";
|
|
453
|
-
var META_FILES_ROOT_DEV = "files_root_dev";
|
|
454
|
-
var META_FILES_ROOT_INO = "files_root_ino";
|
|
455
|
-
var LocalIndexError = class extends Error {
|
|
456
|
-
constructor(code, message) {
|
|
457
|
-
super(message);
|
|
458
|
-
this.code = code;
|
|
459
|
-
this.name = "LocalIndexError";
|
|
460
|
-
}
|
|
461
|
-
};
|
|
462
|
-
var LocalAgentStoreIndex = class _LocalAgentStoreIndex {
|
|
463
|
-
static open(indexPath, options) {
|
|
464
|
-
const resolvedPath = path3.resolve(indexPath);
|
|
465
|
-
const existing = _LocalAgentStoreIndex.openHandles.get(resolvedPath);
|
|
466
|
-
if (existing !== void 0 && !existing.closed) {
|
|
467
|
-
return existing;
|
|
468
|
-
}
|
|
469
|
-
assertNoSymlinkInPath(resolvedPath);
|
|
470
|
-
ensureSecureDirectoryChain(path3.dirname(resolvedPath));
|
|
471
|
-
assertNoSymlinkInPath(resolvedPath);
|
|
472
|
-
const opened = openSecureSqlitePath(resolvedPath, PRIVATE_FILE_MODE);
|
|
473
|
-
let db;
|
|
474
|
-
try {
|
|
475
|
-
db = new options.sqlite(opened.sqlitePath);
|
|
476
|
-
opened.verifyOpenedInode();
|
|
477
|
-
restrictIndexFileModes(resolvedPath);
|
|
478
|
-
const index = new _LocalAgentStoreIndex(resolvedPath, db);
|
|
479
|
-
index.opened = opened;
|
|
480
|
-
index.migrate();
|
|
481
|
-
index.restrictFileModes();
|
|
482
|
-
_LocalAgentStoreIndex.openHandles.set(resolvedPath, index);
|
|
483
|
-
return index;
|
|
484
|
-
} catch (error) {
|
|
485
|
-
db === null || db === void 0 ? void 0 : db.close();
|
|
486
|
-
opened.close();
|
|
487
|
-
throw error;
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
constructor(indexPath, db) {
|
|
491
|
-
this.indexPath = indexPath;
|
|
492
|
-
this.db = db;
|
|
493
|
-
this.closed = false;
|
|
494
|
-
}
|
|
495
|
-
close() {
|
|
496
|
-
var _a;
|
|
497
|
-
if (this.closed) {
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
this.db.close();
|
|
501
|
-
(_a = this.opened) === null || _a === void 0 ? void 0 : _a.close();
|
|
502
|
-
this.opened = void 0;
|
|
503
|
-
this.closed = true;
|
|
504
|
-
_LocalAgentStoreIndex.openHandles.delete(this.indexPath);
|
|
505
|
-
}
|
|
506
|
-
getFile(relPath) {
|
|
507
|
-
const row = this.db.prepare("SELECT rel_path, last_synced_sha, last_seen_etag, size, last_synced_ms, direction, state, tombstone_etag, deleted_at_ms FROM files WHERE rel_path = ?").get(relPath);
|
|
508
|
-
return row === void 0 ? void 0 : fileEntryFromRow(row);
|
|
509
|
-
}
|
|
510
|
-
listFiles() {
|
|
511
|
-
const rows = this.db.prepare("SELECT rel_path, last_synced_sha, last_seen_etag, size, last_synced_ms, direction, state, tombstone_etag, deleted_at_ms FROM files ORDER BY rel_path ASC").all();
|
|
512
|
-
return rows.map(fileEntryFromRow);
|
|
513
|
-
}
|
|
514
|
-
upsertFile(entry) {
|
|
515
|
-
var _a, _b;
|
|
516
|
-
const state = (_a = entry.state) !== null && _a !== void 0 ? _a : "live";
|
|
517
|
-
const tombstoneEtag = state === "tombstoned" ? entry.tombstoneEtag : null;
|
|
518
|
-
const deletedAtMs = state === "tombstoned" ? entry.deletedAtMs : null;
|
|
519
|
-
this.db.prepare(`
|
|
520
|
-
INSERT INTO files (
|
|
521
|
-
rel_path,
|
|
522
|
-
last_synced_sha,
|
|
523
|
-
last_seen_etag,
|
|
524
|
-
size,
|
|
525
|
-
last_synced_ms,
|
|
526
|
-
direction,
|
|
527
|
-
state,
|
|
528
|
-
tombstone_etag,
|
|
529
|
-
deleted_at_ms
|
|
530
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
531
|
-
ON CONFLICT(rel_path) DO UPDATE SET
|
|
532
|
-
last_synced_sha = excluded.last_synced_sha,
|
|
533
|
-
last_seen_etag = excluded.last_seen_etag,
|
|
534
|
-
size = excluded.size,
|
|
535
|
-
last_synced_ms = excluded.last_synced_ms,
|
|
536
|
-
direction = excluded.direction,
|
|
537
|
-
state = excluded.state,
|
|
538
|
-
tombstone_etag = excluded.tombstone_etag,
|
|
539
|
-
deleted_at_ms = excluded.deleted_at_ms
|
|
540
|
-
`).run(entry.relPath, entry.lastSyncedSha, (_b = entry.lastSeenEtag) !== null && _b !== void 0 ? _b : null, entry.size, entry.lastSyncedMs, entry.direction, state, tombstoneEtag !== null && tombstoneEtag !== void 0 ? tombstoneEtag : null, deletedAtMs !== null && deletedAtMs !== void 0 ? deletedAtMs : null);
|
|
541
|
-
this.restrictFileModes();
|
|
542
|
-
}
|
|
543
|
-
listPendingDeletes() {
|
|
544
|
-
const rows = this.db.prepare("SELECT rel_path, base_etag, requested_at_ms, mutation_id FROM pending_deletes ORDER BY rel_path ASC").all();
|
|
545
|
-
return rows.map((row) => {
|
|
546
|
-
var _a;
|
|
547
|
-
return {
|
|
548
|
-
relPath: row.rel_path,
|
|
549
|
-
baseEtag: row.base_etag,
|
|
550
|
-
requestedAtMs: row.requested_at_ms,
|
|
551
|
-
mutationId: (_a = row.mutation_id) !== null && _a !== void 0 ? _a : void 0
|
|
552
|
-
};
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
hasPendingDelete(relPath) {
|
|
556
|
-
const row = this.db.prepare("SELECT rel_path FROM pending_deletes WHERE rel_path = ?").get(relPath);
|
|
557
|
-
return row !== void 0;
|
|
558
|
-
}
|
|
559
|
-
upsertPendingDelete(entry) {
|
|
560
|
-
var _a;
|
|
561
|
-
this.db.prepare(`
|
|
562
|
-
INSERT INTO pending_deletes (
|
|
563
|
-
rel_path,
|
|
564
|
-
base_etag,
|
|
565
|
-
requested_at_ms,
|
|
566
|
-
mutation_id
|
|
567
|
-
) VALUES (?, ?, ?, ?)
|
|
568
|
-
ON CONFLICT(rel_path) DO UPDATE SET
|
|
569
|
-
base_etag = excluded.base_etag,
|
|
570
|
-
requested_at_ms = excluded.requested_at_ms,
|
|
571
|
-
mutation_id = excluded.mutation_id
|
|
572
|
-
`).run(entry.relPath, entry.baseEtag, entry.requestedAtMs, (_a = entry.mutationId) !== null && _a !== void 0 ? _a : null);
|
|
573
|
-
this.restrictFileModes();
|
|
574
|
-
}
|
|
575
|
-
removePendingDelete(relPath) {
|
|
576
|
-
const result = this.db.prepare("DELETE FROM pending_deletes WHERE rel_path = ?").run(relPath);
|
|
577
|
-
return result.changes > 0;
|
|
578
|
-
}
|
|
579
|
-
/** Recovery-mode escape hatch: drop every unflushed deletion intent. */
|
|
580
|
-
clearPendingDeletes() {
|
|
581
|
-
const result = this.db.prepare("DELETE FROM pending_deletes").run();
|
|
582
|
-
return result.changes;
|
|
583
|
-
}
|
|
584
|
-
/**
|
|
585
|
-
* Durable recovery step: unarm scan-based deletion, forget the recorded
|
|
586
|
-
* `files/` root identity, and drop every unflushed deletion intent in one
|
|
587
|
-
* shot. Called when the identity guard trips so a subsequent round starts
|
|
588
|
-
* from the legacy restore semantics until a clean round re-arms. Returns
|
|
589
|
-
* the number of pending deletes cleared.
|
|
590
|
-
*/
|
|
591
|
-
disarmDeletionAndClearPending() {
|
|
592
|
-
const disarm = this.db.transaction(() => {
|
|
593
|
-
this.db.prepare(`
|
|
594
|
-
INSERT INTO meta (key, value)
|
|
595
|
-
VALUES (?, ?)
|
|
596
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value
|
|
597
|
-
`).run(META_DELETION_ARMED, "0");
|
|
598
|
-
this.db.prepare("DELETE FROM meta WHERE key = ?").run(META_FILES_ROOT_DEV);
|
|
599
|
-
this.db.prepare("DELETE FROM meta WHERE key = ?").run(META_FILES_ROOT_INO);
|
|
600
|
-
return this.db.prepare("DELETE FROM pending_deletes").run().changes;
|
|
601
|
-
});
|
|
602
|
-
const cleared = disarm();
|
|
603
|
-
this.restrictFileModes();
|
|
604
|
-
return cleared;
|
|
605
|
-
}
|
|
606
|
-
/**
|
|
607
|
-
* Arms scan-based deletion and records the `files/` root identity in one
|
|
608
|
-
* SQLite transaction so a crash cannot leave `deletion_armed=1` without
|
|
609
|
-
* both identity keys (which the next round would treat as compromised).
|
|
610
|
-
*/
|
|
611
|
-
armDeletionWithIdentity(identity) {
|
|
612
|
-
const arm = this.db.transaction(() => {
|
|
613
|
-
const upsert = this.db.prepare(`
|
|
614
|
-
INSERT INTO meta (key, value)
|
|
615
|
-
VALUES (?, ?)
|
|
616
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value
|
|
617
|
-
`);
|
|
618
|
-
upsert.run(META_DELETION_ARMED, "1");
|
|
619
|
-
upsert.run(META_FILES_ROOT_DEV, String(identity.dev));
|
|
620
|
-
upsert.run(META_FILES_ROOT_INO, String(identity.ino));
|
|
621
|
-
});
|
|
622
|
-
arm();
|
|
623
|
-
this.restrictFileModes();
|
|
624
|
-
}
|
|
625
|
-
deleteFile(relPath) {
|
|
626
|
-
const result = this.db.prepare("DELETE FROM files WHERE rel_path = ?").run(relPath);
|
|
627
|
-
if (result.changes > 0) {
|
|
628
|
-
this.restrictFileModes();
|
|
629
|
-
}
|
|
630
|
-
return result.changes > 0;
|
|
631
|
-
}
|
|
632
|
-
getMeta(key) {
|
|
633
|
-
const row = this.db.prepare("SELECT value FROM meta WHERE key = ?").get(key);
|
|
634
|
-
return row === null || row === void 0 ? void 0 : row.value;
|
|
635
|
-
}
|
|
636
|
-
setMeta(entry) {
|
|
637
|
-
this.db.prepare(`
|
|
638
|
-
INSERT INTO meta (key, value)
|
|
639
|
-
VALUES (?, ?)
|
|
640
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value
|
|
641
|
-
`).run(entry.key, entry.value);
|
|
642
|
-
this.restrictFileModes();
|
|
643
|
-
}
|
|
644
|
-
migrate() {
|
|
645
|
-
this.db.pragma("journal_mode = WAL");
|
|
646
|
-
this.db.pragma("synchronous = NORMAL");
|
|
647
|
-
this.db.pragma("busy_timeout = 5000");
|
|
648
|
-
this.db.exec(`
|
|
649
|
-
CREATE TABLE IF NOT EXISTS meta (
|
|
650
|
-
key TEXT PRIMARY KEY,
|
|
651
|
-
value TEXT NOT NULL
|
|
652
|
-
);
|
|
653
|
-
`);
|
|
654
|
-
const version = this.getMeta("schema_version");
|
|
655
|
-
if (version === void 0) {
|
|
656
|
-
this.createCurrentSchema();
|
|
657
|
-
return;
|
|
658
|
-
}
|
|
659
|
-
const parsedVersion = Number(version);
|
|
660
|
-
if (!Number.isInteger(parsedVersion) || parsedVersion < 1 || parsedVersion > CURRENT_SCHEMA_VERSION) {
|
|
661
|
-
throw new LocalIndexError("unsupported_schema_version", `Unsupported agent store index schema version: ${version}`);
|
|
662
|
-
}
|
|
663
|
-
this.createFilesTableIfNeeded();
|
|
664
|
-
if (parsedVersion < 2) {
|
|
665
|
-
this.migrateV1ToV2();
|
|
666
|
-
}
|
|
667
|
-
if (parsedVersion < 3) {
|
|
668
|
-
this.migrateV2ToV3();
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
createCurrentSchema() {
|
|
672
|
-
this.createFilesTableIfNeeded();
|
|
673
|
-
this.createPendingDeletesTableIfNeeded();
|
|
674
|
-
this.setMeta({
|
|
675
|
-
key: "schema_version",
|
|
676
|
-
value: String(CURRENT_SCHEMA_VERSION)
|
|
677
|
-
});
|
|
678
|
-
}
|
|
679
|
-
createFilesTableIfNeeded() {
|
|
680
|
-
this.db.exec(`
|
|
681
|
-
CREATE TABLE IF NOT EXISTS files (
|
|
682
|
-
rel_path TEXT PRIMARY KEY,
|
|
683
|
-
last_synced_sha TEXT NOT NULL,
|
|
684
|
-
last_seen_etag TEXT,
|
|
685
|
-
size INTEGER NOT NULL,
|
|
686
|
-
last_synced_ms INTEGER NOT NULL,
|
|
687
|
-
direction TEXT NOT NULL CHECK(direction IN ('pulled', 'pushed')),
|
|
688
|
-
state TEXT NOT NULL DEFAULT 'live' CHECK(state IN ('live', 'tombstoned')),
|
|
689
|
-
tombstone_etag TEXT,
|
|
690
|
-
deleted_at_ms INTEGER
|
|
691
|
-
);
|
|
692
|
-
`);
|
|
693
|
-
}
|
|
694
|
-
createPendingDeletesTableIfNeeded() {
|
|
695
|
-
this.db.exec(`
|
|
696
|
-
CREATE TABLE IF NOT EXISTS pending_deletes (
|
|
697
|
-
rel_path TEXT PRIMARY KEY,
|
|
698
|
-
base_etag TEXT NOT NULL,
|
|
699
|
-
requested_at_ms INTEGER NOT NULL,
|
|
700
|
-
mutation_id TEXT
|
|
701
|
-
);
|
|
702
|
-
`);
|
|
703
|
-
}
|
|
704
|
-
migrateV1ToV2() {
|
|
705
|
-
const columns = this.db.prepare("PRAGMA table_info(files)").all();
|
|
706
|
-
if (columns.some((column) => column.name === "last_seen_sha")) {
|
|
707
|
-
this.db.exec("ALTER TABLE files RENAME COLUMN last_seen_sha TO last_synced_sha");
|
|
708
|
-
}
|
|
709
|
-
if (!columns.some((column) => column.name === "last_seen_etag")) {
|
|
710
|
-
this.db.exec("ALTER TABLE files ADD COLUMN last_seen_etag TEXT");
|
|
711
|
-
}
|
|
712
|
-
this.setMeta({
|
|
713
|
-
key: "schema_version",
|
|
714
|
-
value: "2"
|
|
715
|
-
});
|
|
716
|
-
}
|
|
717
|
-
migrateV2ToV3() {
|
|
718
|
-
const columns = this.db.prepare("PRAGMA table_info(files)").all();
|
|
719
|
-
if (!columns.some((column) => column.name === "state")) {
|
|
720
|
-
this.db.exec("ALTER TABLE files ADD COLUMN state TEXT NOT NULL DEFAULT 'live' CHECK(state IN ('live', 'tombstoned'))");
|
|
721
|
-
}
|
|
722
|
-
if (!columns.some((column) => column.name === "tombstone_etag")) {
|
|
723
|
-
this.db.exec("ALTER TABLE files ADD COLUMN tombstone_etag TEXT");
|
|
724
|
-
}
|
|
725
|
-
if (!columns.some((column) => column.name === "deleted_at_ms")) {
|
|
726
|
-
this.db.exec("ALTER TABLE files ADD COLUMN deleted_at_ms INTEGER");
|
|
727
|
-
}
|
|
728
|
-
this.createPendingDeletesTableIfNeeded();
|
|
729
|
-
this.setMeta({
|
|
730
|
-
key: "schema_version",
|
|
731
|
-
value: String(CURRENT_SCHEMA_VERSION)
|
|
732
|
-
});
|
|
733
|
-
}
|
|
734
|
-
restrictFileModes() {
|
|
735
|
-
restrictIndexFileModes(this.indexPath);
|
|
736
|
-
}
|
|
737
|
-
};
|
|
738
|
-
LocalAgentStoreIndex.openHandles = /* @__PURE__ */ new Map();
|
|
739
|
-
function fileEntryFromRow(row) {
|
|
740
|
-
var _a, _b, _c;
|
|
741
|
-
return {
|
|
742
|
-
relPath: row.rel_path,
|
|
743
|
-
lastSyncedSha: row.last_synced_sha,
|
|
744
|
-
lastSeenEtag: (_a = row.last_seen_etag) !== null && _a !== void 0 ? _a : void 0,
|
|
745
|
-
size: row.size,
|
|
746
|
-
lastSyncedMs: row.last_synced_ms,
|
|
747
|
-
direction: row.direction,
|
|
748
|
-
state: row.state,
|
|
749
|
-
tombstoneEtag: (_b = row.tombstone_etag) !== null && _b !== void 0 ? _b : void 0,
|
|
750
|
-
deletedAtMs: (_c = row.deleted_at_ms) !== null && _c !== void 0 ? _c : void 0
|
|
751
|
-
};
|
|
752
|
-
}
|
|
753
|
-
function restrictIndexFileModes(indexPath) {
|
|
754
|
-
for (const filePath of [indexPath, `${indexPath}-wal`, `${indexPath}-shm`]) {
|
|
755
|
-
if (fs4.existsSync(filePath)) {
|
|
756
|
-
fs4.chmodSync(filePath, PRIVATE_FILE_MODE);
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
// ../agent-store-sync/dist/metrics-emitter.js
|
|
762
|
-
var NOOP_METRICS_EMITTER = Object.freeze({
|
|
763
|
-
onDiskFull() {
|
|
764
|
-
},
|
|
765
|
-
onSymlinkRefused() {
|
|
766
|
-
},
|
|
767
|
-
onNetworkError() {
|
|
768
|
-
},
|
|
769
|
-
onRoundCompleted() {
|
|
770
|
-
},
|
|
771
|
-
onError() {
|
|
772
|
-
},
|
|
773
|
-
onConflict() {
|
|
774
|
-
},
|
|
775
|
-
tokenMinted() {
|
|
776
|
-
},
|
|
777
|
-
tokenRefreshUnauthorized() {
|
|
778
|
-
}
|
|
779
|
-
});
|
|
780
|
-
|
|
781
|
-
// ../agent-store-sync/dist/metrics-aggregator.js
|
|
782
|
-
var DISK_FULL_REPEAT_WINDOW_MS = 5 * 60 * 1e3;
|
|
783
|
-
|
|
784
1
|
// ../agent-store-sync/dist/presigned-url.js
|
|
785
2
|
var PresignedUrlRejectedError = class extends Error {
|
|
786
3
|
constructor(options) {
|
|
@@ -841,6 +58,10 @@ var BCS_AGENT_STORE_BUCKET_HOSTS = [
|
|
|
841
58
|
"agent-stores.s3.us-east-1.amazonaws.com",
|
|
842
59
|
"agent-stores.s3.amazonaws.com"
|
|
843
60
|
];
|
|
61
|
+
var PLAYGROUND_AGENT_STORE_BUCKET_HOSTS = [
|
|
62
|
+
"agent-stores-928182716709-us-west-2-an.s3.us-west-2.amazonaws.com",
|
|
63
|
+
"agent-stores-928182716709-us-west-2-an.s3.amazonaws.com"
|
|
64
|
+
];
|
|
844
65
|
function createBcsPresignedUrlValidator() {
|
|
845
66
|
return createHostAllowlistValidator(BCS_AGENT_STORE_BUCKET_HOSTS);
|
|
846
67
|
}
|
|
@@ -851,8 +72,22 @@ function isLocalAgentStoreBackendUrl(backendUrl) {
|
|
|
851
72
|
}
|
|
852
73
|
return trimmed.includes("localhost") || trimmed.includes("lclhst.build");
|
|
853
74
|
}
|
|
75
|
+
function isPlaygroundAgentStoreBackendUrl(backendUrl) {
|
|
76
|
+
try {
|
|
77
|
+
const hostname = new URL(backendUrl).hostname.toLowerCase();
|
|
78
|
+
return hostname === "playground.cursor.sh" || hostname.endsWith(".playground.cursor.sh");
|
|
79
|
+
} catch (_a) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
854
83
|
function createAgentStorePresignedUrlValidatorForBackend(backendUrl) {
|
|
855
|
-
|
|
84
|
+
if (isLocalAgentStoreBackendUrl(backendUrl)) {
|
|
85
|
+
return createLocalDevAgentStorePresignedUrlValidator();
|
|
86
|
+
}
|
|
87
|
+
if (isPlaygroundAgentStoreBackendUrl(backendUrl)) {
|
|
88
|
+
return createHostAllowlistValidator(PLAYGROUND_AGENT_STORE_BUCKET_HOSTS);
|
|
89
|
+
}
|
|
90
|
+
return createBcsPresignedUrlValidator();
|
|
856
91
|
}
|
|
857
92
|
function createLocalDevAgentStorePresignedUrlValidator() {
|
|
858
93
|
const bcsValidator = createBcsPresignedUrlValidator();
|
|
@@ -992,32 +227,6 @@ function extractIPv4MappedAddress(hostname) {
|
|
|
992
227
|
}
|
|
993
228
|
return void 0;
|
|
994
229
|
}
|
|
995
|
-
|
|
996
|
-
// ../agent-store-sync/dist/resilience-events.js
|
|
997
|
-
var NOOP_RESILIENCE_LISTENER = Object.freeze({
|
|
998
|
-
onDiskFull() {
|
|
999
|
-
},
|
|
1000
|
-
onSymlinkRefused() {
|
|
1001
|
-
},
|
|
1002
|
-
onNetworkError() {
|
|
1003
|
-
}
|
|
1004
|
-
});
|
|
1005
|
-
|
|
1006
|
-
// ../agent-store-sync/dist/retrying-client.js
|
|
1007
|
-
var RETRYABLE_CONNECT_CODES = /* @__PURE__ */ new Set([
|
|
1008
|
-
Code.Unavailable,
|
|
1009
|
-
Code.ResourceExhausted,
|
|
1010
|
-
Code.Internal,
|
|
1011
|
-
Code.Aborted,
|
|
1012
|
-
Code.DeadlineExceeded
|
|
1013
|
-
]);
|
|
1014
|
-
|
|
1015
|
-
// ../agent-store-sync/dist/store-lock.js
|
|
1016
|
-
var STORE_LOCK_STALE_MS = 10 * 60 * 1e3;
|
|
1017
|
-
|
|
1018
|
-
// ../agent-store-sync/dist/sync-engine.js
|
|
1019
|
-
var DEFAULT_MAX_FILE_SIZE_BYTES = 100 * 1024 * 1024;
|
|
1020
|
-
var TOMBSTONE_ROW_RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
1021
230
|
export {
|
|
1022
231
|
createAgentStorePresignedUrlValidatorForBackend
|
|
1023
232
|
};
|