@moxt-ai/mobius 0.0.307 → 0.0.308
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/acp/adapter/codex/adapter.d.ts.map +1 -1
- package/dist/acp/adapter/codex/adapter.js +66 -9
- package/dist/acp/adapter/codex/adapter.js.map +1 -1
- package/dist/acp/adapter/codex/tool-event.d.ts +6 -0
- package/dist/acp/adapter/codex/tool-event.d.ts.map +1 -0
- package/dist/acp/adapter/codex/tool-event.js +66 -0
- package/dist/acp/adapter/codex/tool-event.js.map +1 -0
- package/dist/acp/adapter/session-events.d.ts +2 -2
- package/dist/acp/adapter/session-events.d.ts.map +1 -1
- package/dist/acp/adapter/session-events.js +81 -56
- package/dist/acp/adapter/session-events.js.map +1 -1
- package/dist/acp/content/content-externalizer.d.ts.map +1 -1
- package/dist/acp/content/content-externalizer.js +1 -31
- package/dist/acp/content/content-externalizer.js.map +1 -1
- package/dist/acp/harness/codex/agent.d.ts.map +1 -1
- package/dist/acp/harness/codex/agent.js +4 -75
- package/dist/acp/harness/codex/agent.js.map +1 -1
- package/dist/acp/harness/codex/app-server-protocol.d.ts +9 -0
- package/dist/acp/harness/codex/app-server-protocol.d.ts.map +1 -1
- package/dist/acp/harness/codex/app-server-protocol.js +1 -0
- package/dist/acp/harness/codex/app-server-protocol.js.map +1 -1
- package/dist/acp/harness/codex/history.d.ts +5 -0
- package/dist/acp/harness/codex/history.d.ts.map +1 -0
- package/dist/acp/harness/codex/history.js +116 -0
- package/dist/acp/harness/codex/history.js.map +1 -0
- package/dist/cli.js +723 -1346
- package/dist/cli.js.map +4 -4
- package/dist/runtime/command/registry/history.d.ts.map +1 -1
- package/dist/runtime/command/registry/history.js +5 -36
- package/dist/runtime/command/registry/history.js.map +1 -1
- package/dist/runtime.js +662 -1287
- package/dist/runtime.js.map +4 -4
- package/dist/session/history/session-event-history-projection.d.ts.map +1 -1
- package/dist/session/history/session-event-history-projection.js +23 -2
- package/dist/session/history/session-event-history-projection.js.map +1 -1
- package/package.json +2 -2
- package/dist/acp/native-history/codex/codex-history.d.ts +0 -17
- package/dist/acp/native-history/codex/codex-history.d.ts.map +0 -1
- package/dist/acp/native-history/codex/codex-history.js +0 -661
- package/dist/acp/native-history/codex/codex-history.js.map +0 -1
- package/dist/acp/native-history/codex/native-history-events.d.ts +0 -8
- package/dist/acp/native-history/codex/native-history-events.d.ts.map +0 -1
- package/dist/acp/native-history/codex/native-history-events.js +0 -92
- package/dist/acp/native-history/codex/native-history-events.js.map +0 -1
package/dist/runtime.js
CHANGED
|
@@ -21783,8 +21783,6 @@ function encodeSessionPromptDispositionCommand(message) {
|
|
|
21783
21783
|
var NATIVE_SESSION_REQUEST_KIND = "native.session.request";
|
|
21784
21784
|
var NATIVE_SESSION_RESULT_KIND = "native.session.result";
|
|
21785
21785
|
var NATIVE_SESSION_CANCEL_KIND = "native.session.cancel";
|
|
21786
|
-
var SESSION_HISTORY_CHARACTER_LIMIT = 256e3;
|
|
21787
|
-
var SESSION_HISTORY_MESSAGE_LIMIT = 1e3;
|
|
21788
21786
|
var envelope = {
|
|
21789
21787
|
requestId: identifierStringSchema,
|
|
21790
21788
|
sessionId: identifierStringSchema
|
|
@@ -22247,6 +22245,7 @@ var sessionEventOmissionSchema = external_exports.literal("agent-reasoning");
|
|
|
22247
22245
|
var nativeEventPageRequestSchema = external_exports.object({
|
|
22248
22246
|
cursor: external_exports.string().min(1).max(512).nullable(),
|
|
22249
22247
|
eventLimit: external_exports.number().int().min(1).max(1e4),
|
|
22248
|
+
// Legacy callers may still send this option; readers must ignore it.
|
|
22250
22249
|
omit: external_exports.array(sessionEventOmissionSchema).max(1).readonly().optional()
|
|
22251
22250
|
}).readonly();
|
|
22252
22251
|
var queuedPromptRequestEventLogSchema = external_exports.object({
|
|
@@ -22294,6 +22293,7 @@ var SESSION_PREVIEW_HISTORY_PAGE_LOADED_KIND = "session.preview-history.page.loa
|
|
|
22294
22293
|
var pageRequestFields = {
|
|
22295
22294
|
cursor: external_exports.string().min(1).max(512).nullable(),
|
|
22296
22295
|
eventLimit: external_exports.number().int().min(1).max(1e4),
|
|
22296
|
+
// Decode old clients without rejecting their request; omission has no effect.
|
|
22297
22297
|
omit: external_exports.array(sessionEventOmissionSchema).max(1).readonly().optional(),
|
|
22298
22298
|
requestId: identifierStringSchema,
|
|
22299
22299
|
sessionId: identifierStringSchema
|
|
@@ -22691,7 +22691,7 @@ import { fetch as fetch3 } from "undici";
|
|
|
22691
22691
|
// package.json
|
|
22692
22692
|
var package_default = {
|
|
22693
22693
|
name: "@moxt-ai/mobius",
|
|
22694
|
-
version: "0.0.
|
|
22694
|
+
version: "0.0.308",
|
|
22695
22695
|
description: "Mobius CLI for pairing and running local AI agent services.",
|
|
22696
22696
|
type: "module",
|
|
22697
22697
|
bin: {
|
|
@@ -62173,11 +62173,11 @@ var SessionModeManager = class {
|
|
|
62173
62173
|
}
|
|
62174
62174
|
return modes;
|
|
62175
62175
|
}
|
|
62176
|
-
async trySyncMode(query, mode,
|
|
62176
|
+
async trySyncMode(query, mode, errorMessage) {
|
|
62177
62177
|
try {
|
|
62178
62178
|
await query.setPermissionMode(mode);
|
|
62179
62179
|
} catch (error62) {
|
|
62180
|
-
this.options.logError(
|
|
62180
|
+
this.options.logError(errorMessage, error62);
|
|
62181
62181
|
}
|
|
62182
62182
|
}
|
|
62183
62183
|
};
|
|
@@ -66838,6 +66838,9 @@ import {
|
|
|
66838
66838
|
PROTOCOL_VERSION
|
|
66839
66839
|
} from "@agentclientprotocol/sdk";
|
|
66840
66840
|
|
|
66841
|
+
// src/acp/harness/codex/app-server-client.ts
|
|
66842
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
66843
|
+
|
|
66841
66844
|
// src/infra/operation-error.ts
|
|
66842
66845
|
var OperationError = class extends Error {
|
|
66843
66846
|
code;
|
|
@@ -66875,9 +66878,6 @@ var AcpConfigurationValueUnavailableError = class extends AcpExecutionError {
|
|
|
66875
66878
|
}
|
|
66876
66879
|
};
|
|
66877
66880
|
|
|
66878
|
-
// src/acp/harness/codex/app-server-client.ts
|
|
66879
|
-
import { spawn as spawn4 } from "node:child_process";
|
|
66880
|
-
|
|
66881
66881
|
// src/acp/agent/in-process-endpoint.ts
|
|
66882
66882
|
function acpEndpointTerminationError(termination) {
|
|
66883
66883
|
switch (termination.kind) {
|
|
@@ -67129,6 +67129,7 @@ var threadStartResponseSchema = external_exports.object({
|
|
|
67129
67129
|
var threadTurnSchema = external_exports.object({
|
|
67130
67130
|
id: boundedText(256).optional(),
|
|
67131
67131
|
status: turnStatusSchema.optional(),
|
|
67132
|
+
error: external_exports.object({ message: external_exports.string().transform((message) => message.slice(0, 4096)) }).nullish(),
|
|
67132
67133
|
items: external_exports.array(external_exports.unknown()).max(1e5)
|
|
67133
67134
|
});
|
|
67134
67135
|
var threadTurnsSchema = external_exports.array(threadTurnSchema).max(1e5);
|
|
@@ -67596,12 +67597,12 @@ function presentToolItem(item) {
|
|
|
67596
67597
|
};
|
|
67597
67598
|
}
|
|
67598
67599
|
if (item.type === "collabAgentToolCall") {
|
|
67599
|
-
const
|
|
67600
|
+
const spawn8 = item.tool === "spawnAgent";
|
|
67600
67601
|
return {
|
|
67601
67602
|
content: [],
|
|
67602
67603
|
kind: "other",
|
|
67603
67604
|
locations: [],
|
|
67604
|
-
rawInput:
|
|
67605
|
+
rawInput: spawn8 ? {
|
|
67605
67606
|
model: item.model,
|
|
67606
67607
|
prompt: item.prompt,
|
|
67607
67608
|
reasoningEffort: item.reasoningEffort,
|
|
@@ -67609,10 +67610,10 @@ function presentToolItem(item) {
|
|
|
67609
67610
|
} : { receiverThreadIds: item.receiverThreadIds, senderThreadId: item.senderThreadId },
|
|
67610
67611
|
rawOutput: {
|
|
67611
67612
|
agentsStates: item.agentsStates,
|
|
67612
|
-
...
|
|
67613
|
+
...spawn8 ? { receiverThreadIds: item.receiverThreadIds } : {}
|
|
67613
67614
|
},
|
|
67614
67615
|
status: collaborationStatus(item.status),
|
|
67615
|
-
title:
|
|
67616
|
+
title: spawn8 ? "Dispatch subagent" : "Wait for subagent"
|
|
67616
67617
|
};
|
|
67617
67618
|
}
|
|
67618
67619
|
if (item.type === "subAgentActivity" && item.kind === "started") {
|
|
@@ -67922,6 +67923,277 @@ var CodexBorrowedAcpAgent = class {
|
|
|
67922
67923
|
};
|
|
67923
67924
|
};
|
|
67924
67925
|
|
|
67926
|
+
// src/acp/harness/codex/history.ts
|
|
67927
|
+
import { createHash } from "node:crypto";
|
|
67928
|
+
|
|
67929
|
+
// src/acp/content/raster.ts
|
|
67930
|
+
import { basename as basename4, isAbsolute as isAbsolute9, normalize } from "node:path";
|
|
67931
|
+
import { fileURLToPath } from "node:url";
|
|
67932
|
+
|
|
67933
|
+
// src/storage/files/local-files.ts
|
|
67934
|
+
import { createReadStream as createReadStream2 } from "node:fs";
|
|
67935
|
+
import { mkdir as mkdir3, open as open4, readdir as readdir4, readFile as readFile5, realpath as realpath6, stat as stat5 } from "node:fs/promises";
|
|
67936
|
+
function entryKind(entry) {
|
|
67937
|
+
if (entry.isDirectory()) {
|
|
67938
|
+
return "directory";
|
|
67939
|
+
}
|
|
67940
|
+
if (entry.isFile()) {
|
|
67941
|
+
return "file";
|
|
67942
|
+
}
|
|
67943
|
+
if (entry.isSymbolicLink()) {
|
|
67944
|
+
return "symbolic-link";
|
|
67945
|
+
}
|
|
67946
|
+
if (entry.isBlockDevice() || entry.isCharacterDevice()) {
|
|
67947
|
+
return "device";
|
|
67948
|
+
}
|
|
67949
|
+
if (entry.isFIFO()) {
|
|
67950
|
+
return "fifo";
|
|
67951
|
+
}
|
|
67952
|
+
return entry.isSocket() ? "socket" : "unknown";
|
|
67953
|
+
}
|
|
67954
|
+
async function canonicalPath(path7) {
|
|
67955
|
+
return await realpath6(path7);
|
|
67956
|
+
}
|
|
67957
|
+
async function readPathMetadata(path7) {
|
|
67958
|
+
const metadata = await stat5(path7);
|
|
67959
|
+
return {
|
|
67960
|
+
kind: metadata.isDirectory() ? "directory" : metadata.isFile() ? "file" : "other",
|
|
67961
|
+
modifiedAt: metadata.mtime,
|
|
67962
|
+
modifiedMilliseconds: metadata.mtimeMs,
|
|
67963
|
+
size: metadata.size
|
|
67964
|
+
};
|
|
67965
|
+
}
|
|
67966
|
+
async function listDirectory(path7) {
|
|
67967
|
+
const entries = await readdir4(path7, { withFileTypes: true });
|
|
67968
|
+
return entries.map((entry) => ({ kind: entryKind(entry), name: entry.name }));
|
|
67969
|
+
}
|
|
67970
|
+
async function ensurePrivateDirectory(path7) {
|
|
67971
|
+
await mkdir3(path7, { mode: 448, recursive: true });
|
|
67972
|
+
}
|
|
67973
|
+
async function ensureCanonicalDirectory(path7) {
|
|
67974
|
+
await ensurePrivateDirectory(path7);
|
|
67975
|
+
const resolved = await realpath6(path7);
|
|
67976
|
+
return (await stat5(resolved)).isDirectory() ? resolved : null;
|
|
67977
|
+
}
|
|
67978
|
+
async function readFileStart(path7, byteLength) {
|
|
67979
|
+
const bytes = new Uint8Array(byteLength);
|
|
67980
|
+
const handle = await open4(path7, "r");
|
|
67981
|
+
try {
|
|
67982
|
+
await handle.read(bytes, 0, byteLength, 0);
|
|
67983
|
+
} finally {
|
|
67984
|
+
await handle.close();
|
|
67985
|
+
}
|
|
67986
|
+
return bytes;
|
|
67987
|
+
}
|
|
67988
|
+
async function readFileBytes(path7) {
|
|
67989
|
+
return await readFile5(path7);
|
|
67990
|
+
}
|
|
67991
|
+
function readFileChunks(path7, chunkBytes, signal) {
|
|
67992
|
+
return createReadStream2(path7, { highWaterMark: chunkBytes, signal });
|
|
67993
|
+
}
|
|
67994
|
+
|
|
67995
|
+
// src/acp/content/raster.ts
|
|
67996
|
+
var MAX_LOCAL_RASTER_BYTES = 128 * 1024 * 1024;
|
|
67997
|
+
var PNG_SIGNATURE = Uint8Array.of(137, 80, 78, 71);
|
|
67998
|
+
var JPEG_SIGNATURE = Uint8Array.of(255, 216, 255);
|
|
67999
|
+
var GIF87_SIGNATURE = new TextEncoder().encode("GIF87a");
|
|
68000
|
+
var GIF89_SIGNATURE = new TextEncoder().encode("GIF89a");
|
|
68001
|
+
var RIFF_SIGNATURE = new TextEncoder().encode("RIFF");
|
|
68002
|
+
var WEBP_SIGNATURE = new TextEncoder().encode("WEBP");
|
|
68003
|
+
var LocalRasterImage = class {
|
|
68004
|
+
mimeType;
|
|
68005
|
+
name;
|
|
68006
|
+
sourceUri;
|
|
68007
|
+
constructor(name2, mimeType, sourceUri) {
|
|
68008
|
+
this.mimeType = mimeType;
|
|
68009
|
+
this.name = name2;
|
|
68010
|
+
this.sourceUri = sourceUri;
|
|
68011
|
+
}
|
|
68012
|
+
base64 = async () => Buffer.from(await readFileBytes(this.sourceUri)).toString("base64");
|
|
68013
|
+
};
|
|
68014
|
+
function startsWith(bytes, signature, offset = 0) {
|
|
68015
|
+
if (bytes.byteLength < offset + signature.byteLength) {
|
|
68016
|
+
return false;
|
|
68017
|
+
}
|
|
68018
|
+
return signature.every((value, index2) => bytes[offset + index2] === value);
|
|
68019
|
+
}
|
|
68020
|
+
function sniffRasterMime(bytes) {
|
|
68021
|
+
if (startsWith(bytes, PNG_SIGNATURE)) {
|
|
68022
|
+
return "image/png";
|
|
68023
|
+
}
|
|
68024
|
+
if (startsWith(bytes, JPEG_SIGNATURE)) {
|
|
68025
|
+
return "image/jpeg";
|
|
68026
|
+
}
|
|
68027
|
+
if (startsWith(bytes, GIF87_SIGNATURE) || startsWith(bytes, GIF89_SIGNATURE)) {
|
|
68028
|
+
return "image/gif";
|
|
68029
|
+
}
|
|
68030
|
+
if (startsWith(bytes, RIFF_SIGNATURE) && startsWith(bytes, WEBP_SIGNATURE, 8)) {
|
|
68031
|
+
return "image/webp";
|
|
68032
|
+
}
|
|
68033
|
+
return null;
|
|
68034
|
+
}
|
|
68035
|
+
async function resolveCanonicalPath(requested, signal) {
|
|
68036
|
+
signal.throwIfAborted();
|
|
68037
|
+
if (!isAbsolute9(requested) || requested.includes("\0") || normalize(requested) !== requested) {
|
|
68038
|
+
return null;
|
|
68039
|
+
}
|
|
68040
|
+
try {
|
|
68041
|
+
const target = await canonicalPath(requested);
|
|
68042
|
+
signal.throwIfAborted();
|
|
68043
|
+
if (!isAbsolute9(target) || normalize(target) !== target) {
|
|
68044
|
+
return null;
|
|
68045
|
+
}
|
|
68046
|
+
return target;
|
|
68047
|
+
} catch (cause) {
|
|
68048
|
+
signal.throwIfAborted();
|
|
68049
|
+
if (cause instanceof Error && cause.name === "AbortError") {
|
|
68050
|
+
throw cause;
|
|
68051
|
+
}
|
|
68052
|
+
return null;
|
|
68053
|
+
}
|
|
68054
|
+
}
|
|
68055
|
+
function parseLocalImageUri(uri) {
|
|
68056
|
+
const trimmed = uri.trim();
|
|
68057
|
+
if (trimmed.length === 0 || trimmed.length > 2048 || trimmed.includes("\0")) {
|
|
68058
|
+
return null;
|
|
68059
|
+
}
|
|
68060
|
+
if (trimmed.startsWith("data:")) {
|
|
68061
|
+
return null;
|
|
68062
|
+
}
|
|
68063
|
+
if (trimmed.startsWith("file:")) {
|
|
68064
|
+
try {
|
|
68065
|
+
const url2 = new URL(trimmed);
|
|
68066
|
+
if (url2.protocol !== "file:" || url2.host.length > 0) {
|
|
68067
|
+
return null;
|
|
68068
|
+
}
|
|
68069
|
+
return fileURLToPath(url2);
|
|
68070
|
+
} catch {
|
|
68071
|
+
return null;
|
|
68072
|
+
}
|
|
68073
|
+
}
|
|
68074
|
+
if (!isAbsolute9(trimmed) && /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(trimmed)) {
|
|
68075
|
+
return null;
|
|
68076
|
+
}
|
|
68077
|
+
return trimmed;
|
|
68078
|
+
}
|
|
68079
|
+
async function readLocalRaster(uri, signal) {
|
|
68080
|
+
signal.throwIfAborted();
|
|
68081
|
+
const requested = parseLocalImageUri(uri);
|
|
68082
|
+
if (requested === null) {
|
|
68083
|
+
return null;
|
|
68084
|
+
}
|
|
68085
|
+
const target = await resolveCanonicalPath(requested, signal);
|
|
68086
|
+
if (target === null) {
|
|
68087
|
+
return null;
|
|
68088
|
+
}
|
|
68089
|
+
const targetMetadata = await readPathMetadata(target);
|
|
68090
|
+
signal.throwIfAborted();
|
|
68091
|
+
if (targetMetadata.kind !== "file" || targetMetadata.size < 1 || targetMetadata.size > MAX_LOCAL_RASTER_BYTES) {
|
|
68092
|
+
return null;
|
|
68093
|
+
}
|
|
68094
|
+
const header = await readFileStart(target, 12);
|
|
68095
|
+
signal.throwIfAborted();
|
|
68096
|
+
const mimeType = sniffRasterMime(header);
|
|
68097
|
+
if (mimeType === null) {
|
|
68098
|
+
return null;
|
|
68099
|
+
}
|
|
68100
|
+
return new LocalRasterImage(basename4(target) || "Image", mimeType, target);
|
|
68101
|
+
}
|
|
68102
|
+
|
|
68103
|
+
// src/acp/native-history/codex/history-images.ts
|
|
68104
|
+
var IMAGE_MARKER = /\[@image\]\(([^)\r\n]*)(?:\)|$)/g;
|
|
68105
|
+
var DATA_IMAGE_HEADER = /^data:(image\/[a-z+]+);base64,/;
|
|
68106
|
+
var BASE_64 = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
68107
|
+
var SESSION_HISTORY_IMAGE_CHARACTER_LIMIT = 4e6;
|
|
68108
|
+
function isRasterMime(value) {
|
|
68109
|
+
return value === "image/png" || value === "image/jpeg" || value === "image/gif" || value === "image/webp";
|
|
68110
|
+
}
|
|
68111
|
+
function parseNativeHistoryImage(uri) {
|
|
68112
|
+
const header = DATA_IMAGE_HEADER.exec(uri);
|
|
68113
|
+
if (header === null) {
|
|
68114
|
+
return null;
|
|
68115
|
+
}
|
|
68116
|
+
const mimeType = header[1] ?? "";
|
|
68117
|
+
const data = uri.slice(header[0].length);
|
|
68118
|
+
if (!isRasterMime(mimeType) || data.length < 4 || data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
68119
|
+
return null;
|
|
68120
|
+
}
|
|
68121
|
+
if (data.length % 4 !== 0 || !BASE_64.test(data)) {
|
|
68122
|
+
return null;
|
|
68123
|
+
}
|
|
68124
|
+
return { data, mimeType, name: "" };
|
|
68125
|
+
}
|
|
68126
|
+
async function embedLocalHistoryImages(history, signal) {
|
|
68127
|
+
if (history.status !== "available") {
|
|
68128
|
+
return history;
|
|
68129
|
+
}
|
|
68130
|
+
const messages = [];
|
|
68131
|
+
let imageCharacters = 0;
|
|
68132
|
+
for (const message of history.messages) {
|
|
68133
|
+
signal.throwIfAborted();
|
|
68134
|
+
const resolved = await resolveMessageImages(message, imageCharacters, signal);
|
|
68135
|
+
imageCharacters += (resolved.images ?? []).reduce((size, image) => size + image.data.length, 0);
|
|
68136
|
+
messages.push(resolved);
|
|
68137
|
+
}
|
|
68138
|
+
return {
|
|
68139
|
+
...history,
|
|
68140
|
+
messages
|
|
68141
|
+
};
|
|
68142
|
+
}
|
|
68143
|
+
async function resolveMessageImages(message, usedCharacters, signal) {
|
|
68144
|
+
const images = [...message.images ?? []];
|
|
68145
|
+
let imageCharacters = images.reduce((size, image) => size + image.data.length, 0);
|
|
68146
|
+
const text2 = await replaceImageMarkers(message.text, async (uri) => {
|
|
68147
|
+
if (images.length >= 8 || usedCharacters + imageCharacters >= SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
68148
|
+
return "[Image unavailable]";
|
|
68149
|
+
}
|
|
68150
|
+
const embedded = parseNativeHistoryImage(uri);
|
|
68151
|
+
if (embedded !== null) {
|
|
68152
|
+
if (usedCharacters + imageCharacters + embedded.data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
68153
|
+
return "[Image unavailable]";
|
|
68154
|
+
}
|
|
68155
|
+
images.push({ ...embedded, name: `Image ${(images.length + 1).toString()}` });
|
|
68156
|
+
imageCharacters += embedded.data.length;
|
|
68157
|
+
return "";
|
|
68158
|
+
}
|
|
68159
|
+
const local = await readLocalRaster(uri, signal);
|
|
68160
|
+
if (local === null) {
|
|
68161
|
+
return "[Image unavailable]";
|
|
68162
|
+
}
|
|
68163
|
+
const data = await local.base64();
|
|
68164
|
+
if (usedCharacters + imageCharacters + data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
68165
|
+
return "[Image unavailable]";
|
|
68166
|
+
}
|
|
68167
|
+
images.push({
|
|
68168
|
+
data,
|
|
68169
|
+
mimeType: local.mimeType,
|
|
68170
|
+
name: local.name
|
|
68171
|
+
});
|
|
68172
|
+
imageCharacters += data.length;
|
|
68173
|
+
return "";
|
|
68174
|
+
});
|
|
68175
|
+
return {
|
|
68176
|
+
...message,
|
|
68177
|
+
text: text2,
|
|
68178
|
+
...images.length > 0 ? { images } : {}
|
|
68179
|
+
};
|
|
68180
|
+
}
|
|
68181
|
+
async function replaceImageMarkers(text2, replace) {
|
|
68182
|
+
const matches = [...text2.matchAll(IMAGE_MARKER)];
|
|
68183
|
+
if (matches.length === 0) {
|
|
68184
|
+
return text2;
|
|
68185
|
+
}
|
|
68186
|
+
let cursor = 0;
|
|
68187
|
+
let rewritten = "";
|
|
68188
|
+
for (const match of matches) {
|
|
68189
|
+
const index2 = match.index ?? 0;
|
|
68190
|
+
rewritten += text2.slice(cursor, index2);
|
|
68191
|
+
rewritten += await replace(match[1] ?? "");
|
|
68192
|
+
cursor = index2 + match[0].length;
|
|
68193
|
+
}
|
|
68194
|
+
return `${rewritten}${text2.slice(cursor)}`;
|
|
68195
|
+
}
|
|
68196
|
+
|
|
67925
68197
|
// src/acp/harness/codex/owned-agent.ts
|
|
67926
68198
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
67927
68199
|
import { setTimeout as delay } from "node:timers/promises";
|
|
@@ -68574,6 +68846,115 @@ var CodexOwnedAcpAgent = class {
|
|
|
68574
68846
|
};
|
|
68575
68847
|
};
|
|
68576
68848
|
|
|
68849
|
+
// src/acp/harness/codex/history.ts
|
|
68850
|
+
async function replayCodexHistory(client2, threadId, emit, signal) {
|
|
68851
|
+
const deadline = AbortSignal.any([signal, AbortSignal.timeout(6e4)]);
|
|
68852
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
68853
|
+
let cursor = null;
|
|
68854
|
+
let turnIndex = 0;
|
|
68855
|
+
for (; ; ) {
|
|
68856
|
+
deadline.throwIfAborted();
|
|
68857
|
+
const page = threadTurnsPageSchema.parse(
|
|
68858
|
+
await client2.request(
|
|
68859
|
+
"thread/turns/list",
|
|
68860
|
+
{
|
|
68861
|
+
threadId,
|
|
68862
|
+
limit: CODEX_HISTORY_TURN_PAGE_LIMIT,
|
|
68863
|
+
sortDirection: "asc",
|
|
68864
|
+
itemsView: "full",
|
|
68865
|
+
...cursor === null ? {} : { cursor }
|
|
68866
|
+
},
|
|
68867
|
+
deadline
|
|
68868
|
+
)
|
|
68869
|
+
);
|
|
68870
|
+
for (const turn of page.data) {
|
|
68871
|
+
for (const rawItem of turn.items) {
|
|
68872
|
+
deadline.throwIfAborted();
|
|
68873
|
+
const item = decodeThreadItem(rawItem);
|
|
68874
|
+
if (item === null) {
|
|
68875
|
+
continue;
|
|
68876
|
+
}
|
|
68877
|
+
if (item.type === "userMessage") {
|
|
68878
|
+
const text2 = item.content.flatMap((content) => {
|
|
68879
|
+
if (typeof content !== "object" || content === null) {
|
|
68880
|
+
return [];
|
|
68881
|
+
}
|
|
68882
|
+
const type = Reflect.get(content, "type");
|
|
68883
|
+
const text3 = Reflect.get(content, "text");
|
|
68884
|
+
const url2 = Reflect.get(content, "url");
|
|
68885
|
+
if (type === "image" && typeof url2 === "string") {
|
|
68886
|
+
return [`[@image](${url2})`];
|
|
68887
|
+
}
|
|
68888
|
+
return type === "text" && typeof text3 === "string" ? [text3] : [];
|
|
68889
|
+
}).join("");
|
|
68890
|
+
const history = await embedLocalHistoryImages(
|
|
68891
|
+
{ status: "available", truncated: false, messages: [{ role: "user", text: text2 }] },
|
|
68892
|
+
deadline
|
|
68893
|
+
);
|
|
68894
|
+
if (history.status !== "available") {
|
|
68895
|
+
continue;
|
|
68896
|
+
}
|
|
68897
|
+
const message = history.messages[0];
|
|
68898
|
+
for (const image of message?.images ?? []) {
|
|
68899
|
+
await emit({
|
|
68900
|
+
content: { type: "image", data: image.data, mimeType: image.mimeType },
|
|
68901
|
+
messageId: item.id,
|
|
68902
|
+
sessionUpdate: "user_message_chunk"
|
|
68903
|
+
});
|
|
68904
|
+
}
|
|
68905
|
+
const restoredText = message?.text ?? "";
|
|
68906
|
+
if (restoredText.length > 0) {
|
|
68907
|
+
await emit({
|
|
68908
|
+
content: { text: restoredText, type: "text" },
|
|
68909
|
+
messageId: item.id,
|
|
68910
|
+
sessionUpdate: "user_message_chunk"
|
|
68911
|
+
});
|
|
68912
|
+
}
|
|
68913
|
+
} else if (item.type === "agentMessage") {
|
|
68914
|
+
await emit(agentMessageUpdate(item.id, item.text));
|
|
68915
|
+
} else if (item.type === "reasoning") {
|
|
68916
|
+
const text2 = reasoningText(item);
|
|
68917
|
+
if (text2 !== null && text2.length > 0) {
|
|
68918
|
+
await emit({
|
|
68919
|
+
content: { text: text2, type: "text" },
|
|
68920
|
+
messageId: item.id,
|
|
68921
|
+
sessionUpdate: "agent_thought_chunk"
|
|
68922
|
+
});
|
|
68923
|
+
}
|
|
68924
|
+
} else if (item.type === "contextCompaction") {
|
|
68925
|
+
await emit({ compactionId: item.id, sessionUpdate: "compaction_update", status: "completed" });
|
|
68926
|
+
} else {
|
|
68927
|
+
const update = toolCallUpdate(item, "snapshot");
|
|
68928
|
+
if (update !== null) {
|
|
68929
|
+
await emit({ ...update, sessionUpdate: "tool_call" });
|
|
68930
|
+
}
|
|
68931
|
+
}
|
|
68932
|
+
}
|
|
68933
|
+
if (turn.error != null) {
|
|
68934
|
+
const identity2 = createHash("sha256").update(threadId).update("\0").update(turn.id ?? turnIndex.toString()).digest("hex");
|
|
68935
|
+
await emit({
|
|
68936
|
+
sessionUpdate: "tool_call",
|
|
68937
|
+
toolCallId: `agent-error-${identity2}`,
|
|
68938
|
+
title: "Agent error",
|
|
68939
|
+
kind: "other",
|
|
68940
|
+
status: "failed",
|
|
68941
|
+
rawOutput: { message: turn.error.message },
|
|
68942
|
+
content: [{ type: "content", content: { type: "text", text: turn.error.message } }]
|
|
68943
|
+
});
|
|
68944
|
+
}
|
|
68945
|
+
turnIndex += 1;
|
|
68946
|
+
}
|
|
68947
|
+
if (page.nextCursor == null) {
|
|
68948
|
+
return;
|
|
68949
|
+
}
|
|
68950
|
+
if (page.data.length === 0 || seenCursors.has(page.nextCursor)) {
|
|
68951
|
+
throw new AcpExecutionError("Codex repeated a history page cursor", {}, "invalid_native_session_response");
|
|
68952
|
+
}
|
|
68953
|
+
seenCursors.add(page.nextCursor);
|
|
68954
|
+
cursor = page.nextCursor;
|
|
68955
|
+
}
|
|
68956
|
+
}
|
|
68957
|
+
|
|
68577
68958
|
// src/acp/harness/codex/settings.ts
|
|
68578
68959
|
var APPROVAL_TIMEOUT_MILLISECONDS2 = 36e5;
|
|
68579
68960
|
var MODEL_SETTING_ID = "model";
|
|
@@ -69240,83 +69621,7 @@ var CodexAcpAgent = class {
|
|
|
69240
69621
|
// ACP load requires chronological replay. Resume only restores execution;
|
|
69241
69622
|
// native pages supply history without a single full-transcript response.
|
|
69242
69623
|
#replaySavedHistory = async (signal) => {
|
|
69243
|
-
|
|
69244
|
-
const seenCursors = /* @__PURE__ */ new Set();
|
|
69245
|
-
let cursor = null;
|
|
69246
|
-
for (; ; ) {
|
|
69247
|
-
deadline.throwIfAborted();
|
|
69248
|
-
const page = threadTurnsPageSchema.parse(
|
|
69249
|
-
await this.#appServer.request(
|
|
69250
|
-
"thread/turns/list",
|
|
69251
|
-
{
|
|
69252
|
-
threadId: this.#nativeSessionId,
|
|
69253
|
-
limit: CODEX_HISTORY_TURN_PAGE_LIMIT,
|
|
69254
|
-
sortDirection: "asc",
|
|
69255
|
-
itemsView: "full",
|
|
69256
|
-
...cursor === null ? {} : { cursor }
|
|
69257
|
-
},
|
|
69258
|
-
deadline
|
|
69259
|
-
)
|
|
69260
|
-
);
|
|
69261
|
-
await this.#replayHistory(page.data, deadline);
|
|
69262
|
-
if (page.nextCursor == null) {
|
|
69263
|
-
return;
|
|
69264
|
-
}
|
|
69265
|
-
if (page.data.length === 0 || seenCursors.has(page.nextCursor)) {
|
|
69266
|
-
throw new AcpExecutionError(
|
|
69267
|
-
"Codex repeated a history page cursor",
|
|
69268
|
-
{},
|
|
69269
|
-
"invalid_native_session_response"
|
|
69270
|
-
);
|
|
69271
|
-
}
|
|
69272
|
-
seenCursors.add(page.nextCursor);
|
|
69273
|
-
cursor = page.nextCursor;
|
|
69274
|
-
}
|
|
69275
|
-
};
|
|
69276
|
-
#replayHistory = async (turns, signal) => {
|
|
69277
|
-
for (const turn of turns) {
|
|
69278
|
-
for (const rawItem of turn.items) {
|
|
69279
|
-
signal.throwIfAborted();
|
|
69280
|
-
const item = decodeThreadItem(rawItem);
|
|
69281
|
-
if (item === null) {
|
|
69282
|
-
continue;
|
|
69283
|
-
}
|
|
69284
|
-
if (item.type === "userMessage") {
|
|
69285
|
-
const text2 = item.content.flatMap((content) => {
|
|
69286
|
-
if (typeof content !== "object" || content === null) {
|
|
69287
|
-
return [];
|
|
69288
|
-
}
|
|
69289
|
-
const type = Reflect.get(content, "type");
|
|
69290
|
-
const text3 = Reflect.get(content, "text");
|
|
69291
|
-
return type === "text" && typeof text3 === "string" ? [text3] : [];
|
|
69292
|
-
}).join("");
|
|
69293
|
-
if (text2.length > 0) {
|
|
69294
|
-
await this.#emit({
|
|
69295
|
-
content: { text: text2, type: "text" },
|
|
69296
|
-
messageId: item.id,
|
|
69297
|
-
sessionUpdate: "user_message_chunk"
|
|
69298
|
-
});
|
|
69299
|
-
}
|
|
69300
|
-
continue;
|
|
69301
|
-
}
|
|
69302
|
-
if (item.type === "agentMessage") {
|
|
69303
|
-
await this.#emit(agentMessageUpdate(item.id, item.text));
|
|
69304
|
-
continue;
|
|
69305
|
-
}
|
|
69306
|
-
if (item.type === "contextCompaction") {
|
|
69307
|
-
await this.#emit({
|
|
69308
|
-
compactionId: item.id,
|
|
69309
|
-
sessionUpdate: "compaction_update",
|
|
69310
|
-
status: "completed"
|
|
69311
|
-
});
|
|
69312
|
-
continue;
|
|
69313
|
-
}
|
|
69314
|
-
const update = toolCallUpdate(item, "snapshot");
|
|
69315
|
-
if (update !== null) {
|
|
69316
|
-
await this.#emit({ ...update, sessionUpdate: "tool_call" });
|
|
69317
|
-
}
|
|
69318
|
-
}
|
|
69319
|
-
}
|
|
69624
|
+
await replayCodexHistory(this.#appServer, this.#nativeSessionId, this.#emit, signal);
|
|
69320
69625
|
};
|
|
69321
69626
|
/** Announces the manual compact command after every session entry point —
|
|
69322
69627
|
* new, load, resume, and fork — so clients on restored sessions discover
|
|
@@ -69364,7 +69669,7 @@ var CodexAgentSpecification = class extends InProcessAcpAgentSpecification {
|
|
|
69364
69669
|
};
|
|
69365
69670
|
|
|
69366
69671
|
// src/agent/specification/vendors/pi-agent.ts
|
|
69367
|
-
import { createHash } from "node:crypto";
|
|
69672
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
69368
69673
|
import { join as join19 } from "node:path";
|
|
69369
69674
|
import {
|
|
69370
69675
|
methods as methods6
|
|
@@ -69377,7 +69682,7 @@ import { agent as createAgentApp2, methods as methods5 } from "@agentclientproto
|
|
|
69377
69682
|
import { spawnSync } from "node:child_process";
|
|
69378
69683
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
69379
69684
|
import { existsSync as existsSync7, readdirSync as readdirSync6, readFileSync as readFileSync8, realpathSync as realpathSync4, statSync as statSync4, unlinkSync as unlinkSync2 } from "node:fs";
|
|
69380
|
-
import { basename as
|
|
69685
|
+
import { basename as basename5, dirname as dirname7, isAbsolute as isAbsolute12, join as join17 } from "node:path";
|
|
69381
69686
|
import { RequestError as RequestError7 } from "@agentclientprotocol/sdk";
|
|
69382
69687
|
|
|
69383
69688
|
// src/acp/harness/pi/upstream/dist/pi-rpc/process.js
|
|
@@ -69893,7 +70198,7 @@ function toAvailableCommandsFromPiGetCommands(data, opts) {
|
|
|
69893
70198
|
|
|
69894
70199
|
// src/acp/harness/pi/upstream/dist/acp/pi-sessions.js
|
|
69895
70200
|
import { closeSync as closeSync2, existsSync as existsSync4, openSync as openSync2, readdirSync as readdirSync4, readFileSync as readFileSync3, readSync as readSync2, statSync as statSync3 } from "node:fs";
|
|
69896
|
-
import { isAbsolute as
|
|
70201
|
+
import { isAbsolute as isAbsolute10, join as join14, resolve as resolve9 } from "node:path";
|
|
69897
70202
|
var DEFAULT_TAIL_BYTES = 256 * 1024;
|
|
69898
70203
|
var DEFAULT_HEAD_BYTES = 64 * 1024;
|
|
69899
70204
|
function getPiAgentDir(environment) {
|
|
@@ -69915,7 +70220,7 @@ function readSessionDirFromSettings(agentDir) {
|
|
|
69915
70220
|
if (typeof sessionDir !== "string" || !sessionDir.trim()) {
|
|
69916
70221
|
return null;
|
|
69917
70222
|
}
|
|
69918
|
-
return
|
|
70223
|
+
return isAbsolute10(sessionDir) ? sessionDir : resolve9(agentDir, sessionDir);
|
|
69919
70224
|
} catch {
|
|
69920
70225
|
return null;
|
|
69921
70226
|
}
|
|
@@ -70286,7 +70591,7 @@ function getQuietStartup(cwd, environment = process.env) {
|
|
|
70286
70591
|
// src/acp/harness/pi/upstream/dist/acp/session.js
|
|
70287
70592
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
70288
70593
|
import { readFileSync as readFileSync7 } from "node:fs";
|
|
70289
|
-
import { isAbsolute as
|
|
70594
|
+
import { isAbsolute as isAbsolute11, resolve as resolvePath } from "node:path";
|
|
70290
70595
|
import { RequestError as RequestError6 } from "@agentclientprotocol/sdk";
|
|
70291
70596
|
|
|
70292
70597
|
// src/acp/harness/pi/upstream/dist/acp/extension-questions.js
|
|
@@ -70819,7 +71124,7 @@ function toToolCallLocations(args, cwd, line) {
|
|
|
70819
71124
|
if (!path7) {
|
|
70820
71125
|
return void 0;
|
|
70821
71126
|
}
|
|
70822
|
-
const resolvedPath =
|
|
71127
|
+
const resolvedPath = isAbsolute11(path7) ? path7 : resolvePath(cwd, path7);
|
|
70823
71128
|
return [{ path: resolvedPath, ...typeof line === "number" ? { line } : {} }];
|
|
70824
71129
|
}
|
|
70825
71130
|
var SessionManager = class {
|
|
@@ -71359,7 +71664,7 @@ var PiAcpSession = class {
|
|
|
71359
71664
|
const p = getToolPath(args);
|
|
71360
71665
|
if (p) {
|
|
71361
71666
|
try {
|
|
71362
|
-
const abs =
|
|
71667
|
+
const abs = isAbsolute11(p) ? p : resolvePath(this.cwd, p);
|
|
71363
71668
|
snapshotOldText = readFileSync7(abs, "utf8");
|
|
71364
71669
|
this.fileSnapshots.set(toolCallId, { path: p, oldText: snapshotOldText });
|
|
71365
71670
|
if (toolName === "edit") {
|
|
@@ -71442,7 +71747,7 @@ var PiAcpSession = class {
|
|
|
71442
71747
|
let hasStructuredDiff = false;
|
|
71443
71748
|
if (!isError && snapshot) {
|
|
71444
71749
|
try {
|
|
71445
|
-
const abs =
|
|
71750
|
+
const abs = isAbsolute11(snapshot.path) ? snapshot.path : resolvePath(this.cwd, snapshot.path);
|
|
71446
71751
|
const newText = readFileSync7(abs, "utf8");
|
|
71447
71752
|
if (snapshot.oldText === null || newText !== snapshot.oldText) {
|
|
71448
71753
|
hasStructuredDiff = true;
|
|
@@ -71836,7 +72141,7 @@ var PiAcpAgent = class {
|
|
|
71836
72141
|
};
|
|
71837
72142
|
}
|
|
71838
72143
|
async newSession(params) {
|
|
71839
|
-
if (!
|
|
72144
|
+
if (!isAbsolute12(params.cwd)) {
|
|
71840
72145
|
throw RequestError7.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
|
|
71841
72146
|
}
|
|
71842
72147
|
this.lastSessionCwd = params.cwd;
|
|
@@ -72433,7 +72738,7 @@ ${JSON.stringify(stats, null, 2)}`;
|
|
|
72433
72738
|
return { sessions, nextCursor, _meta: {} };
|
|
72434
72739
|
}
|
|
72435
72740
|
async forkSession(params) {
|
|
72436
|
-
if (!
|
|
72741
|
+
if (!isAbsolute12(params.cwd)) {
|
|
72437
72742
|
throw RequestError7.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
|
|
72438
72743
|
}
|
|
72439
72744
|
const source = this.findStoredSession(params.sessionId);
|
|
@@ -72499,7 +72804,7 @@ ${JSON.stringify(stats, null, 2)}`;
|
|
|
72499
72804
|
return { sessionId: session.sessionId, configOptions, modes };
|
|
72500
72805
|
}
|
|
72501
72806
|
async resumeSession(params) {
|
|
72502
|
-
if (!
|
|
72807
|
+
if (!isAbsolute12(params.cwd)) {
|
|
72503
72808
|
throw RequestError7.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
|
|
72504
72809
|
}
|
|
72505
72810
|
this.sessions.close(params.sessionId);
|
|
@@ -72570,7 +72875,7 @@ ${JSON.stringify(stats, null, 2)}`;
|
|
|
72570
72875
|
return response;
|
|
72571
72876
|
}
|
|
72572
72877
|
async loadSession(params) {
|
|
72573
|
-
if (!
|
|
72878
|
+
if (!isAbsolute12(params.cwd)) {
|
|
72574
72879
|
throw RequestError7.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
|
|
72575
72880
|
}
|
|
72576
72881
|
this.sessions.close(params.sessionId);
|
|
@@ -73064,7 +73369,7 @@ function buildStartupInfo(opts) {
|
|
|
73064
73369
|
try {
|
|
73065
73370
|
const prompts = readdirSync6(promptsDir).filter((f) => f.endsWith(".md"));
|
|
73066
73371
|
for (const f of prompts) {
|
|
73067
|
-
promptsItems.push(`/${
|
|
73372
|
+
promptsItems.push(`/${basename5(f, ".md")}`);
|
|
73068
73373
|
}
|
|
73069
73374
|
} catch {
|
|
73070
73375
|
}
|
|
@@ -73244,7 +73549,7 @@ var PiAgentSpecification = class extends InProcessAcpAgentSpecification {
|
|
|
73244
73549
|
// The Pi ACP fork inlines embedded prompt resources into the turn message, so Mobius
|
|
73245
73550
|
// keeps the adapter's opt-in capability flag enabled for every launch it owns.
|
|
73246
73551
|
createLaunchEnvironment = async (_agent, context) => {
|
|
73247
|
-
const workspaceHash =
|
|
73552
|
+
const workspaceHash = createHash2("sha256").update(context.defaultWorkspace).digest("hex").slice(0, 24);
|
|
73248
73553
|
const sessionDirectory = join19(
|
|
73249
73554
|
readStateDirectory(context.environment),
|
|
73250
73555
|
"agents",
|
|
@@ -73760,11 +74065,11 @@ function isAgentVersionSupported(reportedVersion, minimumSupportedVersion) {
|
|
|
73760
74065
|
}
|
|
73761
74066
|
|
|
73762
74067
|
// src/agent/discovery/executable-discovery.ts
|
|
73763
|
-
import { isAbsolute as
|
|
74068
|
+
import { isAbsolute as isAbsolute13 } from "node:path";
|
|
73764
74069
|
async function resolveSpecificationExecutables(executableName, overrideVariable, resolveInstalled, context) {
|
|
73765
74070
|
const override = context.environment[overrideVariable];
|
|
73766
74071
|
if (override !== void 0) {
|
|
73767
|
-
if (override.length === 0 || !
|
|
74072
|
+
if (override.length === 0 || !isAbsolute13(override)) {
|
|
73768
74073
|
return [];
|
|
73769
74074
|
}
|
|
73770
74075
|
const executable = await resolveExecutablePath(override, context.platform);
|
|
@@ -74272,8 +74577,27 @@ var AdapterRegistry = class {
|
|
|
74272
74577
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
74273
74578
|
|
|
74274
74579
|
// src/session/history/session-event-history-projection.ts
|
|
74580
|
+
var MAXIMUM_PROJECTED_REASONING_BYTES = 24 * 1024;
|
|
74581
|
+
function boundReasoning(payload) {
|
|
74582
|
+
if (payload.content.type !== "text" || Buffer.byteLength(payload.content.text, "utf8") <= MAXIMUM_PROJECTED_REASONING_BYTES) {
|
|
74583
|
+
return payload;
|
|
74584
|
+
}
|
|
74585
|
+
const bytes = Buffer.from(payload.content.text, "utf8");
|
|
74586
|
+
let start = bytes.length - MAXIMUM_PROJECTED_REASONING_BYTES;
|
|
74587
|
+
while (start < bytes.length && (bytes.readUInt8(start) & 192) === 128) {
|
|
74588
|
+
start += 1;
|
|
74589
|
+
}
|
|
74590
|
+
return {
|
|
74591
|
+
...payload,
|
|
74592
|
+
content: { ...payload.content, text: bytes.toString("utf8", start) },
|
|
74593
|
+
meta: { ...payload.meta, truncated: true }
|
|
74594
|
+
};
|
|
74595
|
+
}
|
|
74275
74596
|
function projectNewEvent(liveEvent2, eventId) {
|
|
74276
74597
|
const { position: _position, eventId: _liveEventId, ...event } = liveEvent2;
|
|
74598
|
+
if (event.type === "acp" && event.payload.sessionUpdate === "agent_thought_chunk") {
|
|
74599
|
+
return { ...event, eventId, payload: boundReasoning(event.payload) };
|
|
74600
|
+
}
|
|
74277
74601
|
return { ...event, eventId };
|
|
74278
74602
|
}
|
|
74279
74603
|
function replaceAcpPayload(event, payload) {
|
|
@@ -74324,11 +74648,11 @@ function mergeTextChunk(previous, incoming) {
|
|
|
74324
74648
|
}
|
|
74325
74649
|
const content = { text: `${previous.content.text}${incoming.content.text}`, type: "text" };
|
|
74326
74650
|
if (previous.sessionUpdate === "agent_thought_chunk" && incoming.sessionUpdate === "agent_thought_chunk") {
|
|
74327
|
-
return {
|
|
74651
|
+
return boundReasoning({
|
|
74328
74652
|
...previous,
|
|
74329
74653
|
content,
|
|
74330
74654
|
...previous.meta?.truncated === true || incoming.meta?.truncated === true ? { meta: { ...previous.meta, ...incoming.meta, truncated: true } } : {}
|
|
74331
|
-
};
|
|
74655
|
+
});
|
|
74332
74656
|
}
|
|
74333
74657
|
return { ...previous, content };
|
|
74334
74658
|
}
|
|
@@ -75792,12 +76116,30 @@ function sessionConfigProtocolForAgent(_agentId) {
|
|
|
75792
76116
|
}
|
|
75793
76117
|
|
|
75794
76118
|
// src/acp/adapter/session-events.ts
|
|
76119
|
+
var MAXIMUM_REASONING_UPDATE_CHARACTERS = 1e6;
|
|
76120
|
+
function* reasoningWireUpdates(update) {
|
|
76121
|
+
if (update.sessionUpdate !== "agent_thought_chunk" || update.content.type !== "text" || update.content.text.length <= MAXIMUM_REASONING_UPDATE_CHARACTERS) {
|
|
76122
|
+
yield update;
|
|
76123
|
+
return;
|
|
76124
|
+
}
|
|
76125
|
+
const text2 = update.content.text;
|
|
76126
|
+
for (let start = 0; start < text2.length; ) {
|
|
76127
|
+
let end = Math.min(start + MAXIMUM_REASONING_UPDATE_CHARACTERS, text2.length);
|
|
76128
|
+
const last = text2.charCodeAt(end - 1);
|
|
76129
|
+
const next = text2.charCodeAt(end);
|
|
76130
|
+
if (last >= 55296 && last <= 56319 && next >= 56320 && next <= 57343) {
|
|
76131
|
+
end -= 1;
|
|
76132
|
+
}
|
|
76133
|
+
yield { ...update, content: { ...update.content, text: text2.slice(start, end) } };
|
|
76134
|
+
start = end;
|
|
76135
|
+
}
|
|
76136
|
+
}
|
|
75795
76137
|
var AdapterSessionConnection = class {
|
|
75796
76138
|
#connection;
|
|
75797
76139
|
#updates;
|
|
75798
76140
|
#lifetime = new AbortController();
|
|
75799
76141
|
events;
|
|
75800
|
-
constructor(options, externalizer) {
|
|
76142
|
+
constructor(options, externalizer, normalizeEvent) {
|
|
75801
76143
|
const protocol = sessionConfigProtocolForAgent(options.agent.id);
|
|
75802
76144
|
this.#updates = new AgentUpdateStream(async (notification) => {
|
|
75803
76145
|
this.#lifetime.signal.throwIfAborted();
|
|
@@ -75805,58 +76147,60 @@ var AdapterSessionConnection = class {
|
|
|
75805
76147
|
throw new AcpExecutionError("ACP agent referenced an unknown session", {}, "invalid_agent_session");
|
|
75806
76148
|
}
|
|
75807
76149
|
const signal = AbortSignal.any([this.#lifetime.signal, AbortSignal.timeout(3e4)]);
|
|
75808
|
-
const
|
|
75809
|
-
|
|
75810
|
-
|
|
75811
|
-
|
|
75812
|
-
|
|
75813
|
-
|
|
75814
|
-
|
|
75815
|
-
|
|
75816
|
-
|
|
75817
|
-
|
|
75818
|
-
|
|
75819
|
-
|
|
75820
|
-
|
|
75821
|
-
|
|
75822
|
-
|
|
75823
|
-
|
|
75824
|
-
|
|
75825
|
-
|
|
75826
|
-
|
|
75827
|
-
|
|
75828
|
-
|
|
75829
|
-
|
|
75830
|
-
|
|
75831
|
-
|
|
75832
|
-
|
|
75833
|
-
|
|
75834
|
-
|
|
75835
|
-
|
|
75836
|
-
|
|
75837
|
-
|
|
75838
|
-
|
|
75839
|
-
|
|
75840
|
-
|
|
75841
|
-
|
|
76150
|
+
for (const incoming of reasoningWireUpdates(notification.update)) {
|
|
76151
|
+
const externalized = await externalizer.update(options.sessionId(), incoming, signal);
|
|
76152
|
+
signal.throwIfAborted();
|
|
76153
|
+
const update = externalized.agent;
|
|
76154
|
+
const payload = decodeAcpSessionUpdate(JSON.stringify(normalizeEvent(externalized.event)));
|
|
76155
|
+
let event;
|
|
76156
|
+
switch (update.sessionUpdate) {
|
|
76157
|
+
case "available_commands_update":
|
|
76158
|
+
event = {
|
|
76159
|
+
kind: "commands",
|
|
76160
|
+
payload,
|
|
76161
|
+
commands: update.availableCommands.slice(0, 500).map((command) => ({
|
|
76162
|
+
description: truncate(command.description, 500),
|
|
76163
|
+
inputHint: truncate(command.input?.hint ?? "", 255),
|
|
76164
|
+
name: truncate(command.name, 128)
|
|
76165
|
+
})).filter((command) => command.name.length > 0)
|
|
76166
|
+
};
|
|
76167
|
+
break;
|
|
76168
|
+
case "config_option_update":
|
|
76169
|
+
event = {
|
|
76170
|
+
kind: "configuration",
|
|
76171
|
+
payload,
|
|
76172
|
+
configOptions: protocol.normalizeUpdate(options.configOptions(), update.configOptions)
|
|
76173
|
+
};
|
|
76174
|
+
break;
|
|
76175
|
+
case "current_mode_update":
|
|
76176
|
+
event = { kind: "mode", payload, modeId: update.currentModeId };
|
|
76177
|
+
break;
|
|
76178
|
+
case "session_info_update": {
|
|
76179
|
+
const changes = [];
|
|
76180
|
+
if (Object.hasOwn(update, "title")) {
|
|
76181
|
+
changes.push({ kind: "title", value: truncate(update.title ?? "", 500) });
|
|
76182
|
+
}
|
|
76183
|
+
if (Object.hasOwn(update, "updatedAt")) {
|
|
76184
|
+
changes.push({ kind: "updated-at", value: truncate(update.updatedAt ?? "", 128) });
|
|
76185
|
+
}
|
|
76186
|
+
event = { kind: "info", payload, changes };
|
|
76187
|
+
break;
|
|
75842
76188
|
}
|
|
75843
|
-
|
|
75844
|
-
|
|
76189
|
+
case "user_message_chunk":
|
|
76190
|
+
case "agent_message_chunk":
|
|
76191
|
+
case "agent_thought_chunk":
|
|
76192
|
+
case "tool_call":
|
|
76193
|
+
case "tool_call_update":
|
|
76194
|
+
case "plan":
|
|
76195
|
+
case "plan_update":
|
|
76196
|
+
case "plan_removed":
|
|
76197
|
+
event = { kind: "content", payload };
|
|
76198
|
+
break;
|
|
76199
|
+
default:
|
|
76200
|
+
event = { kind: "other", payload };
|
|
75845
76201
|
}
|
|
75846
|
-
|
|
75847
|
-
case "agent_message_chunk":
|
|
75848
|
-
case "agent_thought_chunk":
|
|
75849
|
-
case "tool_call":
|
|
75850
|
-
case "tool_call_update":
|
|
75851
|
-
case "plan":
|
|
75852
|
-
case "plan_update":
|
|
75853
|
-
case "plan_removed":
|
|
75854
|
-
event = { kind: "content", payload };
|
|
75855
|
-
break;
|
|
75856
|
-
default:
|
|
75857
|
-
event = { kind: "other", payload };
|
|
76202
|
+
await options.onEvent(event);
|
|
75858
76203
|
}
|
|
75859
|
-
await options.onEvent(event);
|
|
75860
76204
|
});
|
|
75861
76205
|
this.events = this.#updates;
|
|
75862
76206
|
const client2 = {
|
|
@@ -75903,10 +76247,12 @@ var AdapterSessionConnection = class {
|
|
|
75903
76247
|
};
|
|
75904
76248
|
var AcpSessionConnector = class {
|
|
75905
76249
|
#externalizer;
|
|
75906
|
-
|
|
76250
|
+
#normalizeEvent;
|
|
76251
|
+
constructor(externalizer, normalizeEvent = (event) => event) {
|
|
75907
76252
|
this.#externalizer = externalizer;
|
|
76253
|
+
this.#normalizeEvent = normalizeEvent;
|
|
75908
76254
|
}
|
|
75909
|
-
connectSession = (options) => new AdapterSessionConnection(options, this.#externalizer);
|
|
76255
|
+
connectSession = (options) => new AdapterSessionConnection(options, this.#externalizer, this.#normalizeEvent);
|
|
75910
76256
|
connectQuerySession = (options) => {
|
|
75911
76257
|
const rejectInteraction = async () => {
|
|
75912
76258
|
throw new AcpExecutionError(
|
|
@@ -75924,7 +76270,8 @@ var AcpSessionConnector = class {
|
|
|
75924
76270
|
onElicitationComplete: rejectInteraction
|
|
75925
76271
|
}
|
|
75926
76272
|
},
|
|
75927
|
-
this.#externalizer
|
|
76273
|
+
this.#externalizer,
|
|
76274
|
+
this.#normalizeEvent
|
|
75928
76275
|
);
|
|
75929
76276
|
};
|
|
75930
76277
|
};
|
|
@@ -75944,1042 +76291,8 @@ var ClaudeAdapter = class {
|
|
|
75944
76291
|
close = async () => await this.#queryProcesses.close();
|
|
75945
76292
|
};
|
|
75946
76293
|
|
|
75947
|
-
// src/acp/
|
|
75948
|
-
import {
|
|
75949
|
-
|
|
75950
|
-
// src/acp/content/raster.ts
|
|
75951
|
-
import { basename as basename5, isAbsolute as isAbsolute13, normalize } from "node:path";
|
|
75952
|
-
import { fileURLToPath } from "node:url";
|
|
75953
|
-
|
|
75954
|
-
// src/storage/files/local-files.ts
|
|
75955
|
-
import { createReadStream as createReadStream2 } from "node:fs";
|
|
75956
|
-
import { mkdir as mkdir3, open as open4, readdir as readdir4, readFile as readFile5, realpath as realpath6, stat as stat5 } from "node:fs/promises";
|
|
75957
|
-
function entryKind(entry) {
|
|
75958
|
-
if (entry.isDirectory()) {
|
|
75959
|
-
return "directory";
|
|
75960
|
-
}
|
|
75961
|
-
if (entry.isFile()) {
|
|
75962
|
-
return "file";
|
|
75963
|
-
}
|
|
75964
|
-
if (entry.isSymbolicLink()) {
|
|
75965
|
-
return "symbolic-link";
|
|
75966
|
-
}
|
|
75967
|
-
if (entry.isBlockDevice() || entry.isCharacterDevice()) {
|
|
75968
|
-
return "device";
|
|
75969
|
-
}
|
|
75970
|
-
if (entry.isFIFO()) {
|
|
75971
|
-
return "fifo";
|
|
75972
|
-
}
|
|
75973
|
-
return entry.isSocket() ? "socket" : "unknown";
|
|
75974
|
-
}
|
|
75975
|
-
async function canonicalPath(path7) {
|
|
75976
|
-
return await realpath6(path7);
|
|
75977
|
-
}
|
|
75978
|
-
async function readPathMetadata(path7) {
|
|
75979
|
-
const metadata = await stat5(path7);
|
|
75980
|
-
return {
|
|
75981
|
-
kind: metadata.isDirectory() ? "directory" : metadata.isFile() ? "file" : "other",
|
|
75982
|
-
modifiedAt: metadata.mtime,
|
|
75983
|
-
modifiedMilliseconds: metadata.mtimeMs,
|
|
75984
|
-
size: metadata.size
|
|
75985
|
-
};
|
|
75986
|
-
}
|
|
75987
|
-
async function listDirectory(path7) {
|
|
75988
|
-
const entries = await readdir4(path7, { withFileTypes: true });
|
|
75989
|
-
return entries.map((entry) => ({ kind: entryKind(entry), name: entry.name }));
|
|
75990
|
-
}
|
|
75991
|
-
async function ensurePrivateDirectory(path7) {
|
|
75992
|
-
await mkdir3(path7, { mode: 448, recursive: true });
|
|
75993
|
-
}
|
|
75994
|
-
async function ensureCanonicalDirectory(path7) {
|
|
75995
|
-
await ensurePrivateDirectory(path7);
|
|
75996
|
-
const resolved = await realpath6(path7);
|
|
75997
|
-
return (await stat5(resolved)).isDirectory() ? resolved : null;
|
|
75998
|
-
}
|
|
75999
|
-
async function readFileStart(path7, byteLength) {
|
|
76000
|
-
const bytes = new Uint8Array(byteLength);
|
|
76001
|
-
const handle = await open4(path7, "r");
|
|
76002
|
-
try {
|
|
76003
|
-
await handle.read(bytes, 0, byteLength, 0);
|
|
76004
|
-
} finally {
|
|
76005
|
-
await handle.close();
|
|
76006
|
-
}
|
|
76007
|
-
return bytes;
|
|
76008
|
-
}
|
|
76009
|
-
async function readFileBytes(path7) {
|
|
76010
|
-
return await readFile5(path7);
|
|
76011
|
-
}
|
|
76012
|
-
function readFileChunks(path7, chunkBytes, signal) {
|
|
76013
|
-
return createReadStream2(path7, { highWaterMark: chunkBytes, signal });
|
|
76014
|
-
}
|
|
76015
|
-
|
|
76016
|
-
// src/acp/content/raster.ts
|
|
76017
|
-
var MAX_LOCAL_RASTER_BYTES = 128 * 1024 * 1024;
|
|
76018
|
-
var PNG_SIGNATURE = Uint8Array.of(137, 80, 78, 71);
|
|
76019
|
-
var JPEG_SIGNATURE = Uint8Array.of(255, 216, 255);
|
|
76020
|
-
var GIF87_SIGNATURE = new TextEncoder().encode("GIF87a");
|
|
76021
|
-
var GIF89_SIGNATURE = new TextEncoder().encode("GIF89a");
|
|
76022
|
-
var RIFF_SIGNATURE = new TextEncoder().encode("RIFF");
|
|
76023
|
-
var WEBP_SIGNATURE = new TextEncoder().encode("WEBP");
|
|
76024
|
-
var LocalRasterImage = class {
|
|
76025
|
-
mimeType;
|
|
76026
|
-
name;
|
|
76027
|
-
sourceUri;
|
|
76028
|
-
constructor(name2, mimeType, sourceUri) {
|
|
76029
|
-
this.mimeType = mimeType;
|
|
76030
|
-
this.name = name2;
|
|
76031
|
-
this.sourceUri = sourceUri;
|
|
76032
|
-
}
|
|
76033
|
-
base64 = async () => Buffer.from(await readFileBytes(this.sourceUri)).toString("base64");
|
|
76034
|
-
};
|
|
76035
|
-
function startsWith(bytes, signature, offset = 0) {
|
|
76036
|
-
if (bytes.byteLength < offset + signature.byteLength) {
|
|
76037
|
-
return false;
|
|
76038
|
-
}
|
|
76039
|
-
return signature.every((value, index2) => bytes[offset + index2] === value);
|
|
76040
|
-
}
|
|
76041
|
-
function sniffRasterMime(bytes) {
|
|
76042
|
-
if (startsWith(bytes, PNG_SIGNATURE)) {
|
|
76043
|
-
return "image/png";
|
|
76044
|
-
}
|
|
76045
|
-
if (startsWith(bytes, JPEG_SIGNATURE)) {
|
|
76046
|
-
return "image/jpeg";
|
|
76047
|
-
}
|
|
76048
|
-
if (startsWith(bytes, GIF87_SIGNATURE) || startsWith(bytes, GIF89_SIGNATURE)) {
|
|
76049
|
-
return "image/gif";
|
|
76050
|
-
}
|
|
76051
|
-
if (startsWith(bytes, RIFF_SIGNATURE) && startsWith(bytes, WEBP_SIGNATURE, 8)) {
|
|
76052
|
-
return "image/webp";
|
|
76053
|
-
}
|
|
76054
|
-
return null;
|
|
76055
|
-
}
|
|
76056
|
-
async function resolveCanonicalPath(requested, signal) {
|
|
76057
|
-
signal.throwIfAborted();
|
|
76058
|
-
if (!isAbsolute13(requested) || requested.includes("\0") || normalize(requested) !== requested) {
|
|
76059
|
-
return null;
|
|
76060
|
-
}
|
|
76061
|
-
try {
|
|
76062
|
-
const target = await canonicalPath(requested);
|
|
76063
|
-
signal.throwIfAborted();
|
|
76064
|
-
if (!isAbsolute13(target) || normalize(target) !== target) {
|
|
76065
|
-
return null;
|
|
76066
|
-
}
|
|
76067
|
-
return target;
|
|
76068
|
-
} catch (cause) {
|
|
76069
|
-
signal.throwIfAborted();
|
|
76070
|
-
if (cause instanceof Error && cause.name === "AbortError") {
|
|
76071
|
-
throw cause;
|
|
76072
|
-
}
|
|
76073
|
-
return null;
|
|
76074
|
-
}
|
|
76075
|
-
}
|
|
76076
|
-
function parseLocalImageUri(uri) {
|
|
76077
|
-
const trimmed = uri.trim();
|
|
76078
|
-
if (trimmed.length === 0 || trimmed.length > 2048 || trimmed.includes("\0")) {
|
|
76079
|
-
return null;
|
|
76080
|
-
}
|
|
76081
|
-
if (trimmed.startsWith("data:")) {
|
|
76082
|
-
return null;
|
|
76083
|
-
}
|
|
76084
|
-
if (trimmed.startsWith("file:")) {
|
|
76085
|
-
try {
|
|
76086
|
-
const url2 = new URL(trimmed);
|
|
76087
|
-
if (url2.protocol !== "file:" || url2.host.length > 0) {
|
|
76088
|
-
return null;
|
|
76089
|
-
}
|
|
76090
|
-
return fileURLToPath(url2);
|
|
76091
|
-
} catch {
|
|
76092
|
-
return null;
|
|
76093
|
-
}
|
|
76094
|
-
}
|
|
76095
|
-
if (!isAbsolute13(trimmed) && /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(trimmed)) {
|
|
76096
|
-
return null;
|
|
76097
|
-
}
|
|
76098
|
-
return trimmed;
|
|
76099
|
-
}
|
|
76100
|
-
async function readLocalRaster(uri, signal) {
|
|
76101
|
-
signal.throwIfAborted();
|
|
76102
|
-
const requested = parseLocalImageUri(uri);
|
|
76103
|
-
if (requested === null) {
|
|
76104
|
-
return null;
|
|
76105
|
-
}
|
|
76106
|
-
const target = await resolveCanonicalPath(requested, signal);
|
|
76107
|
-
if (target === null) {
|
|
76108
|
-
return null;
|
|
76109
|
-
}
|
|
76110
|
-
const targetMetadata = await readPathMetadata(target);
|
|
76111
|
-
signal.throwIfAborted();
|
|
76112
|
-
if (targetMetadata.kind !== "file" || targetMetadata.size < 1 || targetMetadata.size > MAX_LOCAL_RASTER_BYTES) {
|
|
76113
|
-
return null;
|
|
76114
|
-
}
|
|
76115
|
-
const header = await readFileStart(target, 12);
|
|
76116
|
-
signal.throwIfAborted();
|
|
76117
|
-
const mimeType = sniffRasterMime(header);
|
|
76118
|
-
if (mimeType === null) {
|
|
76119
|
-
return null;
|
|
76120
|
-
}
|
|
76121
|
-
return new LocalRasterImage(basename5(target) || "Image", mimeType, target);
|
|
76122
|
-
}
|
|
76123
|
-
|
|
76124
|
-
// src/acp/native-history/codex/history-images.ts
|
|
76125
|
-
var IMAGE_MARKER = /\[@image\]\(([^)\r\n]*)(?:\)|$)/g;
|
|
76126
|
-
var DATA_IMAGE_HEADER = /^data:(image\/[a-z+]+);base64,/;
|
|
76127
|
-
var BASE_64 = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
76128
|
-
var SESSION_HISTORY_IMAGE_CHARACTER_LIMIT = 4e6;
|
|
76129
|
-
var SESSION_HISTORY_PREVIEW_TURN_LIMIT = 10;
|
|
76130
|
-
function isRasterMime(value) {
|
|
76131
|
-
return value === "image/png" || value === "image/jpeg" || value === "image/gif" || value === "image/webp";
|
|
76132
|
-
}
|
|
76133
|
-
function parseNativeHistoryImage(uri) {
|
|
76134
|
-
const header = DATA_IMAGE_HEADER.exec(uri);
|
|
76135
|
-
if (header === null) {
|
|
76136
|
-
return null;
|
|
76137
|
-
}
|
|
76138
|
-
const mimeType = header[1] ?? "";
|
|
76139
|
-
const data = uri.slice(header[0].length);
|
|
76140
|
-
if (!isRasterMime(mimeType) || data.length < 4 || data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
76141
|
-
return null;
|
|
76142
|
-
}
|
|
76143
|
-
if (data.length % 4 !== 0 || !BASE_64.test(data)) {
|
|
76144
|
-
return null;
|
|
76145
|
-
}
|
|
76146
|
-
return { data, mimeType, name: "" };
|
|
76147
|
-
}
|
|
76148
|
-
async function embedLocalHistoryImages(history, signal) {
|
|
76149
|
-
if (history.status !== "available") {
|
|
76150
|
-
return history;
|
|
76151
|
-
}
|
|
76152
|
-
const messages = [];
|
|
76153
|
-
let imageCharacters = 0;
|
|
76154
|
-
for (const message of history.messages) {
|
|
76155
|
-
signal.throwIfAborted();
|
|
76156
|
-
const resolved = await resolveMessageImages(message, imageCharacters, signal);
|
|
76157
|
-
imageCharacters += (resolved.images ?? []).reduce((size, image) => size + image.data.length, 0);
|
|
76158
|
-
messages.push(resolved);
|
|
76159
|
-
}
|
|
76160
|
-
return {
|
|
76161
|
-
...history,
|
|
76162
|
-
messages
|
|
76163
|
-
};
|
|
76164
|
-
}
|
|
76165
|
-
async function resolveMessageImages(message, usedCharacters, signal) {
|
|
76166
|
-
const images = [...message.images ?? []];
|
|
76167
|
-
let imageCharacters = images.reduce((size, image) => size + image.data.length, 0);
|
|
76168
|
-
const text2 = await replaceImageMarkers(message.text, async (uri) => {
|
|
76169
|
-
if (images.length >= 8 || usedCharacters + imageCharacters >= SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
76170
|
-
return "[Image unavailable]";
|
|
76171
|
-
}
|
|
76172
|
-
const embedded = parseNativeHistoryImage(uri);
|
|
76173
|
-
if (embedded !== null) {
|
|
76174
|
-
if (usedCharacters + imageCharacters + embedded.data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
76175
|
-
return "[Image unavailable]";
|
|
76176
|
-
}
|
|
76177
|
-
images.push({ ...embedded, name: `Image ${(images.length + 1).toString()}` });
|
|
76178
|
-
imageCharacters += embedded.data.length;
|
|
76179
|
-
return "";
|
|
76180
|
-
}
|
|
76181
|
-
const local = await readLocalRaster(uri, signal);
|
|
76182
|
-
if (local === null) {
|
|
76183
|
-
return "[Image unavailable]";
|
|
76184
|
-
}
|
|
76185
|
-
const data = await local.base64();
|
|
76186
|
-
if (usedCharacters + imageCharacters + data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
76187
|
-
return "[Image unavailable]";
|
|
76188
|
-
}
|
|
76189
|
-
images.push({
|
|
76190
|
-
data,
|
|
76191
|
-
mimeType: local.mimeType,
|
|
76192
|
-
name: local.name
|
|
76193
|
-
});
|
|
76194
|
-
imageCharacters += data.length;
|
|
76195
|
-
return "";
|
|
76196
|
-
});
|
|
76197
|
-
return {
|
|
76198
|
-
...message,
|
|
76199
|
-
text: text2,
|
|
76200
|
-
...images.length > 0 ? { images } : {}
|
|
76201
|
-
};
|
|
76202
|
-
}
|
|
76203
|
-
async function replaceImageMarkers(text2, replace) {
|
|
76204
|
-
const matches = [...text2.matchAll(IMAGE_MARKER)];
|
|
76205
|
-
if (matches.length === 0) {
|
|
76206
|
-
return text2;
|
|
76207
|
-
}
|
|
76208
|
-
let cursor = 0;
|
|
76209
|
-
let rewritten = "";
|
|
76210
|
-
for (const match of matches) {
|
|
76211
|
-
const index2 = match.index ?? 0;
|
|
76212
|
-
rewritten += text2.slice(cursor, index2);
|
|
76213
|
-
rewritten += await replace(match[1] ?? "");
|
|
76214
|
-
cursor = index2 + match[0].length;
|
|
76215
|
-
}
|
|
76216
|
-
return `${rewritten}${text2.slice(cursor)}`;
|
|
76217
|
-
}
|
|
76218
|
-
|
|
76219
|
-
// src/acp/native-history/codex/codex-history.ts
|
|
76220
|
-
var responseSchema = external_exports.union([
|
|
76221
|
-
external_exports.object({
|
|
76222
|
-
id: external_exports.number(),
|
|
76223
|
-
error: external_exports.object({ code: external_exports.number(), message: external_exports.string() })
|
|
76224
|
-
}),
|
|
76225
|
-
external_exports.object({ id: external_exports.number(), result: external_exports.unknown() }),
|
|
76226
|
-
external_exports.object({ method: external_exports.string() })
|
|
76227
|
-
]);
|
|
76228
|
-
var threadSchema = external_exports.object({
|
|
76229
|
-
thread: external_exports.object({
|
|
76230
|
-
id: nativeSessionIdSchema,
|
|
76231
|
-
cwd: external_exports.string().min(1).max(2048).refine((path7) => !path7.includes("\0"))
|
|
76232
|
-
})
|
|
76233
|
-
});
|
|
76234
|
-
var turnsSchema = external_exports.object({
|
|
76235
|
-
data: external_exports.array(
|
|
76236
|
-
external_exports.object({
|
|
76237
|
-
id: external_exports.string().min(1),
|
|
76238
|
-
status: external_exports.enum(["completed", "interrupted", "failed", "inProgress"]),
|
|
76239
|
-
error: external_exports.unknown().nullish(),
|
|
76240
|
-
items: external_exports.array(external_exports.unknown()).max(1e5)
|
|
76241
|
-
})
|
|
76242
|
-
).max(SESSION_HISTORY_MESSAGE_LIMIT),
|
|
76243
|
-
nextCursor: external_exports.string().nullish()
|
|
76244
|
-
});
|
|
76245
|
-
var itemTypeSchema = external_exports.object({ type: external_exports.string().min(1).max(80) });
|
|
76246
|
-
var userMessageSchema = external_exports.object({
|
|
76247
|
-
content: external_exports.array(external_exports.unknown()).max(1e4),
|
|
76248
|
-
type: external_exports.literal("userMessage")
|
|
76249
|
-
});
|
|
76250
|
-
var textSchema = external_exports.object({ text: external_exports.string() });
|
|
76251
|
-
var imageSchema = external_exports.object({ url: external_exports.string() });
|
|
76252
|
-
var agentMessageSchema = textSchema.extend({
|
|
76253
|
-
id: external_exports.string().optional(),
|
|
76254
|
-
phase: external_exports.string().nullish(),
|
|
76255
|
-
type: external_exports.literal("agentMessage")
|
|
76256
|
-
});
|
|
76257
|
-
var reasoningSchema = external_exports.object({
|
|
76258
|
-
id: external_exports.string(),
|
|
76259
|
-
summary: external_exports.array(external_exports.string()).max(1e4),
|
|
76260
|
-
content: external_exports.array(external_exports.string()).max(1e4),
|
|
76261
|
-
type: external_exports.literal("reasoning")
|
|
76262
|
-
});
|
|
76263
|
-
var commandExecutionSchema = external_exports.object({
|
|
76264
|
-
id: external_exports.string(),
|
|
76265
|
-
command: external_exports.string(),
|
|
76266
|
-
cwd: external_exports.string(),
|
|
76267
|
-
status: external_exports.string(),
|
|
76268
|
-
commandActions: external_exports.array(external_exports.object({ type: external_exports.string() }).passthrough()).max(100),
|
|
76269
|
-
aggregatedOutput: external_exports.string().nullish(),
|
|
76270
|
-
exitCode: external_exports.number().int().nullish(),
|
|
76271
|
-
type: external_exports.literal("commandExecution")
|
|
76272
|
-
});
|
|
76273
|
-
var fileChangeSchema = external_exports.object({
|
|
76274
|
-
changes: external_exports.array(external_exports.object({ diff: external_exports.string(), path: external_exports.string() })).max(1e4),
|
|
76275
|
-
id: external_exports.string(),
|
|
76276
|
-
status: external_exports.string(),
|
|
76277
|
-
type: external_exports.literal("fileChange")
|
|
76278
|
-
});
|
|
76279
|
-
var mcpToolCallSchema = external_exports.object({
|
|
76280
|
-
arguments: external_exports.unknown().optional(),
|
|
76281
|
-
error: external_exports.unknown().nullish(),
|
|
76282
|
-
id: external_exports.string(),
|
|
76283
|
-
result: external_exports.unknown().nullish(),
|
|
76284
|
-
server: external_exports.string(),
|
|
76285
|
-
status: external_exports.string(),
|
|
76286
|
-
tool: external_exports.string(),
|
|
76287
|
-
type: external_exports.literal("mcpToolCall")
|
|
76288
|
-
});
|
|
76289
|
-
var dynamicToolCallSchema = external_exports.object({
|
|
76290
|
-
arguments: external_exports.unknown().optional(),
|
|
76291
|
-
contentItems: external_exports.array(external_exports.unknown()).max(1e4).nullish(),
|
|
76292
|
-
id: external_exports.string(),
|
|
76293
|
-
namespace: external_exports.string().nullish(),
|
|
76294
|
-
status: external_exports.string(),
|
|
76295
|
-
tool: external_exports.string(),
|
|
76296
|
-
type: external_exports.literal("dynamicToolCall")
|
|
76297
|
-
});
|
|
76298
|
-
var planSchema = external_exports.object({ id: external_exports.string(), text: external_exports.string(), type: external_exports.literal("plan") });
|
|
76299
|
-
var historyItemSchema = external_exports.discriminatedUnion("type", [
|
|
76300
|
-
userMessageSchema,
|
|
76301
|
-
agentMessageSchema,
|
|
76302
|
-
reasoningSchema,
|
|
76303
|
-
commandExecutionSchema,
|
|
76304
|
-
fileChangeSchema,
|
|
76305
|
-
mcpToolCallSchema,
|
|
76306
|
-
dynamicToolCallSchema,
|
|
76307
|
-
planSchema
|
|
76308
|
-
]);
|
|
76309
|
-
var CodexHistoryResponseError = class extends Error {
|
|
76310
|
-
code;
|
|
76311
|
-
constructor(response) {
|
|
76312
|
-
super(response.message);
|
|
76313
|
-
this.code = response.code;
|
|
76314
|
-
this.name = "CodexHistoryResponseError";
|
|
76315
|
-
}
|
|
76316
|
-
};
|
|
76317
|
-
function bounded(value, maximum) {
|
|
76318
|
-
return value.slice(0, maximum);
|
|
76319
|
-
}
|
|
76320
|
-
function activity(activityId, activityType, sequence, fields) {
|
|
76321
|
-
return {
|
|
76322
|
-
activityId: bounded(activityId, 128) || `history-${sequence.toString()}`,
|
|
76323
|
-
activityType,
|
|
76324
|
-
content: [],
|
|
76325
|
-
input: bounded(fields.input, 1e5),
|
|
76326
|
-
locations: fields.locations.filter((location) => location.length > 0).map((location) => bounded(location, 2048)).slice(0, 100),
|
|
76327
|
-
name: bounded(fields.name, 128),
|
|
76328
|
-
output: bounded(fields.output, 1e5),
|
|
76329
|
-
sequence,
|
|
76330
|
-
status: bounded(fields.status, 64),
|
|
76331
|
-
title: bounded(fields.title, 500),
|
|
76332
|
-
toolKind: bounded(fields.toolKind, 64)
|
|
76333
|
-
};
|
|
76334
|
-
}
|
|
76335
|
-
function errorMessage(value) {
|
|
76336
|
-
if (typeof value === "string") {
|
|
76337
|
-
return value;
|
|
76338
|
-
}
|
|
76339
|
-
if (typeof value === "object" && value !== null) {
|
|
76340
|
-
const message = Reflect.get(value, "message");
|
|
76341
|
-
if (typeof message === "string") {
|
|
76342
|
-
return message;
|
|
76343
|
-
}
|
|
76344
|
-
}
|
|
76345
|
-
return JSON.stringify(value) ?? "Codex stopped before completing this turn.";
|
|
76346
|
-
}
|
|
76347
|
-
function formatted(value) {
|
|
76348
|
-
if (value === void 0) {
|
|
76349
|
-
return "";
|
|
76350
|
-
}
|
|
76351
|
-
if (typeof value === "string") {
|
|
76352
|
-
return value;
|
|
76353
|
-
}
|
|
76354
|
-
return JSON.stringify(value) ?? "";
|
|
76355
|
-
}
|
|
76356
|
-
function toolStatus(status) {
|
|
76357
|
-
return status === "inProgress" ? "running" : status === "completed" ? "completed" : "failed";
|
|
76358
|
-
}
|
|
76359
|
-
function diffContent(path7, newText) {
|
|
76360
|
-
return { newText, path: path7, type: "diff" };
|
|
76361
|
-
}
|
|
76362
|
-
function messageSize(message) {
|
|
76363
|
-
return message.text.length + (message.role === "assistant" ? JSON.stringify(message.activities).length + JSON.stringify(message.content).length : 0);
|
|
76364
|
-
}
|
|
76365
|
-
var SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT = Math.floor(SESSION_HISTORY_CHARACTER_LIMIT / 2);
|
|
76366
|
-
function fitActivity(activity2, maximumCharacters) {
|
|
76367
|
-
const truncate4 = (limit) => ({
|
|
76368
|
-
...activity2,
|
|
76369
|
-
input: bounded(activity2.input, limit),
|
|
76370
|
-
locations: activity2.locations.map((location) => bounded(location, Math.max(1, limit))),
|
|
76371
|
-
name: bounded(activity2.name, limit),
|
|
76372
|
-
output: bounded(activity2.output, limit),
|
|
76373
|
-
title: bounded(activity2.title, limit),
|
|
76374
|
-
toolKind: bounded(activity2.toolKind, limit)
|
|
76375
|
-
});
|
|
76376
|
-
let minimum = 1;
|
|
76377
|
-
let maximum = 1e5;
|
|
76378
|
-
let fitted = truncate4(0);
|
|
76379
|
-
while (minimum <= maximum) {
|
|
76380
|
-
const limit = Math.floor((minimum + maximum) / 2);
|
|
76381
|
-
const candidate = truncate4(limit);
|
|
76382
|
-
if (JSON.stringify(candidate).length <= maximumCharacters) {
|
|
76383
|
-
fitted = candidate;
|
|
76384
|
-
minimum = limit + 1;
|
|
76385
|
-
} else {
|
|
76386
|
-
maximum = limit - 1;
|
|
76387
|
-
}
|
|
76388
|
-
}
|
|
76389
|
-
return fitted;
|
|
76390
|
-
}
|
|
76391
|
-
function fitActivities(activities, maximumCharacters) {
|
|
76392
|
-
if (activities.length === 0) {
|
|
76393
|
-
return activities;
|
|
76394
|
-
}
|
|
76395
|
-
const arrayCharacters = 2 + activities.length - 1;
|
|
76396
|
-
const maximumActivityCharacters = Math.floor(Math.max(0, maximumCharacters - arrayCharacters) / activities.length);
|
|
76397
|
-
return activities.map((activity2) => fitActivity(activity2, maximumActivityCharacters));
|
|
76398
|
-
}
|
|
76399
|
-
function fitHistoryMessage(message, maximumCharacters = SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT) {
|
|
76400
|
-
const text2 = message.text.slice(-maximumCharacters);
|
|
76401
|
-
if (message.role === "user") {
|
|
76402
|
-
return {
|
|
76403
|
-
message: { ...message, text: text2 },
|
|
76404
|
-
truncated: text2.length < message.text.length
|
|
76405
|
-
};
|
|
76406
|
-
}
|
|
76407
|
-
let activities = message.activities;
|
|
76408
|
-
const content = message.content;
|
|
76409
|
-
let fitted = { ...message, activities, content, text: text2 };
|
|
76410
|
-
if (messageSize(fitted) > maximumCharacters && activities.length > 0) {
|
|
76411
|
-
const maximumActivityCharacters = maximumCharacters - text2.length - JSON.stringify(content).length;
|
|
76412
|
-
activities = fitActivities(activities, maximumActivityCharacters);
|
|
76413
|
-
fitted = { ...fitted, activities };
|
|
76414
|
-
}
|
|
76415
|
-
const excess = Math.max(0, messageSize(fitted) - maximumCharacters);
|
|
76416
|
-
if (excess > 0) {
|
|
76417
|
-
const maximumTextLength = Math.max(0, fitted.text.length - excess);
|
|
76418
|
-
fitted = {
|
|
76419
|
-
...fitted,
|
|
76420
|
-
text: maximumTextLength === 0 ? "" : fitted.text.slice(-maximumTextLength)
|
|
76421
|
-
};
|
|
76422
|
-
}
|
|
76423
|
-
return {
|
|
76424
|
-
message: fitted,
|
|
76425
|
-
truncated: fitted.text.length < message.text.length || JSON.stringify(activities).length < JSON.stringify(message.activities).length
|
|
76426
|
-
};
|
|
76427
|
-
}
|
|
76428
|
-
function turnOutcome2(status) {
|
|
76429
|
-
switch (status) {
|
|
76430
|
-
case "completed":
|
|
76431
|
-
return "succeeded";
|
|
76432
|
-
case "interrupted":
|
|
76433
|
-
return "cancelled";
|
|
76434
|
-
case "failed":
|
|
76435
|
-
return "failed";
|
|
76436
|
-
case "inProgress":
|
|
76437
|
-
return void 0;
|
|
76438
|
-
default: {
|
|
76439
|
-
const unhandled = status;
|
|
76440
|
-
throw new Error(`Unknown Codex turn status: ${String(unhandled)}`);
|
|
76441
|
-
}
|
|
76442
|
-
}
|
|
76443
|
-
}
|
|
76444
|
-
function decodeHistory(thread, value, options) {
|
|
76445
|
-
const page = turnsSchema.parse(value);
|
|
76446
|
-
const nativeTurn = options.nativeTurn?.();
|
|
76447
|
-
const coveredCommandIds = nativeTurn != null && page.data[0]?.id === nativeTurn.nativeTurnId ? [nativeTurn.commandId] : [];
|
|
76448
|
-
const messages = [];
|
|
76449
|
-
let characters = 0;
|
|
76450
|
-
let truncated = page.nextCursor != null;
|
|
76451
|
-
for (const turn of page.data.toReversed()) {
|
|
76452
|
-
const outcome = turnOutcome2(turn.status);
|
|
76453
|
-
const turnMessageCharacterLimit = Math.max(
|
|
76454
|
-
1,
|
|
76455
|
-
Math.floor(SESSION_HISTORY_CHARACTER_LIMIT / Math.max(1, turn.items.length + (turn.error == null ? 0 : 1)))
|
|
76456
|
-
);
|
|
76457
|
-
let sequence = 0;
|
|
76458
|
-
let assistantMessageIndex = null;
|
|
76459
|
-
const append = (message) => {
|
|
76460
|
-
const fitted = fitHistoryMessage(message, turnMessageCharacterLimit);
|
|
76461
|
-
if (fitted.message.text.length === 0 && (fitted.message.images?.length ?? 0) === 0 && (fitted.message.role === "user" || fitted.message.activities.length === 0 && fitted.message.content.length === 0)) {
|
|
76462
|
-
return;
|
|
76463
|
-
}
|
|
76464
|
-
truncated ||= fitted.truncated;
|
|
76465
|
-
messages.push(fitted.message);
|
|
76466
|
-
if (fitted.message.role === "assistant") {
|
|
76467
|
-
assistantMessageIndex = messages.length - 1;
|
|
76468
|
-
}
|
|
76469
|
-
characters += messageSize(fitted.message);
|
|
76470
|
-
};
|
|
76471
|
-
for (const item of turn.items) {
|
|
76472
|
-
const decoded = historyItemSchema.safeParse(item);
|
|
76473
|
-
if (!decoded.success) {
|
|
76474
|
-
continue;
|
|
76475
|
-
}
|
|
76476
|
-
const historyItem = decoded.data;
|
|
76477
|
-
if (historyItem.type === "userMessage") {
|
|
76478
|
-
const text2 = historyItem.content.map((block) => {
|
|
76479
|
-
const { type } = itemTypeSchema.parse(block);
|
|
76480
|
-
if (type === "text") {
|
|
76481
|
-
return textSchema.parse(block).text;
|
|
76482
|
-
}
|
|
76483
|
-
if (type === "image") {
|
|
76484
|
-
return `[@image](${imageSchema.parse(block).url})`;
|
|
76485
|
-
}
|
|
76486
|
-
return "[Attachment]";
|
|
76487
|
-
}).join("");
|
|
76488
|
-
append({
|
|
76489
|
-
role: "user",
|
|
76490
|
-
text: text2
|
|
76491
|
-
});
|
|
76492
|
-
} else if (historyItem.type === "agentMessage") {
|
|
76493
|
-
append({ activities: [], content: [], role: "assistant", text: historyItem.text });
|
|
76494
|
-
} else if (historyItem.type === "reasoning") {
|
|
76495
|
-
const output2 = (historyItem.content.length > 0 ? historyItem.content : historyItem.summary).join(
|
|
76496
|
-
"\n\n"
|
|
76497
|
-
);
|
|
76498
|
-
if (output2.length > 0) {
|
|
76499
|
-
append({
|
|
76500
|
-
activities: [
|
|
76501
|
-
activity(historyItem.id, "reasoning", sequence, {
|
|
76502
|
-
input: "",
|
|
76503
|
-
locations: [],
|
|
76504
|
-
name: "",
|
|
76505
|
-
output: output2,
|
|
76506
|
-
status: "completed",
|
|
76507
|
-
title: "Reasoning",
|
|
76508
|
-
toolKind: ""
|
|
76509
|
-
})
|
|
76510
|
-
],
|
|
76511
|
-
content: [],
|
|
76512
|
-
role: "assistant",
|
|
76513
|
-
text: ""
|
|
76514
|
-
});
|
|
76515
|
-
sequence += 1;
|
|
76516
|
-
}
|
|
76517
|
-
} else if (historyItem.type === "commandExecution") {
|
|
76518
|
-
const action = historyItem.commandActions[0]?.type ?? "execute";
|
|
76519
|
-
append({
|
|
76520
|
-
activities: [
|
|
76521
|
-
activity(historyItem.id, "tool", sequence, {
|
|
76522
|
-
input: JSON.stringify({ command: historyItem.command, cwd: historyItem.cwd }),
|
|
76523
|
-
locations: [historyItem.cwd],
|
|
76524
|
-
name: "",
|
|
76525
|
-
output: JSON.stringify({
|
|
76526
|
-
formatted_output: historyItem.aggregatedOutput ?? "",
|
|
76527
|
-
...historyItem.exitCode == null ? {} : { exit_code: historyItem.exitCode }
|
|
76528
|
-
}),
|
|
76529
|
-
status: toolStatus(historyItem.status),
|
|
76530
|
-
title: historyItem.command,
|
|
76531
|
-
toolKind: action
|
|
76532
|
-
})
|
|
76533
|
-
],
|
|
76534
|
-
content: [],
|
|
76535
|
-
role: "assistant",
|
|
76536
|
-
text: ""
|
|
76537
|
-
});
|
|
76538
|
-
sequence += 1;
|
|
76539
|
-
} else if (historyItem.type === "fileChange") {
|
|
76540
|
-
const paths = historyItem.changes.map((change) => change.path);
|
|
76541
|
-
const content = historyItem.changes.map(
|
|
76542
|
-
(change) => diffContent(change.path, change.diff)
|
|
76543
|
-
);
|
|
76544
|
-
append({
|
|
76545
|
-
activities: [
|
|
76546
|
-
activity(historyItem.id, "tool", sequence, {
|
|
76547
|
-
input: JSON.stringify({ changes: paths }),
|
|
76548
|
-
locations: paths,
|
|
76549
|
-
name: "",
|
|
76550
|
-
output: "",
|
|
76551
|
-
status: toolStatus(historyItem.status),
|
|
76552
|
-
title: paths.join(", "),
|
|
76553
|
-
toolKind: "edit"
|
|
76554
|
-
})
|
|
76555
|
-
].map((entry) => ({ ...entry, content })),
|
|
76556
|
-
content: [],
|
|
76557
|
-
role: "assistant",
|
|
76558
|
-
text: ""
|
|
76559
|
-
});
|
|
76560
|
-
sequence += 1;
|
|
76561
|
-
} else if (historyItem.type === "mcpToolCall") {
|
|
76562
|
-
append({
|
|
76563
|
-
activities: [
|
|
76564
|
-
activity(historyItem.id, "tool", sequence, {
|
|
76565
|
-
input: formatted(historyItem.arguments),
|
|
76566
|
-
locations: [],
|
|
76567
|
-
name: historyItem.tool,
|
|
76568
|
-
output: formatted(historyItem.error ?? historyItem.result),
|
|
76569
|
-
status: toolStatus(historyItem.status),
|
|
76570
|
-
title: `${historyItem.server}/${historyItem.tool}`,
|
|
76571
|
-
toolKind: "other"
|
|
76572
|
-
})
|
|
76573
|
-
],
|
|
76574
|
-
content: [],
|
|
76575
|
-
role: "assistant",
|
|
76576
|
-
text: ""
|
|
76577
|
-
});
|
|
76578
|
-
sequence += 1;
|
|
76579
|
-
} else if (historyItem.type === "dynamicToolCall") {
|
|
76580
|
-
append({
|
|
76581
|
-
activities: [
|
|
76582
|
-
activity(historyItem.id, "tool", sequence, {
|
|
76583
|
-
input: formatted(historyItem.arguments),
|
|
76584
|
-
locations: [],
|
|
76585
|
-
name: historyItem.tool,
|
|
76586
|
-
output: formatted(historyItem.contentItems),
|
|
76587
|
-
status: toolStatus(historyItem.status),
|
|
76588
|
-
title: historyItem.namespace == null ? historyItem.tool : `${historyItem.namespace}/${historyItem.tool}`,
|
|
76589
|
-
toolKind: "other"
|
|
76590
|
-
})
|
|
76591
|
-
],
|
|
76592
|
-
content: [],
|
|
76593
|
-
role: "assistant",
|
|
76594
|
-
text: ""
|
|
76595
|
-
});
|
|
76596
|
-
sequence += 1;
|
|
76597
|
-
} else if (historyItem.type === "plan") {
|
|
76598
|
-
append({
|
|
76599
|
-
activities: [
|
|
76600
|
-
activity(historyItem.id, "plan", sequence, {
|
|
76601
|
-
input: "",
|
|
76602
|
-
locations: [],
|
|
76603
|
-
name: "",
|
|
76604
|
-
output: historyItem.text,
|
|
76605
|
-
status: "completed",
|
|
76606
|
-
title: "Plan",
|
|
76607
|
-
toolKind: ""
|
|
76608
|
-
})
|
|
76609
|
-
],
|
|
76610
|
-
content: [],
|
|
76611
|
-
role: "assistant",
|
|
76612
|
-
text: ""
|
|
76613
|
-
});
|
|
76614
|
-
sequence += 1;
|
|
76615
|
-
}
|
|
76616
|
-
}
|
|
76617
|
-
if (turn.error != null) {
|
|
76618
|
-
append({
|
|
76619
|
-
activities: [
|
|
76620
|
-
activity(`agent-error-${sequence.toString()}`, "tool", sequence, {
|
|
76621
|
-
input: "",
|
|
76622
|
-
locations: [],
|
|
76623
|
-
name: "",
|
|
76624
|
-
output: errorMessage(turn.error),
|
|
76625
|
-
status: "failed",
|
|
76626
|
-
title: "Agent error",
|
|
76627
|
-
toolKind: "other"
|
|
76628
|
-
})
|
|
76629
|
-
],
|
|
76630
|
-
content: [],
|
|
76631
|
-
role: "assistant",
|
|
76632
|
-
text: ""
|
|
76633
|
-
});
|
|
76634
|
-
}
|
|
76635
|
-
if (assistantMessageIndex !== null) {
|
|
76636
|
-
const assistant = messages[assistantMessageIndex];
|
|
76637
|
-
if (assistant?.role === "assistant") {
|
|
76638
|
-
characters -= messageSize(assistant);
|
|
76639
|
-
const updated = {
|
|
76640
|
-
...assistant,
|
|
76641
|
-
...outcome === void 0 ? {} : { outcome }
|
|
76642
|
-
};
|
|
76643
|
-
const fitted = fitHistoryMessage(updated, turnMessageCharacterLimit);
|
|
76644
|
-
truncated ||= fitted.truncated;
|
|
76645
|
-
messages[assistantMessageIndex] = fitted.message;
|
|
76646
|
-
characters += messageSize(fitted.message);
|
|
76647
|
-
}
|
|
76648
|
-
} else if (outcome !== void 0) {
|
|
76649
|
-
const message = {
|
|
76650
|
-
activities: [],
|
|
76651
|
-
content: [],
|
|
76652
|
-
role: "assistant",
|
|
76653
|
-
...outcome === void 0 ? {} : { outcome },
|
|
76654
|
-
text: ""
|
|
76655
|
-
};
|
|
76656
|
-
const fitted = fitHistoryMessage(message, turnMessageCharacterLimit);
|
|
76657
|
-
truncated ||= fitted.truncated;
|
|
76658
|
-
messages.push(fitted.message);
|
|
76659
|
-
characters += messageSize(fitted.message);
|
|
76660
|
-
}
|
|
76661
|
-
while (messages.length > SESSION_HISTORY_MESSAGE_LIMIT || characters > SESSION_HISTORY_CHARACTER_LIMIT) {
|
|
76662
|
-
const removed = messages.shift();
|
|
76663
|
-
if (removed !== void 0) {
|
|
76664
|
-
characters -= messageSize(removed);
|
|
76665
|
-
}
|
|
76666
|
-
truncated = true;
|
|
76667
|
-
}
|
|
76668
|
-
}
|
|
76669
|
-
return {
|
|
76670
|
-
nativeSessionId: thread.id,
|
|
76671
|
-
cwd: thread.cwd,
|
|
76672
|
-
history: {
|
|
76673
|
-
status: "available",
|
|
76674
|
-
messages,
|
|
76675
|
-
truncated,
|
|
76676
|
-
coveredCommandIds,
|
|
76677
|
-
coveredMessageIds: []
|
|
76678
|
-
}
|
|
76679
|
-
};
|
|
76680
|
-
}
|
|
76681
|
-
async function readCodexHistoryWithOptions(agent, cwd, nativeSessionId, signal, options) {
|
|
76682
|
-
signal.throwIfAborted();
|
|
76683
|
-
nativeSessionIdSchema.parse(nativeSessionId);
|
|
76684
|
-
if (agent.id !== "codex" || !await revalidateExecutable(agent.agentIdentity)) {
|
|
76685
|
-
throw new AcpExecutionError(
|
|
76686
|
-
"The local Codex executable changed. Restart Mobius to discover it again.",
|
|
76687
|
-
{},
|
|
76688
|
-
"agent_executable_changed"
|
|
76689
|
-
);
|
|
76690
|
-
}
|
|
76691
|
-
signal.throwIfAborted();
|
|
76692
|
-
const launch = executableLaunch2(agent.agentIdentity.realPath, ["app-server"]);
|
|
76693
|
-
const child = spawn8(launch.command, [...launch.arguments], {
|
|
76694
|
-
cwd,
|
|
76695
|
-
env: { ...process.env, ...agent.environment },
|
|
76696
|
-
...platformSpawnOptions,
|
|
76697
|
-
shell: false,
|
|
76698
|
-
stdio: ["pipe", "pipe", "ignore"]
|
|
76699
|
-
});
|
|
76700
|
-
const response = Promise.withResolvers();
|
|
76701
|
-
let state = { kind: "initializing", requestId: 1 };
|
|
76702
|
-
const seenCursors = /* @__PURE__ */ new Set();
|
|
76703
|
-
let pendingBytes = 0;
|
|
76704
|
-
let pendingFragments = [];
|
|
76705
|
-
const fail = (cause) => response.reject(
|
|
76706
|
-
cause instanceof AcpExecutionError ? cause : new AcpExecutionError(
|
|
76707
|
-
"Saved Codex history could not be read.",
|
|
76708
|
-
{ cause },
|
|
76709
|
-
"native_history_unavailable"
|
|
76710
|
-
)
|
|
76711
|
-
);
|
|
76712
|
-
const send2 = (message) => {
|
|
76713
|
-
child.stdin.write(`${JSON.stringify(message)}
|
|
76714
|
-
`);
|
|
76715
|
-
};
|
|
76716
|
-
const onData = (chunk) => {
|
|
76717
|
-
try {
|
|
76718
|
-
let cursor = 0;
|
|
76719
|
-
let newline = chunk.indexOf("\n");
|
|
76720
|
-
while (newline >= 0) {
|
|
76721
|
-
const fragment = chunk.slice(cursor, newline);
|
|
76722
|
-
const lineBytes = pendingBytes + Buffer.byteLength(fragment);
|
|
76723
|
-
if (lineBytes > 32 * 1024 * 1024) {
|
|
76724
|
-
throw new AcpExecutionError(
|
|
76725
|
-
"This saved conversation is too large to preview.",
|
|
76726
|
-
{},
|
|
76727
|
-
"native_history_too_large"
|
|
76728
|
-
);
|
|
76729
|
-
}
|
|
76730
|
-
const line = pendingFragments.length === 0 ? fragment : [...pendingFragments, fragment].join("");
|
|
76731
|
-
pendingBytes = 0;
|
|
76732
|
-
pendingFragments = [];
|
|
76733
|
-
cursor = newline + 1;
|
|
76734
|
-
newline = chunk.indexOf("\n", cursor);
|
|
76735
|
-
if (line.trim().length === 0) {
|
|
76736
|
-
continue;
|
|
76737
|
-
}
|
|
76738
|
-
const value = JSON.parse(line);
|
|
76739
|
-
const message = responseSchema.parse(value);
|
|
76740
|
-
if (!("id" in message)) {
|
|
76741
|
-
continue;
|
|
76742
|
-
}
|
|
76743
|
-
if (message.id !== state.requestId) {
|
|
76744
|
-
throw new AcpExecutionError(
|
|
76745
|
-
"Codex returned an invalid history response.",
|
|
76746
|
-
{},
|
|
76747
|
-
"invalid_native_session_response"
|
|
76748
|
-
);
|
|
76749
|
-
}
|
|
76750
|
-
if ("error" in message) {
|
|
76751
|
-
fail(
|
|
76752
|
-
new AcpExecutionError(
|
|
76753
|
-
"Saved Codex history could not be read.",
|
|
76754
|
-
{ cause: new CodexHistoryResponseError(message.error) },
|
|
76755
|
-
"native_history_unavailable"
|
|
76756
|
-
)
|
|
76757
|
-
);
|
|
76758
|
-
return;
|
|
76759
|
-
}
|
|
76760
|
-
switch (state.kind) {
|
|
76761
|
-
case "initializing":
|
|
76762
|
-
state = { kind: "metadata", requestId: 2 };
|
|
76763
|
-
send2({ method: "initialized", params: {} });
|
|
76764
|
-
send2({
|
|
76765
|
-
id: state.requestId,
|
|
76766
|
-
method: "thread/read",
|
|
76767
|
-
params: { threadId: nativeSessionId, includeTurns: false }
|
|
76768
|
-
});
|
|
76769
|
-
break;
|
|
76770
|
-
case "metadata": {
|
|
76771
|
-
const { thread } = threadSchema.parse(message.result);
|
|
76772
|
-
state = { kind: "turns", requestId: 3, thread, pages: [] };
|
|
76773
|
-
send2({
|
|
76774
|
-
id: state.requestId,
|
|
76775
|
-
method: "thread/turns/list",
|
|
76776
|
-
params: {
|
|
76777
|
-
threadId: nativeSessionId,
|
|
76778
|
-
limit: SESSION_HISTORY_PREVIEW_TURN_LIMIT,
|
|
76779
|
-
sortDirection: "desc",
|
|
76780
|
-
itemsView: "full"
|
|
76781
|
-
}
|
|
76782
|
-
});
|
|
76783
|
-
break;
|
|
76784
|
-
}
|
|
76785
|
-
case "turns": {
|
|
76786
|
-
const page = turnsSchema.parse(message.result);
|
|
76787
|
-
const pages = [...state.pages, ...page.data];
|
|
76788
|
-
const maxTurns = SESSION_HISTORY_MESSAGE_LIMIT;
|
|
76789
|
-
if (page.nextCursor == null || pages.length >= maxTurns) {
|
|
76790
|
-
response.resolve(
|
|
76791
|
-
decodeHistory(
|
|
76792
|
-
state.thread,
|
|
76793
|
-
{
|
|
76794
|
-
data: pages.slice(0, maxTurns),
|
|
76795
|
-
nextCursor: page.nextCursor
|
|
76796
|
-
},
|
|
76797
|
-
options
|
|
76798
|
-
)
|
|
76799
|
-
);
|
|
76800
|
-
return;
|
|
76801
|
-
}
|
|
76802
|
-
if (page.data.length === 0 || seenCursors.has(page.nextCursor)) {
|
|
76803
|
-
throw new AcpExecutionError(
|
|
76804
|
-
"Codex repeated a history page cursor.",
|
|
76805
|
-
{},
|
|
76806
|
-
"invalid_native_session_response"
|
|
76807
|
-
);
|
|
76808
|
-
}
|
|
76809
|
-
seenCursors.add(page.nextCursor);
|
|
76810
|
-
state = { kind: "turns", requestId: state.requestId + 1, thread: state.thread, pages };
|
|
76811
|
-
send2({
|
|
76812
|
-
id: state.requestId,
|
|
76813
|
-
method: "thread/turns/list",
|
|
76814
|
-
params: {
|
|
76815
|
-
threadId: nativeSessionId,
|
|
76816
|
-
cursor: page.nextCursor,
|
|
76817
|
-
limit: Math.min(SESSION_HISTORY_PREVIEW_TURN_LIMIT, maxTurns - pages.length),
|
|
76818
|
-
sortDirection: "desc",
|
|
76819
|
-
itemsView: "full"
|
|
76820
|
-
}
|
|
76821
|
-
});
|
|
76822
|
-
break;
|
|
76823
|
-
}
|
|
76824
|
-
default: {
|
|
76825
|
-
const unhandled = state;
|
|
76826
|
-
throw new Error(`Unknown history read state: ${String(unhandled)}`);
|
|
76827
|
-
}
|
|
76828
|
-
}
|
|
76829
|
-
}
|
|
76830
|
-
const remainder = chunk.slice(cursor);
|
|
76831
|
-
if (remainder.length > 0) {
|
|
76832
|
-
pendingBytes += Buffer.byteLength(remainder);
|
|
76833
|
-
if (pendingBytes > 32 * 1024 * 1024) {
|
|
76834
|
-
throw new AcpExecutionError(
|
|
76835
|
-
"This saved conversation is too large to preview.",
|
|
76836
|
-
{},
|
|
76837
|
-
"native_history_too_large"
|
|
76838
|
-
);
|
|
76839
|
-
}
|
|
76840
|
-
pendingFragments.push(remainder);
|
|
76841
|
-
}
|
|
76842
|
-
} catch (cause) {
|
|
76843
|
-
fail(cause);
|
|
76844
|
-
}
|
|
76845
|
-
};
|
|
76846
|
-
const abort = () => response.reject(signal.reason);
|
|
76847
|
-
const onExit = () => fail(
|
|
76848
|
-
new AcpExecutionError(
|
|
76849
|
-
"Codex stopped before its saved history was available.",
|
|
76850
|
-
{},
|
|
76851
|
-
"native_history_unavailable"
|
|
76852
|
-
)
|
|
76853
|
-
);
|
|
76854
|
-
const timeout = setTimeout(
|
|
76855
|
-
() => fail(new AcpExecutionError("Reading saved Codex history timed out.", {}, "native_history_timeout")),
|
|
76856
|
-
6e4
|
|
76857
|
-
);
|
|
76858
|
-
child.stdout.setEncoding("utf8");
|
|
76859
|
-
child.stdout.on("data", onData);
|
|
76860
|
-
child.stdin.on("error", fail);
|
|
76861
|
-
child.on("error", fail);
|
|
76862
|
-
child.on("exit", onExit);
|
|
76863
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
76864
|
-
try {
|
|
76865
|
-
if (signal.aborted) {
|
|
76866
|
-
abort();
|
|
76867
|
-
} else {
|
|
76868
|
-
send2({
|
|
76869
|
-
id: 1,
|
|
76870
|
-
method: "initialize",
|
|
76871
|
-
params: { clientInfo: { name: "mobius_history", version: "1.0.0" } }
|
|
76872
|
-
});
|
|
76873
|
-
}
|
|
76874
|
-
const snapshot = await response.promise;
|
|
76875
|
-
return {
|
|
76876
|
-
...snapshot,
|
|
76877
|
-
history: await embedLocalHistoryImages(snapshot.history, signal)
|
|
76878
|
-
};
|
|
76879
|
-
} finally {
|
|
76880
|
-
clearTimeout(timeout);
|
|
76881
|
-
signal.removeEventListener("abort", abort);
|
|
76882
|
-
child.stdout.removeListener("data", onData);
|
|
76883
|
-
if (child.pid !== void 0) {
|
|
76884
|
-
await stopProcessTree(child);
|
|
76885
|
-
}
|
|
76886
|
-
child.stdin.removeListener("error", fail);
|
|
76887
|
-
child.removeListener("error", fail);
|
|
76888
|
-
child.removeListener("exit", onExit);
|
|
76889
|
-
}
|
|
76890
|
-
}
|
|
76891
|
-
var readCodexFullHistory = async (agent, cwd, nativeSessionId, signal, nativeTurn) => await readCodexHistoryWithOptions(agent, cwd, nativeSessionId, signal, {
|
|
76892
|
-
...nativeTurn === void 0 ? {} : { nativeTurn }
|
|
76893
|
-
});
|
|
76894
|
-
|
|
76895
|
-
// src/acp/native-history/codex/native-history-events.ts
|
|
76896
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
76897
|
-
function toolKind(value) {
|
|
76898
|
-
switch (value) {
|
|
76899
|
-
case "read":
|
|
76900
|
-
case "edit":
|
|
76901
|
-
case "delete":
|
|
76902
|
-
case "move":
|
|
76903
|
-
case "search":
|
|
76904
|
-
case "execute":
|
|
76905
|
-
case "think":
|
|
76906
|
-
case "fetch":
|
|
76907
|
-
case "switch_mode":
|
|
76908
|
-
case "other":
|
|
76909
|
-
return value;
|
|
76910
|
-
default:
|
|
76911
|
-
return "other";
|
|
76912
|
-
}
|
|
76913
|
-
}
|
|
76914
|
-
function toolStatus2(value) {
|
|
76915
|
-
switch (value) {
|
|
76916
|
-
case "pending":
|
|
76917
|
-
return "pending";
|
|
76918
|
-
case "running":
|
|
76919
|
-
case "in_progress":
|
|
76920
|
-
return "in_progress";
|
|
76921
|
-
case "completed":
|
|
76922
|
-
return "completed";
|
|
76923
|
-
default:
|
|
76924
|
-
return "failed";
|
|
76925
|
-
}
|
|
76926
|
-
}
|
|
76927
|
-
function activityEvent(activity2) {
|
|
76928
|
-
if (activity2.activityType === "reasoning") {
|
|
76929
|
-
return {
|
|
76930
|
-
payload: {
|
|
76931
|
-
content: { text: activity2.output, type: "text" },
|
|
76932
|
-
messageId: activity2.activityId,
|
|
76933
|
-
sessionUpdate: "agent_thought_chunk"
|
|
76934
|
-
},
|
|
76935
|
-
type: "acp"
|
|
76936
|
-
};
|
|
76937
|
-
}
|
|
76938
|
-
return {
|
|
76939
|
-
payload: {
|
|
76940
|
-
content: activity2.content,
|
|
76941
|
-
kind: toolKind(activity2.toolKind),
|
|
76942
|
-
locations: activity2.locations.map((path7) => ({ path: path7 })),
|
|
76943
|
-
rawInput: activity2.input,
|
|
76944
|
-
rawOutput: activity2.output,
|
|
76945
|
-
sessionUpdate: "tool_call",
|
|
76946
|
-
status: toolStatus2(activity2.status),
|
|
76947
|
-
title: activity2.title,
|
|
76948
|
-
toolCallId: activity2.activityId,
|
|
76949
|
-
...activity2.name.length === 0 ? {} : { name: activity2.name }
|
|
76950
|
-
},
|
|
76951
|
-
type: "acp"
|
|
76952
|
-
};
|
|
76953
|
-
}
|
|
76954
|
-
function contentEvent(sessionUpdate, messageId, content) {
|
|
76955
|
-
return { payload: { content, messageId, sessionUpdate }, type: "acp" };
|
|
76956
|
-
}
|
|
76957
|
-
function historyEvents(history) {
|
|
76958
|
-
return history.messages.flatMap((message, index2) => {
|
|
76959
|
-
const messageId = `native-history-${index2.toString()}`;
|
|
76960
|
-
const sessionUpdate = message.role === "user" ? "user_message_chunk" : "agent_message_chunk";
|
|
76961
|
-
const images = (message.images ?? []).map(
|
|
76962
|
-
(image) => contentEvent(sessionUpdate, messageId, {
|
|
76963
|
-
data: image.data,
|
|
76964
|
-
mimeType: image.mimeType,
|
|
76965
|
-
type: "image"
|
|
76966
|
-
})
|
|
76967
|
-
);
|
|
76968
|
-
const text2 = message.text.length === 0 ? [] : [contentEvent(sessionUpdate, messageId, { text: message.text, type: "text" })];
|
|
76969
|
-
if (message.role === "user") {
|
|
76970
|
-
return [...images, ...text2];
|
|
76971
|
-
}
|
|
76972
|
-
const activities = message.activities.map(activityEvent);
|
|
76973
|
-
const content = message.content.map((block) => contentEvent(sessionUpdate, messageId, block));
|
|
76974
|
-
return [...activities, ...content, ...images, ...text2];
|
|
76975
|
-
});
|
|
76976
|
-
}
|
|
76977
|
-
function nativeHistoryEvents(sessionId, nativeSessionId, history, eventLimit, cursor, eventStore) {
|
|
76978
|
-
const events = historyEvents(history);
|
|
76979
|
-
const generationId = createHash2("sha256").update(nativeSessionId).update("\0").update(JSON.stringify(events)).digest("hex");
|
|
76980
|
-
eventStore.materialize(sessionId, generationId, events);
|
|
76981
|
-
return eventStore.page(sessionId, eventLimit, cursor);
|
|
76982
|
-
}
|
|
76294
|
+
// src/acp/adapter/codex/adapter.ts
|
|
76295
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
76983
76296
|
|
|
76984
76297
|
// src/storage/session/temporary-session-event-cache.ts
|
|
76985
76298
|
import { mkdtempSync, rmSync as rmSync2 } from "node:fs";
|
|
@@ -82189,13 +81502,85 @@ function openPreviewEventCache() {
|
|
|
82189
81502
|
}
|
|
82190
81503
|
}
|
|
82191
81504
|
|
|
81505
|
+
// src/acp/adapter/codex/tool-event.ts
|
|
81506
|
+
var toolEventSchema = external_exports.looseObject({
|
|
81507
|
+
sessionUpdate: external_exports.enum(["tool_call", "tool_call_update"]),
|
|
81508
|
+
rawInput: external_exports.unknown().optional(),
|
|
81509
|
+
rawOutput: external_exports.unknown().optional()
|
|
81510
|
+
});
|
|
81511
|
+
var TRUNCATED_TOOL_PAYLOAD_CHARACTER_LIMIT = 32768;
|
|
81512
|
+
var MAX_TOOL_PAYLOAD_DEPTH = 16;
|
|
81513
|
+
function payloadText(value) {
|
|
81514
|
+
let text2;
|
|
81515
|
+
try {
|
|
81516
|
+
text2 = JSON.stringify(value) ?? "";
|
|
81517
|
+
} catch {
|
|
81518
|
+
text2 = "Tool payload could not be represented as JSON.";
|
|
81519
|
+
}
|
|
81520
|
+
return text2.slice(0, TRUNCATED_TOOL_PAYLOAD_CHARACTER_LIMIT);
|
|
81521
|
+
}
|
|
81522
|
+
function fitNesting(value, depth = 0) {
|
|
81523
|
+
if (typeof value !== "object" || value === null) {
|
|
81524
|
+
return value;
|
|
81525
|
+
}
|
|
81526
|
+
if (depth === MAX_TOOL_PAYLOAD_DEPTH && Object.keys(value).length > 0) {
|
|
81527
|
+
return `[truncated: nesting depth] ${payloadText(value)}`;
|
|
81528
|
+
}
|
|
81529
|
+
if (Array.isArray(value)) {
|
|
81530
|
+
return value.map((child) => fitNesting(child, depth + 1));
|
|
81531
|
+
}
|
|
81532
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, fitNesting(child, depth + 1)]));
|
|
81533
|
+
}
|
|
81534
|
+
function prepareCodexToolUpdate(update) {
|
|
81535
|
+
if (update.sessionUpdate !== "tool_call" && update.sessionUpdate !== "tool_call_update") {
|
|
81536
|
+
return update;
|
|
81537
|
+
}
|
|
81538
|
+
return {
|
|
81539
|
+
...update,
|
|
81540
|
+
...update.rawOutput === void 0 ? {} : { rawOutput: fitNesting(update.rawOutput) },
|
|
81541
|
+
...update._meta == null ? {} : {
|
|
81542
|
+
_meta: Object.fromEntries(
|
|
81543
|
+
Object.entries(update._meta).map(([key, child]) => [key, fitNesting(child, 1)])
|
|
81544
|
+
)
|
|
81545
|
+
}
|
|
81546
|
+
};
|
|
81547
|
+
}
|
|
81548
|
+
function fitPayload(value) {
|
|
81549
|
+
if (value === void 0 || boundedJsonSchema.safeParse(value).success) {
|
|
81550
|
+
return value;
|
|
81551
|
+
}
|
|
81552
|
+
return { truncated: true, text: payloadText(value) };
|
|
81553
|
+
}
|
|
81554
|
+
function fitCodexToolEvent(event) {
|
|
81555
|
+
const decoded = toolEventSchema.safeParse(event);
|
|
81556
|
+
if (!decoded.success) {
|
|
81557
|
+
return event;
|
|
81558
|
+
}
|
|
81559
|
+
return {
|
|
81560
|
+
...decoded.data,
|
|
81561
|
+
rawInput: fitPayload(decoded.data.rawInput),
|
|
81562
|
+
rawOutput: fitPayload(decoded.data.rawOutput)
|
|
81563
|
+
};
|
|
81564
|
+
}
|
|
81565
|
+
|
|
82192
81566
|
// src/acp/adapter/codex/adapter.ts
|
|
82193
81567
|
var CodexAdapter = class {
|
|
82194
81568
|
#queryProcesses;
|
|
82195
81569
|
#connector;
|
|
81570
|
+
#dependencies;
|
|
81571
|
+
#contentExternalizer;
|
|
82196
81572
|
#previewCache = null;
|
|
82197
81573
|
constructor(dependencies) {
|
|
82198
|
-
this.#
|
|
81574
|
+
this.#dependencies = dependencies;
|
|
81575
|
+
this.#contentExternalizer = {
|
|
81576
|
+
update: async (sessionId, update, signal) => {
|
|
81577
|
+
signal.throwIfAborted();
|
|
81578
|
+
const prepared = prepareCodexToolUpdate(update);
|
|
81579
|
+
signal.throwIfAborted();
|
|
81580
|
+
return await dependencies.contentExternalizer.update(sessionId, prepared, signal);
|
|
81581
|
+
}
|
|
81582
|
+
};
|
|
81583
|
+
this.#connector = new AcpSessionConnector(this.#contentExternalizer, fitCodexToolEvent);
|
|
82199
81584
|
this.#queryProcesses = new AgentQueryProcesses(dependencies.processes, this.#connector);
|
|
82200
81585
|
}
|
|
82201
81586
|
capabilities = async (query) => await this.#queryProcesses.capabilities(query);
|
|
@@ -82209,21 +81594,73 @@ var CodexAdapter = class {
|
|
|
82209
81594
|
}
|
|
82210
81595
|
};
|
|
82211
81596
|
previewSessionEvents = async (query, request) => {
|
|
82212
|
-
const { agent, cwd
|
|
81597
|
+
const { agent, cwd } = query;
|
|
81598
|
+
const signal = AbortSignal.any([query.signal, AbortSignal.timeout(6e4)]);
|
|
82213
81599
|
const { sessionId } = request;
|
|
82214
|
-
|
|
82215
|
-
|
|
82216
|
-
if (
|
|
82217
|
-
throw new AcpExecutionError(
|
|
81600
|
+
signal.throwIfAborted();
|
|
81601
|
+
nativeSessionIdSchema.parse(request.nativeSessionId);
|
|
81602
|
+
if (agent.id !== "codex") {
|
|
81603
|
+
throw new AcpExecutionError(
|
|
81604
|
+
"The Codex adapter cannot preview history for another agent.",
|
|
81605
|
+
{},
|
|
81606
|
+
"agent_adapter_mismatch"
|
|
81607
|
+
);
|
|
82218
81608
|
}
|
|
82219
|
-
|
|
82220
|
-
|
|
82221
|
-
|
|
82222
|
-
|
|
82223
|
-
|
|
82224
|
-
|
|
82225
|
-
|
|
81609
|
+
if (!await revalidateExecutable(agent.agentIdentity)) {
|
|
81610
|
+
throw new AcpExecutionError(
|
|
81611
|
+
"The local Codex executable changed. Restart Mobius to discover it again.",
|
|
81612
|
+
{},
|
|
81613
|
+
"agent_executable_changed"
|
|
81614
|
+
);
|
|
81615
|
+
}
|
|
81616
|
+
this.#previewCache ??= openPreviewEventCache();
|
|
81617
|
+
const events = [];
|
|
81618
|
+
await this.#dependencies.processes.runTransient(
|
|
81619
|
+
signal,
|
|
81620
|
+
async () => {
|
|
81621
|
+
const client2 = new CodexAppServerClient({
|
|
81622
|
+
command: agent.command,
|
|
81623
|
+
cwd,
|
|
81624
|
+
environment: agent.environment,
|
|
81625
|
+
handlers: {
|
|
81626
|
+
onNotification: async () => void 0,
|
|
81627
|
+
onServerRequest: async () => {
|
|
81628
|
+
throw new AcpExecutionError(
|
|
81629
|
+
"Unexpected request while reading saved history",
|
|
81630
|
+
{},
|
|
81631
|
+
"invalid_native_session_response"
|
|
81632
|
+
);
|
|
81633
|
+
}
|
|
81634
|
+
}
|
|
81635
|
+
});
|
|
81636
|
+
return {
|
|
81637
|
+
client: client2,
|
|
81638
|
+
closeProcess: async () => {
|
|
81639
|
+
client2.detach();
|
|
81640
|
+
await stopProcessTree(client2.child());
|
|
81641
|
+
}
|
|
81642
|
+
};
|
|
81643
|
+
},
|
|
81644
|
+
async ({ client: client2 }) => {
|
|
81645
|
+
await client2.initialize(signal);
|
|
81646
|
+
return await replayCodexHistory(
|
|
81647
|
+
client2,
|
|
81648
|
+
request.nativeSessionId,
|
|
81649
|
+
async (update) => {
|
|
81650
|
+
const externalized = await this.#contentExternalizer.update(sessionId, update, signal);
|
|
81651
|
+
events.push({
|
|
81652
|
+
type: "acp",
|
|
81653
|
+
payload: decodeAcpSessionUpdate(JSON.stringify(fitCodexToolEvent(externalized.event)))
|
|
81654
|
+
});
|
|
81655
|
+
},
|
|
81656
|
+
signal
|
|
81657
|
+
);
|
|
81658
|
+
},
|
|
81659
|
+
async (runtime) => await runtime.closeProcess()
|
|
82226
81660
|
);
|
|
81661
|
+
const generationId = createHash4("sha256").update(request.nativeSessionId).update("\0").update(JSON.stringify(events)).digest("hex");
|
|
81662
|
+
this.#previewCache.events.materialize(sessionId, generationId, events);
|
|
81663
|
+
return this.#previewCache.events.page(sessionId, request.eventLimit, request.cursor);
|
|
82227
81664
|
};
|
|
82228
81665
|
};
|
|
82229
81666
|
|
|
@@ -82262,18 +81699,6 @@ var harnessAdapters = (agent, dependencies) => {
|
|
|
82262
81699
|
|
|
82263
81700
|
// src/acp/content/content-externalizer.ts
|
|
82264
81701
|
var MAXIMUM_ENCODED_CONTENT_CHARACTERS = 4e6;
|
|
82265
|
-
var MAXIMUM_REASONING_CHUNK_BYTES = 24 * 1024;
|
|
82266
|
-
function reasoningTail(text2) {
|
|
82267
|
-
if (Buffer.byteLength(text2, "utf8") <= MAXIMUM_REASONING_CHUNK_BYTES) {
|
|
82268
|
-
return text2;
|
|
82269
|
-
}
|
|
82270
|
-
const bytes = Buffer.from(text2, "utf8");
|
|
82271
|
-
let start = bytes.length - MAXIMUM_REASONING_CHUNK_BYTES;
|
|
82272
|
-
while (start < bytes.length && (bytes.readUInt8(start) & 192) === 128) {
|
|
82273
|
-
start += 1;
|
|
82274
|
-
}
|
|
82275
|
-
return bytes.toString("utf8", start);
|
|
82276
|
-
}
|
|
82277
81702
|
function decodeBase64(data) {
|
|
82278
81703
|
if (data.length > MAXIMUM_ENCODED_CONTENT_CHARACTERS || data.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/u.test(data)) {
|
|
82279
81704
|
throw new Error("The ACP embedded content is not valid bounded base64");
|
|
@@ -82469,24 +81894,7 @@ var AcpContentExternalizer = class {
|
|
|
82469
81894
|
}
|
|
82470
81895
|
update = async (sessionId, update, signal) => {
|
|
82471
81896
|
switch (update.sessionUpdate) {
|
|
82472
|
-
case "agent_thought_chunk":
|
|
82473
|
-
if (update.content.type === "text") {
|
|
82474
|
-
const text2 = reasoningTail(update.content.text);
|
|
82475
|
-
const bounded2 = { ...update, content: { ...update.content, text: text2 } };
|
|
82476
|
-
return {
|
|
82477
|
-
agent: bounded2,
|
|
82478
|
-
event: {
|
|
82479
|
-
...bounded2,
|
|
82480
|
-
...text2 === update.content.text ? {} : { meta: { truncated: true } }
|
|
82481
|
-
}
|
|
82482
|
-
};
|
|
82483
|
-
}
|
|
82484
|
-
const content = await this.#content(sessionId, update.content, signal);
|
|
82485
|
-
return {
|
|
82486
|
-
agent: { ...update, content: content.agent },
|
|
82487
|
-
event: { ...update, content: content.event }
|
|
82488
|
-
};
|
|
82489
|
-
}
|
|
81897
|
+
case "agent_thought_chunk":
|
|
82490
81898
|
case "user_message_chunk":
|
|
82491
81899
|
case "agent_message_chunk":
|
|
82492
81900
|
case "compaction_summary_chunk": {
|
|
@@ -82648,7 +82056,7 @@ import { randomUUID as randomUUID10 } from "node:crypto";
|
|
|
82648
82056
|
import { resolve as resolve14 } from "node:path";
|
|
82649
82057
|
|
|
82650
82058
|
// src/storage/installation/installation-files.ts
|
|
82651
|
-
import { createHash as
|
|
82059
|
+
import { createHash as createHash5, randomUUID as randomUUID9 } from "node:crypto";
|
|
82652
82060
|
import { mkdir as mkdir4, open as open5, readdir as readdir5, rename as rename3, unlink as unlink3, writeFile } from "node:fs/promises";
|
|
82653
82061
|
import { dirname as dirname9, join as join23 } from "node:path";
|
|
82654
82062
|
|
|
@@ -82675,7 +82083,7 @@ function connectionFilePath(connectionDirectory2, connectionId2) {
|
|
|
82675
82083
|
return join23(connectionDirectory2, `${connectionId2}.json`);
|
|
82676
82084
|
}
|
|
82677
82085
|
function channelIndexFilePath(installationDirectory2, channelId) {
|
|
82678
|
-
return join23(installationDirectory2, "channels", `mci_${
|
|
82086
|
+
return join23(installationDirectory2, "channels", `mci_${createHash5("sha256").update(channelId).digest("hex")}.json`);
|
|
82679
82087
|
}
|
|
82680
82088
|
async function readInstallationFile(path7) {
|
|
82681
82089
|
let handle;
|
|
@@ -86984,7 +86392,7 @@ async function settleAbandonedTurn(projection, operations, cancellation) {
|
|
|
86984
86392
|
}
|
|
86985
86393
|
|
|
86986
86394
|
// src/session/turn/execution-receipts.ts
|
|
86987
|
-
import { createHash as
|
|
86395
|
+
import { createHash as createHash6, randomUUID as randomUUID12 } from "node:crypto";
|
|
86988
86396
|
var MAX_TERMINAL_RECEIPTS = 1024;
|
|
86989
86397
|
function isTerminal(state) {
|
|
86990
86398
|
return state === "succeeded" || state === "failed" || state === "cancelled";
|
|
@@ -87100,7 +86508,7 @@ var ExecutionReceipts = class {
|
|
|
87100
86508
|
];
|
|
87101
86509
|
});
|
|
87102
86510
|
claimExecution = (commandId, sessionId, commandJson) => {
|
|
87103
|
-
const commandHash =
|
|
86511
|
+
const commandHash = createHash6("sha256").update(commandJson).digest("hex");
|
|
87104
86512
|
let existing = this.#executions.get(commandId);
|
|
87105
86513
|
const previous = this.outcome(commandId);
|
|
87106
86514
|
if (existing?.sessionId === sessionId && !existing.started && previous?.type === "lifecycle-metadata" && previous.payload.kind === "prompt.failed-before-start" && previous.payload.code === "runtime_restarted") {
|
|
@@ -87453,9 +86861,9 @@ var SessionTurns = class {
|
|
|
87453
86861
|
#bySessionId = /* @__PURE__ */ new Map();
|
|
87454
86862
|
#operations;
|
|
87455
86863
|
#activity;
|
|
87456
|
-
constructor(operations,
|
|
86864
|
+
constructor(operations, activity = new RuntimeTurnActivity()) {
|
|
87457
86865
|
this.#operations = operations;
|
|
87458
|
-
this.#activity =
|
|
86866
|
+
this.#activity = activity;
|
|
87459
86867
|
}
|
|
87460
86868
|
acceptsPrompts = () => this.#activity.acceptsPrompts();
|
|
87461
86869
|
session = (sessionId) => {
|
|
@@ -87788,7 +87196,7 @@ function buildSessionLayer(options) {
|
|
|
87788
87196
|
}
|
|
87789
87197
|
|
|
87790
87198
|
// src/session/content/external-content-store.ts
|
|
87791
|
-
import { createHash as
|
|
87199
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
87792
87200
|
import { join as join27 } from "node:path";
|
|
87793
87201
|
|
|
87794
87202
|
// src/storage/files/scratch-directory.ts
|
|
@@ -87912,7 +87320,7 @@ var LocalExternalContentStore = class {
|
|
|
87912
87320
|
const active = AbortSignal.any([signal, this.#lifetime.signal]);
|
|
87913
87321
|
active.throwIfAborted();
|
|
87914
87322
|
const metadata = metadataSchema.parse({ kind, mediaType, name: name2 });
|
|
87915
|
-
const key =
|
|
87323
|
+
const key = createHash7("sha256").update(bytes).digest("hex");
|
|
87916
87324
|
const request = `mobius-content:${kind}:${key}`;
|
|
87917
87325
|
const existing = this.#entries.get(request);
|
|
87918
87326
|
if (existing !== void 0 && existing.expiresAt > Date.now()) {
|
|
@@ -88777,7 +88185,7 @@ var SessionError = class extends OperationError {
|
|
|
88777
88185
|
};
|
|
88778
88186
|
|
|
88779
88187
|
// src/session/settings/discover-agent-settings.ts
|
|
88780
|
-
import { createHash as
|
|
88188
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
88781
88189
|
|
|
88782
88190
|
// src/agent/settings/agent-settings-base.ts
|
|
88783
88191
|
var AgentSettingsLaunchSelectionResult = class {
|
|
@@ -89095,7 +88503,7 @@ function settingsRevision(agent, reportedAgentVersion, settings, modelEffort) {
|
|
|
89095
88503
|
unsupportedModelIds: modelEffort.unsupportedModelIds,
|
|
89096
88504
|
valuesByModel: {}
|
|
89097
88505
|
};
|
|
89098
|
-
return
|
|
88506
|
+
return createHash8("sha256").update(
|
|
89099
88507
|
JSON.stringify({
|
|
89100
88508
|
adapterVersion: agent.kind === "acp-adapter-process" ? agent.adapterVersion : agent.agentVersion,
|
|
89101
88509
|
agentId: agent.id,
|
|
@@ -89404,35 +88812,7 @@ async function resolveSessionDirectories(directories, bindingId, directoryId, ad
|
|
|
89404
88812
|
}
|
|
89405
88813
|
|
|
89406
88814
|
// src/runtime/command/registry/history.ts
|
|
89407
|
-
function
|
|
89408
|
-
return event?.type === "acp" && event.payload.sessionUpdate === "agent_thought_chunk";
|
|
89409
|
-
}
|
|
89410
|
-
function omitAgentReasoning(events) {
|
|
89411
|
-
const retained = [];
|
|
89412
|
-
let previousReasoningMessageId;
|
|
89413
|
-
for (const positioned of events) {
|
|
89414
|
-
const { event } = positioned;
|
|
89415
|
-
if (event.type !== "acp" || event.payload.sessionUpdate !== "agent_thought_chunk") {
|
|
89416
|
-
previousReasoningMessageId = void 0;
|
|
89417
|
-
retained.push(positioned);
|
|
89418
|
-
continue;
|
|
89419
|
-
}
|
|
89420
|
-
const messageId = event.payload.messageId ?? null;
|
|
89421
|
-
if (previousReasoningMessageId === void 0 || previousReasoningMessageId !== messageId) {
|
|
89422
|
-
retained.push({
|
|
89423
|
-
...positioned,
|
|
89424
|
-
event: {
|
|
89425
|
-
...event,
|
|
89426
|
-
mobiusMetadata: { omitted: true },
|
|
89427
|
-
payload: { ...event.payload, content: { text: "", type: "text" } }
|
|
89428
|
-
}
|
|
89429
|
-
});
|
|
89430
|
-
}
|
|
89431
|
-
previousReasoningMessageId = messageId;
|
|
89432
|
-
}
|
|
89433
|
-
return retained;
|
|
89434
|
-
}
|
|
89435
|
-
async function loadHistoryPage(sessionId, eventLimit, initialCursor, omitReasoning, queuedPromptRequests, load) {
|
|
88815
|
+
async function loadHistoryPage(sessionId, eventLimit, initialCursor, queuedPromptRequests, load) {
|
|
89436
88816
|
let cursor = initialCursor;
|
|
89437
88817
|
let loaded = [];
|
|
89438
88818
|
let sessionGenerationId = null;
|
|
@@ -89459,9 +88839,7 @@ async function loadHistoryPage(sessionId, eventLimit, initialCursor, omitReasoni
|
|
|
89459
88839
|
});
|
|
89460
88840
|
loaded = [...events, ...loaded];
|
|
89461
88841
|
sourceNextCursor = replay.nextCursor;
|
|
89462
|
-
|
|
89463
|
-
const reasoningContinuesBeforePage = sourceNextCursor !== null && isAgentReasoning(loaded[0]?.event);
|
|
89464
|
-
if (visible2.length >= eventLimit && !reasoningContinuesBeforePage) {
|
|
88842
|
+
if (loaded.length >= eventLimit) {
|
|
89465
88843
|
break;
|
|
89466
88844
|
}
|
|
89467
88845
|
cursor = sourceNextCursor;
|
|
@@ -89469,8 +88847,7 @@ async function loadHistoryPage(sessionId, eventLimit, initialCursor, omitReasoni
|
|
|
89469
88847
|
if (sessionGenerationId === null || throughPosition === null) {
|
|
89470
88848
|
throw new SessionError("session_history_unavailable", "The Session history is unavailable");
|
|
89471
88849
|
}
|
|
89472
|
-
const
|
|
89473
|
-
const orderedEvents = visible.slice(-eventLimit);
|
|
88850
|
+
const orderedEvents = loaded.slice(-eventLimit);
|
|
89474
88851
|
const nextCursor = orderedEvents[0]?.cursor ?? null;
|
|
89475
88852
|
return {
|
|
89476
88853
|
events: {
|
|
@@ -89512,7 +88889,6 @@ async function executeSessionHistoryPageLoad(socket, command, config2, resolveAg
|
|
|
89512
88889
|
command.sessionId,
|
|
89513
88890
|
command.eventLimit,
|
|
89514
88891
|
command.cursor,
|
|
89515
|
-
command.omit?.includes("agent-reasoning") === true,
|
|
89516
88892
|
recovery.queuedPromptRequests,
|
|
89517
88893
|
async (eventLimit, cursor) => await sessions.loadSessionEvents(loadOptions, eventLimit, cursor)
|
|
89518
88894
|
);
|
|
@@ -89559,7 +88935,6 @@ async function executeSessionPreviewHistoryPageLoad(socket, command, config2, re
|
|
|
89559
88935
|
command.sessionId,
|
|
89560
88936
|
command.eventLimit,
|
|
89561
88937
|
command.cursor,
|
|
89562
|
-
command.omit?.includes("agent-reasoning") === true,
|
|
89563
88938
|
[],
|
|
89564
88939
|
async (eventLimit, cursor) => await sessions.previewNativeSessionEvents(loadOptions, command.sessionId, eventLimit, cursor)
|
|
89565
88940
|
);
|
|
@@ -90292,7 +89667,7 @@ async function executePrompt({
|
|
|
90292
89667
|
}
|
|
90293
89668
|
|
|
90294
89669
|
// src/runtime/relay/artifact-download.ts
|
|
90295
|
-
import { createHash as
|
|
89670
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
90296
89671
|
import { fetch as fetch4 } from "undici";
|
|
90297
89672
|
var ARTIFACT_DOWNLOAD_TIMEOUT_MILLISECONDS = 2e4;
|
|
90298
89673
|
function downloadUrl(config2, artifact) {
|
|
@@ -90380,7 +89755,7 @@ async function downloadPromptArtifact(config2, artifact, signal) {
|
|
|
90380
89755
|
);
|
|
90381
89756
|
}
|
|
90382
89757
|
const bytes = await responseBytes(response, artifact.byteLength, requestSignal);
|
|
90383
|
-
if (
|
|
89758
|
+
if (createHash9("sha256").update(bytes).digest("hex") !== artifact.sha256) {
|
|
90384
89759
|
throw new PromptArtifactError(
|
|
90385
89760
|
"artifact_integrity_failed",
|
|
90386
89761
|
"The prompt artifact failed integrity validation"
|