orkestrator 2.34.5-beta → 2.35.1-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 +62881 -59863
- package/package.json +3 -3
- package/resources/acp-bridge/dist/index.js +132 -36
- 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.1-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.1-beta",
|
|
43
|
+
"@orkestrator/toolchain": "2.35.1-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
|
};
|
|
@@ -10106,7 +10114,7 @@ var MAX_SESSIONS = parseBoundedInteger(process.env.ACP_MAX_SESSIONS, 256, 1, 256
|
|
|
10106
10114
|
var MAX_APPROVALS_PER_SESSION = 64;
|
|
10107
10115
|
var MAX_STRUCTURED_RESULTS = 4;
|
|
10108
10116
|
var MAX_STRUCTURED_RESULT_BYTES = 1024 * 1024;
|
|
10109
|
-
var TRANSCRIPT_CHECK_INTERVAL_BYTES =
|
|
10117
|
+
var TRANSCRIPT_CHECK_INTERVAL_BYTES = 1024 * 1024;
|
|
10110
10118
|
var MAX_PROMPT_JOURNAL = 512;
|
|
10111
10119
|
var MAX_PERSISTED_GROK_INTERJECTION_BYTES = 512 * 1024;
|
|
10112
10120
|
var MAX_STATE_FILE_BYTES = parseBoundedInteger(process.env.ACP_MAX_STATE_FILE_BYTES, 16 * 1024 * 1024, 512 * 1024, 16 * 1024 * 1024);
|
|
@@ -11271,6 +11279,24 @@ function persistedSnapshot() {
|
|
|
11271
11279
|
};
|
|
11272
11280
|
return boundPersistedSnapshot(snapshot);
|
|
11273
11281
|
}
|
|
11282
|
+
var STREAMING_PERSIST_INTERVAL_MS = 1000;
|
|
11283
|
+
var streamingPersistTimer = null;
|
|
11284
|
+
function scheduleStreamingPersist() {
|
|
11285
|
+
if (!stateFile || streamingPersistTimer)
|
|
11286
|
+
return;
|
|
11287
|
+
streamingPersistTimer = setTimeout(() => {
|
|
11288
|
+
streamingPersistTimer = null;
|
|
11289
|
+
schedulePersist();
|
|
11290
|
+
}, STREAMING_PERSIST_INTERVAL_MS);
|
|
11291
|
+
streamingPersistTimer.unref();
|
|
11292
|
+
}
|
|
11293
|
+
function flushStreamingPersist() {
|
|
11294
|
+
if (streamingPersistTimer) {
|
|
11295
|
+
clearTimeout(streamingPersistTimer);
|
|
11296
|
+
streamingPersistTimer = null;
|
|
11297
|
+
}
|
|
11298
|
+
return persistState();
|
|
11299
|
+
}
|
|
11274
11300
|
function schedulePersist() {
|
|
11275
11301
|
if (!stateFile || persistenceScheduled)
|
|
11276
11302
|
return;
|
|
@@ -12076,7 +12102,7 @@ function commitToolPartMutation(state, part, source) {
|
|
|
12076
12102
|
failTranscriptLimit(state);
|
|
12077
12103
|
return false;
|
|
12078
12104
|
}
|
|
12079
|
-
|
|
12105
|
+
scheduleStreamingPersist();
|
|
12080
12106
|
return true;
|
|
12081
12107
|
}
|
|
12082
12108
|
function activeSubagentLaunch(state, toolUseId) {
|
|
@@ -15666,6 +15692,71 @@ function isStringTuple(value) {
|
|
|
15666
15692
|
return Array.isArray(value) && value.length === 2 && typeof value[0] === "string";
|
|
15667
15693
|
}
|
|
15668
15694
|
|
|
15695
|
+
// ../protocol/src/agent-system-instructions.ts
|
|
15696
|
+
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.";
|
|
15697
|
+
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.";
|
|
15698
|
+
var GENERAL_AGENT_INSTRUCTIONS = [
|
|
15699
|
+
AGENT_IMAGE_PREVIEW_INSTRUCTION,
|
|
15700
|
+
AGENT_DOCUMENT_INSTRUCTION
|
|
15701
|
+
];
|
|
15702
|
+
function agentSystemInstructions(providerSpecific = []) {
|
|
15703
|
+
return [...GENERAL_AGENT_INSTRUCTIONS, ...providerSpecific].filter((line) => line.trim().length > 0).join(`
|
|
15704
|
+
|
|
15705
|
+
`);
|
|
15706
|
+
}
|
|
15707
|
+
var REPOSITORY_INSTRUCTIONS_FILE = "AGENTS.md";
|
|
15708
|
+
function repositoryInstructionsBlock(path, content, truncated) {
|
|
15709
|
+
return [
|
|
15710
|
+
`# Repository instructions (${REPOSITORY_INSTRUCTIONS_FILE})`,
|
|
15711
|
+
`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}:`,
|
|
15712
|
+
content.trimEnd(),
|
|
15713
|
+
...truncated ? [
|
|
15714
|
+
`[${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.]`
|
|
15715
|
+
] : []
|
|
15716
|
+
].join(`
|
|
15717
|
+
|
|
15718
|
+
`);
|
|
15719
|
+
}
|
|
15720
|
+
|
|
15721
|
+
// ../protocol/src/node/repository-instructions.ts
|
|
15722
|
+
import { open as open3, realpath as realpath2 } from "node:fs/promises";
|
|
15723
|
+
import { join as join5, relative as relative2, isAbsolute as isAbsolute2 } from "node:path";
|
|
15724
|
+
var MAX_REPOSITORY_INSTRUCTIONS_BYTES = 256 * 1024;
|
|
15725
|
+
async function readRepositoryInstructions(cwd, maxBytes = MAX_REPOSITORY_INSTRUCTIONS_BYTES) {
|
|
15726
|
+
const path = join5(cwd, REPOSITORY_INSTRUCTIONS_FILE);
|
|
15727
|
+
try {
|
|
15728
|
+
const [root, target] = await Promise.all([realpath2(cwd), realpath2(path)]);
|
|
15729
|
+
const inside = relative2(root, target);
|
|
15730
|
+
if (!inside || inside.startsWith("..") || isAbsolute2(inside))
|
|
15731
|
+
return;
|
|
15732
|
+
const handle = await open3(target, "r");
|
|
15733
|
+
try {
|
|
15734
|
+
const buffer = Buffer.alloc(maxBytes + 1);
|
|
15735
|
+
const { bytesRead } = await handle.read(buffer, 0, maxBytes + 1, 0);
|
|
15736
|
+
const truncated = bytesRead > maxBytes;
|
|
15737
|
+
const text = new TextDecoder().decode(buffer.subarray(0, Math.min(bytesRead, maxBytes))).replace(/�$/, "");
|
|
15738
|
+
return text.trim() ? repositoryInstructionsBlock(path, text, truncated) : undefined;
|
|
15739
|
+
} finally {
|
|
15740
|
+
await handle.close();
|
|
15741
|
+
}
|
|
15742
|
+
} catch {
|
|
15743
|
+
return;
|
|
15744
|
+
}
|
|
15745
|
+
}
|
|
15746
|
+
|
|
15747
|
+
// ../../bridges/acp-bridge/src/acp-session-instructions.ts
|
|
15748
|
+
async function sessionInstructions(policy, cwd) {
|
|
15749
|
+
if (policy?.id === "coordinator-read-only")
|
|
15750
|
+
return;
|
|
15751
|
+
const parts = [
|
|
15752
|
+
agentSystemInstructions(),
|
|
15753
|
+
policy?.projectResources === true ? undefined : await readRepositoryInstructions(cwd)
|
|
15754
|
+
].filter((part) => Boolean(part));
|
|
15755
|
+
return parts.length > 0 ? parts.join(`
|
|
15756
|
+
|
|
15757
|
+
`) : undefined;
|
|
15758
|
+
}
|
|
15759
|
+
|
|
15669
15760
|
// ../protocol/src/mcp-elicitation-form.ts
|
|
15670
15761
|
function record2(value) {
|
|
15671
15762
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -15862,7 +15953,7 @@ import { randomUUID } from "node:crypto";
|
|
|
15862
15953
|
import { rmSync as rmSync2 } from "node:fs";
|
|
15863
15954
|
import { copyFile, lstat as lstat2, mkdtemp, rm as rm2 } from "node:fs/promises";
|
|
15864
15955
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
15865
|
-
import { delimiter, isAbsolute as
|
|
15956
|
+
import { delimiter, isAbsolute as isAbsolute3, join as join6, resolve as resolve4 } from "node:path";
|
|
15866
15957
|
var DEFAULT_MAX_UNTRACKED_FILE_BYTES = 2 * 1024 * 1024;
|
|
15867
15958
|
var DEFAULT_MAX_UNTRACKED_FILES = 5000;
|
|
15868
15959
|
var DEFAULT_SLOW_SNAPSHOT_MS = 500;
|
|
@@ -16144,8 +16235,8 @@ class WorkspaceChangeProbe {
|
|
|
16144
16235
|
return;
|
|
16145
16236
|
return {
|
|
16146
16237
|
root,
|
|
16147
|
-
indexPath:
|
|
16148
|
-
objectsPath:
|
|
16238
|
+
indexPath: isAbsolute3(index) ? index : resolve4(cwd, index),
|
|
16239
|
+
objectsPath: isAbsolute3(objects) ? objects : resolve4(cwd, objects)
|
|
16149
16240
|
};
|
|
16150
16241
|
}).catch(() => {
|
|
16151
16242
|
return;
|
|
@@ -16188,8 +16279,8 @@ class WorkspaceChangeProbe {
|
|
|
16188
16279
|
return;
|
|
16189
16280
|
const { root, indexPath } = repo.location;
|
|
16190
16281
|
const started = this.now();
|
|
16191
|
-
const tempIndex =
|
|
16192
|
-
const objectDirectory = await mkdtemp(
|
|
16282
|
+
const tempIndex = join6(this.tempDir, `orkestrator-probe-${randomUUID()}.index`);
|
|
16283
|
+
const objectDirectory = await mkdtemp(join6(this.tempDir, "orkestrator-probe-objects-"));
|
|
16193
16284
|
temporaryObjectDirectories.add(objectDirectory);
|
|
16194
16285
|
let retained = false;
|
|
16195
16286
|
try {
|
|
@@ -16206,7 +16297,7 @@ class WorkspaceChangeProbe {
|
|
|
16206
16297
|
const included = [];
|
|
16207
16298
|
const skipped = new Map;
|
|
16208
16299
|
for (const path of untracked) {
|
|
16209
|
-
const stats = await lstat2(
|
|
16300
|
+
const stats = await lstat2(join6(root, path)).catch(() => {
|
|
16210
16301
|
return;
|
|
16211
16302
|
});
|
|
16212
16303
|
if (!stats)
|
|
@@ -16858,7 +16949,7 @@ function workspaceObservationReportIssues(value) {
|
|
|
16858
16949
|
import { createHash as createHash6, randomUUID as randomUUID2 } from "node:crypto";
|
|
16859
16950
|
import { readdirSync, readFileSync as readFileSync2 } from "node:fs";
|
|
16860
16951
|
import { appendFile as appendFile2, mkdir as mkdir2, rename as rename2, rm as rm3, writeFile as writeFile2 } from "node:fs/promises";
|
|
16861
|
-
import { join as
|
|
16952
|
+
import { join as join7 } from "node:path";
|
|
16862
16953
|
var DEFAULT_EVIDENCE_SPOOL_LIMITS = {
|
|
16863
16954
|
maxEntries: 2048,
|
|
16864
16955
|
maxEntryBytes: 256 * 1024,
|
|
@@ -17121,7 +17212,7 @@ class ChangeEvidenceSpool {
|
|
|
17121
17212
|
const lines = this.pendingLines.splice(0).join("");
|
|
17122
17213
|
this.enqueueIo(async () => {
|
|
17123
17214
|
await mkdir2(directory, { recursive: true, mode: 448 });
|
|
17124
|
-
await appendFile2(
|
|
17215
|
+
await appendFile2(join7(directory, ENTRIES_FILE), lines, { mode: 384 });
|
|
17125
17216
|
});
|
|
17126
17217
|
}
|
|
17127
17218
|
persistBody(id, bytes) {
|
|
@@ -17129,9 +17220,9 @@ class ChangeEvidenceSpool {
|
|
|
17129
17220
|
if (!directory || this.restoring)
|
|
17130
17221
|
return;
|
|
17131
17222
|
this.enqueueIo(async () => {
|
|
17132
|
-
const bodies =
|
|
17223
|
+
const bodies = join7(directory, BODY_DIRECTORY);
|
|
17133
17224
|
await mkdir2(bodies, { recursive: true, mode: 448 });
|
|
17134
|
-
await writeFile2(
|
|
17225
|
+
await writeFile2(join7(bodies, bodyFileName(id)), bytes, { mode: 384, flag: "wx" }).catch((error) => {
|
|
17135
17226
|
if (error.code !== "EEXIST")
|
|
17136
17227
|
throw error;
|
|
17137
17228
|
});
|
|
@@ -17141,7 +17232,7 @@ class ChangeEvidenceSpool {
|
|
|
17141
17232
|
const directory = this.directory;
|
|
17142
17233
|
if (!directory)
|
|
17143
17234
|
return;
|
|
17144
|
-
this.enqueueIo(() => rm3(
|
|
17235
|
+
this.enqueueIo(() => rm3(join7(directory, BODY_DIRECTORY, bodyFileName(id)), { force: true }));
|
|
17145
17236
|
}
|
|
17146
17237
|
compactPersisted() {
|
|
17147
17238
|
const directory = this.directory;
|
|
@@ -17152,7 +17243,7 @@ class ChangeEvidenceSpool {
|
|
|
17152
17243
|
`);
|
|
17153
17244
|
this.enqueueIo(async () => {
|
|
17154
17245
|
await mkdir2(directory, { recursive: true, mode: 448 });
|
|
17155
|
-
const file =
|
|
17246
|
+
const file = join7(directory, ENTRIES_FILE);
|
|
17156
17247
|
const temp = `${file}.${process.pid}.tmp`;
|
|
17157
17248
|
await writeFile2(temp, body ? `${body}
|
|
17158
17249
|
` : "", { mode: 384 });
|
|
@@ -17164,10 +17255,10 @@ class ChangeEvidenceSpool {
|
|
|
17164
17255
|
await this.io;
|
|
17165
17256
|
}
|
|
17166
17257
|
restore(directory) {
|
|
17167
|
-
const bodyDirectory =
|
|
17258
|
+
const bodyDirectory = join7(directory, BODY_DIRECTORY);
|
|
17168
17259
|
try {
|
|
17169
17260
|
for (const name of readdirSync(bodyDirectory)) {
|
|
17170
|
-
const bytes = new Uint8Array(readFileSync2(
|
|
17261
|
+
const bytes = new Uint8Array(readFileSync2(join7(bodyDirectory, name)));
|
|
17171
17262
|
const id = evidenceBodyId(bytes);
|
|
17172
17263
|
if (bodyFileName(id) !== name)
|
|
17173
17264
|
continue;
|
|
@@ -17179,7 +17270,7 @@ class ChangeEvidenceSpool {
|
|
|
17179
17270
|
} catch {}
|
|
17180
17271
|
let text = "";
|
|
17181
17272
|
try {
|
|
17182
|
-
text = readFileSync2(
|
|
17273
|
+
text = readFileSync2(join7(directory, ENTRIES_FILE), "utf8");
|
|
17183
17274
|
} catch {
|
|
17184
17275
|
return;
|
|
17185
17276
|
}
|
|
@@ -18353,7 +18444,11 @@ async function createSessionReserved(clientSessionKey, signal, spawnOptions = {}
|
|
|
18353
18444
|
const created = await child.request("session/new", {
|
|
18354
18445
|
cwd: workingDirectory,
|
|
18355
18446
|
additionalDirectories: [],
|
|
18356
|
-
mcpServers: configuredAcpMcpServers(spawnOptions.agentMcp)
|
|
18447
|
+
mcpServers: configuredAcpMcpServers(spawnOptions.agentMcp),
|
|
18448
|
+
...sessionInstructionsMeta(providerConfig, await sessionInstructions(effectiveTurnExecutionPolicy({
|
|
18449
|
+
policy: spawnOptions.policy,
|
|
18450
|
+
readOnly: spawnOptions.readOnly
|
|
18451
|
+
}), workingDirectory))
|
|
18357
18452
|
}, RPC_TIMEOUT_MS, signal);
|
|
18358
18453
|
if (!isObject3(created) || typeof created.sessionId !== "string") {
|
|
18359
18454
|
throw new Error(`${provider} returned an invalid ACP session`);
|
|
@@ -18477,7 +18572,8 @@ async function startDeferredSession(state) {
|
|
|
18477
18572
|
const created = await child.request("session/new", {
|
|
18478
18573
|
cwd: workingDirectory,
|
|
18479
18574
|
additionalDirectories: [],
|
|
18480
|
-
mcpServers: configuredAcpMcpServers(state.agentMcp)
|
|
18575
|
+
mcpServers: configuredAcpMcpServers(state.agentMcp),
|
|
18576
|
+
...sessionInstructionsMeta(providerConfig, await sessionInstructions(effectiveTurnExecutionPolicy(state), workingDirectory))
|
|
18481
18577
|
}, RPC_TIMEOUT_MS);
|
|
18482
18578
|
if (!isObject3(created) || typeof created.sessionId !== "string") {
|
|
18483
18579
|
throw new Error(`${provider} returned an invalid ACP session`);
|
|
@@ -19403,7 +19499,7 @@ function applySessionUpdate(state, params) {
|
|
|
19403
19499
|
failTranscriptLimit(state);
|
|
19404
19500
|
return;
|
|
19405
19501
|
}
|
|
19406
|
-
|
|
19502
|
+
scheduleStreamingPersist();
|
|
19407
19503
|
}
|
|
19408
19504
|
function composerPatchFromSpawn(options) {
|
|
19409
19505
|
const patch = {};
|
|
@@ -20327,8 +20423,8 @@ var STRUCTURED_OUTPUT_FAILURE_CODES = new Set([
|
|
|
20327
20423
|
|
|
20328
20424
|
// ../../bridges/acp-bridge/src/prompt-attachments.ts
|
|
20329
20425
|
import { constants as constants2 } from "node:fs";
|
|
20330
|
-
import { lstat as lstat3, open as
|
|
20331
|
-
import { isAbsolute as
|
|
20426
|
+
import { lstat as lstat3, open as open4, realpath as realpath3 } from "node:fs/promises";
|
|
20427
|
+
import { isAbsolute as isAbsolute4, join as join8, relative as relative3, resolve as resolve8, sep as sep2 } from "node:path";
|
|
20332
20428
|
|
|
20333
20429
|
class PromptAttachmentError extends Error {
|
|
20334
20430
|
code;
|
|
@@ -20427,10 +20523,10 @@ function attachmentErrorForFsFailure(error) {
|
|
|
20427
20523
|
var BRIDGE_ATTACHMENT_ROOT_ENV = "ORKESTRATOR_BRIDGE_ATTACHMENT_ROOT";
|
|
20428
20524
|
function configuredAttachmentRoot(env = process.env) {
|
|
20429
20525
|
const value = env[BRIDGE_ATTACHMENT_ROOT_ENV]?.trim();
|
|
20430
|
-
return value &&
|
|
20526
|
+
return value && isAbsolute4(value) ? resolve8(value) : undefined;
|
|
20431
20527
|
}
|
|
20432
20528
|
function attachmentContainmentRoot(filePath, workspaceRoot, extraRoot = configuredAttachmentRoot()) {
|
|
20433
|
-
if (extraRoot &&
|
|
20529
|
+
if (extraRoot && isAbsolute4(filePath) && isPathWithin(extraRoot, resolve8(filePath))) {
|
|
20434
20530
|
return extraRoot;
|
|
20435
20531
|
}
|
|
20436
20532
|
return resolve8(workspaceRoot);
|
|
@@ -20438,13 +20534,13 @@ function attachmentContainmentRoot(filePath, workspaceRoot, extraRoot = configur
|
|
|
20438
20534
|
function isPathWithin(root, candidate) {
|
|
20439
20535
|
if (candidate === root)
|
|
20440
20536
|
return true;
|
|
20441
|
-
const childPath =
|
|
20442
|
-
return Boolean(childPath) && childPath !== ".." && !childPath.startsWith(`..${sep2}`) && !
|
|
20537
|
+
const childPath = relative3(root, candidate);
|
|
20538
|
+
return Boolean(childPath) && childPath !== ".." && !childPath.startsWith(`..${sep2}`) && !isAbsolute4(childPath);
|
|
20443
20539
|
}
|
|
20444
20540
|
async function assertNoSymlinkComponents(root, targetPath) {
|
|
20445
20541
|
let currentPath = root;
|
|
20446
|
-
for (const segment of
|
|
20447
|
-
currentPath =
|
|
20542
|
+
for (const segment of relative3(root, targetPath).split(sep2).filter(Boolean)) {
|
|
20543
|
+
currentPath = join8(currentPath, segment);
|
|
20448
20544
|
const stats = await lstat3(currentPath).catch((error) => {
|
|
20449
20545
|
throw attachmentErrorForFsFailure(error);
|
|
20450
20546
|
});
|
|
@@ -20456,7 +20552,7 @@ async function assertNoSymlinkComponents(root, targetPath) {
|
|
|
20456
20552
|
async function assertOpenedWorkspaceFile(targetPath, canonicalRoot, openedStats) {
|
|
20457
20553
|
const [pathStats, canonicalTarget] = await Promise.all([
|
|
20458
20554
|
lstat3(targetPath),
|
|
20459
|
-
|
|
20555
|
+
realpath3(targetPath)
|
|
20460
20556
|
]).catch((error) => {
|
|
20461
20557
|
throw attachmentErrorForFsFailure(error);
|
|
20462
20558
|
});
|
|
@@ -20477,22 +20573,22 @@ function assertStableRead(initial, final, bytesRead) {
|
|
|
20477
20573
|
}
|
|
20478
20574
|
async function readWorkspaceImage(filePath, workspaceRoot) {
|
|
20479
20575
|
const lexicalRoot = attachmentContainmentRoot(filePath, workspaceRoot);
|
|
20480
|
-
const targetPath =
|
|
20576
|
+
const targetPath = isAbsolute4(filePath) ? resolve8(filePath) : resolve8(lexicalRoot, filePath);
|
|
20481
20577
|
if (!isPathWithin(lexicalRoot, targetPath)) {
|
|
20482
20578
|
throw new PromptAttachmentError("attachment_outside_workspace", "Image attachment must be contained in the current workspace");
|
|
20483
20579
|
}
|
|
20484
|
-
const canonicalRoot = await
|
|
20580
|
+
const canonicalRoot = await realpath3(lexicalRoot).catch((error) => {
|
|
20485
20581
|
throw attachmentErrorForFsFailure(error);
|
|
20486
20582
|
});
|
|
20487
20583
|
await assertNoSymlinkComponents(lexicalRoot, targetPath);
|
|
20488
|
-
const canonicalTarget = await
|
|
20584
|
+
const canonicalTarget = await realpath3(targetPath).catch((error) => {
|
|
20489
20585
|
throw attachmentErrorForFsFailure(error);
|
|
20490
20586
|
});
|
|
20491
20587
|
if (!isPathWithin(canonicalRoot, canonicalTarget)) {
|
|
20492
20588
|
throw new PromptAttachmentError("attachment_outside_workspace", "Image attachment must be contained in the current workspace");
|
|
20493
20589
|
}
|
|
20494
20590
|
const noFollow = constants2.O_NOFOLLOW ?? 0;
|
|
20495
|
-
const handle = await
|
|
20591
|
+
const handle = await open4(targetPath, constants2.O_RDONLY | noFollow).catch((error) => {
|
|
20496
20592
|
throw attachmentErrorForFsFailure(error);
|
|
20497
20593
|
});
|
|
20498
20594
|
try {
|
|
@@ -22349,9 +22445,7 @@ function shutdown() {
|
|
|
22349
22445
|
...[...sessions.values()].map((state) => state.child?.close()),
|
|
22350
22446
|
...[...cursorToolReplayProcesses].map((child) => child.close())
|
|
22351
22447
|
]);
|
|
22352
|
-
await
|
|
22353
|
-
return;
|
|
22354
|
-
});
|
|
22448
|
+
await flushStreamingPersist();
|
|
22355
22449
|
await new Promise((resolvePromise) => server.close(() => resolvePromise()));
|
|
22356
22450
|
})();
|
|
22357
22451
|
return shutdownPromise;
|
|
@@ -22546,6 +22640,7 @@ export {
|
|
|
22546
22640
|
findHistoryMessage,
|
|
22547
22641
|
finishSubagentTool,
|
|
22548
22642
|
flattenedRetriableProviderTail,
|
|
22643
|
+
flushStreamingPersist,
|
|
22549
22644
|
grokBridgeGeneration,
|
|
22550
22645
|
grokInterjectionDigest,
|
|
22551
22646
|
grokQuestionTimeoutMs,
|
|
@@ -22667,6 +22762,7 @@ export {
|
|
|
22667
22762
|
saturatedText,
|
|
22668
22763
|
scheduleCursorToolMetadataReconcile,
|
|
22669
22764
|
schedulePersist,
|
|
22765
|
+
scheduleStreamingPersist,
|
|
22670
22766
|
sendJson,
|
|
22671
22767
|
server,
|
|
22672
22768
|
sessionCreations,
|