orkestrator 2.34.5-beta → 2.35.0-beta
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/client.js +65 -12
- package/dist/main.js +62570 -59725
- package/package.json +3 -3
- package/resources/acp-bridge/dist/index.js +108 -30
- package/resources/claude-bridge/dist/index.js +594 -303
- package/resources/codex-bridge/dist/index.js +188 -73
- package/resources/cursor-bridge/dist/index.js +227 -38
- package/resources/cursor-bridge/runtime/install.json +1 -1
- package/resources/pi-bridge/dist/index.js +49 -0
- package/resources/pi-bridge/runtime/install.json +1 -1
|
@@ -63,6 +63,7 @@ var PROMPT_TIMEOUT_MS = parseBoundedInteger(process.env.CURSOR_BRIDGE_PROMPT_TIM
|
|
|
63
63
|
var CANCEL_ACK_TIMEOUT_MS = parseBoundedInteger(process.env.CURSOR_BRIDGE_CANCEL_ACK_TIMEOUT_MS, 30 * 1000, 1000, 5 * 60 * 1000);
|
|
64
64
|
var CLOSE_ACK_TIMEOUT_MS = 4000;
|
|
65
65
|
var CATALOG_TIMEOUT_MS = 30000;
|
|
66
|
+
var ACCOUNT_LOOKUP_TIMEOUT_MS = 3000;
|
|
66
67
|
var LOGIN_TIMEOUT_MS = 10 * 60 * 1000;
|
|
67
68
|
function authenticate(headers) {
|
|
68
69
|
const bearer = firstHeader(headers.authorization);
|
|
@@ -132,6 +133,8 @@ import { Cursor, FileCredentialStore } from "@cursor/sdk";
|
|
|
132
133
|
var CURSOR_AUTHENTICATION_REQUIRED_MESSAGE = "Cursor is not signed in. Sign in from Settings › Cursor, or set a Cursor API key.";
|
|
133
134
|
var AUTH_CACHE_TTL_MS = 15000;
|
|
134
135
|
var authCache;
|
|
136
|
+
var accountLookup;
|
|
137
|
+
var accountLookupTimeoutMs = ACCOUNT_LOOKUP_TIMEOUT_MS;
|
|
135
138
|
|
|
136
139
|
class LazyFileCredentialStore {
|
|
137
140
|
store;
|
|
@@ -152,16 +155,25 @@ var credentialStore = new LazyFileCredentialStore;
|
|
|
152
155
|
var cursorAuth = Cursor.auth;
|
|
153
156
|
var cursorMe = Cursor.me;
|
|
154
157
|
function useCursorCredentialRuntimeForTests(runtime) {
|
|
155
|
-
const previous = {
|
|
158
|
+
const previous = {
|
|
159
|
+
store: credentialStore,
|
|
160
|
+
auth: cursorAuth,
|
|
161
|
+
me: cursorMe,
|
|
162
|
+
meTimeoutMs: accountLookupTimeoutMs
|
|
163
|
+
};
|
|
156
164
|
credentialStore = runtime.store;
|
|
157
165
|
cursorAuth = runtime.auth;
|
|
158
166
|
cursorMe = runtime.me;
|
|
167
|
+
accountLookupTimeoutMs = runtime.meTimeoutMs ?? ACCOUNT_LOOKUP_TIMEOUT_MS;
|
|
159
168
|
authCache = undefined;
|
|
169
|
+
accountLookup = undefined;
|
|
160
170
|
return () => {
|
|
161
171
|
credentialStore = previous.store;
|
|
162
172
|
cursorAuth = previous.auth;
|
|
163
173
|
cursorMe = previous.me;
|
|
174
|
+
accountLookupTimeoutMs = previous.meTimeoutMs;
|
|
164
175
|
authCache = undefined;
|
|
176
|
+
accountLookup = undefined;
|
|
165
177
|
};
|
|
166
178
|
}
|
|
167
179
|
async function resolveCredential() {
|
|
@@ -198,10 +210,8 @@ async function authStatus() {
|
|
|
198
210
|
if (credential && authCache?.credential === credential && authCache.expiresAt > Date.now()) {
|
|
199
211
|
return authCache.value;
|
|
200
212
|
}
|
|
201
|
-
const
|
|
202
|
-
const me =
|
|
203
|
-
return;
|
|
204
|
-
}) : undefined;
|
|
213
|
+
const lookup = credential ? await lookUpAccount(credential) : { settled: true, account: undefined };
|
|
214
|
+
const me = lookup.account;
|
|
205
215
|
const label = [me?.userFirstName, me?.userLastName].filter(Boolean).join(" ") || me?.apiKeyName || ("email" in sdkStatus ? sdkStatus.email : undefined) || stored?.email || "Cursor account";
|
|
206
216
|
const value = {
|
|
207
217
|
state: "signed-in",
|
|
@@ -212,11 +222,52 @@ async function authStatus() {
|
|
|
212
222
|
signIn: fromEnvironment ? { kind: "none", hint: "Remove CURSOR_API_KEY to sign out." } : { kind: "browser-url" },
|
|
213
223
|
signOut: !fromEnvironment
|
|
214
224
|
};
|
|
215
|
-
if (credential) {
|
|
225
|
+
if (credential && lookup.settled) {
|
|
216
226
|
authCache = { credential, expiresAt: Date.now() + AUTH_CACHE_TTL_MS, value };
|
|
217
227
|
}
|
|
218
228
|
return value;
|
|
219
229
|
}
|
|
230
|
+
async function lookUpAccount(credential) {
|
|
231
|
+
const meFn = cursorMe;
|
|
232
|
+
if (!meFn)
|
|
233
|
+
return { settled: true, account: undefined };
|
|
234
|
+
let entry = accountLookup;
|
|
235
|
+
if (!entry || entry.credential !== credential || entry.expiresAt <= Date.now()) {
|
|
236
|
+
const started = {
|
|
237
|
+
credential,
|
|
238
|
+
expiresAt: Date.now() + AUTH_CACHE_TTL_MS,
|
|
239
|
+
timedOut: false,
|
|
240
|
+
result: meFn({ apiKey: credential }).catch(() => {
|
|
241
|
+
return;
|
|
242
|
+
})
|
|
243
|
+
};
|
|
244
|
+
started.result.finally(() => {
|
|
245
|
+
if (accountLookup === started)
|
|
246
|
+
accountLookup = undefined;
|
|
247
|
+
});
|
|
248
|
+
entry = accountLookup = started;
|
|
249
|
+
}
|
|
250
|
+
if (entry.timedOut)
|
|
251
|
+
return { settled: false, account: undefined };
|
|
252
|
+
const active = entry;
|
|
253
|
+
const { result } = entry;
|
|
254
|
+
let timer;
|
|
255
|
+
try {
|
|
256
|
+
return await Promise.race([
|
|
257
|
+
result.then((account) => ({ settled: true, account })),
|
|
258
|
+
new Promise((resolve) => {
|
|
259
|
+
timer = setTimeout(() => {
|
|
260
|
+
active.timedOut = true;
|
|
261
|
+
resolve({ settled: false, account: undefined });
|
|
262
|
+
}, accountLookupTimeoutMs);
|
|
263
|
+
timer.unref();
|
|
264
|
+
})
|
|
265
|
+
]);
|
|
266
|
+
} finally {
|
|
267
|
+
if (timer)
|
|
268
|
+
clearTimeout(timer);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
220
271
|
function beginLogin(options = {}) {
|
|
221
272
|
const controller = new AbortController;
|
|
222
273
|
let publishUrl = () => {
|
|
@@ -252,6 +303,7 @@ function beginLogin(options = {}) {
|
|
|
252
303
|
}
|
|
253
304
|
async function logout() {
|
|
254
305
|
authCache = undefined;
|
|
306
|
+
accountLookup = undefined;
|
|
255
307
|
await cursorAuth.logout({ store: credentialStore });
|
|
256
308
|
}
|
|
257
309
|
function isExpired(expiresAtMs) {
|
|
@@ -23886,6 +23938,63 @@ var PROTECTED_SEGMENTS = new Set([
|
|
|
23886
23938
|
]);
|
|
23887
23939
|
|
|
23888
23940
|
// ../protocol/src/review-evidence-frames.ts
|
|
23941
|
+
var SYSTEM_INSTRUCTIONS_FRAME_OPEN = "<orkestrator-system-instructions>";
|
|
23942
|
+
var SYSTEM_INSTRUCTIONS_FRAME_CLOSE = "</orkestrator-system-instructions>";
|
|
23943
|
+
function neutralizeSystemInstructionMarkers(content) {
|
|
23944
|
+
if (!content.includes(SYSTEM_INSTRUCTIONS_FRAME_OPEN) && !content.includes(SYSTEM_INSTRUCTIONS_FRAME_CLOSE)) {
|
|
23945
|
+
return content;
|
|
23946
|
+
}
|
|
23947
|
+
return content.replaceAll(SYSTEM_INSTRUCTIONS_FRAME_CLOSE, "\\u003c/orkestrator-system-instructions\\u003e").replaceAll(SYSTEM_INSTRUCTIONS_FRAME_OPEN, "\\u003corkestrator-system-instructions\\u003e");
|
|
23948
|
+
}
|
|
23949
|
+
function wrapSystemInstructions(...parts) {
|
|
23950
|
+
const content = neutralizeSystemInstructionMarkers(parts.filter((part) => part.trim().length > 0).join(`
|
|
23951
|
+
|
|
23952
|
+
`));
|
|
23953
|
+
return `${SYSTEM_INSTRUCTIONS_FRAME_OPEN}
|
|
23954
|
+
${content}
|
|
23955
|
+
${SYSTEM_INSTRUCTIONS_FRAME_CLOSE}`;
|
|
23956
|
+
}
|
|
23957
|
+
function stripSystemInstructions(source) {
|
|
23958
|
+
if (!source.includes(SYSTEM_INSTRUCTIONS_FRAME_OPEN))
|
|
23959
|
+
return source;
|
|
23960
|
+
const openLength = SYSTEM_INSTRUCTIONS_FRAME_OPEN.length;
|
|
23961
|
+
const closeLength = SYSTEM_INSTRUCTIONS_FRAME_CLOSE.length;
|
|
23962
|
+
const removed = [];
|
|
23963
|
+
const openStack = [];
|
|
23964
|
+
let index = 0;
|
|
23965
|
+
while (index < source.length) {
|
|
23966
|
+
if (source.startsWith(SYSTEM_INSTRUCTIONS_FRAME_OPEN, index)) {
|
|
23967
|
+
openStack.push(index);
|
|
23968
|
+
index += openLength;
|
|
23969
|
+
continue;
|
|
23970
|
+
}
|
|
23971
|
+
if (source.startsWith(SYSTEM_INSTRUCTIONS_FRAME_CLOSE, index)) {
|
|
23972
|
+
const open = openStack.pop();
|
|
23973
|
+
if (open !== undefined)
|
|
23974
|
+
removed.push([open, index + closeLength]);
|
|
23975
|
+
index += closeLength;
|
|
23976
|
+
continue;
|
|
23977
|
+
}
|
|
23978
|
+
index += 1;
|
|
23979
|
+
}
|
|
23980
|
+
if (removed.length === 0)
|
|
23981
|
+
return source;
|
|
23982
|
+
removed.sort((left, right) => left[0] - right[0]);
|
|
23983
|
+
let result = "";
|
|
23984
|
+
let cursor = 0;
|
|
23985
|
+
for (const [start, end] of removed) {
|
|
23986
|
+
if (start < cursor) {
|
|
23987
|
+
cursor = Math.max(cursor, end);
|
|
23988
|
+
continue;
|
|
23989
|
+
}
|
|
23990
|
+
result += source.slice(cursor, start);
|
|
23991
|
+
cursor = end;
|
|
23992
|
+
}
|
|
23993
|
+
result += source.slice(cursor);
|
|
23994
|
+
return result.replace(/\n{3,}/g, `
|
|
23995
|
+
|
|
23996
|
+
`).trim();
|
|
23997
|
+
}
|
|
23889
23998
|
var COORDINATOR_WORKER_NO_PR_INSTRUCTION = "Do not open a pull request, even if the prompt below asks you to: commit your work and report back. Orkestrator raises the pull request from a PR tab once the work has been reviewed.";
|
|
23890
23999
|
var COORDINATOR_JOB_DELEGATION_INSTRUCTION = `This is a server-attested same-project worker delegation. Work only inside this disposable environment under its normal sandbox and approval policy, then report meaningful completion, failure, or blocking details through Orkestrator mail. ${COORDINATOR_WORKER_NO_PR_INSTRUCTION}`;
|
|
23891
24000
|
var COORDINATOR_ENVIRONMENT_DELEGATION_INSTRUCTION = `This is a server-attested same-project worker delegation. Perform it inside this disposable worker under its normal sandbox and approval policy, then report meaningful completion, failure, or blocking details through Orkestrator mail. ${COORDINATOR_WORKER_NO_PR_INSTRUCTION}`;
|
|
@@ -31538,6 +31647,10 @@ var configHomeForTests;
|
|
|
31538
31647
|
function setCursorMcpConfigHomeForTests(home) {
|
|
31539
31648
|
configHomeForTests = home;
|
|
31540
31649
|
}
|
|
31650
|
+
var skillsProjectForTests;
|
|
31651
|
+
function setCursorSkillsProjectForTests(directory) {
|
|
31652
|
+
skillsProjectForTests = directory;
|
|
31653
|
+
}
|
|
31541
31654
|
var attachedConfigKeys = new WeakMap;
|
|
31542
31655
|
var attachedConfigRevisions = new WeakMap;
|
|
31543
31656
|
var fingerprintForTests;
|
|
@@ -31629,7 +31742,7 @@ async function attach(state) {
|
|
|
31629
31742
|
await closeHosted?.();
|
|
31630
31743
|
throw new SessionClosedError;
|
|
31631
31744
|
}
|
|
31632
|
-
const skills = readOnly ? hostSkillCustomTools(process.env, workingDirectory) : undefined;
|
|
31745
|
+
const skills = readOnly ? hostSkillCustomTools(process.env, skillsProjectForTests ?? workingDirectory) : undefined;
|
|
31633
31746
|
const customTools = hosted || research || skills ? { ...skills?.customTools, ...research?.customTools, ...hosted?.customTools } : undefined;
|
|
31634
31747
|
const httpMcpServerNames = hosted ? [] : allowHttpMcp ? Object.keys(mcpServers) : [];
|
|
31635
31748
|
state.hostedMcpClose = closeHosted;
|
|
@@ -31641,16 +31754,18 @@ async function attach(state) {
|
|
|
31641
31754
|
...skills ? [COORDINATOR_SKILLS_SERVER] : []
|
|
31642
31755
|
];
|
|
31643
31756
|
state.attachedMcpKey = mcpConnectionKey(state.agentMcp);
|
|
31757
|
+
const settingSources = cursorSettingSources(policy, {
|
|
31758
|
+
readOnly,
|
|
31759
|
+
selectsServers: selectServers !== undefined
|
|
31760
|
+
});
|
|
31761
|
+
state.loadsProjectRules = settingSources.includes("project");
|
|
31644
31762
|
const options = {
|
|
31645
31763
|
apiKey,
|
|
31646
31764
|
model: modelSelection(state.composer),
|
|
31647
31765
|
mode: state.composer.selectedModeId === "plan" ? "plan" : "agent",
|
|
31648
31766
|
local: {
|
|
31649
31767
|
cwd: workingDirectory,
|
|
31650
|
-
settingSources
|
|
31651
|
-
readOnly,
|
|
31652
|
-
selectsServers: selectServers !== undefined
|
|
31653
|
-
}),
|
|
31768
|
+
settingSources,
|
|
31654
31769
|
sandboxOptions: { enabled: policy.sandbox === "provider" },
|
|
31655
31770
|
autoReview: policy.sandbox === "provider" && policy.approvals === "auto-approve",
|
|
31656
31771
|
...customTools ? { customTools } : {}
|
|
@@ -32202,11 +32317,8 @@ function pushHistoricRow(state, row, planned) {
|
|
|
32202
32317
|
}
|
|
32203
32318
|
function historicUserTexts(body) {
|
|
32204
32319
|
const extract = (value) => {
|
|
32205
|
-
|
|
32206
|
-
|
|
32207
|
-
if (isObject(value) && nonBlank(value.text))
|
|
32208
|
-
return value.text;
|
|
32209
|
-
return;
|
|
32320
|
+
const raw = typeof value === "string" ? value : isObject(value) && nonBlank(value.text) ? value.text : undefined;
|
|
32321
|
+
return raw === undefined ? undefined : stripSystemInstructions(raw);
|
|
32210
32322
|
};
|
|
32211
32323
|
const texts = [];
|
|
32212
32324
|
const remaining = new Map;
|
|
@@ -32296,6 +32408,58 @@ function pushMessage(state, role, content, parts, messageId = randomBytes5(12).t
|
|
|
32296
32408
|
state.messages.push(message);
|
|
32297
32409
|
chargeTranscript(state, Buffer.byteLength(JSON.stringify(message)));
|
|
32298
32410
|
}
|
|
32411
|
+
// ../protocol/src/agent-system-instructions.ts
|
|
32412
|
+
var AGENT_IMAGE_PREVIEW_INSTRUCTION = "Orkestrator renders Markdown images inline in the transcript. When you show the user an image in your reply (a screenshot, rendered preview, or chart) using Markdown image syntax, reference it by its absolute path. In a managed worktree or container environment, save the file inside the working directory, preferably in a git-ignored folder so preview files stay out of the change set. Local image previews are limited to Orkestrator-managed workspace storage or the container's /workspace. Project-home checkouts are excluded from host preview reads, even when they are the working directory, so images saved there cannot be previewed from a local Markdown path. Paths outside previewable storage, such as /tmp, also show a placeholder.";
|
|
32413
|
+
var AGENT_DOCUMENT_INSTRUCTION = "When the user asks for a document (a report, design doc, plan, analysis, guide, or other writing to keep), prefer writing it as a Markdown file in a `docs/` folder at the root of the working directory, and tell the user the file's path. Project instructions (such as AGENTS.md or CLAUDE.md), local skills, and the user's own request take priority over this default when they say where or how to write documents.";
|
|
32414
|
+
var GENERAL_AGENT_INSTRUCTIONS = [
|
|
32415
|
+
AGENT_IMAGE_PREVIEW_INSTRUCTION,
|
|
32416
|
+
AGENT_DOCUMENT_INSTRUCTION
|
|
32417
|
+
];
|
|
32418
|
+
function agentSystemInstructions(providerSpecific = []) {
|
|
32419
|
+
return [...GENERAL_AGENT_INSTRUCTIONS, ...providerSpecific].filter((line) => line.trim().length > 0).join(`
|
|
32420
|
+
|
|
32421
|
+
`);
|
|
32422
|
+
}
|
|
32423
|
+
var REPOSITORY_INSTRUCTIONS_FILE = "AGENTS.md";
|
|
32424
|
+
function repositoryInstructionsBlock(path, content, truncated) {
|
|
32425
|
+
return [
|
|
32426
|
+
`# Repository instructions (${REPOSITORY_INSTRUCTIONS_FILE})`,
|
|
32427
|
+
`This session does not load the repository's ${REPOSITORY_INSTRUCTIONS_FILE} on its own, so Orkestrator includes it here. Follow it as project instructions. Contents of ${path}:`,
|
|
32428
|
+
content.trimEnd(),
|
|
32429
|
+
...truncated ? [
|
|
32430
|
+
`[${REPOSITORY_INSTRUCTIONS_FILE} is longer than this session can hold, so it is cut here. Read the rest from ${path} before relying on anything it may say.]`
|
|
32431
|
+
] : []
|
|
32432
|
+
].join(`
|
|
32433
|
+
|
|
32434
|
+
`);
|
|
32435
|
+
}
|
|
32436
|
+
|
|
32437
|
+
// ../protocol/src/node/repository-instructions.ts
|
|
32438
|
+
import { open as open3, realpath } from "node:fs/promises";
|
|
32439
|
+
import { join as join7, relative as relative3, isAbsolute as isAbsolute3 } from "node:path";
|
|
32440
|
+
var MAX_REPOSITORY_INSTRUCTIONS_BYTES = 256 * 1024;
|
|
32441
|
+
async function readRepositoryInstructions(cwd, maxBytes = MAX_REPOSITORY_INSTRUCTIONS_BYTES) {
|
|
32442
|
+
const path = join7(cwd, REPOSITORY_INSTRUCTIONS_FILE);
|
|
32443
|
+
try {
|
|
32444
|
+
const [root, target] = await Promise.all([realpath(cwd), realpath(path)]);
|
|
32445
|
+
const inside = relative3(root, target);
|
|
32446
|
+
if (!inside || inside.startsWith("..") || isAbsolute3(inside))
|
|
32447
|
+
return;
|
|
32448
|
+
const handle = await open3(target, "r");
|
|
32449
|
+
try {
|
|
32450
|
+
const buffer = Buffer.alloc(maxBytes + 1);
|
|
32451
|
+
const { bytesRead } = await handle.read(buffer, 0, maxBytes + 1, 0);
|
|
32452
|
+
const truncated = bytesRead > maxBytes;
|
|
32453
|
+
const text = new TextDecoder().decode(buffer.subarray(0, Math.min(bytesRead, maxBytes))).replace(/�$/, "");
|
|
32454
|
+
return text.trim() ? repositoryInstructionsBlock(path, text, truncated) : undefined;
|
|
32455
|
+
} finally {
|
|
32456
|
+
await handle.close();
|
|
32457
|
+
}
|
|
32458
|
+
} catch {
|
|
32459
|
+
return;
|
|
32460
|
+
}
|
|
32461
|
+
}
|
|
32462
|
+
|
|
32299
32463
|
// ../protocol/src/structured-output-text.ts
|
|
32300
32464
|
var STRUCTURED_OUTPUT_RECOVERY_CHARS = 1024 * 1024;
|
|
32301
32465
|
var STRUCTURED_OUTPUT_RECOVERY_CANDIDATES = 256;
|
|
@@ -32508,7 +32672,7 @@ import { randomUUID as randomUUID2 } from "node:crypto";
|
|
|
32508
32672
|
import { rmSync } from "node:fs";
|
|
32509
32673
|
import { copyFile, lstat, mkdtemp, rm as rm2 } from "node:fs/promises";
|
|
32510
32674
|
import { tmpdir } from "node:os";
|
|
32511
|
-
import { delimiter, isAbsolute as
|
|
32675
|
+
import { delimiter, isAbsolute as isAbsolute4, join as join8, resolve as resolve4 } from "node:path";
|
|
32512
32676
|
var DEFAULT_MAX_UNTRACKED_FILE_BYTES = 2 * 1024 * 1024;
|
|
32513
32677
|
var DEFAULT_MAX_UNTRACKED_FILES = 5000;
|
|
32514
32678
|
var DEFAULT_SLOW_SNAPSHOT_MS = 500;
|
|
@@ -32790,8 +32954,8 @@ class WorkspaceChangeProbe {
|
|
|
32790
32954
|
return;
|
|
32791
32955
|
return {
|
|
32792
32956
|
root,
|
|
32793
|
-
indexPath:
|
|
32794
|
-
objectsPath:
|
|
32957
|
+
indexPath: isAbsolute4(index) ? index : resolve4(cwd, index),
|
|
32958
|
+
objectsPath: isAbsolute4(objects) ? objects : resolve4(cwd, objects)
|
|
32795
32959
|
};
|
|
32796
32960
|
}).catch(() => {
|
|
32797
32961
|
return;
|
|
@@ -32834,8 +32998,8 @@ class WorkspaceChangeProbe {
|
|
|
32834
32998
|
return;
|
|
32835
32999
|
const { root, indexPath } = repo.location;
|
|
32836
33000
|
const started = this.now();
|
|
32837
|
-
const tempIndex =
|
|
32838
|
-
const objectDirectory = await mkdtemp(
|
|
33001
|
+
const tempIndex = join8(this.tempDir, `orkestrator-probe-${randomUUID2()}.index`);
|
|
33002
|
+
const objectDirectory = await mkdtemp(join8(this.tempDir, "orkestrator-probe-objects-"));
|
|
32839
33003
|
temporaryObjectDirectories.add(objectDirectory);
|
|
32840
33004
|
let retained = false;
|
|
32841
33005
|
try {
|
|
@@ -32852,7 +33016,7 @@ class WorkspaceChangeProbe {
|
|
|
32852
33016
|
const included = [];
|
|
32853
33017
|
const skipped = new Map;
|
|
32854
33018
|
for (const path of untracked) {
|
|
32855
|
-
const stats = await lstat(
|
|
33019
|
+
const stats = await lstat(join8(root, path)).catch(() => {
|
|
32856
33020
|
return;
|
|
32857
33021
|
});
|
|
32858
33022
|
if (!stats)
|
|
@@ -33105,10 +33269,28 @@ Before that final message you may send ordinary prose progress updates. Keep the
|
|
|
33105
33269
|
|
|
33106
33270
|
${JSON.stringify(schema)}`;
|
|
33107
33271
|
}
|
|
33108
|
-
|
|
33109
|
-
const
|
|
33272
|
+
function cursorPromptText(state, input, repositoryInstructions) {
|
|
33273
|
+
const parts = [
|
|
33274
|
+
cursorAppliedPolicy(state).id === "coordinator-read-only" ? "" : agentSystemInstructions(),
|
|
33275
|
+
cursorAppliedPolicy(state).id === "coordinator-read-only" ? "" : repositoryInstructions ?? ""
|
|
33276
|
+
].filter((part) => part.length > 0);
|
|
33277
|
+
return [
|
|
33278
|
+
input.prompt,
|
|
33279
|
+
parts.length > 0 ? wrapSystemInstructions(...parts) : "",
|
|
33280
|
+
input.schema ? structuredPromptInstruction(input.schema) : ""
|
|
33281
|
+
].filter((part) => part.length > 0).join(`
|
|
33110
33282
|
|
|
33111
|
-
|
|
33283
|
+
`);
|
|
33284
|
+
}
|
|
33285
|
+
async function repositoryInstructionsFor(state, cwd = workingDirectory) {
|
|
33286
|
+
if (cursorAppliedPolicy(state).id === "coordinator-read-only" || state.loadsProjectRules || state.repositoryInstructionsAgentId === state.agentId) {
|
|
33287
|
+
return;
|
|
33288
|
+
}
|
|
33289
|
+
return readRepositoryInstructions(cwd);
|
|
33290
|
+
}
|
|
33291
|
+
async function dispatchPrompt(state, agent, input) {
|
|
33292
|
+
const repositoryInstructions = await repositoryInstructionsFor(state);
|
|
33293
|
+
const text = cursorPromptText(state, input, repositoryInstructions);
|
|
33112
33294
|
const images = input.images.map((image) => ({
|
|
33113
33295
|
data: image.data,
|
|
33114
33296
|
mimeType: image.mimeType
|
|
@@ -33154,6 +33336,8 @@ ${structuredPromptInstruction(input.schema)}` : input.prompt;
|
|
|
33154
33336
|
throw error;
|
|
33155
33337
|
});
|
|
33156
33338
|
diagnostics?.sent(run.id);
|
|
33339
|
+
if (!state.loadsProjectRules)
|
|
33340
|
+
state.repositoryInstructionsAgentId = state.agentId;
|
|
33157
33341
|
if (input.userMessageId) {
|
|
33158
33342
|
const userMessage = state.messages.find((message) => message.id === input.userMessageId);
|
|
33159
33343
|
if (userMessage?.role === "user") {
|
|
@@ -33169,6 +33353,7 @@ ${structuredPromptInstruction(input.schema)}` : input.prompt;
|
|
|
33169
33353
|
async function dispatchCompaction(state, agent) {
|
|
33170
33354
|
const promptSequence = state.promptSequence;
|
|
33171
33355
|
const diagnostics = createRunDiagnostics(state);
|
|
33356
|
+
state.repositoryInstructionsAgentId = undefined;
|
|
33172
33357
|
const start = () => agent.summarize();
|
|
33173
33358
|
const run = await (diagnostics ? diagnostics.follow(start) : start()).catch((error) => {
|
|
33174
33359
|
diagnostics?.close("send-failed");
|
|
@@ -33701,8 +33886,8 @@ async function withTimeout3(work, timeoutMs) {
|
|
|
33701
33886
|
}
|
|
33702
33887
|
// ../../bridges/cursor-bridge/src/prompt-attachments.ts
|
|
33703
33888
|
import { constants } from "node:fs";
|
|
33704
|
-
import { lstat as lstat2, open as
|
|
33705
|
-
import { isAbsolute as
|
|
33889
|
+
import { lstat as lstat2, open as open4, realpath as realpath2 } from "node:fs/promises";
|
|
33890
|
+
import { isAbsolute as isAbsolute5, join as join9, relative as relative4, resolve as resolve6, sep as sep3 } from "node:path";
|
|
33706
33891
|
|
|
33707
33892
|
class PromptAttachmentError extends Error {
|
|
33708
33893
|
code;
|
|
@@ -33787,10 +33972,10 @@ function attachmentErrorForFsFailure(error) {
|
|
|
33787
33972
|
var BRIDGE_ATTACHMENT_ROOT_ENV = "ORKESTRATOR_BRIDGE_ATTACHMENT_ROOT";
|
|
33788
33973
|
function configuredAttachmentRoot(env = process.env) {
|
|
33789
33974
|
const value = env[BRIDGE_ATTACHMENT_ROOT_ENV]?.trim();
|
|
33790
|
-
return value &&
|
|
33975
|
+
return value && isAbsolute5(value) ? resolve6(value) : undefined;
|
|
33791
33976
|
}
|
|
33792
33977
|
function attachmentContainmentRoot(filePath, workspaceRoot, extraRoot = configuredAttachmentRoot()) {
|
|
33793
|
-
if (extraRoot &&
|
|
33978
|
+
if (extraRoot && isAbsolute5(filePath) && isPathWithin(extraRoot, resolve6(filePath))) {
|
|
33794
33979
|
return extraRoot;
|
|
33795
33980
|
}
|
|
33796
33981
|
return resolve6(workspaceRoot);
|
|
@@ -33798,13 +33983,13 @@ function attachmentContainmentRoot(filePath, workspaceRoot, extraRoot = configur
|
|
|
33798
33983
|
function isPathWithin(root, candidate) {
|
|
33799
33984
|
if (candidate === root)
|
|
33800
33985
|
return true;
|
|
33801
|
-
const childPath =
|
|
33802
|
-
return Boolean(childPath) && childPath !== ".." && !childPath.startsWith(`..${sep3}`) && !
|
|
33986
|
+
const childPath = relative4(root, candidate);
|
|
33987
|
+
return Boolean(childPath) && childPath !== ".." && !childPath.startsWith(`..${sep3}`) && !isAbsolute5(childPath);
|
|
33803
33988
|
}
|
|
33804
33989
|
async function assertNoSymlinkComponents(root, targetPath) {
|
|
33805
33990
|
let currentPath = root;
|
|
33806
|
-
for (const segment of
|
|
33807
|
-
currentPath =
|
|
33991
|
+
for (const segment of relative4(root, targetPath).split(sep3).filter(Boolean)) {
|
|
33992
|
+
currentPath = join9(currentPath, segment);
|
|
33808
33993
|
const stats = await lstat2(currentPath).catch((error) => {
|
|
33809
33994
|
throw attachmentErrorForFsFailure(error);
|
|
33810
33995
|
});
|
|
@@ -33816,7 +34001,7 @@ async function assertNoSymlinkComponents(root, targetPath) {
|
|
|
33816
34001
|
async function assertOpenedWorkspaceFile(targetPath, canonicalRoot, openedStats) {
|
|
33817
34002
|
const [pathStats, canonicalTarget] = await Promise.all([
|
|
33818
34003
|
lstat2(targetPath),
|
|
33819
|
-
|
|
34004
|
+
realpath2(targetPath)
|
|
33820
34005
|
]).catch((error) => {
|
|
33821
34006
|
throw attachmentErrorForFsFailure(error);
|
|
33822
34007
|
});
|
|
@@ -33837,22 +34022,22 @@ function assertStableRead(initial, final, bytesRead) {
|
|
|
33837
34022
|
}
|
|
33838
34023
|
async function readWorkspaceImage(filePath, workspaceRoot) {
|
|
33839
34024
|
const lexicalRoot = attachmentContainmentRoot(filePath, workspaceRoot);
|
|
33840
|
-
const targetPath =
|
|
34025
|
+
const targetPath = isAbsolute5(filePath) ? resolve6(filePath) : resolve6(lexicalRoot, filePath);
|
|
33841
34026
|
if (!isPathWithin(lexicalRoot, targetPath)) {
|
|
33842
34027
|
throw new PromptAttachmentError("attachment_outside_workspace", "Image attachment must be contained in the current workspace");
|
|
33843
34028
|
}
|
|
33844
|
-
const canonicalRoot = await
|
|
34029
|
+
const canonicalRoot = await realpath2(lexicalRoot).catch((error) => {
|
|
33845
34030
|
throw attachmentErrorForFsFailure(error);
|
|
33846
34031
|
});
|
|
33847
34032
|
await assertNoSymlinkComponents(lexicalRoot, targetPath);
|
|
33848
|
-
const canonicalTarget = await
|
|
34033
|
+
const canonicalTarget = await realpath2(targetPath).catch((error) => {
|
|
33849
34034
|
throw attachmentErrorForFsFailure(error);
|
|
33850
34035
|
});
|
|
33851
34036
|
if (!isPathWithin(canonicalRoot, canonicalTarget)) {
|
|
33852
34037
|
throw new PromptAttachmentError("attachment_outside_workspace", "Image attachment must be contained in the current workspace");
|
|
33853
34038
|
}
|
|
33854
34039
|
const noFollow = constants.O_NOFOLLOW ?? 0;
|
|
33855
|
-
const handle = await
|
|
34040
|
+
const handle = await open4(targetPath, constants.O_RDONLY | noFollow).catch((error) => {
|
|
33856
34041
|
throw attachmentErrorForFsFailure(error);
|
|
33857
34042
|
});
|
|
33858
34043
|
try {
|
|
@@ -36497,6 +36682,7 @@ if (process.argv.includes("--login")) {
|
|
|
36497
36682
|
export {
|
|
36498
36683
|
ABANDONED_COMPACTION_NOTE,
|
|
36499
36684
|
ABANDONED_TOOL_NOTE,
|
|
36685
|
+
ACCOUNT_LOOKUP_TIMEOUT_MS,
|
|
36500
36686
|
BRIDGE_ATTACHMENT_ROOT_ENV,
|
|
36501
36687
|
CANCEL_ACK_TIMEOUT_MS,
|
|
36502
36688
|
CATALOG_TIMEOUT_MS,
|
|
@@ -36594,6 +36780,7 @@ export {
|
|
|
36594
36780
|
cursorDeniedTools,
|
|
36595
36781
|
cursorMcpConfigFingerprint,
|
|
36596
36782
|
cursorMcpConfigRevision,
|
|
36783
|
+
cursorPromptText,
|
|
36597
36784
|
cursorSdkStateDirectoryPath,
|
|
36598
36785
|
detachAgent,
|
|
36599
36786
|
dispatchCompaction,
|
|
@@ -36649,6 +36836,7 @@ export {
|
|
|
36649
36836
|
rememberedOwnerRow,
|
|
36650
36837
|
renderToolCall,
|
|
36651
36838
|
reopenPersistenceForTests,
|
|
36839
|
+
repositoryInstructionsFor,
|
|
36652
36840
|
resolveCredential,
|
|
36653
36841
|
resolveCursorExecutionPolicy,
|
|
36654
36842
|
resumeSession,
|
|
@@ -36669,6 +36857,7 @@ export {
|
|
|
36669
36857
|
sessions,
|
|
36670
36858
|
setCursorMcpConfigHomeForTests,
|
|
36671
36859
|
setCursorMcpFingerprintForTests,
|
|
36860
|
+
setCursorSkillsProjectForTests,
|
|
36672
36861
|
setMaxIndexedCallsForTests,
|
|
36673
36862
|
setPromptJournal,
|
|
36674
36863
|
setResumableAgentArchived,
|
|
@@ -3824,6 +3824,7 @@ var COORDINATOR_CONTROL_TOOL_NAMES = Object.freeze([
|
|
|
3824
3824
|
"stop_node_environment",
|
|
3825
3825
|
"stop_worker_turn",
|
|
3826
3826
|
"switch_provider_account",
|
|
3827
|
+
"set_account_auto_switch",
|
|
3827
3828
|
"transfer_files",
|
|
3828
3829
|
"update_schedule",
|
|
3829
3830
|
"update_ticket"
|
|
@@ -27935,6 +27936,7 @@ var TOOL_CALL_TIMEOUT_MS = 120000;
|
|
|
27935
27936
|
var MAX_MCP_TOOLS = 128;
|
|
27936
27937
|
var MAX_MCP_RESULT_BYTES = 50000;
|
|
27937
27938
|
var MAX_MCP_DESCRIPTION_BYTES = 4000;
|
|
27939
|
+
var MAX_MCP_INSTRUCTIONS_BYTES = 8000;
|
|
27938
27940
|
var MAX_MCP_SCHEMA_BYTES = 20000;
|
|
27939
27941
|
var COORDINATOR_MAIL_TOOLS = new Set([
|
|
27940
27942
|
...COORDINATOR_CONTROL_TOOL_NAMES,
|
|
@@ -28028,6 +28030,7 @@ async function preparePiMcp(state, options = {}) {
|
|
|
28028
28030
|
grantedToolNames: new Set,
|
|
28029
28031
|
granted: nativeAgentUserMcpGrant(state.policy) !== undefined,
|
|
28030
28032
|
tools: [],
|
|
28033
|
+
instructions: [],
|
|
28031
28034
|
connections: [],
|
|
28032
28035
|
connectionKey: mcpConnectionKey(state),
|
|
28033
28036
|
configKey: "",
|
|
@@ -28077,6 +28080,19 @@ function piMcpExtension(state) {
|
|
|
28077
28080
|
}
|
|
28078
28081
|
};
|
|
28079
28082
|
}
|
|
28083
|
+
function piMcpInstructions(state) {
|
|
28084
|
+
const entries = runtimes.get(state)?.instructions ?? [];
|
|
28085
|
+
if (entries.length === 0)
|
|
28086
|
+
return;
|
|
28087
|
+
return [
|
|
28088
|
+
"# MCP Server Instructions",
|
|
28089
|
+
"The following MCP servers have provided instructions for how to use their tools and resources:",
|
|
28090
|
+
...entries.map((entry) => `## ${entry.serverId}
|
|
28091
|
+
${entry.text}`)
|
|
28092
|
+
].join(`
|
|
28093
|
+
|
|
28094
|
+
`);
|
|
28095
|
+
}
|
|
28080
28096
|
async function closePiMcp(state) {
|
|
28081
28097
|
const runtime = runtimes.get(state);
|
|
28082
28098
|
if (runtime)
|
|
@@ -28136,6 +28152,13 @@ async function connectAndRegister(state, runtime, server) {
|
|
|
28136
28152
|
return detachedServer(server);
|
|
28137
28153
|
}
|
|
28138
28154
|
runtime.connections.push(connection);
|
|
28155
|
+
const instructions = connection.instructions?.trim();
|
|
28156
|
+
if (instructions) {
|
|
28157
|
+
runtime.instructions.push({
|
|
28158
|
+
serverId: server.id,
|
|
28159
|
+
text: instructions.length > MAX_MCP_INSTRUCTIONS_BYTES ? instructions.slice(0, MAX_MCP_INSTRUCTIONS_BYTES) : instructions
|
|
28160
|
+
});
|
|
28161
|
+
}
|
|
28139
28162
|
const tools = connection.tools.slice(0, MAX_MCP_TOOLS);
|
|
28140
28163
|
const names = [];
|
|
28141
28164
|
for (const listed of tools) {
|
|
@@ -28274,7 +28297,9 @@ var defaultTransport = {
|
|
|
28274
28297
|
try {
|
|
28275
28298
|
await client.connect(transport);
|
|
28276
28299
|
const listed = await client.listTools();
|
|
28300
|
+
const instructions = client.getInstructions();
|
|
28277
28301
|
return {
|
|
28302
|
+
...instructions ? { instructions } : {},
|
|
28278
28303
|
tools: (listed.tools ?? []).map((tool) => ({
|
|
28279
28304
|
name: tool.name,
|
|
28280
28305
|
...tool.description ? { description: tool.description } : {},
|
|
@@ -28932,6 +28957,21 @@ function readString2(value) {
|
|
|
28932
28957
|
// ../../bridges/pi-bridge/src/agent-session.ts
|
|
28933
28958
|
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
28934
28959
|
import { existsSync as existsSync2 } from "node:fs";
|
|
28960
|
+
|
|
28961
|
+
// ../protocol/src/agent-system-instructions.ts
|
|
28962
|
+
var AGENT_IMAGE_PREVIEW_INSTRUCTION = "Orkestrator renders Markdown images inline in the transcript. When you show the user an image in your reply (a screenshot, rendered preview, or chart) using Markdown image syntax, reference it by its absolute path. In a managed worktree or container environment, save the file inside the working directory, preferably in a git-ignored folder so preview files stay out of the change set. Local image previews are limited to Orkestrator-managed workspace storage or the container's /workspace. Project-home checkouts are excluded from host preview reads, even when they are the working directory, so images saved there cannot be previewed from a local Markdown path. Paths outside previewable storage, such as /tmp, also show a placeholder.";
|
|
28963
|
+
var AGENT_DOCUMENT_INSTRUCTION = "When the user asks for a document (a report, design doc, plan, analysis, guide, or other writing to keep), prefer writing it as a Markdown file in a `docs/` folder at the root of the working directory, and tell the user the file's path. Project instructions (such as AGENTS.md or CLAUDE.md), local skills, and the user's own request take priority over this default when they say where or how to write documents.";
|
|
28964
|
+
var GENERAL_AGENT_INSTRUCTIONS = [
|
|
28965
|
+
AGENT_IMAGE_PREVIEW_INSTRUCTION,
|
|
28966
|
+
AGENT_DOCUMENT_INSTRUCTION
|
|
28967
|
+
];
|
|
28968
|
+
function agentSystemInstructions(providerSpecific = []) {
|
|
28969
|
+
return [...GENERAL_AGENT_INSTRUCTIONS, ...providerSpecific].filter((line) => line.trim().length > 0).join(`
|
|
28970
|
+
|
|
28971
|
+
`);
|
|
28972
|
+
}
|
|
28973
|
+
|
|
28974
|
+
// ../../bridges/pi-bridge/src/agent-session.ts
|
|
28935
28975
|
import { realpath, stat as stat2 } from "node:fs/promises";
|
|
28936
28976
|
import { join as join6, resolve as resolve3, sep } from "node:path";
|
|
28937
28977
|
|
|
@@ -31194,12 +31234,20 @@ async function reconcileAgentMcp(state, options = {}) {
|
|
|
31194
31234
|
await detachSession(state);
|
|
31195
31235
|
}
|
|
31196
31236
|
}
|
|
31237
|
+
function piAppendedInstructions(state) {
|
|
31238
|
+
const mcp = piMcpInstructions(state);
|
|
31239
|
+
return [
|
|
31240
|
+
...state.policy?.id === "coordinator-read-only" ? [] : [agentSystemInstructions()],
|
|
31241
|
+
...mcp ? [mcp] : []
|
|
31242
|
+
];
|
|
31243
|
+
}
|
|
31197
31244
|
async function createPiSessionServices(state, options) {
|
|
31198
31245
|
const loaderPolicy = piResourceLoaderPolicy(state, options.cwd);
|
|
31199
31246
|
const services = await createAgentSessionServices({
|
|
31200
31247
|
...options,
|
|
31201
31248
|
resourceLoaderOptions: {
|
|
31202
31249
|
...loaderPolicy.discovery,
|
|
31250
|
+
appendSystemPromptOverride: (base) => [...base, ...piAppendedInstructions(state)],
|
|
31203
31251
|
extensionFactories: [
|
|
31204
31252
|
{ name: "orkestrator", factory: approvalExtension(state) },
|
|
31205
31253
|
{ name: "orkestrator-mcp", factory: piMcpExtension(state) },
|
|
@@ -35947,6 +35995,7 @@ export {
|
|
|
35947
35995
|
parsePromptAttachments,
|
|
35948
35996
|
parseTranscriptTailLimit as parseTailLimit,
|
|
35949
35997
|
persistBarrier,
|
|
35998
|
+
piAppendedInstructions,
|
|
35950
35999
|
piReadiness,
|
|
35951
36000
|
piReportedPolicy,
|
|
35952
36001
|
piResourceLoaderPolicy,
|