@cursor/july 0.1.31 → 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/docs/404.html +1 -1
- package/dist/docs/ab.html +2 -2
- package/dist/docs/assets/{app.DigB_9cQ.js → app.CgZqLyWL.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.B1uHGxBZ.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.BCMX25Bv.js → VPLocalSearchBox.C4KigoQn.js} +1 -1
- package/dist/docs/assets/chunks/{theme.BDDWeELx.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 +9 -98
- package/dist/files-backends/agent-store-presigned-url.d.ts.map +1 -1
- package/dist/files-backends/agent-store-presigned-url.js +199 -314
- package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/files-backends/cursor-hosted.js +25 -2
- 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 +3 -23
- package/src/files-backends/agent-store-presigned-url.ts +9 -401
- package/src/files-backends/cursor-hosted.ts +32 -6
- 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/docs/assets/chunks/@localSearchIndexroot.CnFFl07y.js +0 -1
- package/dist/playground/assets/index-50PKeJlG.css +0 -1
- package/dist/playground/assets/index-C0f2Wl1q.js +0 -85
|
@@ -1,347 +1,232 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
if (!isAwsS3Hostname(hostname)) {
|
|
37
|
-
throw new PresignedUrlRejectedError({
|
|
38
|
-
code: "host_not_allowed",
|
|
39
|
-
message: `Refused presigned URL whose host is not an AWS S3 endpoint: ${hostname}`,
|
|
40
|
-
url: redactPresignedUrlString(url),
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* True when `hostname` is an AWS S3 object-storage endpoint:
|
|
46
|
-
* `*.amazonaws.com` with at least one label in
|
|
47
|
-
* {@link S3_OBJECT_LABELS}. Covers modern virtual-host, path-style,
|
|
48
|
-
* dualstack, accelerate, and FIPS URLs. Rejects the S3-named control
|
|
49
|
-
* planes (`s3-control`, `s3-outposts`, `s3-object-lambda`) and the
|
|
50
|
-
* legacy regional virtual-host form AWS deprecated in 2019, both of
|
|
51
|
-
* which would otherwise let a tampered presign issuer turn the sync
|
|
52
|
-
* client into a signed-request gadget against non-storage APIs.
|
|
53
|
-
*/
|
|
54
|
-
export function isAwsS3Hostname(hostname) {
|
|
55
|
-
const lowered = hostname.toLowerCase();
|
|
56
|
-
if (lowered !== "amazonaws.com" && !lowered.endsWith(".amazonaws.com")) {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
const labels = lowered.split(".");
|
|
60
|
-
return labels.some(label => S3_OBJECT_LABELS.has(label));
|
|
61
|
-
}
|
|
62
|
-
const S3_OBJECT_LABELS = new Set(["s3", "s3-accelerate", "s3-fips"]);
|
|
63
|
-
/**
|
|
64
|
-
* Like {@link defaultPresignedUrlValidator} plus a case-insensitive
|
|
65
|
-
* exact-match check against `allowedHosts` (no subdomain wildcards).
|
|
66
|
-
*/
|
|
67
|
-
export function createHostAllowlistValidator(allowedHosts) {
|
|
68
|
-
const allowed = new Set(allowedHosts.map(host => host.toLowerCase()));
|
|
69
|
-
return (url) => {
|
|
70
|
-
defaultPresignedUrlValidator(url);
|
|
71
|
-
if (!allowed.has(url.hostname.toLowerCase())) {
|
|
72
|
-
throw new PresignedUrlRejectedError({
|
|
73
|
-
code: "host_not_allowed",
|
|
74
|
-
message: `Refused presigned URL whose host is not in the allowlist: ${url.hostname}`,
|
|
75
|
-
url: redactPresignedUrlString(url),
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
};
|
|
1
|
+
// ../agent-store-sync/dist/presigned-url.js
|
|
2
|
+
var PresignedUrlRejectedError = class extends Error {
|
|
3
|
+
constructor(options) {
|
|
4
|
+
super(options.message);
|
|
5
|
+
this.name = "PresignedUrlRejectedError";
|
|
6
|
+
this.code = options.code;
|
|
7
|
+
this.url = options.url;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
function defaultPresignedUrlValidator(url) {
|
|
11
|
+
assertSafeAuthority(url);
|
|
12
|
+
if (url.protocol !== "https:") {
|
|
13
|
+
throw new PresignedUrlRejectedError({
|
|
14
|
+
code: "scheme_not_allowed",
|
|
15
|
+
message: `Refused presigned URL with non-https scheme: ${url.protocol}`,
|
|
16
|
+
url: redactPresignedUrlString(url)
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
const hostname = stripIPv6Brackets(url.hostname);
|
|
20
|
+
if (isLocalOrInternalHost(hostname)) {
|
|
21
|
+
throw new PresignedUrlRejectedError({
|
|
22
|
+
code: "private_host_not_allowed",
|
|
23
|
+
message: `Refused https presigned URL with private/internal host: ${hostname}`,
|
|
24
|
+
url: redactPresignedUrlString(url)
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
if (!isAwsS3Hostname(hostname)) {
|
|
28
|
+
throw new PresignedUrlRejectedError({
|
|
29
|
+
code: "host_not_allowed",
|
|
30
|
+
message: `Refused presigned URL whose host is not an AWS S3 endpoint: ${hostname}`,
|
|
31
|
+
url: redactPresignedUrlString(url)
|
|
32
|
+
});
|
|
33
|
+
}
|
|
79
34
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
35
|
+
function isAwsS3Hostname(hostname) {
|
|
36
|
+
const lowered = hostname.toLowerCase();
|
|
37
|
+
if (lowered !== "amazonaws.com" && !lowered.endsWith(".amazonaws.com")) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const labels = lowered.split(".");
|
|
41
|
+
return labels.some((label) => S3_OBJECT_LABELS.has(label));
|
|
42
|
+
}
|
|
43
|
+
var S3_OBJECT_LABELS = /* @__PURE__ */ new Set(["s3", "s3-accelerate", "s3-fips"]);
|
|
44
|
+
function createHostAllowlistValidator(allowedHosts) {
|
|
45
|
+
const allowed = new Set(allowedHosts.map((host) => host.toLowerCase()));
|
|
46
|
+
return (url) => {
|
|
47
|
+
defaultPresignedUrlValidator(url);
|
|
48
|
+
if (!allowed.has(url.hostname.toLowerCase())) {
|
|
49
|
+
throw new PresignedUrlRejectedError({
|
|
50
|
+
code: "host_not_allowed",
|
|
51
|
+
message: `Refused presigned URL whose host is not in the allowlist: ${url.hostname}`,
|
|
52
|
+
url: redactPresignedUrlString(url)
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
var BCS_AGENT_STORE_BUCKET_HOSTS = [
|
|
58
|
+
"agent-stores.s3.us-east-1.amazonaws.com",
|
|
59
|
+
"agent-stores.s3.amazonaws.com"
|
|
95
60
|
];
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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"
|
|
99
64
|
];
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
* default (https, S3 endpoint, no private hosts, no userinfo) plus the
|
|
103
|
-
* {@link BCS_AGENT_STORE_BUCKET_HOSTS} pin. Pre-built so callers don't
|
|
104
|
-
* accidentally pass {@link defaultPresignedUrlValidator}, which would
|
|
105
|
-
* accept any AWS S3 bucket on the internet and let a buggy or
|
|
106
|
-
* compromised presign issuer redirect sync traffic away from the real
|
|
107
|
-
* `agent-stores` bucket.
|
|
108
|
-
*/
|
|
109
|
-
export function createBcsPresignedUrlValidator() {
|
|
110
|
-
return createHostAllowlistValidator(BCS_AGENT_STORE_BUCKET_HOSTS);
|
|
65
|
+
function createBcsPresignedUrlValidator() {
|
|
66
|
+
return createHostAllowlistValidator(BCS_AGENT_STORE_BUCKET_HOSTS);
|
|
111
67
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const trimmed = backendUrl.trim();
|
|
119
|
-
if (trimmed === "") {
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
return trimmed.includes("localhost") || trimmed.includes("lclhst.build");
|
|
68
|
+
function isLocalAgentStoreBackendUrl(backendUrl) {
|
|
69
|
+
const trimmed = backendUrl.trim();
|
|
70
|
+
if (trimmed === "") {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
return trimmed.includes("localhost") || trimmed.includes("lclhst.build");
|
|
123
74
|
}
|
|
124
75
|
function isPlaygroundAgentStoreBackendUrl(backendUrl) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
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
|
+
}
|
|
133
82
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return createLocalDevAgentStorePresignedUrlValidator();
|
|
143
|
-
}
|
|
144
|
-
if (isPlaygroundAgentStoreBackendUrl(backendUrl)) {
|
|
145
|
-
return createHostAllowlistValidator(PLAYGROUND_AGENT_STORE_BUCKET_HOSTS);
|
|
146
|
-
}
|
|
147
|
-
return createBcsPresignedUrlValidator();
|
|
83
|
+
function createAgentStorePresignedUrlValidatorForBackend(backendUrl) {
|
|
84
|
+
if (isLocalAgentStoreBackendUrl(backendUrl)) {
|
|
85
|
+
return createLocalDevAgentStorePresignedUrlValidator();
|
|
86
|
+
}
|
|
87
|
+
if (isPlaygroundAgentStoreBackendUrl(backendUrl)) {
|
|
88
|
+
return createHostAllowlistValidator(PLAYGROUND_AGENT_STORE_BUCKET_HOSTS);
|
|
89
|
+
}
|
|
90
|
+
return createBcsPresignedUrlValidator();
|
|
148
91
|
}
|
|
149
92
|
function createLocalDevAgentStorePresignedUrlValidator() {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
assertSafeAuthority(url);
|
|
153
|
-
const hostname = stripIPv6Brackets(url.hostname);
|
|
154
|
-
if (url.protocol === "http:" && isLoopbackHostName(hostname)) {
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
bcsValidator(url);
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Like {@link defaultPresignedUrlValidator} plus `http://localhost` /
|
|
162
|
-
* `127.0.0.1` / `[::1]` (any port) for LocalStack-backed unit tests.
|
|
163
|
-
* Non-loopback `https:` URLs fall through to the strict default (any S3
|
|
164
|
-
* bucket). Do not use for IDE wiring — use
|
|
165
|
-
* {@link createAgentStorePresignedUrlValidatorForBackend} instead.
|
|
166
|
-
*/
|
|
167
|
-
export function localhostPermissivePresignedUrlValidator(url) {
|
|
93
|
+
const bcsValidator = createBcsPresignedUrlValidator();
|
|
94
|
+
return (url) => {
|
|
168
95
|
assertSafeAuthority(url);
|
|
169
96
|
const hostname = stripIPv6Brackets(url.hostname);
|
|
170
97
|
if (url.protocol === "http:" && isLoopbackHostName(hostname)) {
|
|
171
|
-
|
|
98
|
+
return;
|
|
172
99
|
}
|
|
173
|
-
|
|
100
|
+
bcsValidator(url);
|
|
101
|
+
};
|
|
174
102
|
}
|
|
175
103
|
function assertSafeAuthority(url) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Strip the query string and userinfo from a presigned URL so the AWS
|
|
186
|
-
* SigV4 signature never reaches error messages or telemetry.
|
|
187
|
-
*/
|
|
188
|
-
export function redactPresignedUrlString(url) {
|
|
189
|
-
try {
|
|
190
|
-
const parsed = typeof url === "string" ? new URL(url) : url;
|
|
191
|
-
return `${parsed.protocol}//${parsed.host}${parsed.pathname}`;
|
|
192
|
-
}
|
|
193
|
-
catch (_a) {
|
|
194
|
-
return "<unparseable-presigned-url>";
|
|
195
|
-
}
|
|
104
|
+
if (url.username !== "" || url.password !== "") {
|
|
105
|
+
throw new PresignedUrlRejectedError({
|
|
106
|
+
code: "userinfo_not_allowed",
|
|
107
|
+
message: "Refused presigned URL with embedded userinfo",
|
|
108
|
+
url: redactPresignedUrlString(url)
|
|
109
|
+
});
|
|
110
|
+
}
|
|
196
111
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
try {
|
|
205
|
-
parsed = new URL(args.rawUrl);
|
|
206
|
-
}
|
|
207
|
-
catch (_a) {
|
|
208
|
-
throw new Error(`Refusing unparseable presigned URL for ${args.relPath}`);
|
|
209
|
-
}
|
|
210
|
-
try {
|
|
211
|
-
args.validatePresignedUrl(parsed);
|
|
212
|
-
}
|
|
213
|
-
catch (error) {
|
|
214
|
-
throw new Error(`Refusing presigned URL for ${args.relPath}: ${error instanceof Error ? error.message : String(error)}`, { cause: error instanceof Error ? error : undefined });
|
|
215
|
-
}
|
|
112
|
+
function redactPresignedUrlString(url) {
|
|
113
|
+
try {
|
|
114
|
+
const parsed = typeof url === "string" ? new URL(url) : url;
|
|
115
|
+
return `${parsed.protocol}//${parsed.host}${parsed.pathname}`;
|
|
116
|
+
} catch (_a) {
|
|
117
|
+
return "<unparseable-presigned-url>";
|
|
118
|
+
}
|
|
216
119
|
}
|
|
217
120
|
function isLoopbackHostName(hostname) {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
lowered === "ip6-localhost" ||
|
|
221
|
-
lowered === "127.0.0.1" ||
|
|
222
|
-
lowered === "::1" ||
|
|
223
|
-
lowered === "0:0:0:0:0:0:0:1");
|
|
121
|
+
const lowered = hostname.toLowerCase();
|
|
122
|
+
return lowered === "localhost" || lowered === "ip6-localhost" || lowered === "127.0.0.1" || lowered === "::1" || lowered === "0:0:0:0:0:0:0:1";
|
|
224
123
|
}
|
|
225
124
|
function isLocalOrInternalHost(hostname) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
// relies on transport-level allowlists for those.
|
|
240
|
-
return false;
|
|
125
|
+
if (hostname.length === 0) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
if (isLoopbackHostName(hostname)) {
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
if (isIPv4Address(hostname)) {
|
|
132
|
+
return isPrivateOrInternalIPv4(hostname);
|
|
133
|
+
}
|
|
134
|
+
if (isIPv6Address(hostname)) {
|
|
135
|
+
return isPrivateOrInternalIPv6(hostname);
|
|
136
|
+
}
|
|
137
|
+
return false;
|
|
241
138
|
}
|
|
242
139
|
function stripIPv6Brackets(hostname) {
|
|
243
|
-
|
|
244
|
-
? hostname.slice(1, -1)
|
|
245
|
-
: hostname;
|
|
140
|
+
return hostname.startsWith("[") && hostname.endsWith("]") ? hostname.slice(1, -1) : hostname;
|
|
246
141
|
}
|
|
247
142
|
function isIPv4Address(hostname) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
143
|
+
const parts = hostname.split(".");
|
|
144
|
+
if (parts.length !== 4) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
return parts.every((part) => {
|
|
148
|
+
if (part.length === 0 || part.length > 3) {
|
|
149
|
+
return false;
|
|
251
150
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
259
|
-
const n = Number(part);
|
|
260
|
-
return Number.isInteger(n) && n >= 0 && n <= 255;
|
|
261
|
-
});
|
|
151
|
+
if (!/^\d+$/.test(part)) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
const n = Number(part);
|
|
155
|
+
return Number.isInteger(n) && n >= 0 && n <= 255;
|
|
156
|
+
});
|
|
262
157
|
}
|
|
263
158
|
function isPrivateOrInternalIPv4(hostname) {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
return true;
|
|
288
|
-
return false;
|
|
159
|
+
const [a, b] = hostname.split(".").map(Number);
|
|
160
|
+
if (a === void 0 || b === void 0) {
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
if (a === 0)
|
|
164
|
+
return true;
|
|
165
|
+
if (a === 10)
|
|
166
|
+
return true;
|
|
167
|
+
if (a === 127)
|
|
168
|
+
return true;
|
|
169
|
+
if (a === 169 && b === 254)
|
|
170
|
+
return true;
|
|
171
|
+
if (a === 172 && b >= 16 && b <= 31)
|
|
172
|
+
return true;
|
|
173
|
+
if (a === 192 && b === 168)
|
|
174
|
+
return true;
|
|
175
|
+
if (a === 100 && b >= 64 && b <= 127)
|
|
176
|
+
return true;
|
|
177
|
+
if (a >= 224 && a <= 239)
|
|
178
|
+
return true;
|
|
179
|
+
if (a >= 240)
|
|
180
|
+
return true;
|
|
181
|
+
return false;
|
|
289
182
|
}
|
|
290
183
|
function isIPv6Address(hostname) {
|
|
291
|
-
|
|
292
|
-
return hostname.includes(":");
|
|
184
|
+
return hostname.includes(":");
|
|
293
185
|
}
|
|
294
186
|
function isPrivateOrInternalIPv6(hostname) {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
return true;
|
|
317
|
-
}
|
|
318
|
-
return false;
|
|
187
|
+
const lowered = hostname.toLowerCase();
|
|
188
|
+
if (lowered === "::" || lowered === "::1") {
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
const mapped = extractIPv4MappedAddress(lowered);
|
|
192
|
+
if (mapped !== void 0) {
|
|
193
|
+
return isPrivateOrInternalIPv4(mapped);
|
|
194
|
+
}
|
|
195
|
+
if (lowered.startsWith("fc") || lowered.startsWith("fd")) {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
if (lowered.startsWith("fe8") || lowered.startsWith("fe9")) {
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
if (lowered.startsWith("fea") || lowered.startsWith("feb")) {
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
if (lowered.startsWith("ff")) {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
return false;
|
|
319
208
|
}
|
|
320
|
-
// Convert an IPv4-mapped IPv6 literal (`::ffff:a.b.c.d` or
|
|
321
|
-
// `::ffff:hhhh:hhhh`) to its dotted-quad form. Returns undefined otherwise.
|
|
322
209
|
function extractIPv4MappedAddress(hostname) {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
return undefined;
|
|
347
|
-
}
|
|
210
|
+
const dotted = hostname.match(/^(?:0:0:0:0:0|::):?ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i);
|
|
211
|
+
if (dotted) {
|
|
212
|
+
return dotted[1];
|
|
213
|
+
}
|
|
214
|
+
if (hostname.startsWith("::ffff:")) {
|
|
215
|
+
const tail = hostname.slice("::ffff:".length);
|
|
216
|
+
if (isIPv4Address(tail)) {
|
|
217
|
+
return tail;
|
|
218
|
+
}
|
|
219
|
+
const hex = tail.match(/^([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i);
|
|
220
|
+
if (hex) {
|
|
221
|
+
const high = Number.parseInt(hex[1], 16);
|
|
222
|
+
const low = Number.parseInt(hex[2], 16);
|
|
223
|
+
if (Number.isFinite(high) && Number.isFinite(low) && high >= 0 && high <= 65535 && low >= 0 && low <= 65535) {
|
|
224
|
+
return `${high >> 8 & 255}.${high & 255}.${low >> 8 & 255}.${low & 255}`;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return void 0;
|
|
229
|
+
}
|
|
230
|
+
export {
|
|
231
|
+
createAgentStorePresignedUrlValidatorForBackend
|
|
232
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cursor-hosted.d.ts","sourceRoot":"","sources":["../../src/files-backends/cursor-hosted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAGH,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,YAAY,EAGlB,MAAM,aAAa,CAAC;AAWrB;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,gCACjB,CAAC;AAgBhC;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAGT;AAED,MAAM,WAAW,wBAAwB;IACvC,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAuCD,KAAK,kBAAkB,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG;IAChD,gFAAgF;IAChF,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;CACrD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,GAAE,wBAA6B,GACrC,kBAAkB,
|
|
1
|
+
{"version":3,"file":"cursor-hosted.d.ts","sourceRoot":"","sources":["../../src/files-backends/cursor-hosted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAGH,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,YAAY,EAGlB,MAAM,aAAa,CAAC;AAWrB;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,gCACjB,CAAC;AAgBhC;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAGT;AAED,MAAM,WAAW,wBAAwB;IACvC,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAuCD,KAAK,kBAAkB,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG;IAChD,gFAAgF;IAChF,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;CACrD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,GAAE,wBAA6B,GACrC,kBAAkB,CAyWpB"}
|
|
@@ -347,7 +347,19 @@ export function cursorHostedFiles(options = {}) {
|
|
|
347
347
|
return __awaiter(this, void 0, void 0, function* () {
|
|
348
348
|
return yield withFiles((files) => __awaiter(this, void 0, void 0, function* () {
|
|
349
349
|
var _a, _b;
|
|
350
|
-
|
|
350
|
+
// Presigning a read of a path the store has no live object for — never
|
|
351
|
+
// written, or deleted and now holding a tombstone — is a 404. That is
|
|
352
|
+
// absence, which `read()` reports as undefined, not a failure.
|
|
353
|
+
let presigned;
|
|
354
|
+
try {
|
|
355
|
+
presigned = yield storePost(options, files.path("/download"), { paths: [key] });
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
if (error instanceof StoreApiError && error.status === 404) {
|
|
359
|
+
return undefined;
|
|
360
|
+
}
|
|
361
|
+
throw error;
|
|
362
|
+
}
|
|
351
363
|
const url = (_b = (_a = presigned.files) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.url;
|
|
352
364
|
if (url === undefined) {
|
|
353
365
|
return undefined;
|
|
@@ -510,11 +522,22 @@ function sendJson(options, url, method, body) {
|
|
|
510
522
|
throw new Error(`cursorHostedFiles ${url} returned non-JSON (${response.status})`);
|
|
511
523
|
}
|
|
512
524
|
if (!response.ok) {
|
|
513
|
-
throw new
|
|
525
|
+
throw new StoreApiError(response.status, `cursorHostedFiles ${url}: ${describeError(parsed, response.status)}`);
|
|
514
526
|
}
|
|
515
527
|
return parsed;
|
|
516
528
|
});
|
|
517
529
|
}
|
|
530
|
+
/**
|
|
531
|
+
* A non-2xx answer from the files API, carrying the status so a caller can
|
|
532
|
+
* tell "absent" apart from a failure it must not swallow.
|
|
533
|
+
*/
|
|
534
|
+
class StoreApiError extends Error {
|
|
535
|
+
constructor(status, message) {
|
|
536
|
+
super(message);
|
|
537
|
+
this.status = status;
|
|
538
|
+
this.name = "StoreApiError";
|
|
539
|
+
}
|
|
540
|
+
}
|
|
518
541
|
function describeError(parsed, status) {
|
|
519
542
|
if (parsed !== null &&
|
|
520
543
|
typeof parsed === "object" &&
|
|
@@ -73,7 +73,18 @@ export interface CursorRelayCoreOptions<TEvent extends {
|
|
|
73
73
|
fetchImpl?: typeof fetch;
|
|
74
74
|
/** Test seam: override long-poll wait (default 25s). */
|
|
75
75
|
pollWaitMs?: number;
|
|
76
|
+
/**
|
|
77
|
+
* Desired-revision generation for hosted engines. Sent as
|
|
78
|
+
* `x-agent-serve-generation` so the control plane can fence zombies after
|
|
79
|
+
* a redeploy. Defaults to `process.env.AGENT_SERVE_GENERATION` when set.
|
|
80
|
+
*/
|
|
81
|
+
deploymentGeneration?: number;
|
|
76
82
|
}
|
|
83
|
+
/** Must match server-shared `AGENT_SERVE_GENERATION_HEADER`. */
|
|
84
|
+
export declare const AGENT_SERVE_GENERATION_HEADER = "x-agent-serve-generation";
|
|
85
|
+
/** Must match server-shared `AGENT_SERVE_GENERATION_ENV_VAR`. */
|
|
86
|
+
export declare const AGENT_SERVE_GENERATION_ENV_VAR = "AGENT_SERVE_GENERATION";
|
|
87
|
+
export declare function resolveAgentServeDeploymentGeneration(explicit?: number): number | undefined;
|
|
77
88
|
export declare class CursorRelayCore<TEvent extends {
|
|
78
89
|
offset: string;
|
|
79
90
|
}> {
|
|
@@ -84,6 +95,7 @@ export declare class CursorRelayCore<TEvent extends {
|
|
|
84
95
|
private consumePromise;
|
|
85
96
|
private readonly offsetStore;
|
|
86
97
|
private readonly fetchImpl;
|
|
98
|
+
private readonly deploymentGeneration;
|
|
87
99
|
private consumerId;
|
|
88
100
|
/** undefined until the first registration, so a clean first success logs. */
|
|
89
101
|
private lastRegistrationLog;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cursor-relay-core.d.ts","sourceRoot":"","sources":["../../src/internal/cursor-relay-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA6BH,8DAA8D;AAC9D,qBAAa,gBAAgB;IACf,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAArC,YAA6B,QAAQ,EAAE,MAAM,EAAI;IAEjD,OAAO,KAAK,QAAQ,GAEnB;IAEK,IAAI,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAcxC;IAEK,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAWxC;CACF;AAED,6CAA6C;AAC7C,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAMjE;AASD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEzD;AAQD;;;;GAIG;AACH,MAAM,WAAW,YAAY,CAAC,MAAM,SAAS;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE;IAC7D,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,2EAA2E;IAC3E,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IACnD;;;;;;OAMG;IACH,uBAAuB,CAAC,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IACtD;;;;;OAKG;IACH,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,CAAC;IACnD;;;;OAIG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACvC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,sBAAsB,CAAC,MAAM,SAAS;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAC9B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,2CAA2C;IAC3C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"cursor-relay-core.d.ts","sourceRoot":"","sources":["../../src/internal/cursor-relay-core.ts"],"names":[],"mappings":"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"}
|