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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orkestrator",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.35.0-beta",
|
|
4
4
|
"description": "Run the Orkestrator backend service without the desktop application",
|
|
5
5
|
"homepage": "https://orkestrator.dev",
|
|
6
6
|
"repository": {
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"sharp": "0.35.5"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@orkestrator/protocol": "2.
|
|
43
|
-
"@orkestrator/toolchain": "2.
|
|
42
|
+
"@orkestrator/protocol": "2.35.0-beta",
|
|
43
|
+
"@orkestrator/toolchain": "2.35.0-beta"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
|
46
46
|
"bun": ">=1.4.4"
|
|
@@ -9564,6 +9564,14 @@ var PROJECT_TRUST = {
|
|
|
9564
9564
|
afterSubcommand: ["--no-leader"]
|
|
9565
9565
|
}
|
|
9566
9566
|
};
|
|
9567
|
+
var SESSION_RULES_META_FIELD = {
|
|
9568
|
+
grok: "rules"
|
|
9569
|
+
};
|
|
9570
|
+
function sessionInstructionsMeta(config, instructions) {
|
|
9571
|
+
if (!instructions || !Object.hasOwn(SESSION_RULES_META_FIELD, config.id))
|
|
9572
|
+
return {};
|
|
9573
|
+
return { _meta: { [SESSION_RULES_META_FIELD[config.id]]: instructions } };
|
|
9574
|
+
}
|
|
9567
9575
|
var POLICY_ENV = {
|
|
9568
9576
|
grok: { GROK_WORKTREE_INHERITS_MAIN_APPROVALS: "false" }
|
|
9569
9577
|
};
|
|
@@ -15666,6 +15674,71 @@ function isStringTuple(value) {
|
|
|
15666
15674
|
return Array.isArray(value) && value.length === 2 && typeof value[0] === "string";
|
|
15667
15675
|
}
|
|
15668
15676
|
|
|
15677
|
+
// ../protocol/src/agent-system-instructions.ts
|
|
15678
|
+
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.";
|
|
15679
|
+
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.";
|
|
15680
|
+
var GENERAL_AGENT_INSTRUCTIONS = [
|
|
15681
|
+
AGENT_IMAGE_PREVIEW_INSTRUCTION,
|
|
15682
|
+
AGENT_DOCUMENT_INSTRUCTION
|
|
15683
|
+
];
|
|
15684
|
+
function agentSystemInstructions(providerSpecific = []) {
|
|
15685
|
+
return [...GENERAL_AGENT_INSTRUCTIONS, ...providerSpecific].filter((line) => line.trim().length > 0).join(`
|
|
15686
|
+
|
|
15687
|
+
`);
|
|
15688
|
+
}
|
|
15689
|
+
var REPOSITORY_INSTRUCTIONS_FILE = "AGENTS.md";
|
|
15690
|
+
function repositoryInstructionsBlock(path, content, truncated) {
|
|
15691
|
+
return [
|
|
15692
|
+
`# Repository instructions (${REPOSITORY_INSTRUCTIONS_FILE})`,
|
|
15693
|
+
`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}:`,
|
|
15694
|
+
content.trimEnd(),
|
|
15695
|
+
...truncated ? [
|
|
15696
|
+
`[${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.]`
|
|
15697
|
+
] : []
|
|
15698
|
+
].join(`
|
|
15699
|
+
|
|
15700
|
+
`);
|
|
15701
|
+
}
|
|
15702
|
+
|
|
15703
|
+
// ../protocol/src/node/repository-instructions.ts
|
|
15704
|
+
import { open as open3, realpath as realpath2 } from "node:fs/promises";
|
|
15705
|
+
import { join as join5, relative as relative2, isAbsolute as isAbsolute2 } from "node:path";
|
|
15706
|
+
var MAX_REPOSITORY_INSTRUCTIONS_BYTES = 256 * 1024;
|
|
15707
|
+
async function readRepositoryInstructions(cwd, maxBytes = MAX_REPOSITORY_INSTRUCTIONS_BYTES) {
|
|
15708
|
+
const path = join5(cwd, REPOSITORY_INSTRUCTIONS_FILE);
|
|
15709
|
+
try {
|
|
15710
|
+
const [root, target] = await Promise.all([realpath2(cwd), realpath2(path)]);
|
|
15711
|
+
const inside = relative2(root, target);
|
|
15712
|
+
if (!inside || inside.startsWith("..") || isAbsolute2(inside))
|
|
15713
|
+
return;
|
|
15714
|
+
const handle = await open3(target, "r");
|
|
15715
|
+
try {
|
|
15716
|
+
const buffer = Buffer.alloc(maxBytes + 1);
|
|
15717
|
+
const { bytesRead } = await handle.read(buffer, 0, maxBytes + 1, 0);
|
|
15718
|
+
const truncated = bytesRead > maxBytes;
|
|
15719
|
+
const text = new TextDecoder().decode(buffer.subarray(0, Math.min(bytesRead, maxBytes))).replace(/�$/, "");
|
|
15720
|
+
return text.trim() ? repositoryInstructionsBlock(path, text, truncated) : undefined;
|
|
15721
|
+
} finally {
|
|
15722
|
+
await handle.close();
|
|
15723
|
+
}
|
|
15724
|
+
} catch {
|
|
15725
|
+
return;
|
|
15726
|
+
}
|
|
15727
|
+
}
|
|
15728
|
+
|
|
15729
|
+
// ../../bridges/acp-bridge/src/acp-session-instructions.ts
|
|
15730
|
+
async function sessionInstructions(policy, cwd) {
|
|
15731
|
+
if (policy?.id === "coordinator-read-only")
|
|
15732
|
+
return;
|
|
15733
|
+
const parts = [
|
|
15734
|
+
agentSystemInstructions(),
|
|
15735
|
+
policy?.projectResources === true ? undefined : await readRepositoryInstructions(cwd)
|
|
15736
|
+
].filter((part) => Boolean(part));
|
|
15737
|
+
return parts.length > 0 ? parts.join(`
|
|
15738
|
+
|
|
15739
|
+
`) : undefined;
|
|
15740
|
+
}
|
|
15741
|
+
|
|
15669
15742
|
// ../protocol/src/mcp-elicitation-form.ts
|
|
15670
15743
|
function record2(value) {
|
|
15671
15744
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -15862,7 +15935,7 @@ import { randomUUID } from "node:crypto";
|
|
|
15862
15935
|
import { rmSync as rmSync2 } from "node:fs";
|
|
15863
15936
|
import { copyFile, lstat as lstat2, mkdtemp, rm as rm2 } from "node:fs/promises";
|
|
15864
15937
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
15865
|
-
import { delimiter, isAbsolute as
|
|
15938
|
+
import { delimiter, isAbsolute as isAbsolute3, join as join6, resolve as resolve4 } from "node:path";
|
|
15866
15939
|
var DEFAULT_MAX_UNTRACKED_FILE_BYTES = 2 * 1024 * 1024;
|
|
15867
15940
|
var DEFAULT_MAX_UNTRACKED_FILES = 5000;
|
|
15868
15941
|
var DEFAULT_SLOW_SNAPSHOT_MS = 500;
|
|
@@ -16144,8 +16217,8 @@ class WorkspaceChangeProbe {
|
|
|
16144
16217
|
return;
|
|
16145
16218
|
return {
|
|
16146
16219
|
root,
|
|
16147
|
-
indexPath:
|
|
16148
|
-
objectsPath:
|
|
16220
|
+
indexPath: isAbsolute3(index) ? index : resolve4(cwd, index),
|
|
16221
|
+
objectsPath: isAbsolute3(objects) ? objects : resolve4(cwd, objects)
|
|
16149
16222
|
};
|
|
16150
16223
|
}).catch(() => {
|
|
16151
16224
|
return;
|
|
@@ -16188,8 +16261,8 @@ class WorkspaceChangeProbe {
|
|
|
16188
16261
|
return;
|
|
16189
16262
|
const { root, indexPath } = repo.location;
|
|
16190
16263
|
const started = this.now();
|
|
16191
|
-
const tempIndex =
|
|
16192
|
-
const objectDirectory = await mkdtemp(
|
|
16264
|
+
const tempIndex = join6(this.tempDir, `orkestrator-probe-${randomUUID()}.index`);
|
|
16265
|
+
const objectDirectory = await mkdtemp(join6(this.tempDir, "orkestrator-probe-objects-"));
|
|
16193
16266
|
temporaryObjectDirectories.add(objectDirectory);
|
|
16194
16267
|
let retained = false;
|
|
16195
16268
|
try {
|
|
@@ -16206,7 +16279,7 @@ class WorkspaceChangeProbe {
|
|
|
16206
16279
|
const included = [];
|
|
16207
16280
|
const skipped = new Map;
|
|
16208
16281
|
for (const path of untracked) {
|
|
16209
|
-
const stats = await lstat2(
|
|
16282
|
+
const stats = await lstat2(join6(root, path)).catch(() => {
|
|
16210
16283
|
return;
|
|
16211
16284
|
});
|
|
16212
16285
|
if (!stats)
|
|
@@ -16858,7 +16931,7 @@ function workspaceObservationReportIssues(value) {
|
|
|
16858
16931
|
import { createHash as createHash6, randomUUID as randomUUID2 } from "node:crypto";
|
|
16859
16932
|
import { readdirSync, readFileSync as readFileSync2 } from "node:fs";
|
|
16860
16933
|
import { appendFile as appendFile2, mkdir as mkdir2, rename as rename2, rm as rm3, writeFile as writeFile2 } from "node:fs/promises";
|
|
16861
|
-
import { join as
|
|
16934
|
+
import { join as join7 } from "node:path";
|
|
16862
16935
|
var DEFAULT_EVIDENCE_SPOOL_LIMITS = {
|
|
16863
16936
|
maxEntries: 2048,
|
|
16864
16937
|
maxEntryBytes: 256 * 1024,
|
|
@@ -17121,7 +17194,7 @@ class ChangeEvidenceSpool {
|
|
|
17121
17194
|
const lines = this.pendingLines.splice(0).join("");
|
|
17122
17195
|
this.enqueueIo(async () => {
|
|
17123
17196
|
await mkdir2(directory, { recursive: true, mode: 448 });
|
|
17124
|
-
await appendFile2(
|
|
17197
|
+
await appendFile2(join7(directory, ENTRIES_FILE), lines, { mode: 384 });
|
|
17125
17198
|
});
|
|
17126
17199
|
}
|
|
17127
17200
|
persistBody(id, bytes) {
|
|
@@ -17129,9 +17202,9 @@ class ChangeEvidenceSpool {
|
|
|
17129
17202
|
if (!directory || this.restoring)
|
|
17130
17203
|
return;
|
|
17131
17204
|
this.enqueueIo(async () => {
|
|
17132
|
-
const bodies =
|
|
17205
|
+
const bodies = join7(directory, BODY_DIRECTORY);
|
|
17133
17206
|
await mkdir2(bodies, { recursive: true, mode: 448 });
|
|
17134
|
-
await writeFile2(
|
|
17207
|
+
await writeFile2(join7(bodies, bodyFileName(id)), bytes, { mode: 384, flag: "wx" }).catch((error) => {
|
|
17135
17208
|
if (error.code !== "EEXIST")
|
|
17136
17209
|
throw error;
|
|
17137
17210
|
});
|
|
@@ -17141,7 +17214,7 @@ class ChangeEvidenceSpool {
|
|
|
17141
17214
|
const directory = this.directory;
|
|
17142
17215
|
if (!directory)
|
|
17143
17216
|
return;
|
|
17144
|
-
this.enqueueIo(() => rm3(
|
|
17217
|
+
this.enqueueIo(() => rm3(join7(directory, BODY_DIRECTORY, bodyFileName(id)), { force: true }));
|
|
17145
17218
|
}
|
|
17146
17219
|
compactPersisted() {
|
|
17147
17220
|
const directory = this.directory;
|
|
@@ -17152,7 +17225,7 @@ class ChangeEvidenceSpool {
|
|
|
17152
17225
|
`);
|
|
17153
17226
|
this.enqueueIo(async () => {
|
|
17154
17227
|
await mkdir2(directory, { recursive: true, mode: 448 });
|
|
17155
|
-
const file =
|
|
17228
|
+
const file = join7(directory, ENTRIES_FILE);
|
|
17156
17229
|
const temp = `${file}.${process.pid}.tmp`;
|
|
17157
17230
|
await writeFile2(temp, body ? `${body}
|
|
17158
17231
|
` : "", { mode: 384 });
|
|
@@ -17164,10 +17237,10 @@ class ChangeEvidenceSpool {
|
|
|
17164
17237
|
await this.io;
|
|
17165
17238
|
}
|
|
17166
17239
|
restore(directory) {
|
|
17167
|
-
const bodyDirectory =
|
|
17240
|
+
const bodyDirectory = join7(directory, BODY_DIRECTORY);
|
|
17168
17241
|
try {
|
|
17169
17242
|
for (const name of readdirSync(bodyDirectory)) {
|
|
17170
|
-
const bytes = new Uint8Array(readFileSync2(
|
|
17243
|
+
const bytes = new Uint8Array(readFileSync2(join7(bodyDirectory, name)));
|
|
17171
17244
|
const id = evidenceBodyId(bytes);
|
|
17172
17245
|
if (bodyFileName(id) !== name)
|
|
17173
17246
|
continue;
|
|
@@ -17179,7 +17252,7 @@ class ChangeEvidenceSpool {
|
|
|
17179
17252
|
} catch {}
|
|
17180
17253
|
let text = "";
|
|
17181
17254
|
try {
|
|
17182
|
-
text = readFileSync2(
|
|
17255
|
+
text = readFileSync2(join7(directory, ENTRIES_FILE), "utf8");
|
|
17183
17256
|
} catch {
|
|
17184
17257
|
return;
|
|
17185
17258
|
}
|
|
@@ -18353,7 +18426,11 @@ async function createSessionReserved(clientSessionKey, signal, spawnOptions = {}
|
|
|
18353
18426
|
const created = await child.request("session/new", {
|
|
18354
18427
|
cwd: workingDirectory,
|
|
18355
18428
|
additionalDirectories: [],
|
|
18356
|
-
mcpServers: configuredAcpMcpServers(spawnOptions.agentMcp)
|
|
18429
|
+
mcpServers: configuredAcpMcpServers(spawnOptions.agentMcp),
|
|
18430
|
+
...sessionInstructionsMeta(providerConfig, await sessionInstructions(effectiveTurnExecutionPolicy({
|
|
18431
|
+
policy: spawnOptions.policy,
|
|
18432
|
+
readOnly: spawnOptions.readOnly
|
|
18433
|
+
}), workingDirectory))
|
|
18357
18434
|
}, RPC_TIMEOUT_MS, signal);
|
|
18358
18435
|
if (!isObject3(created) || typeof created.sessionId !== "string") {
|
|
18359
18436
|
throw new Error(`${provider} returned an invalid ACP session`);
|
|
@@ -18477,7 +18554,8 @@ async function startDeferredSession(state) {
|
|
|
18477
18554
|
const created = await child.request("session/new", {
|
|
18478
18555
|
cwd: workingDirectory,
|
|
18479
18556
|
additionalDirectories: [],
|
|
18480
|
-
mcpServers: configuredAcpMcpServers(state.agentMcp)
|
|
18557
|
+
mcpServers: configuredAcpMcpServers(state.agentMcp),
|
|
18558
|
+
...sessionInstructionsMeta(providerConfig, await sessionInstructions(effectiveTurnExecutionPolicy(state), workingDirectory))
|
|
18481
18559
|
}, RPC_TIMEOUT_MS);
|
|
18482
18560
|
if (!isObject3(created) || typeof created.sessionId !== "string") {
|
|
18483
18561
|
throw new Error(`${provider} returned an invalid ACP session`);
|
|
@@ -20327,8 +20405,8 @@ var STRUCTURED_OUTPUT_FAILURE_CODES = new Set([
|
|
|
20327
20405
|
|
|
20328
20406
|
// ../../bridges/acp-bridge/src/prompt-attachments.ts
|
|
20329
20407
|
import { constants as constants2 } from "node:fs";
|
|
20330
|
-
import { lstat as lstat3, open as
|
|
20331
|
-
import { isAbsolute as
|
|
20408
|
+
import { lstat as lstat3, open as open4, realpath as realpath3 } from "node:fs/promises";
|
|
20409
|
+
import { isAbsolute as isAbsolute4, join as join8, relative as relative3, resolve as resolve8, sep as sep2 } from "node:path";
|
|
20332
20410
|
|
|
20333
20411
|
class PromptAttachmentError extends Error {
|
|
20334
20412
|
code;
|
|
@@ -20427,10 +20505,10 @@ function attachmentErrorForFsFailure(error) {
|
|
|
20427
20505
|
var BRIDGE_ATTACHMENT_ROOT_ENV = "ORKESTRATOR_BRIDGE_ATTACHMENT_ROOT";
|
|
20428
20506
|
function configuredAttachmentRoot(env = process.env) {
|
|
20429
20507
|
const value = env[BRIDGE_ATTACHMENT_ROOT_ENV]?.trim();
|
|
20430
|
-
return value &&
|
|
20508
|
+
return value && isAbsolute4(value) ? resolve8(value) : undefined;
|
|
20431
20509
|
}
|
|
20432
20510
|
function attachmentContainmentRoot(filePath, workspaceRoot, extraRoot = configuredAttachmentRoot()) {
|
|
20433
|
-
if (extraRoot &&
|
|
20511
|
+
if (extraRoot && isAbsolute4(filePath) && isPathWithin(extraRoot, resolve8(filePath))) {
|
|
20434
20512
|
return extraRoot;
|
|
20435
20513
|
}
|
|
20436
20514
|
return resolve8(workspaceRoot);
|
|
@@ -20438,13 +20516,13 @@ function attachmentContainmentRoot(filePath, workspaceRoot, extraRoot = configur
|
|
|
20438
20516
|
function isPathWithin(root, candidate) {
|
|
20439
20517
|
if (candidate === root)
|
|
20440
20518
|
return true;
|
|
20441
|
-
const childPath =
|
|
20442
|
-
return Boolean(childPath) && childPath !== ".." && !childPath.startsWith(`..${sep2}`) && !
|
|
20519
|
+
const childPath = relative3(root, candidate);
|
|
20520
|
+
return Boolean(childPath) && childPath !== ".." && !childPath.startsWith(`..${sep2}`) && !isAbsolute4(childPath);
|
|
20443
20521
|
}
|
|
20444
20522
|
async function assertNoSymlinkComponents(root, targetPath) {
|
|
20445
20523
|
let currentPath = root;
|
|
20446
|
-
for (const segment of
|
|
20447
|
-
currentPath =
|
|
20524
|
+
for (const segment of relative3(root, targetPath).split(sep2).filter(Boolean)) {
|
|
20525
|
+
currentPath = join8(currentPath, segment);
|
|
20448
20526
|
const stats = await lstat3(currentPath).catch((error) => {
|
|
20449
20527
|
throw attachmentErrorForFsFailure(error);
|
|
20450
20528
|
});
|
|
@@ -20456,7 +20534,7 @@ async function assertNoSymlinkComponents(root, targetPath) {
|
|
|
20456
20534
|
async function assertOpenedWorkspaceFile(targetPath, canonicalRoot, openedStats) {
|
|
20457
20535
|
const [pathStats, canonicalTarget] = await Promise.all([
|
|
20458
20536
|
lstat3(targetPath),
|
|
20459
|
-
|
|
20537
|
+
realpath3(targetPath)
|
|
20460
20538
|
]).catch((error) => {
|
|
20461
20539
|
throw attachmentErrorForFsFailure(error);
|
|
20462
20540
|
});
|
|
@@ -20477,22 +20555,22 @@ function assertStableRead(initial, final, bytesRead) {
|
|
|
20477
20555
|
}
|
|
20478
20556
|
async function readWorkspaceImage(filePath, workspaceRoot) {
|
|
20479
20557
|
const lexicalRoot = attachmentContainmentRoot(filePath, workspaceRoot);
|
|
20480
|
-
const targetPath =
|
|
20558
|
+
const targetPath = isAbsolute4(filePath) ? resolve8(filePath) : resolve8(lexicalRoot, filePath);
|
|
20481
20559
|
if (!isPathWithin(lexicalRoot, targetPath)) {
|
|
20482
20560
|
throw new PromptAttachmentError("attachment_outside_workspace", "Image attachment must be contained in the current workspace");
|
|
20483
20561
|
}
|
|
20484
|
-
const canonicalRoot = await
|
|
20562
|
+
const canonicalRoot = await realpath3(lexicalRoot).catch((error) => {
|
|
20485
20563
|
throw attachmentErrorForFsFailure(error);
|
|
20486
20564
|
});
|
|
20487
20565
|
await assertNoSymlinkComponents(lexicalRoot, targetPath);
|
|
20488
|
-
const canonicalTarget = await
|
|
20566
|
+
const canonicalTarget = await realpath3(targetPath).catch((error) => {
|
|
20489
20567
|
throw attachmentErrorForFsFailure(error);
|
|
20490
20568
|
});
|
|
20491
20569
|
if (!isPathWithin(canonicalRoot, canonicalTarget)) {
|
|
20492
20570
|
throw new PromptAttachmentError("attachment_outside_workspace", "Image attachment must be contained in the current workspace");
|
|
20493
20571
|
}
|
|
20494
20572
|
const noFollow = constants2.O_NOFOLLOW ?? 0;
|
|
20495
|
-
const handle = await
|
|
20573
|
+
const handle = await open4(targetPath, constants2.O_RDONLY | noFollow).catch((error) => {
|
|
20496
20574
|
throw attachmentErrorForFsFailure(error);
|
|
20497
20575
|
});
|
|
20498
20576
|
try {
|