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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orkestrator",
3
- "version": "2.34.5-beta",
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.34.5-beta",
43
- "@orkestrator/toolchain": "2.34.5-beta"
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 isAbsolute2, join as join5, resolve as resolve4 } from "node:path";
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: isAbsolute2(index) ? index : resolve4(cwd, index),
16148
- objectsPath: isAbsolute2(objects) ? objects : resolve4(cwd, objects)
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 = join5(this.tempDir, `orkestrator-probe-${randomUUID()}.index`);
16192
- const objectDirectory = await mkdtemp(join5(this.tempDir, "orkestrator-probe-objects-"));
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(join5(root, path)).catch(() => {
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 join6 } from "node:path";
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(join6(directory, ENTRIES_FILE), lines, { mode: 384 });
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 = join6(directory, BODY_DIRECTORY);
17205
+ const bodies = join7(directory, BODY_DIRECTORY);
17133
17206
  await mkdir2(bodies, { recursive: true, mode: 448 });
17134
- await writeFile2(join6(bodies, bodyFileName(id)), bytes, { mode: 384, flag: "wx" }).catch((error) => {
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(join6(directory, BODY_DIRECTORY, bodyFileName(id)), { force: true }));
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 = join6(directory, ENTRIES_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 = join6(directory, BODY_DIRECTORY);
17240
+ const bodyDirectory = join7(directory, BODY_DIRECTORY);
17168
17241
  try {
17169
17242
  for (const name of readdirSync(bodyDirectory)) {
17170
- const bytes = new Uint8Array(readFileSync2(join6(bodyDirectory, name)));
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(join6(directory, ENTRIES_FILE), "utf8");
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 open3, realpath as realpath2 } from "node:fs/promises";
20331
- import { isAbsolute as isAbsolute3, join as join7, relative as relative2, resolve as resolve8, sep as sep2 } from "node:path";
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 && isAbsolute3(value) ? resolve8(value) : undefined;
20508
+ return value && isAbsolute4(value) ? resolve8(value) : undefined;
20431
20509
  }
20432
20510
  function attachmentContainmentRoot(filePath, workspaceRoot, extraRoot = configuredAttachmentRoot()) {
20433
- if (extraRoot && isAbsolute3(filePath) && isPathWithin(extraRoot, resolve8(filePath))) {
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 = relative2(root, candidate);
20442
- return Boolean(childPath) && childPath !== ".." && !childPath.startsWith(`..${sep2}`) && !isAbsolute3(childPath);
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 relative2(root, targetPath).split(sep2).filter(Boolean)) {
20447
- currentPath = join7(currentPath, segment);
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
- realpath2(targetPath)
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 = isAbsolute3(filePath) ? resolve8(filePath) : resolve8(lexicalRoot, filePath);
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 realpath2(lexicalRoot).catch((error) => {
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 realpath2(targetPath).catch((error) => {
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 open3(targetPath, constants2.O_RDONLY | noFollow).catch((error) => {
20573
+ const handle = await open4(targetPath, constants2.O_RDONLY | noFollow).catch((error) => {
20496
20574
  throw attachmentErrorForFsFailure(error);
20497
20575
  });
20498
20576
  try {